diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/AclPermission.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/AclPermission.java index da5d2ffb8e..0362d8406f 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/AclPermission.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/AclPermission.java @@ -6,23 +6,29 @@ import lombok.Getter; public enum AclPermission { // These are generic permissions created to make the transition to the new ACL format easy. They must be removed - CREATE("create"), - READ("read"), - UPDATE("update"), - DELETE("delete"), + CREATE("create", null), + READ("read", null), + UPDATE("update", null), + DELETE("delete", null), + + CREATE_ORGANIZATIONS("create:organizations", null), + READ_ORGANIZATIONS("read:organizations", null), + UPDATE_ORGANIZATIONS("update:organizations", null), + DELETE_ORGANIZATIONS("delete:organizations", null), + + MANAGE_APPLICATIONS("manage:applications", null), + READ_APPLICATIONS("read:applications", MANAGE_APPLICATIONS), + + CREATE_PAGES("create:pages", null), + READ_PAGES("read:pages", CREATE_PAGES), + UPDATE_PAGES("update:pages", null), + DELETE_PAGES("delete:pages", null); - CREATE_APPLICATIONS("create:applications"), - READ_APPLICATIONS("read:applications"), - UPDATE_APPLICATIONS("update:applications"), - DELETE_APPLICATIONS("delete:applications"), - CREATE_ORGANIZATIONS("create:organizations"), - READ_ORGANIZATIONS("read:organizations"), - UPDATE_ORGANIZATIONS("update:organizations"), - DELETE_ORGANIZATIONS("delete:organizations"); private String value; + private AclPermission parent; - AclPermission(String value) { + AclPermission(String value, AclPermission parent) { this.value = value; } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationPageServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationPageServiceImpl.java index 6675f62afc..978a9050b9 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationPageServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationPageServiceImpl.java @@ -17,6 +17,7 @@ import org.springframework.stereotype.Service; import reactor.core.publisher.Mono; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -61,7 +62,7 @@ public class ApplicationPageServiceImpl implements ApplicationPageService { page.setLayouts(layoutList); } - Mono applicationMono = applicationService.findById(page.getApplicationId()) + Mono applicationMono = applicationService.findById(page.getApplicationId(), AclPermission.CREATE_PAGES) .switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.APPLICATION_ID, page.getApplicationId()))); return applicationMono @@ -178,6 +179,16 @@ public class ApplicationPageServiceImpl implements ApplicationPageService { }); } + private Set adminApplicationPolicy(Organization org, User user) { + Set orgPolicies = org.getPolicies(); + // If a user can create an application on org, they can read, update & delete all applications + return null; + } + + private Set adminPagePolicyForApplication(User user) { + return null; + } + public Mono createApplication(Application application) { if (application.getName() == null || application.getName().trim().isEmpty()) { return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.NAME)); @@ -185,21 +196,29 @@ public class ApplicationPageServiceImpl implements ApplicationPageService { Mono userMono = sessionUserService.getCurrentUser(); Mono applicationMono = userMono - .map(user -> user.getCurrentOrganizationId()) - .flatMap(orgId -> { - Mono orgMono = organizationService.findById(orgId, AclPermission.CREATE_APPLICATIONS) + .flatMap(user -> { + String orgId = user.getCurrentOrganizationId(); + + Mono orgMono = organizationService.findById(orgId, AclPermission.MANAGE_APPLICATIONS) .switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.ORGANIZATION, orgId))); return orgMono.map(org -> { application.setOrganizationId(org.getId()); + // At the organization level, filter out all the application specific policies and apply them + // to the new application that we are creating. Set policySet = org.getPolicies().stream() - // At the organization level, filter out all the application specific policies and apply them - // to the new application that we are creating. .filter(policy -> policy.getPermission().equals(AclPermission.READ_APPLICATIONS.getValue()) || - policy.getPermission().equals(AclPermission.UPDATE_APPLICATIONS.getValue()) || - policy.getPermission().equals(AclPermission.DELETE_APPLICATIONS.getValue()) + policy.getPermission().equals(AclPermission.MANAGE_APPLICATIONS.getValue()) ).collect(Collectors.toSet()); + Set users = policySet.stream() + .map(policy -> policy.getUsers()) + .flatMap(Collection::stream) + .collect(Collectors.toSet()); + policySet.add(Policy.builder() + .permission(AclPermission.CREATE_PAGES.getValue()) + .users(Set.of(user.getUsername())).build() + ); application.setPolicies(policySet); return application; }); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationService.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationService.java index 26794c9960..5021fd73e9 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationService.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationService.java @@ -1,5 +1,6 @@ package com.appsmith.server.services; +import com.appsmith.server.constants.AclPermission; import com.appsmith.server.domains.Application; import reactor.core.publisher.Mono; @@ -7,6 +8,8 @@ public interface ApplicationService extends CrudService { Mono findById(String id); + Mono findById(String id, AclPermission aclPermission); + Mono findByIdAndOrganizationId(String id, String organizationId); Mono findByName(String name); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationServiceImpl.java index 2d784aa8bf..d0823d900b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationServiceImpl.java @@ -94,6 +94,11 @@ public class ApplicationServiceImpl extends BaseService findById(String id, AclPermission aclPermission) { + return repository.findById(id, aclPermission); + } + @Override public Mono findByIdAndOrganizationId(String id, String organizationId) { return repository.findByIdAndOrganizationId(id, organizationId, AclPermission.READ_APPLICATIONS); @@ -111,7 +116,7 @@ public class ApplicationServiceImpl extends BaseService update(String id, Application resource) { - return repository.updateById(id, resource, AclPermission.UPDATE_APPLICATIONS) + return repository.updateById(id, resource, AclPermission.MANAGE_APPLICATIONS) .flatMap(updatedObj -> analyticsService.sendEvent(AnalyticsEvents.UPDATE + "_" + updatedObj.getClass().getSimpleName().toUpperCase(), updatedObj)); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/OrganizationServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/OrganizationServiceImpl.java index 8bcd80a7a0..e7ed64c395 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/OrganizationServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/OrganizationServiceImpl.java @@ -4,7 +4,6 @@ import com.appsmith.external.models.Policy; import com.appsmith.server.constants.AclPermission; import com.appsmith.server.constants.AnalyticsEvents; import com.appsmith.server.constants.FieldName; -import com.appsmith.server.domains.Application; import com.appsmith.server.domains.Organization; import com.appsmith.server.domains.OrganizationPlugin; import com.appsmith.server.domains.OrganizationSetting; @@ -87,18 +86,11 @@ public class OrganizationServiceImpl extends BaseService crudOrgPolicy(User user) { diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/SeedMongoData.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/SeedMongoData.java index 7629358c32..77ddb06ec4 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/SeedMongoData.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/configurations/SeedMongoData.java @@ -42,11 +42,7 @@ public class SeedMongoData { .users(Set.of("api_user")) .build(); - Policy createAppPolicy = Policy.builder().permission(AclPermission.CREATE_APPLICATIONS.getValue()) - .users(Set.of("api_user")) - .build(); - - Policy updateAppPolicy = Policy.builder().permission(AclPermission.UPDATE_APPLICATIONS.getValue()) + Policy manageAppPolicy = Policy.builder().permission(AclPermission.MANAGE_APPLICATIONS.getValue()) .users(Set.of("api_user")) .build(); @@ -55,7 +51,7 @@ public class SeedMongoData { {"api_user", "api_user", UserState.ACTIVATED}, }; Object[][] orgData = { - {"Spring Test Organization", "appsmith-spring-test.com", "appsmith.com", Set.of(readAppPolicy, createAppPolicy, updateAppPolicy)} + {"Spring Test Organization", "appsmith-spring-test.com", "appsmith.com", Set.of(readAppPolicy, manageAppPolicy)} }; Object[][] appData = {