Add transient field on applications to indicate whether it's an example application (#256)
* Add transient field on application to indicate whether it's an example * Add test for marking of example applications * Remove unused constant
This commit is contained in:
parent
dc10f09906
commit
0c344115c3
|
|
@ -7,6 +7,7 @@ import lombok.Getter;
|
|||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import org.springframework.data.annotation.Transient;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
|
@ -29,4 +30,8 @@ public class Application extends BaseDomain {
|
|||
Boolean isPublic = false;
|
||||
|
||||
List<ApplicationPage> pages;
|
||||
|
||||
@Transient
|
||||
boolean appIsExample = false;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ public class ApplicationServiceImpl extends BaseService<ApplicationRepository, A
|
|||
private final PageRepository pageRepository;
|
||||
private final PolicyUtils policyUtils;
|
||||
private final DatasourceService datasourceService;
|
||||
private final ConfigService configService;
|
||||
|
||||
@Autowired
|
||||
public ApplicationServiceImpl(Scheduler scheduler,
|
||||
|
|
@ -58,16 +59,18 @@ public class ApplicationServiceImpl extends BaseService<ApplicationRepository, A
|
|||
AnalyticsService analyticsService,
|
||||
PageRepository pageRepository,
|
||||
PolicyUtils policyUtils,
|
||||
DatasourceService datasourceService) {
|
||||
DatasourceService datasourceService,
|
||||
ConfigService configService) {
|
||||
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository, analyticsService);
|
||||
this.pageRepository = pageRepository;
|
||||
this.policyUtils = policyUtils;
|
||||
this.datasourceService = datasourceService;
|
||||
this.configService = configService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<Application> get(MultiValueMap<String, String> params) {
|
||||
return super.getWithPermission(params, READ_APPLICATIONS);
|
||||
return setTransientFields(super.getWithPermission(params, READ_APPLICATIONS));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -82,32 +85,37 @@ public class ApplicationServiceImpl extends BaseService<ApplicationRepository, A
|
|||
|
||||
@Override
|
||||
public Mono<Application> findById(String id) {
|
||||
return repository.findById(id);
|
||||
return repository.findById(id)
|
||||
.flatMap(this::setTransientFields);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Application> findById(String id, AclPermission aclPermission) {
|
||||
return repository.findById(id, aclPermission);
|
||||
return repository.findById(id, aclPermission)
|
||||
.flatMap(this::setTransientFields);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Application> findByIdAndOrganizationId(String id, String organizationId, AclPermission permission) {
|
||||
return repository.findByIdAndOrganizationId(id, organizationId, permission);
|
||||
return repository.findByIdAndOrganizationId(id, organizationId, permission)
|
||||
.flatMap(this::setTransientFields);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<Application> findByOrganizationId(String organizationId, AclPermission permission) {
|
||||
return repository.findByOrganizationId(organizationId, permission);
|
||||
return setTransientFields(repository.findByOrganizationId(organizationId, permission));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Application> findByName(String name, AclPermission permission) {
|
||||
return repository.findByName(name, permission);
|
||||
return repository.findByName(name, permission)
|
||||
.flatMap(this::setTransientFields);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Application> save(Application application) {
|
||||
return repository.save(application);
|
||||
return repository.save(application)
|
||||
.flatMap(this::setTransientFields);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -252,4 +260,19 @@ public class ApplicationServiceImpl extends BaseService<ApplicationRepository, A
|
|||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private Mono<Application> setTransientFields(Application application) {
|
||||
return setTransientFields(Flux.just(application)).last();
|
||||
}
|
||||
|
||||
private Flux<Application> setTransientFields(Flux<Application> applicationsFlux) {
|
||||
return configService.getTemplateOrganizationId()
|
||||
.defaultIfEmpty("")
|
||||
.cache()
|
||||
.repeat()
|
||||
.zipWith(applicationsFlux, (templateOrganizationId, application) -> {
|
||||
application.setAppIsExample(templateOrganizationId.equals(application.getOrganizationId()));
|
||||
return application;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,4 +7,6 @@ public interface ConfigService extends CrudService<Config, String> {
|
|||
Mono<Config> getByName(String name);
|
||||
|
||||
Mono<Config> updateByName(String name, Config config);
|
||||
|
||||
Mono<String> getTemplateOrganizationId();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ import javax.validation.Validator;
|
|||
@Service
|
||||
public class ConfigServiceImpl extends BaseService<ConfigRepository, Config, String> implements ConfigService {
|
||||
|
||||
private static final String TEMPLATE_ORGANIZATION_CONFIG_NAME = "template-organization";
|
||||
|
||||
public ConfigServiceImpl(Scheduler scheduler,
|
||||
Validator validator,
|
||||
MongoConverter mongoConverter,
|
||||
|
|
@ -43,4 +45,10 @@ public class ConfigServiceImpl extends BaseService<ConfigRepository, Config, Str
|
|||
return repository.save(dbConfig);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<String> getTemplateOrganizationId() {
|
||||
return repository.findByName(TEMPLATE_ORGANIZATION_CONFIG_NAME)
|
||||
.map(config -> config.getConfig().getAsString(FieldName.ORGANIZATION_ID));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.appsmith.server.solutions;
|
||||
|
||||
import com.appsmith.external.models.BaseDomain;
|
||||
import com.appsmith.server.constants.FieldName;
|
||||
import com.appsmith.server.domains.Action;
|
||||
import com.appsmith.server.domains.Application;
|
||||
import com.appsmith.server.domains.Datasource;
|
||||
|
|
@ -14,12 +13,12 @@ import com.appsmith.server.exceptions.AppsmithError;
|
|||
import com.appsmith.server.exceptions.AppsmithException;
|
||||
import com.appsmith.server.repositories.ActionRepository;
|
||||
import com.appsmith.server.repositories.ApplicationRepository;
|
||||
import com.appsmith.server.repositories.ConfigRepository;
|
||||
import com.appsmith.server.repositories.DatasourceRepository;
|
||||
import com.appsmith.server.repositories.OrganizationRepository;
|
||||
import com.appsmith.server.repositories.PageRepository;
|
||||
import com.appsmith.server.services.ActionService;
|
||||
import com.appsmith.server.services.ApplicationPageService;
|
||||
import com.appsmith.server.services.ConfigService;
|
||||
import com.appsmith.server.services.DatasourceContextService;
|
||||
import com.appsmith.server.services.DatasourceService;
|
||||
import com.appsmith.server.services.OrganizationService;
|
||||
|
|
@ -44,8 +43,6 @@ import java.util.Set;
|
|||
@RequiredArgsConstructor
|
||||
public class ExamplesOrganizationCloner {
|
||||
|
||||
public static final String TEMPLATE_ORGANIZATION_CONFIG_NAME = "template-organization";
|
||||
|
||||
private final OrganizationService organizationService;
|
||||
private final OrganizationRepository organizationRepository;
|
||||
private final DatasourceService datasourceService;
|
||||
|
|
@ -54,7 +51,7 @@ public class ExamplesOrganizationCloner {
|
|||
private final DatasourceRepository datasourceRepository;
|
||||
private final ApplicationRepository applicationRepository;
|
||||
private final ActionRepository actionRepository;
|
||||
private final ConfigRepository configRepository;
|
||||
private final ConfigService configService;
|
||||
private final SessionUserService sessionUserService;
|
||||
private final UserService userService;
|
||||
private final ApplicationPageService applicationPageService;
|
||||
|
|
@ -80,21 +77,18 @@ public class ExamplesOrganizationCloner {
|
|||
return Mono.empty();
|
||||
}
|
||||
|
||||
return configRepository.findByName(TEMPLATE_ORGANIZATION_CONFIG_NAME)
|
||||
return configService.getTemplateOrganizationId()
|
||||
.doOnSuccess(config -> {
|
||||
if (config == null) {
|
||||
// If the template organization could not be found, that's okay, the login should not fail. We
|
||||
// will try again the next time the user logs in.
|
||||
log.error(
|
||||
"Couldn't find config by name {}. Skipping creating example organization for user {}.",
|
||||
TEMPLATE_ORGANIZATION_CONFIG_NAME,
|
||||
"Template organization ID not found. Skipping creating example organization for user {}.",
|
||||
user.getEmail()
|
||||
);
|
||||
}
|
||||
})
|
||||
.flatMap(config ->
|
||||
cloneOrganizationForUser(config.getConfig().getAsString(FieldName.ORGANIZATION_ID), user)
|
||||
);
|
||||
.flatMap(templateOrganizationId -> cloneOrganizationForUser(templateOrganizationId, user));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ public class ApplicationServiceTest {
|
|||
.create(applicationMono)
|
||||
.assertNext(application -> {
|
||||
assertThat(application).isNotNull();
|
||||
assertThat(application.isAppIsExample()).isFalse();
|
||||
assertThat(application.getId()).isNotNull();
|
||||
assertThat(application.getName().equals("ApplicationServiceTest TestApp"));
|
||||
assertThat(application.getPolicies()).isNotEmpty();
|
||||
|
|
@ -201,6 +202,7 @@ public class ApplicationServiceTest {
|
|||
StepVerifier.create(getApplication)
|
||||
.assertNext(t -> {
|
||||
assertThat(t).isNotNull();
|
||||
assertThat(t.isAppIsExample()).isFalse();
|
||||
assertThat(t.getId()).isNotNull();
|
||||
assertThat(t.getName()).isEqualTo("validGetApplicationById-Test");
|
||||
})
|
||||
|
|
@ -221,6 +223,7 @@ public class ApplicationServiceTest {
|
|||
StepVerifier.create(getApplication)
|
||||
.assertNext(t -> {
|
||||
assertThat(t).isNotNull();
|
||||
assertThat(t.isAppIsExample()).isFalse();
|
||||
assertThat(t.getId()).isNotNull();
|
||||
assertThat(t.getName()).isEqualTo("validGetApplicationByName-Test");
|
||||
})
|
||||
|
|
@ -248,6 +251,7 @@ public class ApplicationServiceTest {
|
|||
.filter(t -> t.getName().equals("validGetApplications-Test"))
|
||||
.forEach(t -> {
|
||||
assertThat(t.getId()).isNotNull();
|
||||
assertThat(t.isAppIsExample()).isFalse();
|
||||
assertThat(t.getPolicies()).isNotEmpty();
|
||||
assertThat(t.getPolicies()).containsAll(Set.of(readAppPolicy));
|
||||
});
|
||||
|
|
@ -329,6 +333,7 @@ public class ApplicationServiceTest {
|
|||
|
||||
Application application = orgAppDto.getApplications().get(0);
|
||||
assertThat(application.getUserPermissions()).contains("read:applications");
|
||||
assertThat(application.isAppIsExample()).isFalse();
|
||||
})
|
||||
.verifyComplete();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
package com.appsmith.server.solutions;
|
||||
|
||||
import com.appsmith.server.domains.Application;
|
||||
import com.appsmith.server.domains.Organization;
|
||||
import com.appsmith.server.services.ApplicationPageService;
|
||||
import com.appsmith.server.services.ApplicationService;
|
||||
import com.appsmith.server.services.ConfigService;
|
||||
import com.appsmith.server.services.OrganizationService;
|
||||
import com.appsmith.server.services.SessionUserService;
|
||||
import com.appsmith.server.services.UserService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.security.test.context.support.WithUserDetails;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.appsmith.server.acl.AclPermission.READ_APPLICATIONS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@Slf4j
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
@DirtiesContext
|
||||
public class ExampleApplicationsAreMarked {
|
||||
|
||||
@Autowired
|
||||
UserService userService;
|
||||
|
||||
@Autowired
|
||||
private ApplicationService applicationService;
|
||||
|
||||
@Autowired
|
||||
private OrganizationService organizationService;
|
||||
|
||||
@Autowired
|
||||
private ApplicationPageService applicationPageService;
|
||||
|
||||
@Autowired
|
||||
private SessionUserService sessionUserService;
|
||||
|
||||
@MockBean
|
||||
private ConfigService configService;
|
||||
|
||||
@Test
|
||||
@WithUserDetails(value = "api_user")
|
||||
public void exampleApplicationsAreMarked() {
|
||||
Organization newOrganization = new Organization();
|
||||
newOrganization.setName("Template Organization 3");
|
||||
final Mono<List<Application>> resultMono = Mono
|
||||
.zip(
|
||||
organizationService.create(newOrganization),
|
||||
sessionUserService.getCurrentUser()
|
||||
)
|
||||
.flatMap(tuple -> {
|
||||
final Organization organization = tuple.getT1();
|
||||
|
||||
Mockito.when(configService.getTemplateOrganizationId()).thenReturn(Mono.just(organization.getId()));
|
||||
|
||||
final Application app1 = new Application();
|
||||
app1.setName("first application");
|
||||
app1.setOrganizationId(organization.getId());
|
||||
app1.setIsPublic(true);
|
||||
|
||||
final Application app2 = new Application();
|
||||
app2.setName("second application");
|
||||
app2.setOrganizationId(organization.getId());
|
||||
app2.setIsPublic(true);
|
||||
|
||||
final Application app3 = new Application();
|
||||
app3.setName("third application");
|
||||
app3.setOrganizationId(organization.getId());
|
||||
app3.setIsPublic(false);
|
||||
|
||||
return Mono
|
||||
.when(
|
||||
applicationPageService.createApplication(app1),
|
||||
applicationPageService.createApplication(app2),
|
||||
applicationPageService.createApplication(app3)
|
||||
)
|
||||
.thenReturn(organization.getId());
|
||||
})
|
||||
.flatMapMany(organizationId -> applicationService.findByOrganizationId(organizationId, READ_APPLICATIONS))
|
||||
.collectList();
|
||||
|
||||
StepVerifier.create(resultMono)
|
||||
.assertNext(applications -> {
|
||||
assertThat(applications).hasSize(3);
|
||||
assertThat(applications.stream().allMatch(Application::isAppIsExample)).isTrue();
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user