Reliable change application access from public to private & vice versa (#5530)

* Changing application public/private view can no longer be cancelled (for example by client timeout, etc.)

* Update test to only read the datasource used in the application

* Incorporated review comment

* Comment update
This commit is contained in:
Trisha Anand 2021-07-06 21:49:35 +05:30 committed by GitHub
parent 46844053cf
commit d1ef21dce3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 149 additions and 1 deletions

View File

@ -148,7 +148,7 @@ public class ApplicationServiceImpl extends BaseService<ApplicationRepository, A
@Override
public Mono<Application> changeViewAccess(String id, ApplicationAccessDTO applicationAccessDTO) {
return repository
Mono<Application> updateApplicationMono = repository
.findById(id, MAKE_PUBLIC_APPLICATIONS)
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.APPLICATION, id)))
.flatMap(application -> {
@ -165,6 +165,12 @@ public class ApplicationServiceImpl extends BaseService<ApplicationRepository, A
application.setIsPublic(applicationAccessDTO.getPublicAccess());
return generateAndSetPoliciesForPublicView(application, applicationAccessDTO.getPublicAccess());
});
// Use a synchronous sink which does not take subscription cancellations into account. This that even if the
// subscriber has cancelled its subscription, the create method will still generates its event.
return Mono.create(sink -> updateApplicationMono
.subscribe(sink::success, sink::error, null, sink.currentContext())
);
}
@Override

View File

@ -1098,4 +1098,146 @@ public class ApplicationServiceTest {
})
.verifyComplete();
}
@Test
@WithUserDetails(value = "api_user")
public void validChangeViewAccessCancelledMidWay() {
Mockito.when(pluginExecutorHelper.getPluginExecutor(Mockito.any())).thenReturn(Mono.just(new MockPluginExecutor()));
Application testApplication = new Application();
String appName = "ApplicationServiceTest Public View Application Midway Cancellation";
testApplication.setName(appName);
Application originalApplication = applicationPageService.createApplication(testApplication, orgId)
.block();
String pageId = originalApplication.getPages().get(0).getId();
Plugin plugin = pluginService.findByName("Installed Plugin Name").block();
Datasource datasource = new Datasource();
datasource.setName("Public View App Test");
datasource.setPluginId(plugin.getId());
DatasourceConfiguration datasourceConfiguration = new DatasourceConfiguration();
datasourceConfiguration.setUrl("http://test.com");
datasource.setDatasourceConfiguration(datasourceConfiguration);
datasource.setOrganizationId(orgId);
Datasource savedDatasource = datasourceService.create(datasource).block();
ActionDTO action1 = new ActionDTO();
action1.setName("Public View Test action1");
action1.setPageId(pageId);
action1.setDatasource(savedDatasource);
ActionConfiguration actionConfiguration = new ActionConfiguration();
actionConfiguration.setHttpMethod(HttpMethod.GET);
action1.setActionConfiguration(actionConfiguration);
ActionDTO savedAction1 = layoutActionService.createAction(action1).block();
ActionDTO action2 = new ActionDTO();
action2.setName("Public View Test action2");
action2.setPageId(pageId);
action2.setDatasource(savedDatasource);
action2.setActionConfiguration(actionConfiguration);
ActionDTO savedAction2 = layoutActionService.createAction(action2).block();
ActionDTO action3 = new ActionDTO();
action3.setName("Public View Test action3");
action3.setPageId(pageId);
action3.setDatasource(savedDatasource);
action3.setActionConfiguration(actionConfiguration);
ActionDTO savedAction3 = layoutActionService.createAction(action3).block();
ApplicationAccessDTO applicationAccessDTO = new ApplicationAccessDTO();
applicationAccessDTO.setPublicAccess(true);
// Trigger the change view access of application now.
applicationService.changeViewAccess(originalApplication.getId(), applicationAccessDTO)
.timeout(Duration.ofMillis(10))
.subscribe();
Mono<Application> applicationFromDbPostViewChange = Mono.just(originalApplication)
.flatMap(originalApp -> {
try {
// Before fetching the public application, sleep for 5 seconds to ensure that the updating
// all appsmith objects with public permission finishes.
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return applicationRepository.findById(originalApplication.getId(), READ_APPLICATIONS);
})
.cache();
Mono<List<NewAction>> actionsMono = applicationFromDbPostViewChange
.flatMap(clonedAppFromDb -> newActionService
.findAllByApplicationIdAndViewMode(clonedAppFromDb.getId(), false, READ_ACTIONS, null)
.collectList()
);
Mono<List<PageDTO>> pagesMono = applicationFromDbPostViewChange
.flatMapMany(application -> Flux.fromIterable(application.getPages()))
.flatMap(applicationPage -> newPageService.findPageById(applicationPage.getId(), READ_PAGES, false))
.collectList();
Mono<Datasource> datasourceMono = applicationFromDbPostViewChange
.flatMap(application -> datasourceService.findById(savedDatasource.getId(), READ_DATASOURCES));
StepVerifier
.create(Mono.zip(applicationFromDbPostViewChange, actionsMono, pagesMono, datasourceMono))
.assertNext(tuple -> {
Application updatedApplication = tuple.getT1();
List<NewAction> actions = tuple.getT2();
List<PageDTO> pages = tuple.getT3();
Datasource datasource1 = tuple.getT4();
assertThat(updatedApplication).isNotNull();
assertThat(updatedApplication.getIsPublic()).isTrue();
assertThat(updatedApplication
.getPolicies()
.stream()
.filter(policy -> policy.getPermission().equals(READ_APPLICATIONS.getValue()))
.findFirst()
.get()
.getUsers()
).contains("anonymousUser");
for (PageDTO page : pages) {
assertThat(page
.getPolicies()
.stream()
.filter(policy -> policy.getPermission().equals(READ_PAGES.getValue()))
.findFirst()
.get()
.getUsers()
).contains("anonymousUser");
}
for (NewAction action : actions) {
assertThat(action
.getPolicies()
.stream()
.filter(policy -> policy.getPermission().equals(EXECUTE_ACTIONS.getValue()))
.findFirst()
.get()
.getUsers()
).contains("anonymousUser");
}
assertThat(datasource1
.getPolicies()
.stream()
.filter(policy -> policy.getPermission().equals(EXECUTE_DATASOURCES.getValue()))
.findFirst()
.get()
.getUsers()
).contains("anonymousUser");
})
.verifyComplete();
}
}