Merge branch 'feature/acl-org-user-role' into 'feature/acl-spring-object'
GET Organization Users & part base code to update permissions given an org level role. See merge request theappsmith/internal-tools-server!339
This commit is contained in:
commit
10b07d5912
|
|
@ -6,19 +6,26 @@ import java.util.Set;
|
|||
|
||||
import static com.appsmith.server.acl.AclPermission.MANAGE_APPLICATIONS;
|
||||
import static com.appsmith.server.acl.AclPermission.MANAGE_ORGANIZATIONS;
|
||||
import static com.appsmith.server.acl.AclPermission.ORGANIZATION_MANAGE_APPLICATIONS;
|
||||
import static com.appsmith.server.acl.AclPermission.ORGANIZATION_READ_APPLICATIONS;
|
||||
import static com.appsmith.server.acl.AclPermission.READ_APPLICATIONS;
|
||||
import static com.appsmith.server.acl.AclPermission.READ_ORGANIZATIONS;
|
||||
|
||||
@Getter
|
||||
public enum AppsmithRole {
|
||||
APPLICATION_ADMIN(Set.of(MANAGE_APPLICATIONS)),
|
||||
APPLICATION_VIEWER(Set.of(READ_APPLICATIONS)),
|
||||
ORGANIZATION_ADMIN(Set.of(MANAGE_ORGANIZATIONS)),
|
||||
ORGANIZATION_VIEWER(Set.of(READ_ORGANIZATIONS));
|
||||
APPLICATION_ADMIN("Application Administrator", "", Set.of(MANAGE_APPLICATIONS)),
|
||||
APPLICATION_VIEWER("Application Viewer", "", Set.of(READ_APPLICATIONS)),
|
||||
ORGANIZATION_ADMIN("Administrator", "", Set.of(MANAGE_ORGANIZATIONS)),
|
||||
ORGANIZATION_DEVELOPER("Developer", "", Set.of(READ_ORGANIZATIONS, ORGANIZATION_MANAGE_APPLICATIONS)),
|
||||
ORGANIZATION_VIEWER("App Viewer", "", Set.of(ORGANIZATION_READ_APPLICATIONS));
|
||||
|
||||
private Set<AclPermission> permissions;
|
||||
private String name;
|
||||
private String description;
|
||||
|
||||
AppsmithRole(Set<AclPermission> permissions) {
|
||||
AppsmithRole(String name, String description, Set<AclPermission> permissions) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.permissions = permissions;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,19 @@ package com.appsmith.server.controllers;
|
|||
|
||||
import com.appsmith.server.constants.Url;
|
||||
import com.appsmith.server.domains.Organization;
|
||||
import com.appsmith.server.domains.UserRole;
|
||||
import com.appsmith.server.dtos.ResponseDTO;
|
||||
import com.appsmith.server.services.OrganizationService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(Url.ORGANIZATION_URL)
|
||||
|
|
@ -17,4 +26,19 @@ public class OrganizationController extends BaseController<OrganizationService,
|
|||
super(organizationService);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function would be used to fetch all possible user roles at organization level.
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/roles")
|
||||
public Mono<ResponseDTO<Map<String, String>>> getUserRolesForOrganization() {
|
||||
return service.getUserRolesForOrganization()
|
||||
.map(permissions -> new ResponseDTO<>(HttpStatus.OK.value(), permissions, null));
|
||||
}
|
||||
|
||||
@GetMapping("/{orgId}/members")
|
||||
public Mono<ResponseDTO<List<UserRole>>> getUserMembersOfOrganization(@PathVariable String orgId) {
|
||||
return service.getOrganizationMembers(orgId)
|
||||
.map(users -> new ResponseDTO<>(HttpStatus.OK.value(), users, null));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.appsmith.server.domains;
|
||||
|
||||
import com.appsmith.external.models.BaseDomain;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
|
@ -31,6 +32,9 @@ public class Organization extends BaseDomain {
|
|||
|
||||
private String slug;
|
||||
|
||||
@JsonIgnore
|
||||
private List<UserRole> userRoles;
|
||||
|
||||
public String makeSlug() {
|
||||
return toSlug(name);
|
||||
}
|
||||
|
|
@ -38,5 +42,4 @@ public class Organization extends BaseDomain {
|
|||
public static String toSlug(String text) {
|
||||
return text == null ? null : text.replaceAll("[^\\w\\d]+", "-").toLowerCase();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
package com.appsmith.server.domains;
|
||||
|
||||
import com.appsmith.server.acl.AppsmithRole;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
public class UserRole {
|
||||
@JsonIgnore
|
||||
String userId;
|
||||
|
||||
String username;
|
||||
|
||||
String name;
|
||||
|
||||
String roleName;
|
||||
|
||||
@JsonIgnore
|
||||
AppsmithRole role;
|
||||
}
|
||||
|
|
@ -2,15 +2,27 @@ package com.appsmith.server.helpers;
|
|||
|
||||
import com.appsmith.external.models.BaseDomain;
|
||||
import com.appsmith.external.models.Policy;
|
||||
import com.appsmith.server.acl.AclPermission;
|
||||
import com.appsmith.server.acl.PolicyGenerator;
|
||||
import com.appsmith.server.domains.User;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class PolicyUtils<T extends BaseDomain> {
|
||||
|
||||
private final PolicyGenerator policyGenerator;
|
||||
|
||||
public PolicyUtils(PolicyGenerator policyGenerator) {
|
||||
this.policyGenerator = policyGenerator;
|
||||
}
|
||||
|
||||
public T setUserPermissionsInObject(T obj, User user) {
|
||||
|
||||
Set<String> permissions = new HashSet<>();
|
||||
|
|
@ -38,4 +50,70 @@ public class PolicyUtils<T extends BaseDomain> {
|
|||
return obj;
|
||||
}
|
||||
|
||||
public T generateAndAddPoliciesFromPermissions(Set<AclPermission> permissions, T obj, User user) {
|
||||
Map<String, Policy> policyMap = generatePolicyFromPermission(permissions, user);
|
||||
|
||||
// Append the user to the existing permission policy if it already exists.
|
||||
for (Policy policy : obj.getPolicies()) {
|
||||
String permission = policy.getPermission();
|
||||
if (policyMap.containsKey(permission)) {
|
||||
policy.getUsers().addAll(policyMap.get(permission).getUsers());
|
||||
if (policy.getGroups() == null) {
|
||||
policy.setGroups(new HashSet<>());
|
||||
}
|
||||
if (policyMap.get(permission).getGroups() != null) {
|
||||
policy.getGroups().addAll(policyMap.get(permission).getGroups());
|
||||
}
|
||||
// Remove this permission from the policyMap as this has been accounted for in the above code
|
||||
policyMap.remove(permission);
|
||||
}
|
||||
}
|
||||
|
||||
obj.getPolicies().addAll(policyMap.values());
|
||||
return obj;
|
||||
}
|
||||
|
||||
public T generateAndRemovePolicies(Set<AclPermission> permissions, T obj, User user) {
|
||||
Map<String, Policy> policyMap = generatePolicyFromPermission(permissions, user);
|
||||
|
||||
// Remove the user from the existing permission policy if it exists.
|
||||
for (Policy policy : obj.getPolicies()) {
|
||||
String permission = policy.getPermission();
|
||||
if (policyMap.containsKey(permission)) {
|
||||
policy.getUsers().removeAll(policyMap.get(permission).getUsers());
|
||||
if (policy.getGroups() == null) {
|
||||
policy.setGroups(new HashSet<>());
|
||||
}
|
||||
if (policyMap.get(permission).getGroups() != null) {
|
||||
policy.getGroups().removeAll(policyMap.get(permission).getGroups());
|
||||
}
|
||||
// Remove this permission from the policyMap as this has been accounted for in the above code
|
||||
policyMap.remove(permission);
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a set of AclPermissions, generate all policies (including policies from lateral permissions) for the user.
|
||||
* @param permissions
|
||||
* @param user
|
||||
* @return
|
||||
*/
|
||||
private Map<String, Policy> generatePolicyFromPermission(Set<AclPermission> permissions, User user) {
|
||||
return permissions.stream()
|
||||
.map(perm -> {
|
||||
// Create a policy for the invited user using the permission as per the role
|
||||
Policy policyWithCurrentPermission = Policy.builder().permission(perm.getValue())
|
||||
.users(Set.of(user.getUsername())).build();
|
||||
// Generate any and all lateral policies that might come with the current permission
|
||||
Set<Policy> policiesForUser = policyGenerator.getLateralPoliciesForUser(perm, user);
|
||||
policiesForUser.add(policyWithCurrentPermission);
|
||||
return policiesForUser;
|
||||
})
|
||||
.flatMap(Collection::stream)
|
||||
.collect(Collectors.toMap(Policy::getPermission, Function.identity()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
package com.appsmith.server.services;
|
||||
|
||||
import com.appsmith.server.acl.AclPermission;
|
||||
import com.appsmith.server.acl.AppsmithRole;
|
||||
import com.appsmith.server.domains.Organization;
|
||||
import com.appsmith.server.domains.User;
|
||||
import com.appsmith.server.domains.UserRole;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface OrganizationService extends CrudService<Organization, String> {
|
||||
|
|
@ -27,4 +31,12 @@ public interface OrganizationService extends CrudService<Organization, String> {
|
|||
Mono<Organization> findByIdAndPluginsPluginId(String organizationId, String pluginId);
|
||||
|
||||
Flux<Organization> findByIdsIn(Set<String> ids,AclPermission permission);
|
||||
|
||||
Mono<Map<String, String>> getUserRolesForOrganization();
|
||||
|
||||
Mono<Organization> addUserRoleToOrganization(Organization organization, User user, AppsmithRole role);
|
||||
|
||||
Mono<Organization> removeUserRoleFromOrganization(Organization organization, User user);
|
||||
|
||||
Mono<List<UserRole>> getOrganizationMembers(String orgId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.appsmith.server.services;
|
|||
|
||||
import com.appsmith.external.models.Policy;
|
||||
import com.appsmith.server.acl.AclPermission;
|
||||
import com.appsmith.server.acl.AppsmithRole;
|
||||
import com.appsmith.server.acl.PolicyGenerator;
|
||||
import com.appsmith.server.constants.AnalyticsEvents;
|
||||
import com.appsmith.server.constants.FieldName;
|
||||
|
|
@ -10,9 +11,11 @@ import com.appsmith.server.domains.OrganizationPlugin;
|
|||
import com.appsmith.server.domains.OrganizationSetting;
|
||||
import com.appsmith.server.domains.Setting;
|
||||
import com.appsmith.server.domains.User;
|
||||
import com.appsmith.server.domains.UserRole;
|
||||
import com.appsmith.server.dtos.OrganizationPluginStatus;
|
||||
import com.appsmith.server.exceptions.AppsmithError;
|
||||
import com.appsmith.server.exceptions.AppsmithException;
|
||||
import com.appsmith.server.helpers.PolicyUtils;
|
||||
import com.appsmith.server.repositories.OrganizationRepository;
|
||||
import com.appsmith.server.repositories.PluginRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
|
@ -27,12 +30,15 @@ import reactor.core.scheduler.Scheduler;
|
|||
|
||||
import javax.validation.Validator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.appsmith.server.acl.AclPermission.MANAGE_ORGANIZATIONS;
|
||||
import static com.appsmith.server.acl.AclPermission.USER_MANAGE_ORGANIZATIONS;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
|
|
@ -45,6 +51,7 @@ public class OrganizationServiceImpl extends BaseService<OrganizationRepository,
|
|||
private final SessionUserService sessionUserService;
|
||||
private final UserOrganizationService userOrganizationService;
|
||||
private final PolicyGenerator policyGenerator;
|
||||
private final PolicyUtils policyUtils;
|
||||
|
||||
@Autowired
|
||||
public OrganizationServiceImpl(Scheduler scheduler,
|
||||
|
|
@ -58,7 +65,7 @@ public class OrganizationServiceImpl extends BaseService<OrganizationRepository,
|
|||
PluginRepository pluginRepository,
|
||||
SessionUserService sessionUserService,
|
||||
UserOrganizationService userOrganizationService,
|
||||
PolicyGenerator policyGenerator) {
|
||||
PolicyGenerator policyGenerator, PolicyUtils policyUtils) {
|
||||
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository, analyticsService);
|
||||
this.repository = repository;
|
||||
this.settingService = settingService;
|
||||
|
|
@ -67,6 +74,7 @@ public class OrganizationServiceImpl extends BaseService<OrganizationRepository,
|
|||
this.sessionUserService = sessionUserService;
|
||||
this.userOrganizationService = userOrganizationService;
|
||||
this.policyGenerator = policyGenerator;
|
||||
this.policyUtils = policyUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -129,9 +137,6 @@ public class OrganizationServiceImpl extends BaseService<OrganizationRepository,
|
|||
return Mono.error(new AppsmithException(AppsmithError.UNAUTHORIZED_ACCESS));
|
||||
}
|
||||
|
||||
// Set the admin policies for this organization & user
|
||||
organization.setPolicies(crudOrgPolicy(user));
|
||||
|
||||
Mono<Organization> setSlugMono;
|
||||
if (organization.getName() == null) {
|
||||
setSlugMono = Mono.just(organization);
|
||||
|
|
@ -161,6 +166,9 @@ public class OrganizationServiceImpl extends BaseService<OrganizationRepository,
|
|||
}))
|
||||
//Call the BaseService function to save the updated organization
|
||||
.flatMap(super::create)
|
||||
// Set the current user as admin for the organization
|
||||
.flatMap(createdOrg -> addUserRoleToOrganization(createdOrg, user, AppsmithRole.ORGANIZATION_ADMIN))
|
||||
// TODO : Remove the following code
|
||||
.flatMap(savedOrganization -> userOrganizationService
|
||||
.addUserToOrganization(savedOrganization.getId(), user)
|
||||
.thenReturn(savedOrganization));
|
||||
|
|
@ -251,5 +259,87 @@ public class OrganizationServiceImpl extends BaseService<OrganizationRepository,
|
|||
return repository.findByIdsIn(ids, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Map<String, String>> getUserRolesForOrganization() {
|
||||
// Get all the roles for Organization entity from the enum AppsmithRole
|
||||
Map<String, String> appsmithRoles = Arrays.asList(AppsmithRole.values())
|
||||
.stream()
|
||||
.filter(role -> {
|
||||
Set<AclPermission> permissions = role.getPermissions();
|
||||
if (permissions != null && !permissions.isEmpty()) {
|
||||
for (AclPermission permission : permissions) {
|
||||
if (permission.getEntity().equals(Organization.class)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.collect(toMap(role -> role.getName(), AppsmithRole::getDescription));
|
||||
|
||||
return Mono.just(appsmithRoles);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Organization> addUserRoleToOrganization(Organization organization, User user, AppsmithRole role) {
|
||||
List<UserRole> userRoles = organization.getUserRoles();
|
||||
if (userRoles == null) {
|
||||
userRoles = new ArrayList<>();
|
||||
}
|
||||
UserRole userRole = new UserRole();
|
||||
userRole.setUserId(user.getId());
|
||||
userRole.setUsername(user.getUsername());
|
||||
userRole.setName(user.getName());
|
||||
userRole.setRole(role);
|
||||
userRole.setRoleName(role.getName());
|
||||
|
||||
// Add the user and its role to the organization
|
||||
userRoles.add(userRole);
|
||||
|
||||
Set<AclPermission> rolePermissions = role.getPermissions();
|
||||
Organization updatedOrganization = (Organization) policyUtils.generateAndAddPoliciesFromPermissions(rolePermissions, organization, user);
|
||||
updatedOrganization.setUserRoles(userRoles);
|
||||
/**
|
||||
* TODO : Update the underlying application/page/action
|
||||
*/
|
||||
return repository.save(updatedOrganization);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Organization> removeUserRoleFromOrganization(Organization organization, User user) {
|
||||
List<UserRole> userRoles = organization.getUserRoles();
|
||||
if (userRoles == null) {
|
||||
// The user doesnt exist in this organization. Nothing to do here. Return as is.
|
||||
return Mono.just(organization);
|
||||
}
|
||||
for (UserRole role : userRoles) {
|
||||
if (role.getUsername().equals(user.getUsername())) {
|
||||
// Update the organization permissions
|
||||
Set<AclPermission> rolePermissions = role.getRole().getPermissions();
|
||||
Organization updatedPermissionsOrg = (Organization) policyUtils.generateAndRemovePolicies(rolePermissions, organization, user);
|
||||
List<UserRole> finalUserRoles = updatedPermissionsOrg.getUserRoles();
|
||||
// The user exists. Remove the user from the organization :
|
||||
finalUserRoles.remove(role);
|
||||
updatedPermissionsOrg.setUserRoles(finalUserRoles);
|
||||
|
||||
/**
|
||||
* TODO : Update the underlying application/page/action
|
||||
*/
|
||||
|
||||
return repository.save(updatedPermissionsOrg);
|
||||
}
|
||||
}
|
||||
|
||||
// The user was not found in the list of user roles in the organization. Throw the appropriate error.
|
||||
return Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.USER, user.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<List<UserRole>> getOrganizationMembers(String orgId) {
|
||||
return repository
|
||||
.findById(orgId, MANAGE_ORGANIZATIONS)
|
||||
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.ORGANIZATION, orgId)))
|
||||
.map(organization -> organization.getUserRoles());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import com.appsmith.server.dtos.UserProfileDTO;
|
|||
import com.appsmith.server.exceptions.AppsmithError;
|
||||
import com.appsmith.server.exceptions.AppsmithException;
|
||||
import com.appsmith.server.helpers.BeanCopyUtils;
|
||||
import com.appsmith.server.helpers.PolicyUtils;
|
||||
import com.appsmith.server.notifications.EmailSender;
|
||||
import com.appsmith.server.repositories.ApplicationRepository;
|
||||
import com.appsmith.server.repositories.InviteUserRepository;
|
||||
|
|
@ -39,19 +40,15 @@ import javax.validation.Validator;
|
|||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.appsmith.server.acl.AclPermission.MANAGE_APPLICATIONS;
|
||||
import static com.appsmith.server.acl.AclPermission.MANAGE_USERS;
|
||||
import static com.appsmith.server.acl.AclPermission.READ_USERS;
|
||||
import static com.appsmith.server.acl.AclPermission.RESET_PASSWORD_USERS;
|
||||
import static com.appsmith.server.acl.AclPermission.USER_MANAGE_ORGANIZATIONS;
|
||||
|
||||
|
|
@ -70,6 +67,7 @@ public class UserServiceImpl extends BaseService<UserRepository, User, String> i
|
|||
private final UserOrganizationService userOrganizationService;
|
||||
private final ApplicationRepository applicationRepository;
|
||||
private final PolicyGenerator policyGenerator;
|
||||
private final PolicyUtils policyUtils;
|
||||
|
||||
private static final String WELCOME_USER_EMAIL_TEMPLATE = "email/welcomeUserTemplate.html";
|
||||
private static final String INVITE_USER_EMAIL_TEMPLATE = "email/inviteUserCreatorTemplate.html";
|
||||
|
|
@ -94,7 +92,7 @@ public class UserServiceImpl extends BaseService<UserRepository, User, String> i
|
|||
InviteUserRepository inviteUserRepository,
|
||||
UserOrganizationService userOrganizationService,
|
||||
ApplicationRepository applicationRepository,
|
||||
PolicyGenerator policyGenerator) {
|
||||
PolicyGenerator policyGenerator, PolicyUtils policyUtils) {
|
||||
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository, analyticsService);
|
||||
this.repository = repository;
|
||||
this.organizationService = organizationService;
|
||||
|
|
@ -107,6 +105,7 @@ public class UserServiceImpl extends BaseService<UserRepository, User, String> i
|
|||
this.userOrganizationService = userOrganizationService;
|
||||
this.applicationRepository = applicationRepository;
|
||||
this.policyGenerator = policyGenerator;
|
||||
this.policyUtils = policyUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -324,42 +323,8 @@ public class UserServiceImpl extends BaseService<UserRepository, User, String> i
|
|||
}
|
||||
|
||||
Set<AclPermission> invitePermissions = inviteUser.getRole().getPermissions();
|
||||
// Append the permissions to the application
|
||||
Map<String, Policy> policyMap = invitePermissions.stream()
|
||||
.map(perm -> {
|
||||
// Create a policy for the invited user using the permission as per the role
|
||||
Policy policyWithCurrentPermission = Policy.builder().permission(perm.getValue())
|
||||
.users(Set.of(inviteUser.getUsername())).build();
|
||||
// Generate any and all lateral policies that might come with the current permission
|
||||
Set<Policy> policiesForUser = policyGenerator.getLateralPoliciesForUser(perm, inviteUser);
|
||||
policiesForUser.add(policyWithCurrentPermission);
|
||||
return policiesForUser;
|
||||
})
|
||||
.flatMap(Collection::stream)
|
||||
.collect(Collectors.toMap(Policy::getPermission, Function.identity()));
|
||||
|
||||
|
||||
// Append the user to the existing permission policy if it already exists.
|
||||
for (Policy policy : application.getPolicies()) {
|
||||
String permission = policy.getPermission();
|
||||
if (policyMap.containsKey(permission)) {
|
||||
policy.getUsers().addAll(policyMap.get(permission).getUsers());
|
||||
if (policy.getGroups() == null) {
|
||||
policy.setGroups(new HashSet<>());
|
||||
}
|
||||
if (policyMap.get(permission).getGroups() != null) {
|
||||
policy.getGroups().addAll(policyMap.get(permission).getGroups());
|
||||
}
|
||||
// Remove this permission from the policyMap as this has been accounted for in the above code
|
||||
policyMap.remove(permission);
|
||||
}
|
||||
}
|
||||
|
||||
// For all the remaining policies which exist in the policyMap but didnt exist in the application
|
||||
// earlier, just add them to the set
|
||||
application.getPolicies().addAll(policyMap.values());
|
||||
|
||||
return application;
|
||||
// Append the permissions to the application and return
|
||||
return (Application) policyUtils.generateAndAddPoliciesFromPermissions(invitePermissions, application, inviteUser);
|
||||
|
||||
// Append the required permissions to all the pages
|
||||
/**
|
||||
|
|
@ -632,7 +597,7 @@ public class UserServiceImpl extends BaseService<UserRepository, User, String> i
|
|||
|
||||
@Override
|
||||
public Mono<User> update(String id, User userUpdate) {
|
||||
Mono<User> userFromRepository = repository.findById(id, READ_USERS)
|
||||
Mono<User> userFromRepository = repository.findById(id, MANAGE_USERS)
|
||||
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.USER, id)));
|
||||
|
||||
if (userUpdate.getPassword() != null) {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import java.util.Set;
|
|||
|
||||
import static com.appsmith.server.acl.AclPermission.MANAGE_APPLICATIONS;
|
||||
import static com.appsmith.server.acl.AclPermission.MANAGE_PAGES;
|
||||
import static com.appsmith.server.acl.AclPermission.MANAGE_USERS;
|
||||
import static com.appsmith.server.acl.AclPermission.ORGANIZATION_MANAGE_APPLICATIONS;
|
||||
import static com.appsmith.server.acl.AclPermission.READ_APPLICATIONS;
|
||||
import static com.appsmith.server.acl.AclPermission.READ_ORGANIZATIONS;
|
||||
|
|
@ -86,13 +87,17 @@ public class SeedMongoData {
|
|||
.users(Set.of(API_USER_EMAIL))
|
||||
.build();
|
||||
|
||||
Policy manageApiUserPolicy = Policy.builder().permission(MANAGE_USERS.getValue())
|
||||
.users(Set.of(API_USER_EMAIL))
|
||||
.build();
|
||||
|
||||
Policy readTestUserPolicy = Policy.builder().permission(READ_USERS.getValue())
|
||||
.users(Set.of(TEST_USER_EMAIL))
|
||||
.build();
|
||||
|
||||
Object[][] userData = {
|
||||
{"user test", TEST_USER_EMAIL, UserState.ACTIVATED, Set.of(readTestUserPolicy)},
|
||||
{"api_user", API_USER_EMAIL, UserState.ACTIVATED, Set.of(userManageOrgPolicy, readApiUserPolicy)},
|
||||
{"api_user", API_USER_EMAIL, UserState.ACTIVATED, Set.of(userManageOrgPolicy, readApiUserPolicy, manageApiUserPolicy)},
|
||||
};
|
||||
Object[][] orgData = {
|
||||
{"Spring Test Organization", "appsmith-spring-test.com", "appsmith.com", "spring-test-organization",
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
package com.appsmith.server.services;
|
||||
|
||||
import com.appsmith.external.models.Policy;
|
||||
import com.appsmith.server.acl.AppsmithRole;
|
||||
import com.appsmith.server.constants.FieldName;
|
||||
import com.appsmith.server.domains.Organization;
|
||||
import com.appsmith.server.domains.UserRole;
|
||||
import com.appsmith.server.exceptions.AppsmithError;
|
||||
import com.appsmith.server.exceptions.AppsmithException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
|
@ -17,6 +20,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.appsmith.server.acl.AclPermission.MANAGE_ORGANIZATIONS;
|
||||
|
|
@ -26,6 +31,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest
|
||||
@DirtiesContext
|
||||
@Slf4j
|
||||
public class OrganizationServiceTest {
|
||||
|
||||
@Autowired
|
||||
|
|
@ -202,4 +208,40 @@ public class OrganizationServiceTest {
|
|||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAllUserRolesForOrganizationDomain() {
|
||||
Mono<Map<String, String>> userRolesForOrganization = organizationService.getUserRolesForOrganization();
|
||||
|
||||
StepVerifier.create(userRolesForOrganization)
|
||||
.assertNext(roles -> {
|
||||
assertThat(roles).isNotEmpty();
|
||||
assertThat(roles).containsKeys("Administrator", "App Viewer", "Developer");
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUserDetails(value = "api_user")
|
||||
public void getAllMembersForOrganization() {
|
||||
Organization testOrg = new Organization();
|
||||
testOrg.setName("Get All Members For Organization Test");
|
||||
testOrg.setDomain("test.com");
|
||||
testOrg.setWebsite("https://test.com");
|
||||
|
||||
Mono<Organization> createOrganizationMono = organizationService.create(testOrg);
|
||||
Mono<List<UserRole>> usersMono = createOrganizationMono
|
||||
.flatMap(organization -> organizationService.getOrganizationMembers(organization.getId()));
|
||||
|
||||
StepVerifier
|
||||
.create(usersMono)
|
||||
.assertNext(users -> {
|
||||
assertThat(users).isNotNull();
|
||||
UserRole userRole = users.get(0);
|
||||
assertThat(userRole.getName()).isEqualTo("api_user");
|
||||
assertThat(userRole.getRole()).isEqualByComparingTo(AppsmithRole.ORGANIZATION_ADMIN);
|
||||
assertThat(userRole.getRoleName()).isEqualTo(AppsmithRole.ORGANIZATION_ADMIN.getName());
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,6 +74,9 @@ public class UserServiceTest {
|
|||
.verify();
|
||||
}
|
||||
|
||||
/**
|
||||
* The following function tests for switch organization
|
||||
*/
|
||||
@Test
|
||||
@WithUserDetails(value = "api_user")
|
||||
public void updateUserWithValidOrganization() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user