001/*
002 * VM-Operator
003 * Copyright (C) 2024 Michael N. Lipp
004 * 
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
017 */
018
019package org.jdrupes.vmoperator.common;
020
021import com.google.gson.Gson;
022import com.google.gson.JsonObject;
023import com.google.gson.JsonPrimitive;
024import java.util.Collection;
025import java.util.EnumSet;
026import java.util.HashMap;
027import java.util.Map;
028import java.util.Optional;
029import java.util.Set;
030import java.util.function.Function;
031import java.util.stream.Collectors;
032import org.jdrupes.vmoperator.util.GsonPtr;
033
034/**
035 * Represents a VM definition.
036 */
037@SuppressWarnings("PMD.DataClass")
038public class VmDefinitionModel extends K8sDynamicModel {
039
040    /**
041     * Permissions for accessing and manipulating the VM.
042     */
043    public enum Permission {
044        START("start"), STOP("stop"), RESET("reset"),
045        ACCESS_CONSOLE("accessConsole");
046
047        @SuppressWarnings("PMD.UseConcurrentHashMap")
048        private static Map<String, Permission> reprs = new HashMap<>();
049
050        static {
051            for (var value : EnumSet.allOf(Permission.class)) {
052                reprs.put(value.repr, value);
053            }
054        }
055
056        private final String repr;
057
058        Permission(String repr) {
059            this.repr = repr;
060        }
061
062        /**
063         * Create permission from representation in CRD.
064         *
065         * @param value the value
066         * @return the permission
067         */
068        @SuppressWarnings("PMD.AvoidLiteralsInIfCondition")
069        public static Set<Permission> parse(String value) {
070            if ("*".equals(value)) {
071                return EnumSet.allOf(Permission.class);
072            }
073            return Set.of(reprs.get(value));
074        }
075
076        @Override
077        public String toString() {
078            return repr;
079        }
080    }
081
082    /**
083     * Instantiates a new model from the JSON representation.
084     *
085     * @param delegate the gson instance to use for extracting structured data
086     * @param json the JSON
087     */
088    public VmDefinitionModel(Gson delegate, JsonObject json) {
089        super(delegate, json);
090    }
091
092    /**
093     * Collect all permissions for the given user with the given roles.
094     *
095     * @param user the user
096     * @param roles the roles
097     * @return the sets the
098     */
099    public Set<Permission> permissionsFor(String user,
100            Collection<String> roles) {
101        return GsonPtr.to(data())
102            .getAsListOf(JsonObject.class, "spec", "permissions")
103            .stream().filter(p -> GsonPtr.to(p).getAsString("user")
104                .map(u -> u.equals(user)).orElse(false)
105                || GsonPtr.to(p).getAsString("role").map(roles::contains)
106                    .orElse(false))
107            .map(p -> GsonPtr.to(p).getAsListOf(JsonPrimitive.class, "may")
108                .stream())
109            .flatMap(Function.identity()).map(p -> p.getAsString())
110            .map(Permission::parse).map(Set::stream)
111            .flatMap(Function.identity()).collect(Collectors.toSet());
112    }
113
114    /**
115     * Get the display password serial.
116     *
117     * @return the optional
118     */
119    public Optional<Long> displayPasswordSerial() {
120        return GsonPtr.to(status())
121            .get(JsonPrimitive.class, "displayPasswordSerial")
122            .map(JsonPrimitive::getAsLong);
123    }
124}