From e078382b94552f5818597b4c3b77fe30970cdcf9 Mon Sep 17 00:00:00 2001 From: Arpit Mohan Date: Sat, 29 Feb 2020 09:24:26 +0530 Subject: [PATCH] Adding the user policy object that has permissions for ARN objects. Now we need to parse the ARN and match it to the policy in the PreAuthorize & Custom repository functions. --- .../CustomPermissionEvaluator.java | 19 ++++- .../server/configurations/SecurityConfig.java | 8 ++ .../SoftDeleteMongoQueryLookupStrategy.java | 51 +----------- .../mongo/SoftDeletePartTreeMongoQuery.java | 72 +++++++++++++++++ .../java/com/appsmith/server/domains/Arn.java | 22 +++++ .../com/appsmith/server/domains/Group.java | 8 +- .../com/appsmith/server/domains/Policy.java | 22 +++++ .../com/appsmith/server/domains/User.java | 23 +++++- .../appsmith/server/helpers/AclHelper.java | 26 ++++++ .../server/repositories/ActionRepository.java | 2 - .../repositories/ApplicationRepository.java | 21 +---- .../ApplicationRepositoryImpl.java | 46 ----------- .../CustomApplicationRepository.java | 8 ++ .../CustomApplicationRepositoryImpl.java | 80 +++++++++++++++++++ .../appsmith/server/services/CrudService.java | 2 + 15 files changed, 289 insertions(+), 121 deletions(-) create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/mongo/SoftDeletePartTreeMongoQuery.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Arn.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Policy.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/AclHelper.java delete mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ApplicationRepositoryImpl.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomApplicationRepository.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomApplicationRepositoryImpl.java diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CustomPermissionEvaluator.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CustomPermissionEvaluator.java index 6ef331f6bb..6284d0fead 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CustomPermissionEvaluator.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/CustomPermissionEvaluator.java @@ -1,5 +1,8 @@ package com.appsmith.server.configurations; +import com.appsmith.server.domains.User; +import com.appsmith.server.helpers.AclHelper; +import com.appsmith.server.services.AclEntity; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.PermissionEvaluator; import org.springframework.security.core.Authentication; @@ -7,6 +10,7 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.stereotype.Component; import java.io.Serializable; +import java.util.regex.Pattern; @Slf4j @Component @@ -15,8 +19,19 @@ public class CustomPermissionEvaluator implements PermissionEvaluator { @Override public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) { log.debug("In hasPermission with permission: {}", permission); - SimpleGrantedAuthority authority = new SimpleGrantedAuthority((String) permission); - return authentication.getAuthorities().contains(authority); + AclEntity aclEntity = targetDomainObject.getClass().getAnnotation(AclEntity.class); + // Create the ARN + String arn = AclHelper.createArn(aclEntity, (User) authentication.getPrincipal(), null); + String authorityToCheck = AclHelper.concatenatePermissionWithArn((String) permission, arn); + log.debug("Got authority to check: {}", authorityToCheck); + + boolean result = authentication.getAuthorities().stream() + .anyMatch(auth -> auth.getAuthority().equals(authorityToCheck) + || auth.getAuthority().matches(authorityToCheck) + || authorityToCheck.matches(auth.getAuthority()) + ); + log.debug("Got hasPermission result: {}", result); + return result; } @Override diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java index 30b29d661f..68175e11d0 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java @@ -138,4 +138,12 @@ public class SecurityConfig { .logoutSuccessHandler(new LogoutSuccessHandler(objectMapper)) .and().build(); } + + @Bean + public MethodSecurityExpressionHandler methodSecurityExpressionHandler() { + DefaultMethodSecurityExpressionHandler expressionHandler = + new DefaultMethodSecurityExpressionHandler(); + expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator()); + return expressionHandler; + } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/mongo/SoftDeleteMongoQueryLookupStrategy.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/mongo/SoftDeleteMongoQueryLookupStrategy.java index 75175dcd65..bdc688a040 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/mongo/SoftDeleteMongoQueryLookupStrategy.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/mongo/SoftDeleteMongoQueryLookupStrategy.java @@ -69,56 +69,7 @@ public class SoftDeleteMongoQueryLookupStrategy implements QueryLookupStrategy { } ReactivePartTreeMongoQuery partTreeQuery = (ReactivePartTreeMongoQuery) repositoryQuery; - return new SoftDeletePartTreeMongoQuery(method, partTreeQuery); + return new SoftDeletePartTreeMongoQuery(method, partTreeQuery, this.mongoOperations, EXPRESSION_PARSER, evaluationContextProvider); } - private Criteria notDeleted() { - return new Criteria().orOperator( - where("deleted").exists(false), - where("deleted").is(false) - ); - } - - private class SoftDeletePartTreeMongoQuery extends ReactivePartTreeMongoQuery { - private ReactivePartTreeMongoQuery reactivePartTreeQuery; - private Method method; - - SoftDeletePartTreeMongoQuery(Method method, ReactivePartTreeMongoQuery reactivePartTreeMongoQuery) { - super((ReactiveMongoQueryMethod) reactivePartTreeMongoQuery.getQueryMethod(), - mongoOperations, EXPRESSION_PARSER, evaluationContextProvider); - this.reactivePartTreeQuery = reactivePartTreeMongoQuery; - this.method = method; - } - - @Override - protected Query createQuery(ConvertingParameterAccessor accessor) { -// SecurityContext securityContext = SecurityContextHolder.getContext(); -// User userPrincipal = ReactiveSecurityContextHolder.getContext() -// .switchIfEmpty(Mono.error(new Exception("no context"))) -// .map(ctx -> ctx.getAuthentication()) -// .map(auth -> auth.getPrincipal()) -// .map(principal -> { -// if (principal instanceof User) { -// return (User) principal; -// } -// return new User(); -// }).block(); - AclPermission aclPermission = method.getAnnotation(AclPermission.class); - if (aclPermission != null) { - log.debug("Got principal: {}", aclPermission.principal()); - } - Query query = super.createQuery(accessor); - return withNotDeleted(query); - } - - @Override - protected Query createCountQuery(ConvertingParameterAccessor accessor) { - Query query = super.createCountQuery(accessor); - return withNotDeleted(query); - } - - private Query withNotDeleted(Query query) { - return query.addCriteria(notDeleted()); - } - } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/mongo/SoftDeletePartTreeMongoQuery.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/mongo/SoftDeletePartTreeMongoQuery.java new file mode 100644 index 0000000000..e06664d494 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/mongo/SoftDeletePartTreeMongoQuery.java @@ -0,0 +1,72 @@ +package com.appsmith.server.configurations.mongo; + +import com.appsmith.server.services.AclPermission; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.mongodb.core.ReactiveMongoOperations; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.repository.query.ConvertingParameterAccessor; +import org.springframework.data.mongodb.repository.query.MongoQueryMethod; +import org.springframework.data.mongodb.repository.query.ReactiveMongoQueryMethod; +import org.springframework.data.mongodb.repository.query.ReactivePartTreeMongoQuery; +import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; +import org.springframework.expression.spel.standard.SpelExpressionParser; + +import java.lang.reflect.Method; + +import static org.springframework.data.mongodb.core.query.Criteria.where; + +@Slf4j +public class SoftDeletePartTreeMongoQuery extends ReactivePartTreeMongoQuery { + private ReactivePartTreeMongoQuery reactivePartTreeQuery; + private Method method; + + SoftDeletePartTreeMongoQuery(Method method, ReactivePartTreeMongoQuery reactivePartTreeMongoQuery, + ReactiveMongoOperations mongoOperations, + SpelExpressionParser expressionParser, + QueryMethodEvaluationContextProvider evaluationContextProvider) { + super((ReactiveMongoQueryMethod) reactivePartTreeMongoQuery.getQueryMethod(), + mongoOperations, expressionParser, evaluationContextProvider); + this.reactivePartTreeQuery = reactivePartTreeMongoQuery; + this.method = method; + } + + @Override + protected Query createQuery(ConvertingParameterAccessor accessor) { +// SecurityContext securityContext = SecurityContextHolder.getContext(); +// User userPrincipal = ReactiveSecurityContextHolder.getContext() +// .switchIfEmpty(Mono.error(new Exception("no context"))) +// .map(ctx -> ctx.getAuthentication()) +// .map(auth -> auth.getPrincipal()) +// .map(principal -> { +// if (principal instanceof User) { +// return (User) principal; +// } +// return new User(); +// }).block(); + AclPermission aclPermission = method.getAnnotation(AclPermission.class); + if (aclPermission != null) { + log.debug("Got principal: {}", aclPermission.principal()); + } + MongoQueryMethod mongoQueryMethod = this.getQueryMethod(); + Query query = super.createQuery(accessor); + return withNotDeleted(query); + } + + @Override + protected Query createCountQuery(ConvertingParameterAccessor accessor) { + Query query = super.createCountQuery(accessor); + return withNotDeleted(query); + } + + private Query withNotDeleted(Query query) { + return query.addCriteria(notDeleted()); + } + + private Criteria notDeleted() { + return new Criteria().orOperator( + where("deleted").exists(false), + where("deleted").is(false) + ); + } +} \ No newline at end of file diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Arn.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Arn.java new file mode 100644 index 0000000000..1ee1cf12e8 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Arn.java @@ -0,0 +1,22 @@ +package com.appsmith.server.domains; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class Arn { + + String base = "arn:appsmith"; + + String organizationId; + + String entity; + + String entityId; + + @Override + public String toString() { + return base + ":" + organizationId + ":" + entity + ":" + entityId; + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Group.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Group.java index f11c51b541..b14836ac5c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Group.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Group.java @@ -8,6 +8,7 @@ import org.springframework.data.mongodb.core.index.CompoundIndex; import org.springframework.data.mongodb.core.mapping.Document; import javax.validation.constraints.NotNull; +import java.util.HashSet; import java.util.Set; @Getter @@ -25,7 +26,7 @@ public class Group extends BaseDomain { @NotNull private String organizationId; - /* + /** * This is a list of name of permissions. We will query with permission collection by name * This is because permissions are global in nature. They are not specific to a particular org/team. */ @@ -33,6 +34,11 @@ public class Group extends BaseDomain { private Boolean isDefault = false; + /** + * These are the policies attached to the group. All users who are part of this group will inherit these policies + */ + Set policies = new HashSet<>(); + /** * If the display name is null or empty, then just return the actual group name. This is just to ensure that * the client is never sent an empty group name for displaying on the UI. diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Policy.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Policy.java new file mode 100644 index 0000000000..d6f4f2393c --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Policy.java @@ -0,0 +1,22 @@ +package com.appsmith.server.domains; + + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.io.Serializable; +import java.util.Set; + +/* + TODO: Create a PolicyTemplate that will store all complex policies like "publishApp" which requires mulitple permissions + */ +@Getter +@Setter +@ToString +public class Policy implements Serializable { + + Set permissions; + + Set entities; +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/User.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/User.java index c894f50c52..004776802c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/User.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/User.java @@ -1,11 +1,13 @@ package com.appsmith.server.domains; import com.appsmith.external.models.BaseDomain; +import com.appsmith.server.helpers.AclHelper; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; import lombok.Setter; import lombok.ToString; +import org.springframework.data.annotation.Transient; import org.springframework.data.mongodb.core.index.Indexed; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.security.core.GrantedAuthority; @@ -13,7 +15,9 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -57,9 +61,26 @@ public class User extends BaseDomain implements UserDetails { // During evaluation a union of the group permissions and user-specific permissions will take effect. private Set permissions = new HashSet<>(); + private Set policies = new HashSet<>(); + + @JsonIgnore + @Transient + Set flatPermissions = new HashSet<>(); + @Override public Collection getAuthorities() { - return this.getPermissions().stream() + // TODO: Also extract the policies from associated groups + if (this.flatPermissions != null) { + for (Policy policy : this.policies) { + for (String entity : policy.getEntities()) { + for (String permission : policy.getPermissions()) { + flatPermissions.add(AclHelper.concatenatePermissionWithArn(permission, entity)); + } + } + } + } + + return this.getFlatPermissions().stream() .map(permission -> new SimpleGrantedAuthority(permission)) .collect(Collectors.toSet()); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/AclHelper.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/AclHelper.java new file mode 100644 index 0000000000..5df50f8639 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/AclHelper.java @@ -0,0 +1,26 @@ +package com.appsmith.server.helpers; + +import com.appsmith.server.domains.User; +import com.appsmith.server.services.AclEntity; + +public class AclHelper { + + private static final String ARN_PREFIX = "arn:appsmith:"; + + public static final String createArn(AclEntity aclEntity, User principal, String id) { + StringBuilder arnBuilder = new StringBuilder(ARN_PREFIX) + .append(principal.getCurrentOrganizationId()) + .append(":").append(aclEntity.value()); + arnBuilder = (id != null) ? arnBuilder.append(":").append(id) : arnBuilder.append(":*"); + + return arnBuilder.toString(); + } + + public static final String concatenatePermissionWithArn(String permission, String arn) { + return permission + "::" + arn; + } + + public static final String extractArnFromString(String arn) { + return null; + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ActionRepository.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ActionRepository.java index e1cb852f8a..bc18d69efc 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ActionRepository.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ActionRepository.java @@ -10,8 +10,6 @@ import java.util.Set; @Repository public interface ActionRepository extends BaseRepository { - Mono findById(String id); - Mono findByNameAndPageId(String name, String pageId); Flux findByPageId(String pageId); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ApplicationRepository.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ApplicationRepository.java index 553c6a404b..e3fd2ac838 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ApplicationRepository.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ApplicationRepository.java @@ -10,26 +10,9 @@ import org.springframework.stereotype.Repository; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -@NoRepositoryBean +@Repository @AclEntity("applications") -public interface ApplicationRepository extends BaseRepository { - - default Mono findByIdAndOrganizationId(String id, String orgId) { - System.out.println("In the custom implementation"); - return ReactiveSecurityContextHolder.getContext() - .map(ctx -> ctx.getAuthentication()) - .map(auth -> auth.getPrincipal()) - .flatMap(principal -> { - System.out.println("Got principal: " + principal); - return Mono.empty(); - }); - } +public interface ApplicationRepository extends BaseRepository, CustomApplicationRepository { Mono findByName(String name); - -// @Override -// Flux findAll(Example example); - - @Override - Mono findById(String id); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ApplicationRepositoryImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ApplicationRepositoryImpl.java deleted file mode 100644 index 73cf0de800..0000000000 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ApplicationRepositoryImpl.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.appsmith.server.repositories; - -import com.appsmith.server.domains.Application; -import lombok.NonNull; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Example; -import org.springframework.data.mongodb.core.ReactiveMongoOperations; -import org.springframework.data.mongodb.core.ReactiveMongoTemplate; -import org.springframework.data.mongodb.core.query.Criteria; -import org.springframework.data.mongodb.core.query.Query; -import org.springframework.data.mongodb.repository.query.MongoEntityInformation; -import org.springframework.stereotype.Component; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import java.lang.annotation.Annotation; - -import static org.springframework.data.mongodb.core.query.Criteria.where; - -@Component -public class ApplicationRepositoryImpl extends BaseRepositoryImpl implements ApplicationRepository { - -// public ApplicationRepositoryImpl(@NonNull MongoEntityInformation entityInformation, -// @NonNull ReactiveMongoOperations mongoOperations) { -// super(entityInformation, mongoOperations); -// } - - // TODO: Not implemented yet - @Override - public Mono findByIdAndOrganizationId(String id, String orgId) { - Query query = new Query(); - return Mono.empty() ; - } - - @Override - public Mono findByName(String name) { - Query query = new Query(); - query.addCriteria(notDeleted()); - - Annotation[] annotations = entityInformation.getJavaType().getAnnotations(); - return mongoOperations.query(entityInformation.getJavaType()) - .inCollection(entityInformation.getCollectionName()) - .matching(query) - .one(); - } -} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomApplicationRepository.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomApplicationRepository.java new file mode 100644 index 0000000000..d4a01bbe31 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomApplicationRepository.java @@ -0,0 +1,8 @@ +package com.appsmith.server.repositories; + +import com.appsmith.server.domains.Application; +import reactor.core.publisher.Mono; + +public interface CustomApplicationRepository { + Mono findByIdAndOrganizationId(String id, String orgId); +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomApplicationRepositoryImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomApplicationRepositoryImpl.java new file mode 100644 index 0000000000..a95e7dd5e1 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomApplicationRepositoryImpl.java @@ -0,0 +1,80 @@ +package com.appsmith.server.repositories; + +import com.appsmith.server.constants.Entity; +import com.appsmith.server.domains.Application; +import com.appsmith.server.domains.User; +import com.appsmith.server.services.AclEntity; +import lombok.NonNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.ReactiveMongoOperations; +import org.springframework.data.mongodb.core.ReactiveMongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.ReactiveSecurityContextHolder; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +import java.util.Collection; +import java.util.Set; + +import static org.springframework.data.mongodb.core.query.Criteria.where; + +@Component +public class CustomApplicationRepositoryImpl implements CustomApplicationRepository { + + private final ReactiveMongoOperations mongoOperations; + private final ReactiveMongoTemplate mongoTemplate; + + @Autowired + public CustomApplicationRepositoryImpl(@NonNull ReactiveMongoOperations mongoOperations, + ReactiveMongoTemplate mongoTemplate) { + this.mongoOperations = mongoOperations; + this.mongoTemplate = mongoTemplate; + } + + protected Criteria notDeleted() { + return new Criteria().orOperator( + where("deleted").exists(false), + where("deleted").is(false) + ); + } + + protected Criteria userAcl(User user, String permission) { + Set flatPermissions = user.getFlatPermissions(); + String entity = Entity.APPLICATIONS; +// flatPermissions.stream() +// .filter(flatPerm -> ) + return new Criteria().orOperator( + where("acl.users").all(user.getUsername()), + where("acl.groups").all(user.getGroupIds()) + ); + } + + protected Criteria getIdCriteria(Object id) { + return where("id").is(id); + } + + @Override + public Mono findByIdAndOrganizationId(String id, String orgId) { + return ReactiveSecurityContextHolder.getContext() + .map(ctx -> ctx.getAuthentication()) + .flatMap(auth -> { + User user = (User) auth.getPrincipal(); + Query query = new Query(getIdCriteria(id)); + query.addCriteria(where("organizationId").is(orgId)); + query.addCriteria(new Criteria().andOperator(notDeleted(), userAcl(user, "read"))); + + return mongoOperations.query(Application.class) + .matching(query) + .one(); + }); + } + +// @Override +// public Mono findByName(String name) { +// Query query = new Query(); +// return Mono.empty(); +// } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/CrudService.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/CrudService.java index f9f2fa4077..31dfa8d137 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/CrudService.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/CrudService.java @@ -2,6 +2,7 @@ package com.appsmith.server.services; import com.appsmith.external.models.BaseDomain; import com.appsmith.server.constants.AclConstants; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.util.MultiValueMap; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -17,6 +18,7 @@ public interface CrudService { @AclPermission(values = AclConstants.UPDATE_PERMISSION) Mono update(ID id, T resource); + @PreAuthorize("hasPermission(#this.this, 'read')") @AclPermission(values = AclConstants.READ_PERMISSION) Mono getById(ID id);