chore: Adding base repository function to add user permissions to generic domain object (#17733)

## Description

Adding base function to set the user permissions for a user in any domain object. 

As part of this, we also add default permission group to the `SeedMongoData`. Without this fix, the JUnit tests go into an infinite loop. Also fixing the `ExampleWorkspaceClonerTest` file.

## Type of change

- Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

- JUnit

## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
This commit is contained in:
Arpit Mohan 2022-10-19 23:30:30 +02:00 committed by GitHub
parent b2cc280009
commit 4e71432d74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 46 deletions

View File

@ -22,7 +22,9 @@ public interface AppsmithRepository<T> {
Flux<T> queryAll(List<Criteria> criterias, List<String> includeFields, AclPermission permission, Sort sort);
T setUserPermissionsInObject(T obj, Set<String> permissionGroups);
Mono<T> setUserPermissionsInObject(T obj, Set<String> permissionGroups);
Mono<T> setUserPermissionsInObject(T obj);
Mono<T> findByGitSyncIdAndDefaultApplicationId(String defaultApplicationId, String gitSyncId, AclPermission permission);

View File

@ -140,7 +140,7 @@ public abstract class BaseAppsmithRepositoryCEImpl<T extends BaseDomain> {
return mongoOperations.query(this.genericDomain)
.matching(query)
.one()
.map(obj -> (T) setUserPermissionsInObject(obj, permissionGroups));
.flatMap(obj -> setUserPermissionsInObject(obj, permissionGroups));
});
}
@ -175,7 +175,7 @@ public abstract class BaseAppsmithRepositoryCEImpl<T extends BaseDomain> {
}
return findById(id, permission);
})
.map(obj -> (T) setUserPermissionsInObject(obj, permissionGroups));
.flatMap(obj -> setUserPermissionsInObject(obj, permissionGroups));
});
}
@ -213,7 +213,7 @@ public abstract class BaseAppsmithRepositoryCEImpl<T extends BaseDomain> {
return mongoOperations.query(this.genericDomain)
.matching(createQueryWithPermission(criterias, permissionGroups, aclPermission))
.one()
.map(obj -> (T) setUserPermissionsInObject(obj, permissionGroups));
.flatMap(obj -> setUserPermissionsInObject(obj, permissionGroups));
});
}
@ -226,7 +226,7 @@ public abstract class BaseAppsmithRepositoryCEImpl<T extends BaseDomain> {
return mongoOperations.query(this.genericDomain)
.matching(createQueryWithPermission(criterias, permissionGroups, aclPermission))
.first()
.map(obj -> (T) setUserPermissionsInObject(obj, permissionGroups));
.flatMap(obj -> setUserPermissionsInObject(obj, permissionGroups));
});
}
@ -315,14 +315,22 @@ public abstract class BaseAppsmithRepositoryCEImpl<T extends BaseDomain> {
return mongoOperations.query(this.genericDomain)
.matching(query)
.all()
.map(obj -> (T) setUserPermissionsInObject(obj, permissionGroups));
.flatMap(obj -> setUserPermissionsInObject(obj, permissionGroups));
}
public T setUserPermissionsInObject(T obj, Set<String> permissionGroups) {
public Mono<T> setUserPermissionsInObject(T obj) {
return ReactiveSecurityContextHolder.getContext()
.map(ctx -> ctx.getAuthentication())
.map(auth -> auth.getPrincipal())
.flatMap(principal -> getAllPermissionGroupsForUser((User) principal))
.flatMap(permissionGroups -> setUserPermissionsInObject(obj, permissionGroups));
}
public Mono<T> setUserPermissionsInObject(T obj, Set<String> permissionGroups) {
Set<String> permissions = new HashSet<>();
if (CollectionUtils.isEmpty(obj.getPolicies())) {
return obj;
return Mono.just(obj);
}
for (Policy policy : obj.getPolicies()) {
@ -339,7 +347,7 @@ public abstract class BaseAppsmithRepositoryCEImpl<T extends BaseDomain> {
}
obj.setUserPermissions(permissions);
return obj;
return Mono.just(obj);
}
public Mono<T> findByGitSyncIdAndDefaultApplicationId(String defaultApplicationId, String gitSyncId, AclPermission permission) {

View File

@ -40,7 +40,7 @@ public class CustomConfigRepositoryCEImpl extends BaseAppsmithRepositoryImpl<Con
return mongoOperations.query(this.genericDomain)
.matching(query)
.one()
.map(obj -> setUserPermissionsInObject(obj, permissionGroups));
.flatMap(obj -> setUserPermissionsInObject(obj, permissionGroups));
});
}
}

View File

@ -1,11 +1,12 @@
package com.appsmith.server.configurations;
import com.appsmith.external.models.PluginType;
import com.appsmith.external.models.Policy;
import com.appsmith.server.acl.AppsmithRole;
import com.appsmith.server.domains.Application;
import com.appsmith.server.domains.Page;
import com.appsmith.server.domains.PermissionGroup;
import com.appsmith.server.domains.Plugin;
import com.appsmith.external.models.PluginType;
import com.appsmith.server.domains.PricingPlan;
import com.appsmith.server.domains.Tenant;
import com.appsmith.server.domains.User;
@ -13,15 +14,17 @@ import com.appsmith.server.domains.UserRole;
import com.appsmith.server.domains.UserState;
import com.appsmith.server.domains.Workspace;
import com.appsmith.server.domains.WorkspacePlugin;
import com.appsmith.server.dtos.Permission;
import com.appsmith.server.dtos.WorkspacePluginStatus;
import com.appsmith.server.helpers.PolicyUtils;
import com.appsmith.server.repositories.ApplicationRepository;
import com.appsmith.server.repositories.PageRepository;
import com.appsmith.server.repositories.PermissionGroupRepository;
import com.appsmith.server.repositories.PluginRepository;
import com.appsmith.server.repositories.TenantRepository;
import com.appsmith.server.repositories.UserRepository;
import com.appsmith.server.repositories.WorkspaceRepository;
import com.appsmith.server.services.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Bean;
@ -32,8 +35,10 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@ -64,7 +69,9 @@ public class SeedMongoData {
ReactiveMongoTemplate mongoTemplate,
TenantRepository tenantRepository,
UserService userService,
CommonConfig commonConfig) {
CommonConfig commonConfig,
PermissionGroupRepository permissionGroupRepository,
PolicyUtils policyUtils) {
log.info("Seeding the data");
final String API_USER_EMAIL = "api_user";
@ -133,10 +140,10 @@ public class SeedMongoData {
.build();
Object[][] userData = {
{"user test", TEST_USER_EMAIL, UserState.ACTIVATED, Set.of(readTestUserPolicy, userManageWorkspacePolicy)},
{"api_user", API_USER_EMAIL, UserState.ACTIVATED, Set.of(userManageWorkspacePolicy, readApiUserPolicy, manageApiUserPolicy)},
{"admin test", ADMIN_USER_EMAIL, UserState.ACTIVATED, Set.of(readAdminUserPolicy, userManageWorkspacePolicy)},
{"developer test", DEV_USER_EMAIL, UserState.ACTIVATED, Set.of(readDevUserPolicy, userManageWorkspacePolicy)},
{"user test", TEST_USER_EMAIL, UserState.ACTIVATED, new HashSet<>(Arrays.asList(readTestUserPolicy, userManageWorkspacePolicy))},
{"api_user", API_USER_EMAIL, UserState.ACTIVATED, new HashSet<>(Arrays.asList(userManageWorkspacePolicy, readApiUserPolicy, manageApiUserPolicy))},
{"admin test", ADMIN_USER_EMAIL, UserState.ACTIVATED, new HashSet<>(Arrays.asList(readAdminUserPolicy, userManageWorkspacePolicy))},
{"developer test", DEV_USER_EMAIL, UserState.ACTIVATED, new HashSet<>(Arrays.asList(readDevUserPolicy, userManageWorkspacePolicy))},
};
Object[][] workspaceData = {
{"Spring Test Workspace", "appsmith-spring-test.com", "appsmith.com", "spring-test-workspace",
@ -160,7 +167,7 @@ public class SeedMongoData {
{"Not Installed Plugin Name", PluginType.API, "not-installed-plugin"}
};
// Seed the plugin data into the DB
// Seed the plugin data into the DB
Flux<Plugin> pluginFlux = Flux.just(pluginData)
.map(array -> {
log.debug("Creating the plugins");
@ -266,7 +273,23 @@ public class SeedMongoData {
log.debug("Saved the workspace to user. User: {}", u);
return u;
});
}));
})
.flatMap(user -> {
PermissionGroup permissionGroupUser = new PermissionGroup();
permissionGroupUser.setPermissions(Set.of(new Permission(user.getId(), MANAGE_USERS)));
permissionGroupUser.setName(user.getId() + "User Name");
permissionGroupUser.setAssignedToUserIds(Set.of(user.getId()));
return permissionGroupRepository.save(permissionGroupUser)
.flatMap(savedPermissionGroup -> {
Map<String, Policy> crudUserPolicies = policyUtils.generatePolicyFromPermissionGroupForObject(savedPermissionGroup,
user.getId());
User updatedWithPolicies = policyUtils.addPoliciesToExistingObject(crudUserPolicies, user);
return userRepository.save(updatedWithPolicies);
});
})
);
Query workspaceNameQuery = new Query(where("slug").is(workspaceData[0][3]));
Mono<Workspace> workspaceByNameMono = mongoTemplate.findOne(workspaceNameQuery, Workspace.class)
@ -308,14 +331,7 @@ public class SeedMongoData {
.flatMap(pageRepository::save)
)
.blockLast();
// Create user@appsmith.com using UserService
if(!commonConfig.isSignupDisabled()) {
User newUser = new User();
newUser.setEmail("user@appsmith.com");
newUser.setPassword("new-user-test-password");
userService.create(newUser).block();
}
};
}
}

View File

@ -1,6 +1,7 @@
package com.appsmith.server.solutions;
import com.appsmith.external.models.ActionConfiguration;
import com.appsmith.external.models.ActionDTO;
import com.appsmith.external.models.AuthenticationResponse;
import com.appsmith.external.models.Connection;
import com.appsmith.external.models.DBAuth;
@ -9,6 +10,7 @@ import com.appsmith.external.models.DatasourceConfiguration;
import com.appsmith.external.models.Endpoint;
import com.appsmith.external.models.OAuth2;
import com.appsmith.external.models.PEMCertificate;
import com.appsmith.external.models.PluginType;
import com.appsmith.external.models.Property;
import com.appsmith.external.models.SSLDetails;
import com.appsmith.external.models.UploadedFile;
@ -20,11 +22,9 @@ import com.appsmith.server.domains.Layout;
import com.appsmith.server.domains.NewAction;
import com.appsmith.server.domains.NewPage;
import com.appsmith.server.domains.Plugin;
import com.appsmith.external.models.PluginType;
import com.appsmith.server.domains.User;
import com.appsmith.server.domains.Workspace;
import com.appsmith.server.dtos.ActionCollectionDTO;
import com.appsmith.external.models.ActionDTO;
import com.appsmith.server.dtos.DslActionDTO;
import com.appsmith.server.dtos.PageDTO;
import com.appsmith.server.helpers.MockPluginExecutor;
@ -174,7 +174,7 @@ public class ExamplesWorkspaceClonerTests {
}
@Test
@WithUserDetails(value = "user@appsmith.com")
@WithUserDetails(value = "api_user")
public void cloneEmptyWorkspace() {
Workspace newWorkspace = new Workspace();
newWorkspace.setName("Template Workspace");
@ -188,7 +188,7 @@ public class ExamplesWorkspaceClonerTests {
.assertNext(data -> {
assertThat(data.workspace).isNotNull();
assertThat(data.workspace.getId()).isNotNull();
assertThat(data.workspace.getName()).isEqualTo("user's apps");
assertThat(data.workspace.getName()).isEqualTo("api_user's apps");
assertThat(data.workspace.getPolicies()).isNotEmpty();
assertThat(data.applications).isEmpty();
@ -200,7 +200,7 @@ public class ExamplesWorkspaceClonerTests {
}
@Test
@WithUserDetails(value = "user@appsmith.com")
@WithUserDetails(value = "api_user")
public void cloneWorkspaceWithItsContents() {
Workspace newWorkspace = new Workspace();
newWorkspace.setName("Template Workspace");
@ -239,7 +239,7 @@ public class ExamplesWorkspaceClonerTests {
.assertNext(data -> {
assertThat(data.workspace).isNotNull();
assertThat(data.workspace.getId()).isNotNull();
assertThat(data.workspace.getName()).isEqualTo("user's apps");
assertThat(data.workspace.getName()).isEqualTo("api_user's apps");
assertThat(data.workspace.getPolicies()).isNotEmpty();
assertThat(data.applications).hasSize(1);
@ -254,7 +254,7 @@ public class ExamplesWorkspaceClonerTests {
}
@Test
@WithUserDetails(value = "user@appsmith.com")
@WithUserDetails(value = "api_user")
public void cloneWorkspaceWithOnlyPublicApplications() {
Workspace newWorkspace = new Workspace();
newWorkspace.setName("Template Workspace 2");
@ -300,7 +300,7 @@ public class ExamplesWorkspaceClonerTests {
.assertNext(data -> {
assertThat(data.workspace).isNotNull();
assertThat(data.workspace.getId()).isNotNull();
assertThat(data.workspace.getName()).isEqualTo("user's apps");
assertThat(data.workspace.getName()).isEqualTo("api_user's apps");
assertThat(data.workspace.getPolicies()).isNotEmpty();
assertThat(data.applications).hasSize(2);
@ -325,7 +325,7 @@ public class ExamplesWorkspaceClonerTests {
}
@Test
@WithUserDetails(value = "user@appsmith.com")
@WithUserDetails(value = "api_user")
public void cloneWorkspaceWithOnlyPrivateApplications() {
Workspace newWorkspace = new Workspace();
newWorkspace.setName("Template Workspace 2");
@ -356,7 +356,7 @@ public class ExamplesWorkspaceClonerTests {
.assertNext(data -> {
assertThat(data.workspace).isNotNull();
assertThat(data.workspace.getId()).isNotNull();
assertThat(data.workspace.getName()).isEqualTo("user's apps");
assertThat(data.workspace.getName()).isEqualTo("api_user's apps");
assertThat(data.workspace.getPolicies()).isNotEmpty();
assertThat(data.applications).isEmpty();
@ -424,7 +424,7 @@ public class ExamplesWorkspaceClonerTests {
}
@Test
@WithUserDetails(value = "user@appsmith.com")
@WithUserDetails(value = "api_user")
public void cloneWorkspaceWithOnlyDatasources() {
Workspace newWorkspace = new Workspace();
newWorkspace.setName("Template Workspace 2");
@ -465,7 +465,7 @@ public class ExamplesWorkspaceClonerTests {
.assertNext(data -> {
assertThat(data.workspace).isNotNull();
assertThat(data.workspace.getId()).isNotNull();
assertThat(data.workspace.getName()).isEqualTo("user's apps");
assertThat(data.workspace.getName()).isEqualTo("api_user's apps");
assertThat(data.workspace.getPolicies()).isNotEmpty();
assertThat(data.datasources).isEmpty();
@ -477,7 +477,7 @@ public class ExamplesWorkspaceClonerTests {
}
@Test
@WithUserDetails(value = "user@appsmith.com")
@WithUserDetails(value = "api_user")
public void cloneWorkspaceWithOnlyDatasourcesSpecifiedExplicitly() {
Workspace newWorkspace = new Workspace();
newWorkspace.setName("Template Workspace 2");
@ -525,7 +525,7 @@ public class ExamplesWorkspaceClonerTests {
.assertNext(data -> {
assertThat(data.workspace).isNotNull();
assertThat(data.workspace.getId()).isNotNull();
assertThat(data.workspace.getName()).isEqualTo("user's apps");
assertThat(data.workspace.getName()).isEqualTo("api_user's apps");
assertThat(data.workspace.getPolicies()).isNotEmpty();
assertThat(data.datasources).hasSize(1);
@ -539,7 +539,7 @@ public class ExamplesWorkspaceClonerTests {
}
@Test
@WithUserDetails(value = "user@appsmith.com")
@WithUserDetails(value = "api_user")
public void cloneWorkspaceWithDatasourcesAndApplications() {
Workspace newWorkspace = new Workspace();
newWorkspace.setName("Template Workspace 2");
@ -591,7 +591,7 @@ public class ExamplesWorkspaceClonerTests {
.assertNext(data -> {
assertThat(data.workspace).isNotNull();
assertThat(data.workspace.getId()).isNotNull();
assertThat(data.workspace.getName()).isEqualTo("user's apps");
assertThat(data.workspace.getName()).isEqualTo("api_user's apps");
assertThat(data.workspace.getPolicies()).isNotEmpty();
assertThat(data.applications).hasSize(2);
@ -608,7 +608,7 @@ public class ExamplesWorkspaceClonerTests {
}
@Test
@WithUserDetails(value = "user@appsmith.com")
@WithUserDetails(value = "api_user")
public void cloneWorkspaceWithDatasourcesAndApplicationsAndActionsAndCollections() {
Workspace newWorkspace = new Workspace();
newWorkspace.setName("Template Workspace 2");
@ -739,7 +739,7 @@ public class ExamplesWorkspaceClonerTests {
.assertNext(data -> {
assertThat(data.workspace).isNotNull();
assertThat(data.workspace.getId()).isNotNull();
assertThat(data.workspace.getName()).isEqualTo("user's apps");
assertThat(data.workspace.getName()).isEqualTo("api_user's apps");
assertThat(data.workspace.getPolicies()).isNotEmpty();
assertThat(data.applications).hasSize(2);
@ -779,7 +779,7 @@ public class ExamplesWorkspaceClonerTests {
}
@Test
@WithUserDetails(value = "user@appsmith.com")
@WithUserDetails(value = "api_user")
public void cloneApplicationWithActionsThrice() {
Workspace sourceOrg = new Workspace();
sourceOrg.setName("Source Org 2");