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:
parent
46844053cf
commit
d1ef21dce3
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user