From debc0f13fb073b9f9c0e3e6157b215227b9c249e Mon Sep 17 00:00:00 2001 From: Kirill Liubun Date: Wed, 1 Jun 2016 17:50:42 +0300 Subject: [PATCH] Added verification for dependencies in app scope in method promoteScopeToTenant --- .../kaa/server/common/admin/AdminClient.java | 4 +- .../mvp/activity/CtlSchemaActivity.java | 3 +- .../admin/client/mvp/data/DataSource.java | 6 +- .../admin/controller/KaaAdminController.java | 10 +- .../admin/services/KaaAdminServiceImpl.java | 266 ++++++++++-------- .../shared/services/KaaAdminService.java | 2 +- .../control/ControlServerCTLSchemaIT.java | 36 +-- 7 files changed, 179 insertions(+), 148 deletions(-) diff --git a/server/common/admin-rest-client/src/main/java/org/kaaproject/kaa/server/common/admin/AdminClient.java b/server/common/admin-rest-client/src/main/java/org/kaaproject/kaa/server/common/admin/AdminClient.java index 4e5141b754..ef0735a446 100644 --- a/server/common/admin-rest-client/src/main/java/org/kaaproject/kaa/server/common/admin/AdminClient.java +++ b/server/common/admin-rest-client/src/main/java/org/kaaproject/kaa/server/common/admin/AdminClient.java @@ -1275,8 +1275,8 @@ public boolean checkFqnExistsWithAppToken(String fqn, String tenantId, String ap } } - public CTLSchemaMetaInfoDto updateCTLSchemaMetaInfoScope(CTLSchemaMetaInfoDto ctlSchemaMetaInfo) { - return restTemplate.postForObject(restTemplate.getUrl() + "CTL/updateScope", ctlSchemaMetaInfo, CTLSchemaMetaInfoDto.class); + public CTLSchemaMetaInfoDto promoteScopeToTenant(CTLSchemaMetaInfoDto ctlSchemaMetaInfo) { + return restTemplate.postForObject(restTemplate.getUrl() + "CTL/promoteScopeToTenant", ctlSchemaMetaInfo, CTLSchemaMetaInfoDto.class); } public List getSystemLevelCTLSchemas() { diff --git a/server/node/src/main/java/org/kaaproject/kaa/server/admin/client/mvp/activity/CtlSchemaActivity.java b/server/node/src/main/java/org/kaaproject/kaa/server/admin/client/mvp/activity/CtlSchemaActivity.java index 371980c839..932eca6403 100644 --- a/server/node/src/main/java/org/kaaproject/kaa/server/admin/client/mvp/activity/CtlSchemaActivity.java +++ b/server/node/src/main/java/org/kaaproject/kaa/server/admin/client/mvp/activity/CtlSchemaActivity.java @@ -98,8 +98,7 @@ public void onClick(ClickEvent event) { @Override public void onClick(ClickEvent event) { CTLSchemaMetaInfoDto metaInfo = entity.getMetaInfo(); - metaInfo.setApplicationId(null); - KaaAdmin.getDataSource().updateCtlSchemaScope(metaInfo, new BusyAsyncCallback() { + KaaAdmin.getDataSource().promoteScopeToTenant(metaInfo, new BusyAsyncCallback() { @Override public void onFailureImpl(Throwable caught) { Utils.handleException(caught, detailsView); diff --git a/server/node/src/main/java/org/kaaproject/kaa/server/admin/client/mvp/data/DataSource.java b/server/node/src/main/java/org/kaaproject/kaa/server/admin/client/mvp/data/DataSource.java index 8598c498e1..2d39daa50a 100644 --- a/server/node/src/main/java/org/kaaproject/kaa/server/admin/client/mvp/data/DataSource.java +++ b/server/node/src/main/java/org/kaaproject/kaa/server/admin/client/mvp/data/DataSource.java @@ -856,9 +856,9 @@ protected void onResult(Boolean result) { }); } - public void updateCtlSchemaScope(CTLSchemaMetaInfoDto metaInfo, - final AsyncCallback callback) { - rpcService.updateCTLSchemaMetaInfoScope(metaInfo, + public void promoteScopeToTenant(CTLSchemaMetaInfoDto metaInfo, + final AsyncCallback callback) { + rpcService.promoteScopeToTenant(metaInfo, new DataCallback(callback) { @Override protected void onResult(CTLSchemaMetaInfoDto result) { diff --git a/server/node/src/main/java/org/kaaproject/kaa/server/admin/controller/KaaAdminController.java b/server/node/src/main/java/org/kaaproject/kaa/server/admin/controller/KaaAdminController.java index dbfbff3e8e..f69687b2ce 100644 --- a/server/node/src/main/java/org/kaaproject/kaa/server/admin/controller/KaaAdminController.java +++ b/server/node/src/main/java/org/kaaproject/kaa/server/admin/controller/KaaAdminController.java @@ -992,7 +992,7 @@ public boolean checkFqnExistsWithAppToken(@RequestParam String fqn, } /** - * Update existing CTL schema meta info scope by the given CTL schema meta info object. + * Promote existing CTL schema meta info from application to tenant scope * * @param ctlSchemaMetaInfo * the CTL schema meta info object. @@ -1000,13 +1000,13 @@ public boolean checkFqnExistsWithAppToken(@RequestParam String fqn, * @throws KaaAdminServiceException * the kaa admin service exception * - * @return CTLSchemaMetaInfoDto the updated CTL schema meta info object. + * @return CTLSchemaMetaInfoDto the promoted CTL schema meta info object. */ - @RequestMapping(value = "CTL/updateScope", method = RequestMethod.POST) + @RequestMapping(value = "CTL/promoteScopeToTenant", method = RequestMethod.POST) @ResponseBody - public CTLSchemaMetaInfoDto updateCTLSchemaMetaInfoScope(@RequestBody CTLSchemaMetaInfoDto ctlSchemaMetaInfo) + public CTLSchemaMetaInfoDto promoteScopeToTenant(@RequestBody CTLSchemaMetaInfoDto ctlSchemaMetaInfo) throws KaaAdminServiceException { - return kaaAdminService.updateCTLSchemaMetaInfoScope(ctlSchemaMetaInfo); + return kaaAdminService.promoteScopeToTenant(ctlSchemaMetaInfo); } /** diff --git a/server/node/src/main/java/org/kaaproject/kaa/server/admin/services/KaaAdminServiceImpl.java b/server/node/src/main/java/org/kaaproject/kaa/server/admin/services/KaaAdminServiceImpl.java index ee35a6ed40..6f43e8ace4 100644 --- a/server/node/src/main/java/org/kaaproject/kaa/server/admin/services/KaaAdminServiceImpl.java +++ b/server/node/src/main/java/org/kaaproject/kaa/server/admin/services/KaaAdminServiceImpl.java @@ -33,9 +33,11 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; import org.apache.avro.Schema; import org.apache.avro.generic.GenericRecord; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.hibernate.StaleObjectStateException; @@ -170,7 +172,9 @@ public class KaaAdminServiceImpl implements KaaAdminService, InitializingBean { */ private static final int MAX_LIMIT = 500; - /** The application service. */ + /** + * The application service. + */ @Autowired private ControlService controlService; @@ -229,18 +233,18 @@ public EndpointProfileViewDto getEndpointProfileViewByKeyHash(String endpointPro } } EndpointProfileSchemaDto clientProfileSchema = controlService.getProfileSchemaByApplicationIdAndVersion( - endpointProfile.getApplicationId(), - endpointProfile.getClientProfileVersion()); + endpointProfile.getApplicationId(), + endpointProfile.getClientProfileVersion()); ServerProfileSchemaDto serverProfileSchema = controlService.getServerProfileSchemaByApplicationIdAndVersion( - endpointProfile.getApplicationId(), - endpointProfile.getServerProfileVersion()); + endpointProfile.getApplicationId(), + endpointProfile.getServerProfileVersion()); endpointProfileView.setProfileSchemaName(clientProfileSchema.getName()); endpointProfileView.setProfileSchemaVersion(clientProfileSchema.toVersionDto()); endpointProfileView.setServerProfileSchemaName(serverProfileSchema.getName()); endpointProfileView.setServerProfileSchemaVersion(serverProfileSchema.toVersionDto()); - endpointProfileView.setProfileRecord(createRecordFieldFromCtlSchemaAndBody(clientProfileSchema.getCtlSchemaId(), + endpointProfileView.setProfileRecord(createRecordFieldFromCtlSchemaAndBody(clientProfileSchema.getCtlSchemaId(), endpointProfile.getClientProfileBody())); - endpointProfileView.setServerProfileRecord(createRecordFieldFromCtlSchemaAndBody(serverProfileSchema.getCtlSchemaId(), + endpointProfileView.setServerProfileRecord(createRecordFieldFromCtlSchemaAndBody(serverProfileSchema.getCtlSchemaId(), endpointProfile.getServerProfileBody())); List topics = new ArrayList<>(); if (endpointProfile.getSubscriptions() != null) { @@ -262,7 +266,7 @@ public EndpointProfileViewDto getEndpointProfileViewByKeyHash(String endpointPro throw Utils.handleException(e); } } - + private RecordField createRecordFieldFromCtlSchemaAndBody(String ctlSchemaId, String body) throws KaaAdminServiceException { try { RecordField recordField; @@ -359,25 +363,25 @@ public EndpointProfileBodyDto getEndpointProfileBodyByKeyHash(String endpointPro throw Utils.handleException(e); } } - + @Override public EndpointProfileDto updateServerProfile(String endpointKeyHash, - int serverProfileVersion, String serverProfileBody) + int serverProfileVersion, String serverProfileBody) throws KaaAdminServiceException { checkAuthority(KaaAuthorityDto.TENANT_DEVELOPER, KaaAuthorityDto.TENANT_USER); try { - EndpointProfileDto profileDto = controlService.getEndpointProfileByKeyHash(endpointKeyHash); + EndpointProfileDto profileDto = controlService.getEndpointProfileByKeyHash(endpointKeyHash); checkApplicationId(profileDto.getApplicationId()); ServerProfileSchemaDto serverProfileSchema = controlService.getServerProfileSchemaByApplicationIdAndVersion( profileDto.getApplicationId(), serverProfileVersion); RecordField record; try { - record = createRecordFieldFromCtlSchemaAndBody(serverProfileSchema.getCtlSchemaId(), + record = createRecordFieldFromCtlSchemaAndBody(serverProfileSchema.getCtlSchemaId(), serverProfileBody); } catch (Exception e) { LOG.error("Provided server profile body is not valid: ", e); - throw new KaaAdminServiceException("Provided server profile body is not valid: " - + e.getMessage(), ServiceErrorCode.BAD_REQUEST_PARAMS); + throw new KaaAdminServiceException("Provided server profile body is not valid: " + + e.getMessage(), ServiceErrorCode.BAD_REQUEST_PARAMS); } if (!record.isValid()) { throw new KaaAdminServiceException("Provided server profile body is not valid!", ServiceErrorCode.BAD_REQUEST_PARAMS); @@ -391,7 +395,7 @@ record = createRecordFieldFromCtlSchemaAndBody(serverProfileSchema.getCtlSchemaI @Override public EndpointProfileDto updateServerProfile(String endpointKeyHash, - int serverProfileVersion, RecordField serverProfileRecord) + int serverProfileVersion, RecordField serverProfileRecord) throws KaaAdminServiceException { checkAuthority(KaaAuthorityDto.TENANT_DEVELOPER, KaaAuthorityDto.TENANT_USER); try { @@ -535,7 +539,7 @@ public org.kaaproject.kaa.common.dto.admin.UserDto getUserProfile() throws KaaAd Utils.checkNotNull(user); org.kaaproject.kaa.common.dto.admin.UserDto result = new org.kaaproject.kaa.common.dto.admin.UserDto(user.getId().toString(), user.getUsername(), user.getFirstName(), user.getLastName(), user.getMail(), KaaAuthorityDto.valueOf(user - .getAuthorities().iterator().next().getAuthority())); + .getAuthorities().iterator().next().getAuthority())); return result; } catch (Exception e) { throw Utils.handleException(e); @@ -566,7 +570,7 @@ public org.kaaproject.kaa.common.dto.admin.UserDto editUserProfile(org.kaaprojec User user = userFacade.findById(userId); org.kaaproject.kaa.common.dto.admin.UserDto result = new org.kaaproject.kaa.common.dto.admin.UserDto(user.getId().toString(), user.getUsername(), user.getFirstName(), user.getLastName(), user.getMail(), KaaAuthorityDto.valueOf(user - .getAuthorities().iterator().next().getAuthority())); + .getAuthorities().iterator().next().getAuthority())); return result; } catch (Exception e) { throw Utils.handleException(e); @@ -755,7 +759,7 @@ public SdkProfileDto createSdkProfile(SdkProfileDto sdkProfile) throws KaaAdminS this.checkApplicationId(sdkProfile.getApplicationId()); sdkProfile.setCreatedUsername(getCurrentUser().getUsername()); sdkProfile.setCreatedTime(System.currentTimeMillis()); - + ApplicationDto application = controlService.getApplication(sdkProfile.getApplicationId()); if (application == null) { throw new NotFoundException("Application not found!"); @@ -824,7 +828,7 @@ public SdkProfileViewDto getSdkProfileView(String sdkProfileId) throws KaaAdminS getApplicationEventFamilyMapsByApplicationId(applicationId); List aefMapIds = sdkProfile.getAefMapIds(); for (ApplicationEventFamilyMapDto aefDto : aefMaps) { - if (aefMapIds.contains(aefDto.getId())){ + if (aefMapIds.contains(aefDto.getId())) { aefDtoList.add(aefDto); } } @@ -1025,7 +1029,7 @@ public List getProfileSchemasByApplicationId(String ap @Override public List getProfileSchemasByApplicationToken(String applicationToken) throws KaaAdminServiceException { - return getProfileSchemasByApplicationId(checkApplicationToken(applicationToken)); + return getProfileSchemasByApplicationId(checkApplicationToken(applicationToken)); } @Override @@ -1082,8 +1086,8 @@ public ProfileSchemaViewDto saveProfileSchemaView(ProfileSchemaViewDto profileSc if (isEmpty(ctlSchemaId)) { if (profileSchemaView.useExistingCtlSchema()) { CtlSchemaReferenceDto metaInfo = profileSchemaView.getExistingMetaInfo(); - CTLSchemaDto schema = getCTLSchemaByFqnVersionTenantIdAndApplicationId(metaInfo.getMetaInfo().getFqn(), - metaInfo.getVersion(), + CTLSchemaDto schema = getCTLSchemaByFqnVersionTenantIdAndApplicationId(metaInfo.getMetaInfo().getFqn(), + metaInfo.getVersion(), metaInfo.getMetaInfo().getTenantId(), metaInfo.getMetaInfo().getApplicationId()); profileSchema.setCtlSchemaId(schema.getId()); @@ -1098,7 +1102,7 @@ public ProfileSchemaViewDto saveProfileSchemaView(ProfileSchemaViewDto profileSc throw Utils.handleException(e); } } - + @Override public ProfileSchemaViewDto createProfileSchemaFormCtlSchema(CtlSchemaFormDto ctlSchemaForm) throws KaaAdminServiceException { @@ -1153,7 +1157,7 @@ public List getServerProfileSchemaInfosByApplicationId(String app throw Utils.handleException(e); } } - + @Override public List getServerProfileSchemaInfosByEndpointKey(String endpointKeyHash) throws KaaAdminServiceException { checkAuthority(KaaAuthorityDto.TENANT_DEVELOPER, KaaAuthorityDto.TENANT_USER); @@ -1191,7 +1195,7 @@ public ServerProfileSchemaDto getServerProfileSchema(String serverProfileSchemaI throw Utils.handleException(e); } } - + @Override public ServerProfileSchemaDto saveServerProfileSchema(ServerProfileSchemaDto serverProfileSchema) throws KaaAdminServiceException { checkAuthority(KaaAuthorityDto.TENANT_DEVELOPER, KaaAuthorityDto.TENANT_USER); @@ -1233,8 +1237,8 @@ public ServerProfileSchemaViewDto saveServerProfileSchemaView(ServerProfileSchem if (isEmpty(ctlSchemaId)) { if (serverProfileSchemaView.useExistingCtlSchema()) { CtlSchemaReferenceDto metaInfo = serverProfileSchemaView.getExistingMetaInfo(); - CTLSchemaDto schema = getCTLSchemaByFqnVersionTenantIdAndApplicationId(metaInfo.getMetaInfo().getFqn(), - metaInfo.getVersion(), + CTLSchemaDto schema = getCTLSchemaByFqnVersionTenantIdAndApplicationId(metaInfo.getMetaInfo().getFqn(), + metaInfo.getVersion(), metaInfo.getMetaInfo().getTenantId(), metaInfo.getMetaInfo().getApplicationId()); serverProfileSchema.setCtlSchemaId(schema.getId()); @@ -1249,7 +1253,7 @@ public ServerProfileSchemaViewDto saveServerProfileSchemaView(ServerProfileSchem throw Utils.handleException(e); } } - + @Override public ServerProfileSchemaViewDto createServerProfileSchemaFormCtlSchema(CtlSchemaFormDto ctlSchemaForm) throws KaaAdminServiceException { @@ -1268,7 +1272,7 @@ public ServerProfileSchemaViewDto createServerProfileSchemaFormCtlSchema(CtlSche throw Utils.handleException(e); } } - + private void convertToSchemaForm(AbstractSchemaDto dto, SchemaFormAvroConverter converter) throws IOException { Schema schema = new Schema.Parser().parse(dto.getSchema()); RecordField schemaForm = converter.createSchemaFormFromSchema(schema); @@ -1281,7 +1285,7 @@ private void convertToStringSchema(AbstractSchemaDto dto, SchemaFormAvroConverte String schemaString = SchemaFormAvroConverter.createSchemaString(schema, true); dto.setSchema(schemaString); } - + @Override public SchemaInfoDto getEndpointProfileSchemaInfo(String endpointProfileSchemaId) throws KaaAdminServiceException { checkAuthority(KaaAuthorityDto.TENANT_DEVELOPER, KaaAuthorityDto.TENANT_USER); @@ -1485,7 +1489,7 @@ public List getUserNotificationSchemaInfosByApplicationId(String throw Utils.handleException(e); } } - + @Override public NotificationSchemaDto getNotificationSchema(String notificationSchemaId) throws KaaAdminServiceException { checkAuthority(KaaAuthorityDto.TENANT_DEVELOPER, KaaAuthorityDto.TENANT_USER); @@ -1724,7 +1728,7 @@ public void deleteEndpointGroup(String endpointGroupId) throws KaaAdminServiceEx @Override public List getProfileFilterRecordsByEndpointGroupId(String endpointGroupId, - boolean includeDeprecated) throws KaaAdminServiceException { + boolean includeDeprecated) throws KaaAdminServiceException { checkAuthority(KaaAuthorityDto.TENANT_DEVELOPER, KaaAuthorityDto.TENANT_USER); try { checkEndpointGroupId(endpointGroupId); @@ -1742,7 +1746,7 @@ private void checkSchemaId(String schemaId) throws IllegalArgumentException { @Override public ProfileFilterRecordDto getProfileFilterRecord(String endpointProfileSchemaId, String serverProfileSchemaId, - String endpointGroupId) throws KaaAdminServiceException { + String endpointGroupId) throws KaaAdminServiceException { checkAuthority(KaaAuthorityDto.TENANT_DEVELOPER, KaaAuthorityDto.TENANT_USER); try { checkEndpointGroupId(endpointGroupId); @@ -1777,7 +1781,7 @@ public ProfileFilterDto editProfileFilter(ProfileFilterDto profileFilter) throws profileFilter.setModifiedUsername(username); ProfileFilterDto storedProfileFilter = controlService.getProfileFilter(profileFilter.getId()); Utils.checkNotNull(storedProfileFilter); - checkEndpointGroupId(storedProfileFilter.getEndpointGroupId()); + checkEndpointGroupId(storedProfileFilter.getEndpointGroupId()); } validateProfileFilterBody(profileFilter.getEndpointProfileSchemaId(), profileFilter.getServerProfileSchemaId(), @@ -1787,9 +1791,9 @@ public ProfileFilterDto editProfileFilter(ProfileFilterDto profileFilter) throws throw Utils.handleException(e); } } - - private void validateProfileFilterBody(String endpointProfileSchemaId, String serverProfileSchemaId, - String filterBody) throws KaaAdminServiceException { + + private void validateProfileFilterBody(String endpointProfileSchemaId, String serverProfileSchemaId, + String filterBody) throws KaaAdminServiceException { GenericRecord endpointProfileRecord = null; GenericRecord serverProfileRecord = null; try { @@ -1823,7 +1827,7 @@ private void validateProfileFilterBody(String endpointProfileSchemaId, String se throw new KaaAdminServiceException("Invalid profile filter body!", e, ServiceErrorCode.BAD_REQUEST_PARAMS); } } - + private GenericRecord getDefaultRecordFromCtlSchema(String ctlSchemaId) throws Exception { CTLSchemaDto ctlSchema = controlService.getCTLSchemaById(ctlSchemaId); Schema schema = controlService.exportCTLSchemaFlatAsSchema(ctlSchema); @@ -1877,7 +1881,7 @@ public void deleteProfileFilterRecord(String endpointProfileSchemaId, String ser @Override public List getConfigurationRecordsByEndpointGroupId(String endpointGroupId, - boolean includeDeprecated) throws KaaAdminServiceException { + boolean includeDeprecated) throws KaaAdminServiceException { checkAuthority(KaaAuthorityDto.TENANT_DEVELOPER, KaaAuthorityDto.TENANT_USER); try { checkEndpointGroupId(endpointGroupId); @@ -2591,7 +2595,7 @@ public EndpointNotificationDto sendUnicastNotification(NotificationDto notificat GenericRecord record = FormAvroConverter.createGenericRecordFromRecordField(notificationData); GenericAvroConverter converter = new GenericAvroConverter<>(record.getSchema()); byte[] body = converter.encodeToJsonBytes(record); - return sendUnicastNotification(notification,clientKeyHash,body); + return sendUnicastNotification(notification, clientKeyHash, body); } catch (Exception e) { throw Utils.handleException(e); } @@ -2833,7 +2837,7 @@ private org.kaaproject.kaa.common.dto.admin.UserDto toUser(UserDto tenantUser) { User user = userFacade.findById(Long.valueOf(tenantUser.getExternalUid())); org.kaaproject.kaa.common.dto.admin.UserDto result = new org.kaaproject.kaa.common.dto.admin.UserDto(user.getId().toString(), user.getUsername(), user.getFirstName(), user.getLastName(), user.getMail(), KaaAuthorityDto.valueOf(user.getAuthorities() - .iterator().next().getAuthority())); + .iterator().next().getAuthority())); result.setId(tenantUser.getId()); result.setTenantId(tenantUser.getTenantId()); return result; @@ -2880,12 +2884,12 @@ private Schema validateSchema(String avroSchema, boolean isCtl) throws KaaAdminS throw new KaaAdminServiceException(spe.getMessage(), ServiceErrorCode.INVALID_SCHEMA); } } - + private void validateRecordSchema(String avroSchema, boolean isCtl) throws KaaAdminServiceException { Schema schema = validateSchema(avroSchema, isCtl); validateRecordSchema(schema); } - + private void validateRecordSchema(Schema schema) throws KaaAdminServiceException { SchemaUtil.compileAvroSchema(schema); if (schema.getType() != Schema.Type.RECORD) { @@ -3020,7 +3024,7 @@ public List getUserConfigurationSchemaInfosByApplicationId(String @Override public void editUserConfiguration(EndpointUserConfigurationDto endpointUserConfiguration, String applicationId, - RecordField configurationData) throws KaaAdminServiceException { + RecordField configurationData) throws KaaAdminServiceException { checkAuthority(KaaAuthorityDto.TENANT_DEVELOPER, KaaAuthorityDto.TENANT_USER); try { ApplicationDto application = checkApplicationId(applicationId); @@ -3052,27 +3056,27 @@ private void checkCTLSchemaReadScope(String tenantId, String applicationId) thro CTLSchemaScopeDto scope = detectScope(tenantId, applicationId); boolean allowed = false; switch (currentUser.getAuthority()) { - case KAA_ADMIN: - allowed = scope == CTLSchemaScopeDto.SYSTEM; - break; - case TENANT_ADMIN: - if (scope == CTLSchemaScopeDto.TENANT) { - checkTenantId(tenantId); - } - allowed = scope.getLevel() <= CTLSchemaScopeDto.TENANT.getLevel(); - break; - case TENANT_DEVELOPER: - case TENANT_USER: - if (scope == CTLSchemaScopeDto.TENANT) { - checkTenantId(tenantId); - } - if (scope.getLevel() >= CTLSchemaScopeDto.APPLICATION.getLevel()) { - checkApplicationId(applicationId); - } - allowed = scope.getLevel() >= CTLSchemaScopeDto.SYSTEM.getLevel(); - break; - default: - break; + case KAA_ADMIN: + allowed = scope == CTLSchemaScopeDto.SYSTEM; + break; + case TENANT_ADMIN: + if (scope == CTLSchemaScopeDto.TENANT) { + checkTenantId(tenantId); + } + allowed = scope.getLevel() <= CTLSchemaScopeDto.TENANT.getLevel(); + break; + case TENANT_DEVELOPER: + case TENANT_USER: + if (scope == CTLSchemaScopeDto.TENANT) { + checkTenantId(tenantId); + } + if (scope.getLevel() >= CTLSchemaScopeDto.APPLICATION.getLevel()) { + checkApplicationId(applicationId); + } + allowed = scope.getLevel() >= CTLSchemaScopeDto.SYSTEM.getLevel(); + break; + default: + break; } if (!allowed) { throw new KaaAdminServiceException(ServiceErrorCode.PERMISSION_DENIED); @@ -3084,23 +3088,23 @@ private void checkCTLSchemaEditScope(String tenantId, String applicationId) thro CTLSchemaScopeDto scope = detectScope(tenantId, applicationId); boolean allowed = false; switch (currentUser.getAuthority()) { - case KAA_ADMIN: - allowed = scope == CTLSchemaScopeDto.SYSTEM; - break; - case TENANT_ADMIN: - checkTenantId(tenantId); - allowed = scope == CTLSchemaScopeDto.TENANT; - break; - case TENANT_DEVELOPER: - case TENANT_USER: - checkTenantId(tenantId); - if (scope.getLevel() >= CTLSchemaScopeDto.APPLICATION.getLevel()) { - checkApplicationId(applicationId); - } - allowed = scope.getLevel() >= CTLSchemaScopeDto.TENANT.getLevel(); - break; - default: - break; + case KAA_ADMIN: + allowed = scope == CTLSchemaScopeDto.SYSTEM; + break; + case TENANT_ADMIN: + checkTenantId(tenantId); + allowed = scope == CTLSchemaScopeDto.TENANT; + break; + case TENANT_DEVELOPER: + case TENANT_USER: + checkTenantId(tenantId); + if (scope.getLevel() >= CTLSchemaScopeDto.APPLICATION.getLevel()) { + checkApplicationId(applicationId); + } + allowed = scope.getLevel() >= CTLSchemaScopeDto.TENANT.getLevel(); + break; + default: + break; } if (!allowed) { throw new KaaAdminServiceException(ServiceErrorCode.PERMISSION_DENIED); @@ -3137,11 +3141,9 @@ private void checkCTLSchemaVersion(Integer version) throws KaaAdminServiceExcept * Returns a string that contains fully qualified names and version numbers * of the given CTL schemas. * - * @param types - * A collection of CTL schemas - * + * @param types A collection of CTL schemas * @return A string that contains fully qualified names and version numbers - * of the given CTL schemas + * of the given CTL schemas */ private String asText(Collection types) { StringBuilder message = new StringBuilder(); @@ -3158,7 +3160,7 @@ private String asText(Collection types) { public CTLSchemaDto saveCTLSchema(String body, String tenantId, String applicationId) throws KaaAdminServiceException { this.checkAuthority(KaaAuthorityDto.values()); try { - checkCTLSchemaEditScope(tenantId, applicationId); + checkCTLSchemaEditScope(tenantId, applicationId); CTLSchemaParser parser = new CTLSchemaParser(controlService, tenantId); CTLSchemaDto schema = parser.parse(body, applicationId); checkCTLSchemaVersion(schema.getVersion()); @@ -3187,15 +3189,16 @@ public CTLSchemaDto saveCTLSchema(CTLSchemaDto schema) throws KaaAdminServiceExc Utils.checkNotNull(schema); checkCTLSchemaVersion(schema.getVersion()); checkCTLSchemaEditScope(schema.getMetaInfo().getTenantId(), schema.getMetaInfo().getApplicationId()); + // Check if the schema dependencies are present in the database List missingDependencies = new ArrayList<>(); Set dependencies = new HashSet<>(); if (schema.getDependencySet() != null) { for (CTLSchemaDto dependency : schema.getDependencySet()) { - CTLSchemaDto schemaFound = + CTLSchemaDto schemaFound = controlService.getAnyCTLSchemaByFqnVersionTenantIdAndApplicationId( dependency.getMetaInfo().getFqn(), dependency.getVersion(), - schema.getMetaInfo().getTenantId(), schema.getMetaInfo().getApplicationId()); + schema.getMetaInfo().getTenantId(), schema.getMetaInfo().getApplicationId()); if (schemaFound == null) { missingDependencies.add(new FqnVersion(dependency.getMetaInfo().getFqn(), dependency.getVersion())); } else { @@ -3338,12 +3341,39 @@ public boolean checkFqnExistsWithAppToken(String fqn, String tenantId, String ap return checkFqnExists(fqn, tenantId, applicationId); } + @Override - public CTLSchemaMetaInfoDto updateCTLSchemaMetaInfoScope(CTLSchemaMetaInfoDto ctlSchemaMetaInfo) + public CTLSchemaMetaInfoDto promoteScopeToTenant(CTLSchemaMetaInfoDto ctlSchemaMetaInfo) throws KaaAdminServiceException { - this.checkAuthority(KaaAuthorityDto.values()); + checkAuthority(KaaAuthorityDto.values()); + checkCTLSchemaEditScope(ctlSchemaMetaInfo.getTenantId(), ctlSchemaMetaInfo.getApplicationId()); + + final String fqn = ctlSchemaMetaInfo.getFqn(); + final String tenantId = ctlSchemaMetaInfo.getTenantId(); + final String applicationId = ctlSchemaMetaInfo.getApplicationId(); + List versions = ctlSchemaMetaInfo.getVersions(); + ctlSchemaMetaInfo.setApplicationId(null); // promote scope to tenant try { - checkCTLSchemaEditScope(ctlSchemaMetaInfo.getTenantId(), ctlSchemaMetaInfo.getApplicationId()); + Set dependencies = new HashSet<>(); + + // get dep of all versions + for (Integer version : versions) { + CTLSchemaDto schemaFound = controlService.getCTLSchemaByFqnVersionTenantIdAndApplicationId(fqn, version, tenantId, applicationId); + Utils.checkNotNull(schemaFound); + Set schemaDependents = schemaFound.getDependencySet(); + dependencies.addAll(schemaDependents.stream() + .filter(dep -> dep.getMetaInfo().getScope() == CTLSchemaScopeDto.APPLICATION) + .collect(Collectors.toList())); + } + + // check if CT has dependencies with application scope + if (!dependencies.isEmpty()) { + String message = "Can't promote the common type version as it has references on following common type(s) with application scope: " + + asText(dependencies); + throw new KaaAdminServiceException(message, ServiceErrorCode.GENERAL_ERROR); + } + + return controlService.updateCTLSchemaMetaInfoScope(ctlSchemaMetaInfo); } catch (Exception cause) { throw Utils.handleException(cause); @@ -3455,8 +3485,8 @@ public CtlSchemaFormDto getCTLSchemaFormByMetaInfoIdAndVer(String metaInfoId, in } @Override - public CtlSchemaFormDto createNewCTLSchemaFormInstance(String metaInfoId, - Integer sourceVersion, String applicationId) throws KaaAdminServiceException { + public CtlSchemaFormDto createNewCTLSchemaFormInstance(String metaInfoId, + Integer sourceVersion, String applicationId) throws KaaAdminServiceException { checkAuthority(KaaAuthorityDto.values()); try { SchemaFormAvroConverter converter = getCtlSchemaConverterForScope(getCurrentUser().getTenantId(), applicationId); @@ -3471,7 +3501,7 @@ public CtlSchemaFormDto createNewCTLSchemaFormInstance(String metaInfoId, ctlSchemaForm = new CtlSchemaFormDto(); ctlSchemaForm.setMetaInfo(sourceCtlSchema.getMetaInfo()); RecordField form = sourceCtlSchema.getSchema(); - form.updateVersion(form.getContext().getMaxVersion(new Fqn(sourceCtlSchema.getMetaInfo().getFqn()))+1); + form.updateVersion(form.getContext().getMaxVersion(new Fqn(sourceCtlSchema.getMetaInfo().getFqn())) + 1); ctlSchemaForm.setSchema(form); } else { checkCTLSchemaEditScope(getCurrentUser().getTenantId(), applicationId); @@ -3479,7 +3509,7 @@ public CtlSchemaFormDto createNewCTLSchemaFormInstance(String metaInfoId, RecordField form = converter.getEmptySchemaFormInstance(); form.updateVersion(1); ctlSchemaForm.setSchema(form); - CTLSchemaMetaInfoDto metaInfo = new CTLSchemaMetaInfoDto(null, + CTLSchemaMetaInfoDto metaInfo = new CTLSchemaMetaInfoDto(null, getCurrentUser().getTenantId(), applicationId); ctlSchemaForm.setMetaInfo(metaInfo); } @@ -3537,7 +3567,7 @@ public CtlSchemaFormDto saveCTLSchemaForm(CtlSchemaFormDto ctlSchemaForm) throws List missingDependencies = new ArrayList<>(); for (FqnVersion fqnVersion : dependenciesList) { CTLSchemaDto dependency = controlService.getAnyCTLSchemaByFqnVersionTenantIdAndApplicationId( - fqnVersion.getFqnString(), fqnVersion.getVersion(), + fqnVersion.getFqnString(), fqnVersion.getVersion(), ctlSchema.getMetaInfo().getTenantId(), ctlSchema.getMetaInfo().getApplicationId()); if (dependency != null) { dependencies.add(dependency); @@ -3550,13 +3580,13 @@ public CtlSchemaFormDto saveCTLSchemaForm(CtlSchemaFormDto ctlSchemaForm) throws throw new IllegalArgumentException(message); } ctlSchema.setDependencySet(dependencies); - SchemaFormAvroConverter converter = getCtlSchemaConverterForScope(ctlSchema.getMetaInfo().getTenantId(), + SchemaFormAvroConverter converter = getCtlSchemaConverterForScope(ctlSchema.getMetaInfo().getTenantId(), ctlSchema.getMetaInfo().getApplicationId()); Schema avroSchema = converter.createSchemaFromSchemaForm(schemaForm); String schemaBody = SchemaFormAvroConverter.createSchemaString(avroSchema, true); ctlSchema.setBody(schemaBody); } - + CTLSchemaDto savedCtlSchema = saveCTLSchema(ctlSchema); if (savedCtlSchema != null) { CtlSchemaFormDto result = new CtlSchemaFormDto(savedCtlSchema); @@ -3565,7 +3595,7 @@ public CtlSchemaFormDto saveCTLSchemaForm(CtlSchemaFormDto ctlSchemaForm) throws RecordField form = converter.createSchemaFormFromSchema(savedCtlSchema.getBody()); result.setSchema(form); List availableVersions = controlService.getAllCTLSchemaVersionsByFqnTenantIdAndApplicationId( - savedCtlSchema.getMetaInfo().getFqn(), savedCtlSchema.getMetaInfo().getTenantId(), savedCtlSchema.getMetaInfo().getApplicationId()); + savedCtlSchema.getMetaInfo().getFqn(), savedCtlSchema.getMetaInfo().getTenantId(), savedCtlSchema.getMetaInfo().getApplicationId()); availableVersions = availableVersions == null ? Collections.emptyList() : availableVersions; Collections.sort(availableVersions); result.getMetaInfo().setVersions(availableVersions); @@ -3576,7 +3606,7 @@ public CtlSchemaFormDto saveCTLSchemaForm(CtlSchemaFormDto ctlSchemaForm) throws } return null; } - + @Override public boolean checkFqnExists(CtlSchemaFormDto ctlSchemaForm) throws KaaAdminServiceException { checkAuthority(KaaAuthorityDto.values()); @@ -3593,11 +3623,11 @@ public boolean checkFqnExists(CtlSchemaFormDto ctlSchemaForm) throws KaaAdminSer } return false; } - + private SchemaFormAvroConverter getCtlSchemaConverterForScope(String tenantId, String applicationId) throws KaaAdminServiceException { try { if (isEmpty(tenantId)) { - return getCtlSchemaConverterForSystem(); + return getCtlSchemaConverterForSystem(); } if (isEmpty(applicationId)) { return getCtlSchemaConverterForTenant(tenantId); @@ -3607,7 +3637,7 @@ private SchemaFormAvroConverter getCtlSchemaConverterForScope(String tenantId, S throw Utils.handleException(cause); } } - + private SchemaFormAvroConverter getCtlSchemaConverterForSystem() throws KaaAdminServiceException { try { return createSchemaConverterFromCtlTypes(controlService.getAvailableCTLSchemaVersionsForSystem()); @@ -3623,7 +3653,7 @@ private SchemaFormAvroConverter getCtlSchemaConverterForTenant(String tenantId) throw Utils.handleException(cause); } } - + private SchemaFormAvroConverter getCtlSchemaConverterForApplication(String tenantId, String applicationId) throws KaaAdminServiceException { try { return createSchemaConverterFromCtlTypes(controlService.getAvailableCTLSchemaVersionsForApplication(tenantId, applicationId)); @@ -3631,7 +3661,7 @@ private SchemaFormAvroConverter getCtlSchemaConverterForApplication(String tenan throw Utils.handleException(cause); } } - + private SchemaFormAvroConverter createSchemaConverterFromCtlTypes(final Map> ctlTypes) throws KaaAdminServiceException { try { CtlSource ctlSource = new CtlSource() { @@ -3656,14 +3686,14 @@ public FileData exportCTLSchema(String fqn, int version, String applicationId, C Utils.checkNotNull(schemaFound); checkCTLSchemaReadScope(schemaFound.getMetaInfo().getTenantId(), schemaFound.getMetaInfo().getApplicationId()); switch (method) { - case SHALLOW: - return controlService.exportCTLSchemaShallow(schemaFound); - case FLAT: - return controlService.exportCTLSchemaFlat(schemaFound); - case DEEP: - return controlService.exportCTLSchemaDeep(schemaFound); - default: - throw new IllegalArgumentException("The export method " + method.name() + " is not currently supported!"); + case SHALLOW: + return controlService.exportCTLSchemaShallow(schemaFound); + case FLAT: + return controlService.exportCTLSchemaFlat(schemaFound); + case DEEP: + return controlService.exportCTLSchemaDeep(schemaFound); + default: + throw new IllegalArgumentException("The export method " + method.name() + " is not currently supported!"); } } catch (Exception cause) { throw Utils.handleException(cause); @@ -3681,7 +3711,7 @@ public FileData exportCTLSchemaByAppToken(String fqn, int version, String applic @Override public String prepareCTLSchemaExport(String ctlSchemaId, - CTLSchemaExportMethod method) throws KaaAdminServiceException { + CTLSchemaExportMethod method) throws KaaAdminServiceException { checkAuthority(KaaAuthorityDto.values()); try { CTLSchemaDto schemaFound = controlService.getCTLSchemaById(ctlSchemaId); @@ -3761,7 +3791,7 @@ public void revokeCredentials(String applicationToken, String credentialsId) thr throw Utils.handleException(cause); } } - + @Override public void onCredentialsRevoked(String applicationToken, String credentialsId) throws KaaAdminServiceException { @@ -3774,7 +3804,7 @@ public void onCredentialsRevoked(String applicationToken, String credentialsId) this.controlService.onCredentailsRevoked(applicationId, credentials.get().getId()); } catch (Exception cause) { throw Utils.handleException(cause); - } + } } @Override @@ -3783,7 +3813,7 @@ public void provisionRegistration( String credentialsId, Integer serverProfileVersion, String serverProfileBody) - throws KaaAdminServiceException { + throws KaaAdminServiceException { this.checkAuthority(KaaAuthorityDto.TENANT_ADMIN); try { String applicationId = checkApplicationToken(applicationToken); diff --git a/server/node/src/main/java/org/kaaproject/kaa/server/admin/shared/services/KaaAdminService.java b/server/node/src/main/java/org/kaaproject/kaa/server/admin/shared/services/KaaAdminService.java index 6297d0204c..ad99ae1a40 100644 --- a/server/node/src/main/java/org/kaaproject/kaa/server/admin/shared/services/KaaAdminService.java +++ b/server/node/src/main/java/org/kaaproject/kaa/server/admin/shared/services/KaaAdminService.java @@ -409,7 +409,7 @@ public interface KaaAdminService extends RemoteService { boolean checkFqnExistsWithAppToken(String fqn, String tenantId, String applicationToken) throws KaaAdminServiceException; - CTLSchemaMetaInfoDto updateCTLSchemaMetaInfoScope(CTLSchemaMetaInfoDto ctlSchemaMetaInfo) throws KaaAdminServiceException; + CTLSchemaMetaInfoDto promoteScopeToTenant(CTLSchemaMetaInfoDto ctlSchemaMetaInfo) throws KaaAdminServiceException; List getSystemLevelCTLSchemas() throws KaaAdminServiceException; diff --git a/server/node/src/test/java/org/kaaproject/kaa/server/control/ControlServerCTLSchemaIT.java b/server/node/src/test/java/org/kaaproject/kaa/server/control/ControlServerCTLSchemaIT.java index 3938228394..1aa1f087a7 100644 --- a/server/node/src/test/java/org/kaaproject/kaa/server/control/ControlServerCTLSchemaIT.java +++ b/server/node/src/test/java/org/kaaproject/kaa/server/control/ControlServerCTLSchemaIT.java @@ -31,10 +31,8 @@ import org.springframework.http.HttpStatus; import org.springframework.web.client.HttpClientErrorException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.lang.reflect.Array; +import java.util.*; /** * @author Bohdan Khablenko @@ -428,8 +426,8 @@ public void updateCTLSchemaScopeTest() throws Exception { this.loginTenantDeveloper(tenantDeveloperUser); CTLSchemaDto saved = this.createCTLSchema(this.ctlRandomFieldType(), CTL_DEFAULT_NAMESPACE, 1, tenantDeveloperDto.getTenantId(), application.getId(), null, null); CTLSchemaMetaInfoDto metaInfo = saved.getMetaInfo(); - metaInfo.setApplicationId(null); - CTLSchemaMetaInfoDto updatedMetaInfo = client.updateCTLSchemaMetaInfoScope(metaInfo); + metaInfo.setVersions(Arrays.asList(1)); + CTLSchemaMetaInfoDto updatedMetaInfo = client.promoteScopeToTenant(metaInfo); Assert.assertNull(updatedMetaInfo.getApplicationId()); Assert.assertNotNull(updatedMetaInfo.getTenantId()); Assert.assertEquals(tenantDeveloperDto.getTenantId(), updatedMetaInfo.getTenantId()); @@ -437,46 +435,50 @@ public void updateCTLSchemaScopeTest() throws Exception { } @Test - public void updateCTLSchemaScopeForbiddenTest() throws Exception { + public void promoteScopeToTenantForbiddenTest() throws Exception { ApplicationDto application = createApplication(tenantAdminDto); this.loginTenantDeveloper(tenantDeveloperUser); CTLSchemaDto saved = this.createCTLSchema(this.ctlRandomFieldType(), CTL_DEFAULT_NAMESPACE, 1, tenantDeveloperDto.getTenantId(), application.getId(), null, null); final CTLSchemaMetaInfoDto metaInfo = saved.getMetaInfo(); - metaInfo.setApplicationId(null); + + metaInfo.setVersions(Arrays.asList(1)); metaInfo.setTenantId(null); + this.checkForbidden(new TestRestCall() { @Override public void executeRestCall() throws Exception { - client.updateCTLSchemaMetaInfoScope(metaInfo); + client.promoteScopeToTenant(metaInfo); } }); + saved = this.createCTLSchema(this.ctlRandomFieldType(), CTL_DEFAULT_NAMESPACE, 1, tenantDeveloperDto.getTenantId(), null, null, null); final CTLSchemaMetaInfoDto metaInfo2 = saved.getMetaInfo(); + + metaInfo2.setVersions(Arrays.asList(1)); Assert.assertNull(metaInfo2.getApplicationId()); metaInfo2.setApplicationId(application.getId()); + this.checkRestErrorStatusCode(new TestRestCall() { @Override public void executeRestCall() throws Exception { - client.updateCTLSchemaMetaInfoScope(metaInfo2); + client.promoteScopeToTenant(metaInfo2); } - }, HttpStatus.INTERNAL_SERVER_ERROR); + }, HttpStatus.NOT_FOUND); this.loginTenantAdmin(tenantAdminUser); saved = this.createCTLSchema(this.ctlRandomFieldType(), CTL_DEFAULT_NAMESPACE, 1, tenantAdminDto.getTenantId(), null, null, null); final CTLSchemaMetaInfoDto metaInfo3 = saved.getMetaInfo(); + + metaInfo3.setVersions(Arrays.asList(1)); Assert.assertNull(metaInfo3.getApplicationId()); metaInfo3.setApplicationId(application.getId()); + this.checkForbidden(new TestRestCall() { @Override public void executeRestCall() throws Exception { - client.updateCTLSchemaMetaInfoScope(metaInfo3); + client.promoteScopeToTenant(metaInfo3); } }); - - //Assert.assertNull(updatedMetaInfo.getApplicationId()); - //Assert.assertNotNull(updatedMetaInfo.getTenantId()); - //Assert.assertEquals(tenantDeveloperDto.getTenantId(), updatedMetaInfo.getTenantId()); - //Assert.assertEquals(CTLSchemaScopeDto.TENANT, updatedMetaInfo.getScope()); } }