/** * */ package com.thinkbiganalytics.security.rest.controller; /*- * #%L * thinkbig-security-controller * %% * Copyright (C) 2017 ThinkBig Analytics * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import com.thinkbiganalytics.security.GroupPrincipal; import com.thinkbiganalytics.security.UsernamePrincipal; import com.thinkbiganalytics.security.action.AllowableAction; import com.thinkbiganalytics.security.action.AllowedActions; import com.thinkbiganalytics.security.rest.model.Action; import com.thinkbiganalytics.security.rest.model.ActionGroup; import com.thinkbiganalytics.security.rest.model.PermissionsChange; import com.thinkbiganalytics.security.rest.model.Role; import com.thinkbiganalytics.security.rest.model.RoleMembership; import com.thinkbiganalytics.security.rest.model.PermissionsChange.ChangeType; import com.thinkbiganalytics.security.role.SecurityRole; import java.security.Principal; import java.security.acl.Group; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; /** * Contains transformation functions and methods for converting objects between * the REST and domain access control models. */ public class SecurityModelTransform { public Function<AllowedActions, PermissionsChange> toPermissionsChange(ChangeType changeType, String name, Set<String> users, Set<String> groups) { return (allowed) -> { ActionGroup actionSet = toActionGroup(name).apply(allowed); PermissionsChange change = new PermissionsChange(changeType, actionSet); change.setUsers(users); change.setGroups(groups); return change; }; } public Function<AllowedActions, ActionGroup> toActionGroup(String module) { return (allowed) -> { List<Action> list = allowed.getAvailableActions().stream() .map(toAction()) .collect(Collectors.toList()); ActionGroup actions = new ActionGroup(module); actions.setActions(list); return actions; }; } public Function<AllowableAction, Action> toActionGroup() { return (allowable) -> { Action action = new Action(allowable.getSystemName(), allowable.getTitle(), allowable.getDescription()); action.setActions(allowable.getSubActions().stream() .map(toAction()) .collect(Collectors.toList())); return action; }; } public Function<AllowableAction, Action> toAction() { return (allowable) -> { Action action = new Action(allowable.getSystemName(), allowable.getTitle(), allowable.getDescription()); action.setActions(allowable.getSubActions().stream() .map(toAction()) .collect(Collectors.toList())); return action; }; } public Function<SecurityRole, Role> toRole() { return (secRole) -> { Role role = new Role(); role.setSystemName(secRole.getSystemName()); role.setTitle(secRole.getTitle()); role.setDescription(secRole.getDescription()); role.setAllowedActions(toActionGroup(null).apply(secRole.getAllowedActions())); return role; }; } public Function<List<SecurityRole>, List<Role>> toRoles() { return (securityRoles) -> securityRoles.stream().map(toRole()).collect(Collectors.toList()); } public Function<com.thinkbiganalytics.metadata.api.security.RoleMembership, RoleMembership> toRoleMembership() { return (domain) -> { RoleMembership membership = new RoleMembership(); membership.setRole(toRole().apply(domain.getRole())); domain.getMembers().forEach(p -> { if (p instanceof Group) { membership.getGroups().add(p.getName()); } else { membership.getUsers().add(p.getName()); } }); return membership; }; } public void addAction(PermissionsChange change, List<? extends com.thinkbiganalytics.security.action.Action> hierarchy) { ActionGroup actionSet = change.getActionSet(); for (com.thinkbiganalytics.security.action.Action action : hierarchy) { addHierarchy(actionSet, action.getHierarchy().iterator()); } } public UsernamePrincipal asUserPrincipal(String username) { return new UsernamePrincipal(username); } public UsernamePrincipal[] asUserPrincipals(Set<String> userNames) { return userNames.stream() .map(name -> asUserPrincipal(name)) .toArray(UsernamePrincipal[]::new); } public GroupPrincipal[] asGroupPrincipals(Set<String> userNames) { return userNames.stream() .map(name -> new GroupPrincipal(name)) .toArray(GroupPrincipal[]::new); } public Set<Principal> collectPrincipals(PermissionsChange changes) { Set<Principal> set = new HashSet<>(); Collections.addAll(set, asUserPrincipals(changes.getUsers())); Collections.addAll(set, asGroupPrincipals(changes.getGroups())); return set; } /** * Creates a set of domain actions from the REST model actions. The resulting set will * contain only the leaf actions from the domain action hierarchy. */ public Set<com.thinkbiganalytics.security.action.Action> collectActions(PermissionsChange changes) { Set<com.thinkbiganalytics.security.action.Action> set = new HashSet<>(); for (Action modelAction : changes.getActionSet().getActions()) { loadActionSet(modelAction, com.thinkbiganalytics.security.action.Action.create(modelAction.getSystemName(), modelAction.getTitle(), modelAction.getDescription()), set); } return set; } /** * Adds a new domain action to the set if the REST model action represents a leaf of the action hierarchy. * Otherwise, it loads the child actions recursively. */ public void loadActionSet(Action modelAction, com.thinkbiganalytics.security.action.Action action, Set<com.thinkbiganalytics.security.action.Action> set) { if (modelAction.getActions().isEmpty()) { set.add(action); } else { for (Action modelChild : modelAction.getActions()) { loadActionSet(modelChild, action.subAction(modelChild.getSystemName(), modelChild.getTitle(), modelChild.getDescription()), set); } } } // // public void addAction(PermissionsChange change, com.thinkbiganalytics.security.action.Action domainAction) { // ActionGroup actionSet = new ActionGroup(""); // addHierarchy(actionSet, domainAction.getHierarchy().iterator()); // } private void addHierarchy(ActionGroup actionSet, Iterator<com.thinkbiganalytics.security.action.Action> itr) { if (itr.hasNext()) { com.thinkbiganalytics.security.action.Action domainAction = itr.next(); Action subAction = actionSet.getAction(domainAction.getSystemName()) .map(sa -> sa) .orElseGet(() -> { Action newAction = new Action(domainAction.getSystemName()); actionSet.addAction(newAction); return newAction; }); addHierarchy(subAction, itr); } } private void addHierarchy(Action parentAction, Iterator<com.thinkbiganalytics.security.action.Action> itr) { if (itr.hasNext()) { com.thinkbiganalytics.security.action.Action domainAction = itr.next(); Action subAction = parentAction.getAction(domainAction.getSystemName()) .map(sa -> sa) .orElseGet(() -> { Action newAction = new Action(domainAction.getSystemName()); parentAction.addAction(newAction); return newAction; }); addHierarchy(subAction, itr); } } }