diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/Base64File.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/Base64File.java new file mode 100644 index 0000000000..67ca3429f5 --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/Base64File.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.common; + +public class Base64File { + + private String name; + private String base64String; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getBase64String() { + return base64String; + } + + public void setBase64String(String base64String) { + this.base64String = base64String; + } +} diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/FileDataHolder.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/FileDataHolder.java new file mode 100644 index 0000000000..1a3d4cfd8c --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/FileDataHolder.java @@ -0,0 +1,50 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.common; + +import java.io.InputStream; + +public class FileDataHolder { + + private String name; + private InputStream file; + + public FileDataHolder(String name, InputStream file) { + this.name = name; + this.file = file; + } + public FileDataHolder() { + + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public InputStream getFile() { + return file; + } + + public void setFile(InputStream file) { + this.file = file; + } +} diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/IdentityServerResponse.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/IdentityServerResponse.java new file mode 100644 index 0000000000..69f33f7c66 --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/IdentityServerResponse.java @@ -0,0 +1,102 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.common; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class IdentityServerResponse { + private int id; + private String providerName; + private String name; + private String description; + private String url; + private String serviceProviderAppsUrl; + private String username; + private List> apiParamList; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getProviderName() { + return providerName; + } + + public void setProviderName(String providerName) { + this.providerName = providerName; + } + + public String getServiceProviderAppsUrl() { + return serviceProviderAppsUrl; + } + + public void setServiceProviderAppsUrl(String serviceProviderAppsUrl) { + this.serviceProviderAppsUrl = serviceProviderAppsUrl; + } + + public List> getApiParamList() { + return apiParamList; + } + + public void setApiParamList(Map apiParams) { + this.apiParamList = apiParams.entrySet().stream().map(param -> { + Map paramMap = new HashMap<>(); + paramMap.put(param.getKey(), param.getValue()); + return paramMap; + }).collect(Collectors.toList()); + } +} diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/SPApplication.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/SPApplication.java new file mode 100644 index 0000000000..da4b094bfc --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/SPApplication.java @@ -0,0 +1,98 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.common; + + +import io.entgra.application.mgt.common.response.Application; + +import java.util.List; + +public class SPApplication { + private String id; + private String name; + private String description; + private String image; + private String accessUrl; + private String access; + private String self; + private List existingApplications; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } + + public String getAccessUrl() { + return accessUrl; + } + + public void setAccessUrl(String accessUrl) { + this.accessUrl = accessUrl; + } + + public String getAccess() { + return access; + } + + public void setAccess(String access) { + this.access = access; + } + + public String getSelf() { + return self; + } + + public void setSelf(String self) { + this.self = self; + } + + public List getExistingApplications() { + return existingApplications; + } + + public void setExistingApplications(List existingApplications) { + this.existingApplications = existingApplications; + } +} diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/SPApplicationListResponse.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/SPApplicationListResponse.java new file mode 100644 index 0000000000..bbe1f5da7f --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/SPApplicationListResponse.java @@ -0,0 +1,59 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.common; + +import java.util.List; + +public class SPApplicationListResponse { + private int totalResults; + private int startIndex; + private int count; + private List applications; + + public int getTotalResults() { + return totalResults; + } + + public void setTotalResults(int totalResults) { + this.totalResults = totalResults; + } + + public int getStartIndex() { + return startIndex; + } + + public void setStartIndex(int startIndex) { + this.startIndex = startIndex; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + public List getApplications() { + return applications; + } + + public void setApplications(List applications) { + this.applications = applications; + } +} diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/dto/IdentityServerDTO.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/dto/IdentityServerDTO.java new file mode 100644 index 0000000000..bf1ed88fef --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/dto/IdentityServerDTO.java @@ -0,0 +1,112 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.common.dto; + +import com.google.gson.Gson; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class IdentityServerDTO { + + private int id; + private String providerName; + private String name; + private String description; + private String url; + private String username; + private String password; + private Map apiParams; + + public IdentityServerDTO() { + this.apiParams = new HashMap<>(); + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getProviderName() { + return providerName; + } + + public void setProviderName(String providerName) { + this.providerName = providerName; + } + + public String constructApiParamsJsonString() { + return new Gson().toJson(apiParams); + } + + public Set getApiParamKeys() { + return apiParams.keySet(); + } + + public Map getApiParams() { + return apiParams; + } + + public void setApiParams(Map apiParams) { + this.apiParams = apiParams; + } +} diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/dto/IdentityServiceProviderDTO.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/dto/IdentityServiceProviderDTO.java new file mode 100644 index 0000000000..d9e8e2ac60 --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/dto/IdentityServiceProviderDTO.java @@ -0,0 +1,41 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.common.dto; + +import java.util.List; + +public class IdentityServiceProviderDTO { + private String name; + private List requiredApiParams; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getRequiredApiParams() { + return requiredApiParams; + } + + public void setRequiredApiParams(List requiredApiParams) { + this.requiredApiParams = requiredApiParams; + } +} diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/exception/IdentityServerManagementException.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/exception/IdentityServerManagementException.java new file mode 100644 index 0000000000..f2168ec32b --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/exception/IdentityServerManagementException.java @@ -0,0 +1,34 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.common.exception; + +/** + * Exception that will be thrown if any error occurs while calling identity server services . + */ +public class IdentityServerManagementException extends ApplicationManagementException { + + public IdentityServerManagementException(String message, Throwable throwable) { + super(message, throwable); + setMessage(message); + } + + public IdentityServerManagementException(String message) { + super(message); + setMessage(message); + } +} diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/services/ApplicationManager.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/services/ApplicationManager.java index 88fc2a87f2..82e78096b1 100644 --- a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/services/ApplicationManager.java +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/services/ApplicationManager.java @@ -16,6 +16,10 @@ */ package io.entgra.application.mgt.common.services; +import io.entgra.application.mgt.common.ApplicationType; +import io.entgra.application.mgt.common.Base64File; +import io.entgra.application.mgt.common.dto.ApplicationDTO; +import io.entgra.application.mgt.common.exception.ResourceManagementException; import org.apache.cxf.jaxrs.ext.multipart.Attachment; import io.entgra.application.mgt.common.ApplicationArtifact; import io.entgra.application.mgt.common.LifecycleChanger; @@ -30,15 +34,10 @@ import io.entgra.application.mgt.common.response.ApplicationRelease; import io.entgra.application.mgt.common.response.Category; import io.entgra.application.mgt.common.response.Tag; import io.entgra.application.mgt.common.wrapper.CustomAppReleaseWrapper; -import io.entgra.application.mgt.common.wrapper.CustomAppWrapper; import io.entgra.application.mgt.common.wrapper.EntAppReleaseWrapper; import io.entgra.application.mgt.common.wrapper.ApplicationUpdateWrapper; -import io.entgra.application.mgt.common.wrapper.ApplicationWrapper; import io.entgra.application.mgt.common.wrapper.PublicAppReleaseWrapper; -import io.entgra.application.mgt.common.wrapper.PublicAppWrapper; import io.entgra.application.mgt.common.wrapper.WebAppReleaseWrapper; -import io.entgra.application.mgt.common.wrapper.WebAppWrapper; - import java.util.List; /** @@ -46,21 +45,95 @@ import java.util.List; */ public interface ApplicationManager { - /*** - * The method is responsible to add new application into entgra App Manager. + /** + * This method is responsible for handling application creation * - * @param applicationWrapper Application that need to be created. - * @param applicationArtifact contains artifact data. i.e image name and stream, icon name and stream etc. - * @param isPublished checks if application should be published - * @return {@link Application} - * @throws ApplicationManagementException Catch all other throwing exceptions and throw {@link ApplicationManagementException} + * @param appId application id of the application to which the release should be created + * @param releaseWrapper {@link EntAppReleaseWrapper} of the release to be created + * @param isPublished If the app should be added in PUBLISHED state instead of initial state + * @return Created application release bean + * @throws ApplicationManagementException if any error occurred while creating the application */ - Application createEntApp(ApplicationWrapper applicationWrapper, ApplicationArtifact applicationArtifact, boolean isPublished) + ApplicationRelease createEntAppRelease(int appId, EntAppReleaseWrapper releaseWrapper, boolean isPublished) throws ApplicationManagementException; - Application createWebClip(WebAppWrapper webAppWrapper, ApplicationArtifact applicationArtifact, boolean isPublished) - throws ApplicationManagementException; + /** + * This method is responsible for handling application creation + * + * @param appId application id of the application to which the release should be created + * @param releaseWrapper {@link WebAppReleaseWrapper} of the release to be created + * @param isPublished If the app should be added in PUBLISHED state instead of initial state + * @return Created application release bean + * @throws ApplicationManagementException if any error occurred while creating the application + */ + ApplicationRelease createWebAppRelease(int appId, WebAppReleaseWrapper releaseWrapper, boolean isPublished) + throws ApplicationManagementException, ResourceManagementException; + + /** + * This method is responsible for handling application creation + * + * @param appId application id of the application to which the release should be created + * @param releaseWrapper {@link PublicAppReleaseWrapper} of the release to be created + * @param isPublished If the app should be added in PUBLISHED state instead of initial state + * @return Created application release bean + * @throws ApplicationManagementException if any error occurred while creating the application + */ + ApplicationRelease createPubAppRelease(int appId, PublicAppReleaseWrapper releaseWrapper, boolean isPublished) + throws ApplicationManagementException, ResourceManagementException; + + /** + * This method is responsible for handling application creation + * + * @param appId application id of the application to which the release should be created + * @param releaseWrapper {@link CustomAppReleaseWrapper} of the release to be created + * @param isPublished If the app should be added in PUBLISHED state instead of initial state + * @return Created application release bean + * @throws ApplicationManagementException if any error occurred while creating the application + */ + ApplicationRelease createCustomAppRelease(int appId, CustomAppReleaseWrapper releaseWrapper, boolean isPublished) + throws ResourceManagementException, ApplicationManagementException; + /** + * Checks if release is available for a given application wrapper, and if exists it uploads + * the artifacts of the release + * + * @param app Application wrapper bean of the application + * @param Application Wrapper class + * @return constructed ApplicationDTO after uploading the release artifacts if exist + * @throws ApplicationManagementException if any error occurred while uploading release artifacts + */ + ApplicationDTO uploadReleaseArtifactIfExist(T app) throws ApplicationManagementException; + + /** + * Check if public app release packageName is valid (I.E invalid if packageName already exists) + * + * @param packageName name of the application release package + * @throws ApplicationManagementException if package name is invalid + */ + void validatePublicAppReleasePackageName(String packageName) throws ApplicationManagementException; + + /** + * This method is responsible to add application data into APPM database. However, before call this method it is + * required to do the validation of request and check the existence of application releaseDTO. + * + * @param applicationDTO Application DTO object. + * @param isPublished Wether the app should be added in PUBLISHED state instead of initial state + * @return {@link Application} + * @throws ApplicationManagementException which throws if error occurs while during application management. + */ + Application addAppDataIntoDB(ApplicationDTO applicationDTO, boolean isPublished) throws + ApplicationManagementException; + + /** + * This method is responsible for handling application creation + * + * @param app Application wrapper object which depends on the application type + * @param isPublished If the app should be created in PUBLISHED state + * @param Application wrapper class which depends on the application type + * @return Created application bean + * @throws ApplicationManagementException if any error occurred while creating the application + */ + Application createApplication(T app, boolean isPublished) throws ApplicationManagementException; /** * Add an application to favourites * @param appId id of the application @@ -82,12 +155,6 @@ public interface ApplicationManager { */ boolean isFavouriteApp(int appId) throws ApplicationManagementException; - Application createPublicApp(PublicAppWrapper publicAppWrapper, ApplicationArtifact applicationArtifact, boolean isPublished) - throws ApplicationManagementException; - - Application createCustomApp(CustomAppWrapper customAppWrapper, ApplicationArtifact applicationArtifact, boolean isPublished) - throws ApplicationManagementException; - /** * Check the existence of an application for given application name and the device type. * @@ -136,6 +203,15 @@ public interface ApplicationManager { ApplicationList getFavouriteApplications(Filter filter) throws ApplicationManagementException; + /** + * Use to delete application artifact files (For example this is useful to delete application release artifacts + * (I.E screenshots) when an application is deleted) + * + * @param directoryPaths directory paths that contains release artifacts (I.E screenshots) + * @throws ApplicationManagementException if error occurred while deleting artifacts + */ + void deleteApplicationArtifacts(List directoryPaths) throws ApplicationManagementException; + /** * To get the applications based on the search filter. * @@ -145,6 +221,24 @@ public interface ApplicationManager { */ ApplicationList getApplications(Filter filter) throws ApplicationManagementException; + /** + * + * @param applicationReleaseDTOs application releases of the application + * @return if application is hide-able + * @throws ApplicationManagementException if any error occurred while checking if hide-able + */ + boolean isHideableApp(List applicationReleaseDTOs) + throws ApplicationManagementException; + + /** + * + * @param applicationReleaseDTOs application releases of the application + * @return if application is deletable + * @throws ApplicationManagementException if any error occurred while checking if deletable + */ + boolean isDeletableApp(List applicationReleaseDTOs) + throws ApplicationManagementException; + /** * To get list of applications that application releases has given package names. * @@ -155,6 +249,28 @@ public interface ApplicationManager { */ List getApplications(List packageNames) throws ApplicationManagementException; + /** + * To create an application release for an ApplicationDTO. + * + * @param applicationDTO ApplicationDTO of the release + * @param applicationReleaseDTO ApplicatonRelease that need to be be created. + * @param type {@link ApplicationType} + * @param isPublished if the app should be added in PUBLISHED state instead of initial state + * @return the unique id of the application release, if the application release succeeded else -1 + */ + ApplicationRelease createRelease(ApplicationDTO applicationDTO, ApplicationReleaseDTO applicationReleaseDTO, + ApplicationType type, boolean isPublished) + throws ApplicationManagementException; + + /** + * Get application and all application releases associated to the application for the given application Id + * + * @param applicationId Application Id + * @return {@link ApplicationDTO} + * @throws ApplicationManagementException if error occurred application data from the database. + */ + ApplicationDTO getApplication(int applicationId) throws ApplicationManagementException; + /** * To get the Application for given Id. * @@ -225,7 +341,6 @@ public interface ApplicationManager { void updateApplicationImageArtifact(String uuid, ApplicationArtifact applicationArtifact) throws ApplicationManagementException; - /** * To update release images. * @@ -238,17 +353,7 @@ public interface ApplicationManager { ApplicationArtifact applicationArtifact) throws ApplicationManagementException; /** - * To create an application release for an ApplicationDTO. - * - * @param applicationId ID of the ApplicationDTO - * @param entAppReleaseWrapper ApplicatonRelease that need to be be created. - * @param isPublished checks if application should be published - * @return the unique id of the application release, if the application release succeeded else -1 - */ - ApplicationRelease createEntAppRelease(int applicationId, EntAppReleaseWrapper entAppReleaseWrapper, - ApplicationArtifact applicationArtifact, boolean isPublished) throws ApplicationManagementException; - - /*** + * Use to update existing enterprise app release * * @param releaseUuid UUID of the application release. * @param entAppReleaseWrapper {@link ApplicationReleaseDTO} @@ -256,30 +361,100 @@ public interface ApplicationManager { * @return If the application release is updated correctly True returns, otherwise retuen False */ ApplicationRelease updateEntAppRelease(String releaseUuid, EntAppReleaseWrapper entAppReleaseWrapper, - ApplicationArtifact applicationArtifact) throws ApplicationManagementException; + ApplicationArtifact applicationArtifact) throws ApplicationManagementException; + + /** + * Use to update existing public app release + * + * @param releaseUuid UUID of the application release. + * @param publicAppReleaseWrapper {@link ApplicationReleaseDTO} + * @param applicationArtifact {@link ApplicationArtifact} + * @return If the application release is updated correctly True returns, otherwise retuen False + */ ApplicationRelease updatePubAppRelease(String releaseUuid, PublicAppReleaseWrapper publicAppReleaseWrapper, - ApplicationArtifact applicationArtifact) throws ApplicationManagementException; + ApplicationArtifact applicationArtifact) throws ApplicationManagementException; + /** + * Use to update existing web app release + * + * @param releaseUuid UUID of the application release. + * @param webAppReleaseWrapper {@link ApplicationReleaseDTO} + * @param applicationArtifact {@link ApplicationArtifact} + * @return If the application release is updated correctly True returns, otherwise retuen False + */ ApplicationRelease updateWebAppRelease(String releaseUuid, WebAppReleaseWrapper webAppReleaseWrapper, - ApplicationArtifact applicationArtifact) throws ApplicationManagementException; + ApplicationArtifact applicationArtifact) throws ApplicationManagementException; + /** + * Use to update existing custom app release + * + * @param releaseUuid UUID of the application release. + * @param customAppReleaseWrapper {@link ApplicationReleaseDTO} + * @param applicationArtifact {@link ApplicationArtifact} + * @return If the application release is updated correctly True returns, otherwise retuen False + */ ApplicationRelease updateCustomAppRelease(String releaseUuid, CustomAppReleaseWrapper customAppReleaseWrapper, - ApplicationArtifact applicationArtifact) throws ApplicationManagementException; + ApplicationArtifact applicationArtifact) throws ApplicationManagementException; - /*** + /** * To validate the application creating request * */ - void validateAppCreatingRequest(T param) throws ApplicationManagementException; + void validateAppCreatingRequest(T param) throws ApplicationManagementException, RequestValidatingException; - /*** + /** * * @throws ApplicationManagementException throws if payload does not satisfy requirements. */ - void validateReleaseCreatingRequest(T param, String deviceType) throws ApplicationManagementException; + void validateReleaseCreatingRequest(T releases, String deviceType) throws ApplicationManagementException; + + /** + * Validate enterprise application release + * + */ + void validateEntAppReleaseCreatingRequest(EntAppReleaseWrapper releaseWrapper, String deviceType) + throws RequestValidatingException, ApplicationManagementException; + + /** + * Validate custom application release + * + */ + void validateCustomAppReleaseCreatingRequest(CustomAppReleaseWrapper releaseWrapper, String deviceType) + throws RequestValidatingException, ApplicationManagementException; + + /** + * Validate web application release + * + */ + void validateWebAppReleaseCreatingRequest(WebAppReleaseWrapper releaseWrapper) + throws RequestValidatingException, ApplicationManagementException; + + /** + * Validate public application release + * + */ + void validatePublicAppReleaseCreatingRequest(PublicAppReleaseWrapper releaseWrapper, String deviceType) + throws RequestValidatingException, ApplicationManagementException; - /*** + /** + * Validates image files of the application release + * + * @param iconFile icon of the application release + * @param screenshots screenshots of the application release + * @throws RequestValidatingException if any image is invalid + */ + void validateImageArtifacts(Base64File iconFile, List screenshots) throws RequestValidatingException; + + /** + * Validates any base64 files, for example a base64file may an empty file name which is invalid + * + * @param file Base64 File to be validated + * @throws RequestValidatingException if the file is invalid + */ + void validateBase64File(Base64File file) throws RequestValidatingException; + + /*** * * @param iconFile Icon file for the application. * @param bannerFile Banner file for the application. @@ -289,6 +464,14 @@ public interface ApplicationManager { void validateImageArtifacts(Attachment iconFile, Attachment bannerFile, List attachmentList) throws RequestValidatingException; + /** + * Validates binary file of the application release + * + * @param binaryFile binary file of the application release + * @throws RequestValidatingException if binary file is invalid + */ + void validateBinaryArtifact(Base64File binaryFile) throws RequestValidatingException; + void validateBinaryArtifact(Attachment binaryFile) throws RequestValidatingException; void addApplicationCategories(List categories) throws ApplicationManagementException; @@ -331,14 +514,13 @@ public interface ApplicationManager { void updateSubsStatus(int deviceId, int operationId, String status) throws ApplicationManagementException; - - /** - * Get plist content to download and install the application. - * - * @param uuid Release UUID of the application. - * @return plist string - * @throws ApplicationManagementException Application management exception - */ + /** + * Get plist content to download and install the application. + * + * @param uuid Release UUID of the application. + * @return plist string + * @throws ApplicationManagementException Application management exception + */ String getPlistArtifact(String uuid) throws ApplicationManagementException; List getReleaseByPackageNames(List packageIds) throws ApplicationManagementException; diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/services/SPApplicationManager.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/services/SPApplicationManager.java new file mode 100644 index 0000000000..bd4b1dd015 --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/services/SPApplicationManager.java @@ -0,0 +1,165 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.common.services; + +import io.entgra.application.mgt.common.IdentityServerResponse; +import io.entgra.application.mgt.common.SPApplicationListResponse; +import io.entgra.application.mgt.common.dto.IdentityServerDTO; +import io.entgra.application.mgt.common.dto.IdentityServiceProviderDTO; +import io.entgra.application.mgt.common.exception.ApplicationManagementException; +import io.entgra.application.mgt.common.exception.RequestValidatingException; +import io.entgra.application.mgt.common.response.Application; +import java.util.List; + +public interface SPApplicationManager { + + /** + * Removes consumer application from service provider + * + * @param identityServerId of the service provider + * @param spUID uid of the service provider + * @param appIds List of application ids to be removed + * @throws ApplicationManagementException if errors while removing appIds from service provider + */ + void detachSPApplications(int identityServerId, String spUID, List appIds) throws ApplicationManagementException; + + /** + * Maps consumer applications to service provider + * + * @param identityServerId of the service provider + * @param spUID uid of the service provider + * @param appIds List of application ids to be mapped + * @throws ApplicationManagementException if errors while mapping appIds to service provider + */ + void attachSPApplications(int identityServerId, String spUID, List appIds) throws ApplicationManagementException; + + /** + * + * @param identityServerId of the identity server that is to be retrieved + * @return Identity server for the given ID + * @throws ApplicationManagementException if error occurred while getting identity server + */ + IdentityServerResponse getIdentityServerResponse(int identityServerId) throws ApplicationManagementException; + + /** + * + * @return Available identity servers + * @throws ApplicationManagementException if error occurred while getting identity servers + */ + List getIdentityServers() throws ApplicationManagementException; + + /** + * Create a new Identity Server + * + * @return {@link IdentityServerResponse} + * @throws ApplicationManagementException if error occurred while getting identity servers + */ + IdentityServerResponse createIdentityServer(IdentityServerDTO identityServerDTO) throws ApplicationManagementException; + + /** + * Update existing Identity Server + * + * @param id of the identity server to be updated + * @param updateIdentityServerDTO identity server dto bean with updated fields + * @throws ApplicationManagementException if error occurred while getting identity servers + */ + IdentityServerResponse updateIdentityServer(IdentityServerDTO updateIdentityServerDTO, int id) throws ApplicationManagementException; + + /** + * Delete Identity Server + * + * @param id of the identity server to be deleted + * @throws ApplicationManagementException if error occurred while getting identity servers + */ + void deleteIdentityServer(int id) throws ApplicationManagementException; + + /** + * Check if Identity Server exists with the same name + * + * @param name of the identity server + * @return if name already exists for identity server + */ + boolean isIdentityServerNameExist(String name) throws ApplicationManagementException; + + /** + * Check if Identity Server exists with the same url + * + * @param url of the identity server + * @return if url already exists for identity server + */ + boolean isIdentityServerUrlExist(String url) throws ApplicationManagementException; + + /** + * Retrieve service provider apps from identity server + * + * @param identityServerId Id of the identity server + * @return {@link SPApplicationListResponse} + * @throws ApplicationManagementException if error while retrieving sp applications + */ + SPApplicationListResponse retrieveSPApplicationFromIdentityServer(int identityServerId, Integer offset, Integer limit) + throws ApplicationManagementException; + + /** + * + * @param identityServerId of the service provider + * @param spUID uid of the service provider + * @return Applications that are mapped to given service provider uid and identity server id + * @throws ApplicationManagementException + */ + List getSPApplications(int identityServerId, String spUID) throws ApplicationManagementException; + + /** + * This method is responsible for creating a new application and mapping it the given service provider uid + * and identity server id + * + * @param app Application wrapper of the application that should be created + * @param identityServerId id of the identity server to which the created application should be mapped + * @param spId uid of the service provder to which the created application should be mapped + * @param Application wrapper class which depends on application type (PUBLIC, ENTERPRISE & etc) + * @param isPublished If the app should be added in PUBLISHED state instead of initial state + * @return Application bean of the created application + * @throws ApplicationManagementException if errors while creating and mapping the application + * @throws RequestValidatingException if app contains any invalid payload + */ + Application createSPApplication(T app, int identityServerId, String spId, boolean isPublished) throws ApplicationManagementException, RequestValidatingException; + + /** + * Validates application ids of the applications that should be attached + * + * @param appIds application ids to be validated + * @throws ApplicationManagementException if invalid service provider, identity server Id or app Ids provided + */ + void validateAttachAppsRequest(int identityServerId, String serviceProviderId, List appIds) throws ApplicationManagementException; + + /** + * Validates application ids of the applications that should be detached + * + * @param identityServerId id of identity server + * @param spId uid of service provider from which applications should be detached + * @param appIds applications ids to be detached + * @throws ApplicationManagementException + */ + void validateDetachAppsRequest(int identityServerId, String spId, List appIds) throws ApplicationManagementException; + + /** + * Get available identity service providers + * + * @return list of available service providers' names + */ + List getIdentityServiceProviders() throws ApplicationManagementException; +} diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/ApplicationWrapper.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/ApplicationWrapper.java index f109b7b78d..82e52cdebe 100644 --- a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/ApplicationWrapper.java +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/ApplicationWrapper.java @@ -20,6 +20,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import javax.validation.constraints.NotNull; +import java.util.ArrayList; import java.util.List; @ApiModel(value = "ApplicationWrapper", description = "ApplicationWrapper represents the an ApplicationDTO in ApplicationDTO Store") @@ -80,7 +81,7 @@ public class ApplicationWrapper { value = "List of application releases", required = true) @NotNull - private List entAppReleaseWrappers; + private List entAppReleaseWrappers = new ArrayList<>(); public String getName() { diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/CustomAppReleaseWrapper.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/CustomAppReleaseWrapper.java index eb30c7e912..566e67d5d5 100644 --- a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/CustomAppReleaseWrapper.java +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/CustomAppReleaseWrapper.java @@ -16,10 +16,12 @@ */ package io.entgra.application.mgt.common.wrapper; +import io.entgra.application.mgt.common.Base64File; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import javax.validation.constraints.NotNull; +import java.util.List; @ApiModel(value = "CustomAppReleaseWrapper", description = "This class holds the details when releasing an Custom app release to application store") public class CustomAppReleaseWrapper { @@ -65,6 +67,22 @@ public class CustomAppReleaseWrapper { @NotNull private String packageName; + @ApiModelProperty(name = "screenshots", + value = "screenshots of the application") + private List screenshots; + + @ApiModelProperty(name = "icon", + value = "icon of the application") + private Base64File icon; + + @ApiModelProperty(name = "binaryFile", + value = "binary file of the application") + private Base64File binaryFile; + + @ApiModelProperty(name = "icon", + value = "banner of the application") + private Base64File banner; + public String getReleaseType() { return releaseType; } @@ -122,4 +140,36 @@ public class CustomAppReleaseWrapper { public void setPackageName(String packageName) { this.packageName = packageName; } + + public List getScreenshots() { + return screenshots; + } + + public void setScreenshots(List screenshots) { + this.screenshots = screenshots; + } + + public Base64File getIcon() { + return icon; + } + + public void setIcon(Base64File icon) { + this.icon = icon; + } + + public Base64File getBinaryFile() { + return binaryFile; + } + + public void setBinaryFile(Base64File binaryFile) { + this.binaryFile = binaryFile; + } + + public Base64File getBanner() { + return banner; + } + + public void setBanner(Base64File banner) { + this.banner = banner; + } } diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/CustomAppWrapper.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/CustomAppWrapper.java index 4c0a392d89..b874a83661 100644 --- a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/CustomAppWrapper.java +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/CustomAppWrapper.java @@ -20,6 +20,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import javax.validation.constraints.NotNull; +import java.util.ArrayList; import java.util.List; @ApiModel(value = "CustomAppWrapper", description = "CustomAppWrapper represents an Application used to install in IoT devices") @@ -78,7 +79,7 @@ public class CustomAppWrapper { value = "List of custom app releases", required = true) @NotNull - private List customAppReleaseWrappers; + private List customAppReleaseWrappers = new ArrayList<>(); public String getName() { return name; diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/EntAppReleaseWrapper.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/EntAppReleaseWrapper.java index 4d39506e9b..6fdb22dc80 100644 --- a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/EntAppReleaseWrapper.java +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/EntAppReleaseWrapper.java @@ -16,10 +16,12 @@ */ package io.entgra.application.mgt.common.wrapper; +import io.entgra.application.mgt.common.Base64File; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import javax.validation.constraints.NotNull; +import java.util.List; @ApiModel(value = "ApplicationReleaseDTO", description = "This class holds the details when releasing an ApplicationDTO to application store") public class EntAppReleaseWrapper { @@ -68,6 +70,22 @@ public class EntAppReleaseWrapper { value = "PackageName of the application installer specifically for windows") private String packageName; + @ApiModelProperty(name = "screenshots", + value = "screenshots of the application") + private List screenshots; + + @ApiModelProperty(name = "icon", + value = "icon of the application") + private Base64File icon; + + @ApiModelProperty(name = "binaryFile", + value = "binary file of the application") + private Base64File binaryFile; + + @ApiModelProperty(name = "icon", + value = "banner of the application") + private Base64File banner; + public String getReleaseType() { return releaseType; } @@ -123,4 +141,36 @@ public class EntAppReleaseWrapper { public void setPackageName(String packageName) { this.packageName = packageName; } + + public List getScreenshots() { + return screenshots; + } + + public void setScreenshots(List screenshots) { + this.screenshots = screenshots; + } + + public Base64File getIcon() { + return icon; + } + + public void setIcon(Base64File icon) { + this.icon = icon; + } + + public Base64File getBinaryFile() { + return binaryFile; + } + + public void setBinaryFile(Base64File binaryFile) { + this.binaryFile = binaryFile; + } + + public Base64File getBanner() { + return banner; + } + + public void setBanner(Base64File banner) { + this.banner = banner; + } } diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/PublicAppReleaseWrapper.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/PublicAppReleaseWrapper.java index 4b60e52941..3fdbdab0b4 100644 --- a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/PublicAppReleaseWrapper.java +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/PublicAppReleaseWrapper.java @@ -16,10 +16,12 @@ */ package io.entgra.application.mgt.common.wrapper; +import io.entgra.application.mgt.common.Base64File; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import javax.validation.constraints.NotNull; +import java.util.List; @ApiModel(value = "Public App Release Wrapper", description = "This class holds the details when releasing an Public App" + " Release to application store") @@ -72,6 +74,18 @@ public class PublicAppReleaseWrapper { @NotNull private String supportedOsVersions; + @ApiModelProperty(name = "screenshots", + value = "screenshots of the application") + private List screenshots; + + @ApiModelProperty(name = "icon", + value = "icon of the application") + private Base64File icon; + + @ApiModelProperty(name = "icon", + value = "banner of the application") + private Base64File banner; + public String getReleaseType() { return releaseType; } @@ -123,4 +137,28 @@ public class PublicAppReleaseWrapper { public String getSupportedOsVersions() { return supportedOsVersions; } public void setSupportedOsVersions(String supportedOsVersions) { this.supportedOsVersions = supportedOsVersions; } + + public Base64File getIcon() { + return icon; + } + + public void setIcon(Base64File icon) { + this.icon = icon; + } + + public List getScreenshots() { + return screenshots; + } + + public void setScreenshots(List screenshots) { + this.screenshots = screenshots; + } + + public Base64File getBanner() { + return banner; + } + + public void setBanner(Base64File banner) { + this.banner = banner; + } } diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/PublicAppWrapper.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/PublicAppWrapper.java index 5f653257cb..1025aa47f9 100644 --- a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/PublicAppWrapper.java +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/PublicAppWrapper.java @@ -20,6 +20,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import javax.validation.constraints.NotNull; +import java.util.ArrayList; import java.util.List; @ApiModel(value = "PublicAppWrapper", description = "PublicAppWrapper represents an Application in App Store") @@ -77,8 +78,7 @@ public class PublicAppWrapper { @ApiModelProperty(name = "applicationReleaseWrappers", value = "List of public app releases", required = true) - @NotNull - private List publicAppReleaseWrappers; + private List publicAppReleaseWrappers = new ArrayList<>(); public String getName() { return name; diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/WebAppReleaseWrapper.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/WebAppReleaseWrapper.java index 090307a32d..3d0a343c74 100644 --- a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/WebAppReleaseWrapper.java +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/WebAppReleaseWrapper.java @@ -16,10 +16,12 @@ */ package io.entgra.application.mgt.common.wrapper; +import io.entgra.application.mgt.common.Base64File; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import javax.validation.constraints.NotNull; +import java.util.List; @ApiModel(value = "ApplicationReleaseDTO", description = "This class holds the details when releasing an ApplicationDTO to application store") public class WebAppReleaseWrapper { @@ -63,6 +65,18 @@ public class WebAppReleaseWrapper { @NotNull private String url; + @ApiModelProperty(name = "screenshots", + value = "screenshots of the application") + private List screenshots; + + @ApiModelProperty(name = "icon", + value = "icon of the application") + private Base64File icon; + + @ApiModelProperty(name = "icon", + value = "banner of the application") + private Base64File banner; + public String getReleaseType() { return releaseType; } @@ -114,4 +128,28 @@ public class WebAppReleaseWrapper { public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } + + public List getScreenshots() { + return screenshots; + } + + public void setScreenshots(List screenshots) { + this.screenshots = screenshots; + } + + public Base64File getIcon() { + return icon; + } + + public void setIcon(Base64File icon) { + this.icon = icon; + } + + public Base64File getBanner() { + return banner; + } + + public void setBanner(Base64File banner) { + this.banner = banner; + } } diff --git a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/WebAppWrapper.java b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/WebAppWrapper.java index 8455f0ce67..e6f02593ad 100644 --- a/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/WebAppWrapper.java +++ b/components/application-mgt/io.entgra.application.mgt.common/src/main/java/io/entgra/application/mgt/common/wrapper/WebAppWrapper.java @@ -20,6 +20,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import javax.validation.constraints.NotNull; +import java.util.ArrayList; import java.util.List; @ApiModel(value = "WebAppWrapper", description = "WebAppWrapper represents an ApplicationDTO in ApplicationDTO Store") @@ -78,7 +79,7 @@ public class WebAppWrapper { value = "List of web clip releases", required = true) @NotNull - private List webAppReleaseWrappers; + private List webAppReleaseWrappers = new ArrayList<>(); public String getName() { return name; diff --git a/components/application-mgt/io.entgra.application.mgt.core/pom.xml b/components/application-mgt/io.entgra.application.mgt.core/pom.xml index 398c41cafc..81b0cd151d 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/pom.xml +++ b/components/application-mgt/io.entgra.application.mgt.core/pom.xml @@ -90,6 +90,7 @@ !io.entgra.application.mgt.core.internal.*, io.entgra.application.mgt.core.* + * diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/config/ConfigurationManager.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/config/ConfigurationManager.java index ab85f87bb3..f0753a0942 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/config/ConfigurationManager.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/config/ConfigurationManager.java @@ -36,8 +36,12 @@ public class ConfigurationManager { private Configuration configuration; + private IdentityServiceProviderConfiguration identityServiceProviderConfiguration; + private static String configPath; + private static String identityServerConfigPath; + private static volatile ConfigurationManager configurationManager; private ConfigurationManager() { @@ -54,12 +58,26 @@ public class ConfigurationManager { } catch (ApplicationManagementException e) { log.error(e); } + } else { + try { + configurationManager.initConfig(); + } catch (ApplicationManagementException e) { + log.error(e); + } } } } return configurationManager; } + public static synchronized void setIdentityServerConfigPathConfigLocation(String configPath) throws InvalidConfigurationException { + if (identityServerConfigPath == null) { + identityServerConfigPath = configPath; + } else { + throw new InvalidConfigurationException("Configuration path " + configPath + " is already defined"); + } + } + public static synchronized void setConfigLocation(String configPath) throws InvalidConfigurationException { if (ConfigurationManager.configPath == null) { ConfigurationManager.configPath = configPath; @@ -71,16 +89,21 @@ public class ConfigurationManager { private void initConfig() throws ApplicationManagementException { try { JAXBContext jaxbContext = JAXBContext.newInstance(Configuration.class); + JAXBContext jaxbISConfigContext = JAXBContext.newInstance(IdentityServiceProviderConfiguration.class); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + Unmarshaller identityServerConfigUnmarshaller = jaxbISConfigContext.createUnmarshaller(); if (configPath == null) { configPath = Constants.DEFAULT_CONFIG_FILE_LOCATION; } + if (identityServerConfigPath == null) { + identityServerConfigPath = Constants.DEFAULT_IDENTITY_SERVERS_CONFIG_FILE_LOCATION; + } //TODO: Add validation for the configurations this.configuration = (Configuration) unmarshaller.unmarshal(new File(configPath)); + this.identityServiceProviderConfiguration = (IdentityServiceProviderConfiguration) identityServerConfigUnmarshaller.unmarshal(new File(identityServerConfigPath)); } catch (Exception e) { log.error(e); - throw new InvalidConfigurationException("Error occurred while initializing application config: " - + configPath, e); + throw new InvalidConfigurationException("Error occurred while initializing application managements configs: ", e); } } @@ -88,6 +111,10 @@ public class ConfigurationManager { return configuration; } + public IdentityServiceProviderConfiguration getIdentityServerConfiguration() { + return identityServiceProviderConfiguration; + } + public Extension getExtension(Extension.Name extName) throws InvalidConfigurationException { for (Extension extension : configuration.getExtensions()) { if (extension.getName().contentEquals(extName.toString())) { diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/config/Extension.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/config/Extension.java index 282f051889..98741a5efd 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/config/Extension.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/config/Extension.java @@ -77,6 +77,7 @@ public class Extension { * ApplicationManagement Extensions. */ public enum Name { + SPApplicationManager, ApplicationManager, ApplicationReleaseManager, CategoryManager, diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/config/IdentityServiceProvider.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/config/IdentityServiceProvider.java new file mode 100644 index 0000000000..63098fdd1b --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/config/IdentityServiceProvider.java @@ -0,0 +1,55 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.core.config; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "IdentityServiceProvider") +public class IdentityServiceProvider { + private String providerName; + private String providerClassName; + private String serviceProvidersPageUri; + + @XmlElement(name = "ProviderName") + public String getProviderName() { + return providerName; + } + + @XmlElement(name = "ProviderClassName") + public String getProviderClassName() { + return providerClassName; + } + + @XmlElement(name = "ServiceProvidersPageUri") + public String getServiceProvidersPageUri() { + return serviceProvidersPageUri; + } + + public void setProviderName(String providerName) { + this.providerName = providerName; + } + + public void setServiceProvidersPageUri(String serviceProvidersPageUri) { + this.serviceProvidersPageUri = serviceProvidersPageUri; + } + + public void setProviderClassName(String providerClassName) { + this.providerClassName = providerClassName; + } +} diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/config/IdentityServiceProviderConfiguration.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/config/IdentityServiceProviderConfiguration.java new file mode 100644 index 0000000000..b8b7350413 --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/config/IdentityServiceProviderConfiguration.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved. + * + * Entgra (pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.core.config; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.List; + +/** + * Represents the Application Management Configuration. + */ +@XmlRootElement(name = "IdentityServiceProviderConfiguration") +public class IdentityServiceProviderConfiguration { + + private List identityServiceProviders; + + @XmlElementWrapper(name = "IdentityServiceProviders") + @XmlElement(name = "IdentityServiceProvider") + public List getIdentityServiceProviders() { + return identityServiceProviders; + } + + public IdentityServiceProvider getIdentityServerDetailByProviderName(String identityServiceProviderName) { + for (IdentityServiceProvider identityServiceProvider : identityServiceProviders) { + if (identityServiceProvider.getProviderName().equals(identityServiceProviderName)) { + return identityServiceProvider; + } + } + return null; + } + + public void setIdentityServiceProviders(List identityServiceProviders) { + this.identityServiceProviders = identityServiceProviders; + } +} + diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/SPApplicationDAO.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/SPApplicationDAO.java new file mode 100644 index 0000000000..3d5d171585 --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/SPApplicationDAO.java @@ -0,0 +1,130 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.core.dao; + +import io.entgra.application.mgt.common.dto.IdentityServerDTO; +import io.entgra.application.mgt.common.dto.ApplicationDTO; +import io.entgra.application.mgt.core.exception.ApplicationManagementDAOException; + +import java.util.List; + +public interface SPApplicationDAO { + + /** + * Use to check if an identity server exists with the same name + * + * @param name name of the identity server + * @return if identity server with the given name exists + */ + boolean isExistingIdentityServerName(String name, int tenantId) throws ApplicationManagementDAOException; + + /** + * Use to check if an identity server exists with the same url + * + * @param url name of the identity server + * @return if identity server with the given url exists + */ + boolean isExistingIdentityServerUrl(String url, int tenantId) throws ApplicationManagementDAOException; + + /** + * Update existing identity server in the database + * + * @param updatedIdentityServerDTO bean with the updated fields of the identity server + */ + void updateIdentityServer(IdentityServerDTO updatedIdentityServerDTO, int tenantId, int identityServerId) + throws ApplicationManagementDAOException; + + /** + * Create new identity server in the database + * + * @param identityServerDTO DTO bean with the details of identity server to be created + * @return id of the newly created identity server + */ + int createIdentityServer(IdentityServerDTO identityServerDTO, int tenantId) throws ApplicationManagementDAOException; + + /** + * + * @param identityServerId Id of identity server in which the service provider is in + * @param spUID Service provider uid of which the applications to be retrieved + * @return the service provider applications for the given service provider + * @throws ApplicationManagementDAOException if any db error occurred + */ + List getSPApplications(int identityServerId, String spUID, int tenantId) throws ApplicationManagementDAOException; + + /** + * + * @param identityServerId Id of identity server in which the service provider is in + * @param spUID Id of the service provider to which the application should be mapped + * @param appId Id of the application that should be mapped + * @return Primary key of the new service provider and application mapping entry + * @throws ApplicationManagementDAOException if any db error occurred + */ + int attachSPApplication(int identityServerId, String spUID, int appId, int tenantId) throws ApplicationManagementDAOException; + + /** + * + * @param identityServerId Id of identity server in which the service provider is in + * @param spUID Id of the service provider from which the application should be removed + * @param appId Id of the application that should be removed + * @throws ApplicationManagementDAOException if any db error occurred + */ + void detachSPApplication(int identityServerId, String spUID, int appId, int tenantId) throws ApplicationManagementDAOException; + + /** + * + * @return All available identity servers + * @throws ApplicationManagementDAOException if any db error occurred + */ + List getIdentityServers(int tenantId) throws ApplicationManagementDAOException; + + /** + * + * @param id Id of the Identity Server to be retrieved + * @return Identity Server of the given id + * @throws ApplicationManagementDAOException if any db error occurred + */ + IdentityServerDTO getIdentityServerById(int id, int tenantId) throws ApplicationManagementDAOException; + + /** + * Verify whether application exist for given identity server id, service provider id and application id. + * Because if an application does not exist for those, it should not be mapped + * + * @param appId Id of the application. + * @param identityServerId Id of the identity server. + * @param spUID UID of the service provider. + * @throws ApplicationManagementDAOException Application Management DAO Exception. + */ + boolean isSPApplicationExist(int identityServerId, String spUID, int appId, int tenantId) throws ApplicationManagementDAOException; + + /** + * Delete application from all service providers if exists. When an application is deleted from the database + * it shoulbe be deleted from mapping table as well + * + * @param applicationId Id of the application to be deleted + * @throws ApplicationManagementDAOException if any db error occurred + */ + void deleteApplicationFromServiceProviders(int applicationId, int tenantId) throws ApplicationManagementDAOException; + + /** + * Delete identity server from db + * + * @param id of the identity server to be deleted + * @throws ApplicationManagementDAOException if any db error occurred + */ + void deleteIdentityServer(int id, int tenantId) throws ApplicationManagementDAOException; +} diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/common/ApplicationManagementDAOFactory.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/common/ApplicationManagementDAOFactory.java index 414ca0d015..9352a12aeb 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/common/ApplicationManagementDAOFactory.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/common/ApplicationManagementDAOFactory.java @@ -17,6 +17,11 @@ */ package io.entgra.application.mgt.core.dao.common; +import io.entgra.application.mgt.core.dao.SPApplicationDAO; +import io.entgra.application.mgt.core.dao.impl.application.spapplication.GenericSPApplicationDAOImpl; +import io.entgra.application.mgt.core.dao.impl.application.spapplication.OracleSPApplicationDAOImpl; +import io.entgra.application.mgt.core.dao.impl.application.spapplication.PostgreSQLSPApplicationDAOImpl; +import io.entgra.application.mgt.core.dao.impl.application.spapplication.SQLServerSPApplicationDAOImpl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import io.entgra.application.mgt.common.exception.UnsupportedDatabaseEngineException; @@ -101,6 +106,25 @@ public class ApplicationManagementDAOFactory { throw new IllegalStateException("Database engine has not initialized properly."); } + public static SPApplicationDAO getSPApplicationDAO() { + if (databaseEngine != null) { + switch (databaseEngine) { + case Constants.DataBaseTypes.DB_TYPE_H2: + case Constants.DataBaseTypes.DB_TYPE_MYSQL: + return new GenericSPApplicationDAOImpl(); + case Constants.DataBaseTypes.DB_TYPE_POSTGRESQL: + return new PostgreSQLSPApplicationDAOImpl(); + case Constants.DataBaseTypes.DB_TYPE_MSSQL: + return new SQLServerSPApplicationDAOImpl(); + case Constants.DataBaseTypes.DB_TYPE_ORACLE: + return new OracleSPApplicationDAOImpl(); + default: + throw new UnsupportedDatabaseEngineException("Unsupported database engine : " + databaseEngine); + } + } + throw new IllegalStateException("Database engine has not initialized properly."); + } + public static LifecycleStateDAO getLifecycleStateDAO() { if (databaseEngine != null) { switch (databaseEngine) { diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/GenericApplicationDAOImpl.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/GenericApplicationDAOImpl.java index 679f2ed713..fe05de200e 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/GenericApplicationDAOImpl.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/GenericApplicationDAOImpl.java @@ -140,12 +140,12 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic sql += "INNER JOIN AP_APP_FAVOURITES ON " + "AP_APP.ID = AP_APP_FAVOURITES.AP_APP_ID "; } - sql += "INNER JOIN AP_APP_RELEASE ON " + sql += "LEFT JOIN AP_APP_RELEASE ON " + "AP_APP.ID = AP_APP_RELEASE.AP_APP_ID " + "INNER JOIN (SELECT AP_APP.ID FROM AP_APP "; if (StringUtils.isNotEmpty(filter.getVersion()) || StringUtils.isNotEmpty(filter.getAppReleaseState()) || StringUtils.isNotEmpty(filter.getAppReleaseType())) { - sql += "INNER JOIN AP_APP_RELEASE ON AP_APP.ID = AP_APP_RELEASE.AP_APP_ID "; + sql += "LEFT JOIN AP_APP_RELEASE ON AP_APP.ID = AP_APP_RELEASE.AP_APP_ID "; } sql += "WHERE AP_APP.TENANT_ID = ? "; @@ -186,7 +186,7 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic sql += "LIMIT ? OFFSET ? "; } sql += ") AS app_data ON app_data.ID = AP_APP.ID " - + "INNER JOIN (" + + "LEFT JOIN (" + "SELECT AP_APP_LIFECYCLE_STATE.UPDATED_AT, AP_APP_LIFECYCLE_STATE.AP_APP_RELEASE_ID " + "FROM AP_APP_LIFECYCLE_STATE WHERE AP_APP_LIFECYCLE_STATE.ID " + "IN(SELECT MAX(AP_APP_LIFECYCLE_STATE.ID) " @@ -266,9 +266,9 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic Connection conn; PreparedStatement stmt = null; ResultSet rs = null; - String sql = "SELECT count(AP_APP.ID) AS APP_COUNT " + String sql = "SELECT count(DISTINCT AP_APP.ID) AS APP_COUNT " + "FROM AP_APP " - + "INNER JOIN AP_APP_RELEASE ON " + + "LEFT JOIN AP_APP_RELEASE ON " + "AP_APP.ID = AP_APP_RELEASE.AP_APP_ID " + "INNER JOIN (SELECT ID FROM AP_APP) AS app_data ON app_data.ID = AP_APP.ID " + "WHERE AP_APP.TENANT_ID = ?"; @@ -360,6 +360,7 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic } } + @Override public ApplicationDTO getApplication(String releaseUuid, int tenantId) throws ApplicationManagementDAOException { if (log.isDebugEnabled()) { @@ -618,7 +619,7 @@ public class GenericApplicationDAOImpl extends AbstractDAOImpl implements Applic + "AP_APP_RELEASE.CURRENT_STATE AS RELEASE_CURRENT_STATE, " + "AP_APP_RELEASE.RATED_USERS AS RATED_USER_COUNT " + "FROM AP_APP " - + "INNER JOIN AP_APP_RELEASE ON " + + "LEFT JOIN AP_APP_RELEASE ON " + "AP_APP.ID = AP_APP_RELEASE.AP_APP_ID AND " + "AP_APP.TENANT_ID = AP_APP_RELEASE.TENANT_ID " + "WHERE " diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/OracleApplicationDAOImpl.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/OracleApplicationDAOImpl.java index da3d5e8aae..6f4c31f1b9 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/OracleApplicationDAOImpl.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/OracleApplicationDAOImpl.java @@ -87,12 +87,12 @@ public class OracleApplicationDAOImpl extends GenericApplicationDAOImpl { sql += "INNER JOIN AP_APP_FAVOURITES ON " + "AP_APP.ID = AP_APP_FAVOURITES.AP_APP_ID "; } - sql += "INNER JOIN AP_APP_RELEASE ON " - + "AP_APP.ID = AP_APP_RELEASE.AP_APP_ID " - + "INNER JOIN (SELECT AP_APP.ID FROM AP_APP ORDER BY ID "; + sql += "LEFT JOIN AP_APP_RELEASE ON " + + "AP_APP.ID = AP_APP_RELEASE.AP_APP_ID " + + "INNER JOIN (SELECT AP_APP.ID FROM AP_APP "; if (StringUtils.isNotEmpty(filter.getVersion()) || StringUtils.isNotEmpty(filter.getAppReleaseState()) || StringUtils.isNotEmpty(filter.getAppReleaseType())) { - sql += "INNER JOIN AP_APP_RELEASE ON AP_APP.ID = AP_APP_RELEASE.AP_APP_ID "; + sql += "LEFT JOIN AP_APP_RELEASE ON AP_APP.ID = AP_APP_RELEASE.AP_APP_ID "; } if (StringUtils.isNotEmpty(filter.getAppType())) { sql += "AND AP_APP.TYPE = ? "; @@ -131,7 +131,7 @@ public class OracleApplicationDAOImpl extends GenericApplicationDAOImpl { sql += "OFFSET ? ROWS FETCH NEXT ? ROWS ONLY "; } sql += ") AS app_data ON app_data.ID = AP_APP.ID " - + "INNER JOIN (" + + "LEFT JOIN (" + "SELECT AP_APP_LIFECYCLE_STATE.UPDATED_AT, AP_APP_LIFECYCLE_STATE.AP_APP_RELEASE_ID " + "FROM AP_APP_LIFECYCLE_STATE WHERE AP_APP_LIFECYCLE_STATE.ID " + "IN(SELECT MAX(AP_APP_LIFECYCLE_STATE.ID) " diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/SQLServerApplicationDAOImpl.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/SQLServerApplicationDAOImpl.java index 1319c458e4..0ddbe3c333 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/SQLServerApplicationDAOImpl.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/SQLServerApplicationDAOImpl.java @@ -86,12 +86,12 @@ public class SQLServerApplicationDAOImpl extends GenericApplicationDAOImpl { sql += "INNER JOIN AP_APP_FAVOURITES ON " + "AP_APP.ID = AP_APP_FAVOURITES.AP_APP_ID "; } - sql += "INNER JOIN AP_APP_RELEASE ON " + sql += "LEFT JOIN AP_APP_RELEASE ON " + "AP_APP.ID = AP_APP_RELEASE.AP_APP_ID " + "INNER JOIN (SELECT AP_APP.ID FROM AP_APP "; if (StringUtils.isNotEmpty(filter.getVersion()) || StringUtils.isNotEmpty(filter.getAppReleaseState()) || StringUtils.isNotEmpty(filter.getAppReleaseType())) { - sql += "INNER JOIN AP_APP_RELEASE ON AP_APP.ID = AP_APP_RELEASE.AP_APP_ID "; + sql += "LEFT JOIN AP_APP_RELEASE ON AP_APP.ID = AP_APP_RELEASE.AP_APP_ID "; } if (StringUtils.isNotEmpty(filter.getAppType())) { sql += "AND AP_APP.TYPE = ? "; @@ -130,7 +130,7 @@ public class SQLServerApplicationDAOImpl extends GenericApplicationDAOImpl { sql += "ORDER BY ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY "; } sql += ") AS app_data ON app_data.ID = AP_APP.ID " - + "INNER JOIN (" + + "LEFT JOIN (" + "SELECT AP_APP_LIFECYCLE_STATE.UPDATED_AT, AP_APP_LIFECYCLE_STATE.AP_APP_RELEASE_ID " + "FROM AP_APP_LIFECYCLE_STATE WHERE AP_APP_LIFECYCLE_STATE.ID " + "IN(SELECT MAX(AP_APP_LIFECYCLE_STATE.ID) " diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/spapplication/GenericSPApplicationDAOImpl.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/spapplication/GenericSPApplicationDAOImpl.java new file mode 100644 index 0000000000..501c965b79 --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/spapplication/GenericSPApplicationDAOImpl.java @@ -0,0 +1,486 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.core.dao.impl.application.spapplication; + +import io.entgra.application.mgt.common.dto.IdentityServerDTO; +import io.entgra.application.mgt.common.dto.ApplicationDTO; +import io.entgra.application.mgt.common.exception.DBConnectionException; +import io.entgra.application.mgt.core.dao.SPApplicationDAO; +import io.entgra.application.mgt.core.dao.impl.AbstractDAOImpl; +import io.entgra.application.mgt.core.dao.impl.application.GenericApplicationDAOImpl; +import io.entgra.application.mgt.core.exception.ApplicationManagementDAOException; +import io.entgra.application.mgt.core.exception.UnexpectedServerErrorException; +import io.entgra.application.mgt.core.util.DAOUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; + +public class GenericSPApplicationDAOImpl extends AbstractDAOImpl implements SPApplicationDAO { + + private static final Log log = LogFactory.getLog(GenericApplicationDAOImpl.class); + @Override + public List getIdentityServers(int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT ID, PROVIDER_NAME, NAME, DESCRIPTION, URL, API_PARAMS, USERNAME, PASSWORD, TENANT_ID " + + "FROM AP_IDENTITY_SERVER " + + "WHERE TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setInt(1, tenantId); + try (ResultSet rs = stmt.executeQuery()){ + if (log.isDebugEnabled()) { + log.debug("Successfully retrieved available identity servers" ); + } + return DAOUtil.loadIdentityServers(rs); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to retrieve available identity servers"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to retrieve available identity servers"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public IdentityServerDTO getIdentityServerById(int id, int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT ID, PROVIDER_NAME, NAME, DESCRIPTION, URL, API_PARAMS, USERNAME, PASSWORD, TENANT_ID " + + "FROM AP_IDENTITY_SERVER " + + "WHERE TENANT_ID = ? AND " + + "ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setInt(1, tenantId); + stmt.setInt(2, id); + try (ResultSet rs = stmt.executeQuery()){ + if (log.isDebugEnabled()) { + log.debug("Successfully retrieved available identity servers" ); + } + return DAOUtil.loadIdentityServer(rs); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to retrieve available identity servers"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to retrieve available identity servers"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (UnexpectedServerErrorException e) { + String msg = "Found more than one identity server for id: " + id; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public boolean isExistingIdentityServerName(String name, int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT ID AS ID " + + "FROM AP_IDENTITY_SERVER " + + "WHERE " + + "LOWER(NAME) = LOWER(?) AND " + + "TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setString(1, name); + stmt.setInt(2, tenantId); + try (ResultSet rs = stmt.executeQuery()){ + return rs.next(); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to check if identity server name: " + name + + " already exist"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to check if identity server with the name " + name + + " already exists."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public boolean isExistingIdentityServerUrl(String url, int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT ID AS ID " + + "FROM AP_IDENTITY_SERVER " + + "WHERE " + + "LOWER(URL) = LOWER(?) AND " + + "TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setString(1, url); + stmt.setInt(2, tenantId); + try (ResultSet rs = stmt.executeQuery()){ + return rs.next(); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to check if identity server url: " + url + + " already exist"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to check if identity server with the url " + url + + " already exists."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public void updateIdentityServer(IdentityServerDTO updatedIdentityServerDTO, int tenantId, int identityServerId) + throws ApplicationManagementDAOException { + String sql = "UPDATE AP_IDENTITY_SERVER " + + "SET "; + if (updatedIdentityServerDTO.getName() != null) { + sql += "NAME = ?, "; + } + if (updatedIdentityServerDTO.getUrl() != null) { + sql += "URL = ?, "; + } + if (updatedIdentityServerDTO.getProviderName() != null) { + sql += "PROVIDER_NAME = ?, "; + } + if (updatedIdentityServerDTO.getUsername() != null) { + sql += "USERNAME = ?, "; + } + if (updatedIdentityServerDTO.getPassword() != null) { + sql += "PASSWORD = ?, "; + } + if (updatedIdentityServerDTO.getDescription() != null) { + sql += "DESCRIPTION = ?, "; + } + sql += "API_PARAMS = ? " + + "WHERE ID = ? AND TENANT_ID = ?"; + + try { + int index = 1; + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + if (updatedIdentityServerDTO.getName() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getName()); + } + if (updatedIdentityServerDTO.getUrl() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getUrl()); + } + if (updatedIdentityServerDTO.getProviderName() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getProviderName()); + } + if (updatedIdentityServerDTO.getUsername() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getUsername()); + } + if (updatedIdentityServerDTO.getPassword() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getPassword()); + } + if (updatedIdentityServerDTO.getDescription() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getDescription()); + } + stmt.setString(index++, updatedIdentityServerDTO.constructApiParamsJsonString()); + stmt.setInt(index++, identityServerId); + stmt.setInt(index, tenantId); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to update identity server."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred when executing SQL to update identity server. Executed query: " + sql; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int createIdentityServer(IdentityServerDTO identityServerDTO, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to create an identity server"); + } + String sql = "INSERT INTO AP_IDENTITY_SERVER " + + "(PROVIDER_NAME, NAME, DESCRIPTION, URL, API_PARAMS, USERNAME, PASSWORD, TENANT_ID) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setString(1, identityServerDTO.getProviderName()); + stmt.setString(2, identityServerDTO.getName()); + stmt.setString(3, identityServerDTO.getDescription()); + stmt.setString(4, identityServerDTO.getUrl()); + stmt.setString(5, identityServerDTO.constructApiParamsJsonString()); + stmt.setString(6, identityServerDTO.getUsername()); + stmt.setString(7, identityServerDTO.getPassword()); + stmt.setInt(8, tenantId); + stmt.executeUpdate(); + try (ResultSet rs = stmt.getGeneratedKeys()) { + if (rs.next()) { + return rs.getInt(1); + } + return -1; + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while creating identity server "; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to create an identity server "; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public List getSPApplications(int identityServerId, String spUID, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Getting identity server applications from the database"); + } + String sql = "SELECT " + + "AP_APP.ID AS APP_ID, " + + "AP_APP.NAME AS APP_NAME, " + + "AP_APP.DESCRIPTION AS APP_DESCRIPTION, " + + "AP_APP.TYPE AS APP_TYPE, " + + "AP_APP.STATUS AS APP_STATUS, " + + "AP_APP.SUB_TYPE AS APP_SUB_TYPE, " + + "AP_APP.CURRENCY AS APP_CURRENCY, " + + "AP_APP.RATING AS APP_RATING, " + + "AP_APP.DEVICE_TYPE_ID AS APP_DEVICE_TYPE_ID, " + + "AP_APP_RELEASE.ID AS RELEASE_ID, " + + "AP_APP_RELEASE.DESCRIPTION AS RELEASE_DESCRIPTION, " + + "AP_APP_RELEASE.VERSION AS RELEASE_VERSION, " + + "AP_APP_RELEASE.UUID AS RELEASE_UUID, " + + "AP_APP_RELEASE.RELEASE_TYPE AS RELEASE_TYPE, " + + "AP_APP_RELEASE.INSTALLER_LOCATION AS AP_RELEASE_STORED_LOC, " + + "AP_APP_RELEASE.ICON_LOCATION AS AP_RELEASE_ICON_LOC, " + + "AP_APP_RELEASE.BANNER_LOCATION AS AP_RELEASE_BANNER_LOC, " + + "AP_APP_RELEASE.SC_1_LOCATION AS AP_RELEASE_SC1, " + + "AP_APP_RELEASE.SC_2_LOCATION AS AP_RELEASE_SC2, " + + "AP_APP_RELEASE.SC_3_LOCATION AS AP_RELEASE_SC3, " + + "AP_APP_RELEASE.APP_HASH_VALUE AS RELEASE_HASH_VALUE, " + + "AP_APP_RELEASE.APP_PRICE AS RELEASE_PRICE, " + + "AP_APP_RELEASE.APP_META_INFO AS RELEASE_META_INFO, " + + "AP_APP_RELEASE.PACKAGE_NAME AS PACKAGE_NAME, " + + "AP_APP_RELEASE.SUPPORTED_OS_VERSIONS AS RELEASE_SUP_OS_VERSIONS, " + + "AP_APP_RELEASE.RATING AS RELEASE_RATING, " + + "AP_APP_RELEASE.CURRENT_STATE AS RELEASE_CURRENT_STATE, " + + "AP_APP_RELEASE.RATED_USERS AS RATED_USER_COUNT " + + "FROM AP_APP " + + "LEFT JOIN AP_APP_RELEASE ON " + + "AP_APP.ID = AP_APP_RELEASE.AP_APP_ID AND " + + "AP_APP.TENANT_ID = AP_APP_RELEASE.TENANT_ID " + + "INNER JOIN AP_IS_SP_APP_MAPPING as SP_APPS on SP_APPS.AP_APP_ID = AP_APP.ID " + + "WHERE " + + "SP_APPS.SP_UID = ? " + + "AND SP_APPS.IS_ID = ? " + + "AND AP_APP.TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setString(1, spUID); + stmt.setInt(2, identityServerId); + stmt.setInt(3, tenantId); + try (ResultSet rs = stmt.executeQuery()) { + if (log.isDebugEnabled()) { + log.debug("Successfully retrieved basic details of the identity server applications"); + } + return DAOUtil.loadApplications(rs); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to get identity server applications for application release"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while getting identity server applications while executing query. Executed query: " + sql; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public boolean isSPApplicationExist(int identityServerId, String spUID, int appId, int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT AP_APP_ID AS ID " + + "FROM AP_IS_SP_APP_MAPPING SP_MAPPING " + + "WHERE " + + "SP_UID = ? AND AP_APP_ID = ? " + + "AND IS_ID = ? AND " + + "TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setString(1, spUID); + stmt.setInt(2, appId); + stmt.setInt(3, identityServerId); + stmt.setInt(4, tenantId); + try (ResultSet rs = stmt.executeQuery()){ + return rs.next(); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to check whether the existence of " + + "sp application with id " + appId + " for service provider which has UID " + spUID; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to check whether the existence of service provider application " + + "with id " + appId + " for service provider which has UID " + spUID + ". executed query " + sql; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public void detachSPApplication(int identityServerId, String spUID, int appId, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to map an application wit identity server:service provider"); + log.debug("Application Details : "); + log.debug("App ID : " + appId + " SP UID : " + spUID + " IS ID : " + identityServerId); + } + String sql = "DELETE FROM AP_IS_SP_APP_MAPPING " + + "WHERE SP_UID = ? " + + "AND AP_APP_ID = ? " + + "AND IS_ID = ? " + + "AND TENANT_ID = ? "; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setString(1, spUID); + stmt.setInt(2, appId); + stmt.setInt(3, identityServerId); + stmt.setInt(4, tenantId); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to create an sp application mapping which has " + + "application id " + appId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to create an application which has application id " + + appId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int attachSPApplication(int identityServerId, String spUID, int appId, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to map an application wit identity server:service provider"); + log.debug("Application Details : "); + log.debug("App ID : " + appId + " SP UID : " + spUID + " IS ID : " + identityServerId); + } + String sql = "INSERT INTO AP_IS_SP_APP_MAPPING " + + "(SP_UID, " + + "AP_APP_ID, " + + "IS_ID, TENANT_ID) " + + "VALUES (?, ?, ?, ?)"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setString(1, spUID); + stmt.setInt(2, appId); + stmt.setInt(3, identityServerId); + stmt.setInt(4, tenantId); + stmt.executeUpdate(); + try (ResultSet rs = stmt.getGeneratedKeys()) { + if (rs.next()) { + return rs.getInt(1); + } + return -1; + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to create an sp application mapping which has " + + "application id " + appId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to create an application which has application id " + + appId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public void deleteApplicationFromServiceProviders(int applicationId, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to delete application with the id: " + applicationId + " from service providers"); + } + String sql = "DELETE FROM AP_IS_SP_APP_MAPPING WHERE AP_APP_ID = ? AND TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setInt(1, applicationId); + stmt.setInt(2, tenantId); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to create an sp application mapping which has " + + "application id " + applicationId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to create an application which has application id " + + applicationId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public void deleteIdentityServer(int id, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to delete identity server with the id: " + id); + } + String sql = "DELETE FROM AP_IDENTITY_SERVER WHERE ID = ? AND TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setInt(1, id); + stmt.setInt(2, tenantId); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to delete an identity server with the id " + id; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to delete an identity server which has the id " + + id; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + +} diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/spapplication/OracleSPApplicationDAOImpl.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/spapplication/OracleSPApplicationDAOImpl.java new file mode 100644 index 0000000000..77dc285375 --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/spapplication/OracleSPApplicationDAOImpl.java @@ -0,0 +1,487 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.core.dao.impl.application.spapplication; + +import io.entgra.application.mgt.common.dto.IdentityServerDTO; +import io.entgra.application.mgt.common.dto.ApplicationDTO; +import io.entgra.application.mgt.common.exception.DBConnectionException; +import io.entgra.application.mgt.core.dao.SPApplicationDAO; +import io.entgra.application.mgt.core.dao.impl.AbstractDAOImpl; +import io.entgra.application.mgt.core.exception.ApplicationManagementDAOException; +import io.entgra.application.mgt.core.exception.UnexpectedServerErrorException; +import io.entgra.application.mgt.core.util.DAOUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; + +public class OracleSPApplicationDAOImpl extends AbstractDAOImpl implements SPApplicationDAO { + + private static final Log log = LogFactory.getLog(OracleSPApplicationDAOImpl.class); + + @Override + public List getIdentityServers(int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT ID, PROVIDER_NAME, NAME, DESCRIPTION, URL, API_PARAMS, USERNAME, PASSWORD, TENANT_ID " + + "FROM AP_IDENTITY_SERVER " + + "WHERE TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setInt(1, tenantId); + try (ResultSet rs = stmt.executeQuery()){ + if (log.isDebugEnabled()) { + log.debug("Successfully retrieved available identity servers" ); + } + return DAOUtil.loadIdentityServers(rs); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to retrieve available identity servers"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to retrieve available identity servers"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public IdentityServerDTO getIdentityServerById(int id, int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT ID, PROVIDER_NAME, NAME, DESCRIPTION, URL, API_PARAMS, USERNAME, PASSWORD, TENANT_ID " + + "FROM AP_IDENTITY_SERVER " + + "WHERE TENANT_ID = ? AND " + + "ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setInt(1, tenantId); + stmt.setInt(2, id); + try (ResultSet rs = stmt.executeQuery()){ + if (log.isDebugEnabled()) { + log.debug("Successfully retrieved available identity servers" ); + } + return DAOUtil.loadIdentityServer(rs); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to retrieve available identity servers"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to retrieve available identity servers"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (UnexpectedServerErrorException e) { + String msg = "Found more than one identity server for id: " + id; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public boolean isExistingIdentityServerUrl(String url, int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT AP_APP.ID AS ID " + + "FROM AP_IDENTITY_SERVER " + + "WHERE " + + "LOWER(URL) = LOWER(?) AND " + + "AP_APP.TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setString(1, url); + stmt.setInt(2, tenantId); + try (ResultSet rs = stmt.executeQuery()){ + return rs.next(); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to check if identity server url: " + url + + " already exist"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to check if identity server with the url " + url + + " already exists."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public boolean isExistingIdentityServerName(String name, int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT AP_APP.ID AS ID " + + "FROM AP_IDENTITY_SERVER " + + "WHERE " + + "LOWER(NAME) = LOWER(?) AND " + + "AP_APP.TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setString(1, name); + stmt.setInt(2, tenantId); + try (ResultSet rs = stmt.executeQuery()){ + return rs.next(); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to check if identity server name: " + name + + " already exist"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to check if identity server with the name " + name + + " already exists."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public void updateIdentityServer(IdentityServerDTO updatedIdentityServerDTO, int tenantId, int identityServerId) + throws ApplicationManagementDAOException { + String sql = "UPDATE AP_IDENTITY_SERVER " + + "SET "; + if (updatedIdentityServerDTO.getName() != null) { + sql += "NAME = ?, "; + } + if (updatedIdentityServerDTO.getUrl() != null) { + sql += "URL = ?, "; + } + if (updatedIdentityServerDTO.getProviderName() != null) { + sql += "PROVIDER_NAME = ?, "; + } + if (updatedIdentityServerDTO.getUsername() != null) { + sql += "USERNAME = ?, "; + } + if (updatedIdentityServerDTO.getPassword() != null) { + sql += "PASSWORD = ?, "; + } + if (updatedIdentityServerDTO.getDescription() != null) { + sql += "DESCRIPTION = ?, "; + } + sql += "API_PARAMS = ? " + + "WHERE ID = ? AND TENANT_ID = ?"; + + try { + int index = 1; + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + if (updatedIdentityServerDTO.getName() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getName()); + } + if (updatedIdentityServerDTO.getUrl() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getUrl()); + } + if (updatedIdentityServerDTO.getProviderName() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getProviderName()); + } + if (updatedIdentityServerDTO.getUsername() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getUsername()); + } + if (updatedIdentityServerDTO.getPassword() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getPassword()); + } + if (updatedIdentityServerDTO.getDescription() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getDescription()); + } + stmt.setString(index++, updatedIdentityServerDTO.constructApiParamsJsonString()); + stmt.setInt(index++, identityServerId); + stmt.setInt(index, tenantId); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to update identity server."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred when executing SQL to update identity server. Executed query: " + sql; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int createIdentityServer(IdentityServerDTO identityServerDTO, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to create an identity server"); + } + String sql = "INSERT INTO AP_IDENTITY_SERVER " + + "(PROVIDER_NAME, " + + "NAME, " + + "DESCRIPTION, URL, API_PARAMS, USERNAME, PASSWORD, TENANT_ID) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setString(1, identityServerDTO.getProviderName()); + stmt.setString(2, identityServerDTO.getName()); + stmt.setString(3, identityServerDTO.getDescription()); + stmt.setString(4, identityServerDTO.getUrl()); + stmt.setString(5, identityServerDTO.constructApiParamsJsonString()); + stmt.setString(6, identityServerDTO.getUsername()); + stmt.setString(7, identityServerDTO.getPassword()); + stmt.setInt(8, tenantId); + stmt.executeUpdate(); + try (ResultSet rs = stmt.getGeneratedKeys()) { + if (rs.next()) { + return rs.getInt(1); + } + return -1; + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while creating identity server "; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to create an identity server "; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public List getSPApplications(int identityServerId, String spUID, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Getting identity server applications from the database"); + } + String sql = "SELECT " + + "AP_APP.ID AS APP_ID, " + + "AP_APP.NAME AS APP_NAME, " + + "AP_APP.DESCRIPTION AS APP_DESCRIPTION, " + + "AP_APP.TYPE AS APP_TYPE, " + + "AP_APP.STATUS AS APP_STATUS, " + + "AP_APP.SUB_TYPE AS APP_SUB_TYPE, " + + "AP_APP.CURRENCY AS APP_CURRENCY, " + + "AP_APP.RATING AS APP_RATING, " + + "AP_APP.DEVICE_TYPE_ID AS APP_DEVICE_TYPE_ID, " + + "AP_APP_RELEASE.ID AS RELEASE_ID, " + + "AP_APP_RELEASE.DESCRIPTION AS RELEASE_DESCRIPTION, " + + "AP_APP_RELEASE.VERSION AS RELEASE_VERSION, " + + "AP_APP_RELEASE.UUID AS RELEASE_UUID, " + + "AP_APP_RELEASE.RELEASE_TYPE AS RELEASE_TYPE, " + + "AP_APP_RELEASE.INSTALLER_LOCATION AS AP_RELEASE_STORED_LOC, " + + "AP_APP_RELEASE.ICON_LOCATION AS AP_RELEASE_ICON_LOC, " + + "AP_APP_RELEASE.BANNER_LOCATION AS AP_RELEASE_BANNER_LOC, " + + "AP_APP_RELEASE.SC_1_LOCATION AS AP_RELEASE_SC1, " + + "AP_APP_RELEASE.SC_2_LOCATION AS AP_RELEASE_SC2, " + + "AP_APP_RELEASE.SC_3_LOCATION AS AP_RELEASE_SC3, " + + "AP_APP_RELEASE.APP_HASH_VALUE AS RELEASE_HASH_VALUE, " + + "AP_APP_RELEASE.APP_PRICE AS RELEASE_PRICE, " + + "AP_APP_RELEASE.APP_META_INFO AS RELEASE_META_INFO, " + + "AP_APP_RELEASE.PACKAGE_NAME AS PACKAGE_NAME, " + + "AP_APP_RELEASE.SUPPORTED_OS_VERSIONS AS RELEASE_SUP_OS_VERSIONS, " + + "AP_APP_RELEASE.RATING AS RELEASE_RATING, " + + "AP_APP_RELEASE.CURRENT_STATE AS RELEASE_CURRENT_STATE, " + + "AP_APP_RELEASE.RATED_USERS AS RATED_USER_COUNT " + + "FROM AP_APP " + + "LEFT JOIN AP_APP_RELEASE ON " + + "AP_APP.ID = AP_APP_RELEASE.AP_APP_ID AND " + + "AP_APP.TENANT_ID = AP_APP_RELEASE.TENANT_ID " + + "INNER JOIN AP_IS_SP_APP_MAPPING as SP_APPS on SP_APPS.AP_APP_ID = AP_APP.ID " + + "WHERE " + + "SP_APPS.SP_UID = ? " + + "AND SP_APPS.IS_ID = ? " + + "AND AP_APP.TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setString(1, spUID); + stmt.setInt(2, identityServerId); + stmt.setInt(3, tenantId); + try (ResultSet rs = stmt.executeQuery()) { + if (log.isDebugEnabled()) { + log.debug("Successfully retrieved basic details of the identity server applications"); + } + return DAOUtil.loadApplications(rs); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to get identity server applications for application release"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while getting identity server applications while executing query. Executed query: " + sql; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public boolean isSPApplicationExist(int identityServerId, String spUID, int appId, int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT AP_APP_ID AS ID " + + "FROM AP_IS_SP_APP_MAPPING SP_MAPPING " + + "WHERE " + + "SP_UID = ? AND AP_APP_ID = ? " + + "AND IS_ID = ? AND " + + "TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setString(1, spUID); + stmt.setInt(2, appId); + stmt.setInt(3, identityServerId); + stmt.setInt(4, tenantId); + try (ResultSet rs = stmt.executeQuery()){ + return rs.next(); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to check whether the existence of " + + "sp application with id " + appId + " for service provider which has UID " + spUID; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to check whether the existence of service provider application " + + "with id " + appId + " for service provider which has UID " + spUID + ". executed query " + sql; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public void detachSPApplication(int identityServerId, String spUID, int appId, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to map an application wit identity server:service provider"); + log.debug("Application Details : "); + log.debug("App ID : " + appId + " SP UID : " + spUID + " IS ID : " + identityServerId); + } + String sql = "DELETE FROM AP_IS_SP_APP_MAPPING " + + "WHERE SP_UID = ? " + + "AND AP_APP_ID = ? " + + "AND IS_ID = ? " + + "AND TENANT_ID = ? "; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setString(1, spUID); + stmt.setInt(2, appId); + stmt.setInt(3, identityServerId); + stmt.setInt(4, tenantId); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to create an sp application mapping which has " + + "application id " + appId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to create an application which has application id " + + appId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int attachSPApplication(int identityServerId, String spUID, int appId, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to map an application wit identity server:service provider"); + log.debug("Application Details : "); + log.debug("App ID : " + appId + " SP UID : " + spUID + " IS ID : " + identityServerId); + } + String sql = "INSERT INTO AP_IS_SP_APP_MAPPING " + + "(SP_UID, " + + "AP_APP_ID, " + + "IS_ID, TENANT_ID) " + + "VALUES (?, ?, ?, ?)"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setString(1, spUID); + stmt.setInt(2, appId); + stmt.setInt(3, identityServerId); + stmt.setInt(4, tenantId); + stmt.executeUpdate(); + try (ResultSet rs = stmt.getGeneratedKeys()) { + if (rs.next()) { + return rs.getInt(1); + } + return -1; + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to create an sp application mapping which has " + + "application id " + appId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to create an application which has application id " + + appId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public void deleteApplicationFromServiceProviders(int applicationId, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to delete application with the id: " + applicationId + " from service providers"); + } + String sql = "DELETE FROM AP_IS_SP_APP_MAPPING WHERE AP_APP_ID = ? AND TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setInt(1, applicationId); + stmt.setInt(2, tenantId); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to create an sp application mapping which has " + + "application id " + applicationId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to create an application which has application id " + + applicationId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public void deleteIdentityServer(int id, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to delete identity server with the id: " + id); + } + String sql = "DELETE FROM AP_IDENTITY_SERVER WHERE ID = ? AND TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setInt(1, id); + stmt.setInt(2, tenantId); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to delete an identity server with the id " + id; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to delete an identity server which has the id " + + id; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + +} diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/spapplication/PostgreSQLSPApplicationDAOImpl.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/spapplication/PostgreSQLSPApplicationDAOImpl.java new file mode 100644 index 0000000000..5e33a4c278 --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/spapplication/PostgreSQLSPApplicationDAOImpl.java @@ -0,0 +1,487 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.core.dao.impl.application.spapplication; + +import io.entgra.application.mgt.common.dto.IdentityServerDTO; +import io.entgra.application.mgt.common.dto.ApplicationDTO; +import io.entgra.application.mgt.common.exception.DBConnectionException; +import io.entgra.application.mgt.core.dao.SPApplicationDAO; +import io.entgra.application.mgt.core.dao.impl.AbstractDAOImpl; +import io.entgra.application.mgt.core.exception.ApplicationManagementDAOException; +import io.entgra.application.mgt.core.exception.UnexpectedServerErrorException; +import io.entgra.application.mgt.core.util.DAOUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; + +public class PostgreSQLSPApplicationDAOImpl extends AbstractDAOImpl implements SPApplicationDAO { + + private static final Log log = LogFactory.getLog(PostgreSQLSPApplicationDAOImpl.class); + + @Override + public List getIdentityServers(int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT ID, PROVIDER_NAME, NAME, DESCRIPTION, URL, API_PARAMS, USERNAME, PASSWORD, TENANT_ID " + + "FROM AP_IDENTITY_SERVER " + + "WHERE TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setInt(1, tenantId); + try (ResultSet rs = stmt.executeQuery()){ + if (log.isDebugEnabled()) { + log.debug("Successfully retrieved available identity servers" ); + } + return DAOUtil.loadIdentityServers(rs); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to retrieve available identity servers"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to retrieve available identity servers"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public IdentityServerDTO getIdentityServerById(int id, int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT ID, PROVIDER_NAME, NAME, DESCRIPTION, URL, API_PARAMS, USERNAME, PASSWORD, TENANT_ID " + + "FROM AP_IDENTITY_SERVER " + + "WHERE TENANT_ID = ? AND " + + "ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setInt(1, tenantId); + stmt.setInt(2, id); + try (ResultSet rs = stmt.executeQuery()){ + if (log.isDebugEnabled()) { + log.debug("Successfully retrieved available identity servers" ); + } + return DAOUtil.loadIdentityServer(rs); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to retrieve available identity servers"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to retrieve available identity servers"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (UnexpectedServerErrorException e) { + String msg = "Found more than one identity server for id: " + id; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public boolean isExistingIdentityServerUrl(String url, int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT AP_APP.ID AS ID " + + "FROM AP_IDENTITY_SERVER " + + "WHERE " + + "LOWER(URL) = LOWER(?) AND " + + "AP_APP.TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setString(1, url); + stmt.setInt(2, tenantId); + try (ResultSet rs = stmt.executeQuery()){ + return rs.next(); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to check if identity server url: " + url + + " already exist"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to check if identity server with the url " + url + + " already exists."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public boolean isExistingIdentityServerName(String name, int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT AP_APP.ID AS ID " + + "FROM AP_IDENTITY_SERVER " + + "WHERE " + + "LOWER(NAME) = LOWER(?) AND " + + "AP_APP.TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setString(1, name); + stmt.setInt(2, tenantId); + try (ResultSet rs = stmt.executeQuery()){ + return rs.next(); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to check if identity server name: " + name + + " already exist"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to check if identity server with the name " + name + + " already exists."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public void updateIdentityServer(IdentityServerDTO updatedIdentityServerDTO, int tenantId, int identityServerId) + throws ApplicationManagementDAOException { + String sql = "UPDATE AP_IDENTITY_SERVER " + + "SET "; + if (updatedIdentityServerDTO.getName() != null) { + sql += "NAME = ?, "; + } + if (updatedIdentityServerDTO.getUrl() != null) { + sql += "URL = ?, "; + } + if (updatedIdentityServerDTO.getProviderName() != null) { + sql += "PROVIDER_NAME = ?, "; + } + if (updatedIdentityServerDTO.getUsername() != null) { + sql += "USERNAME = ?, "; + } + if (updatedIdentityServerDTO.getPassword() != null) { + sql += "PASSWORD = ?, "; + } + if (updatedIdentityServerDTO.getDescription() != null) { + sql += "DESCRIPTION = ?, "; + } + sql += "API_PARAMS = ? " + + "WHERE ID = ? AND TENANT_ID = ?"; + + try { + int index = 1; + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + if (updatedIdentityServerDTO.getName() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getName()); + } + if (updatedIdentityServerDTO.getUrl() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getUrl()); + } + if (updatedIdentityServerDTO.getProviderName() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getProviderName()); + } + if (updatedIdentityServerDTO.getUsername() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getUsername()); + } + if (updatedIdentityServerDTO.getPassword() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getPassword()); + } + if (updatedIdentityServerDTO.getDescription() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getDescription()); + } + stmt.setString(index++, updatedIdentityServerDTO.constructApiParamsJsonString()); + stmt.setInt(index++, identityServerId); + stmt.setInt(index, tenantId); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to update identity server."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred when executing SQL to update identity server. Executed query: " + sql; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int createIdentityServer(IdentityServerDTO identityServerDTO, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to create an identity server"); + } + String sql = "INSERT INTO AP_IDENTITY_SERVER " + + "(PROVIDER_NAME, " + + "NAME, " + + "DESCRIPTION, URL, API_PARAMS, USERNAME, PASSWORD, TENANT_ID) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setString(1, identityServerDTO.getProviderName()); + stmt.setString(2, identityServerDTO.getName()); + stmt.setString(3, identityServerDTO.getDescription()); + stmt.setString(4, identityServerDTO.getUrl()); + stmt.setString(5, identityServerDTO.constructApiParamsJsonString()); + stmt.setString(6, identityServerDTO.getUsername()); + stmt.setString(7, identityServerDTO.getPassword()); + stmt.setInt(8, tenantId); + stmt.executeUpdate(); + try (ResultSet rs = stmt.getGeneratedKeys()) { + if (rs.next()) { + return rs.getInt(1); + } + return -1; + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while creating identity server "; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to create an identity server "; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public List getSPApplications(int identityServerId, String spUID, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Getting identity server applications from the database"); + } + String sql = "SELECT " + + "AP_APP.ID AS APP_ID, " + + "AP_APP.NAME AS APP_NAME, " + + "AP_APP.DESCRIPTION AS APP_DESCRIPTION, " + + "AP_APP.TYPE AS APP_TYPE, " + + "AP_APP.STATUS AS APP_STATUS, " + + "AP_APP.SUB_TYPE AS APP_SUB_TYPE, " + + "AP_APP.CURRENCY AS APP_CURRENCY, " + + "AP_APP.RATING AS APP_RATING, " + + "AP_APP.DEVICE_TYPE_ID AS APP_DEVICE_TYPE_ID, " + + "AP_APP_RELEASE.ID AS RELEASE_ID, " + + "AP_APP_RELEASE.DESCRIPTION AS RELEASE_DESCRIPTION, " + + "AP_APP_RELEASE.VERSION AS RELEASE_VERSION, " + + "AP_APP_RELEASE.UUID AS RELEASE_UUID, " + + "AP_APP_RELEASE.RELEASE_TYPE AS RELEASE_TYPE, " + + "AP_APP_RELEASE.INSTALLER_LOCATION AS AP_RELEASE_STORED_LOC, " + + "AP_APP_RELEASE.ICON_LOCATION AS AP_RELEASE_ICON_LOC, " + + "AP_APP_RELEASE.BANNER_LOCATION AS AP_RELEASE_BANNER_LOC, " + + "AP_APP_RELEASE.SC_1_LOCATION AS AP_RELEASE_SC1, " + + "AP_APP_RELEASE.SC_2_LOCATION AS AP_RELEASE_SC2, " + + "AP_APP_RELEASE.SC_3_LOCATION AS AP_RELEASE_SC3, " + + "AP_APP_RELEASE.APP_HASH_VALUE AS RELEASE_HASH_VALUE, " + + "AP_APP_RELEASE.APP_PRICE AS RELEASE_PRICE, " + + "AP_APP_RELEASE.APP_META_INFO AS RELEASE_META_INFO, " + + "AP_APP_RELEASE.PACKAGE_NAME AS PACKAGE_NAME, " + + "AP_APP_RELEASE.SUPPORTED_OS_VERSIONS AS RELEASE_SUP_OS_VERSIONS, " + + "AP_APP_RELEASE.RATING AS RELEASE_RATING, " + + "AP_APP_RELEASE.CURRENT_STATE AS RELEASE_CURRENT_STATE, " + + "AP_APP_RELEASE.RATED_USERS AS RATED_USER_COUNT " + + "FROM AP_APP " + + "LEFT JOIN AP_APP_RELEASE ON " + + "AP_APP.ID = AP_APP_RELEASE.AP_APP_ID AND " + + "AP_APP.TENANT_ID = AP_APP_RELEASE.TENANT_ID " + + "INNER JOIN AP_IS_SP_APP_MAPPING as SP_APPS on SP_APPS.AP_APP_ID = AP_APP.ID " + + "WHERE " + + "SP_APPS.SP_UID = ? " + + "AND SP_APPS.IS_ID = ? " + + "AND AP_APP.TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setString(1, spUID); + stmt.setInt(2, identityServerId); + stmt.setInt(3, tenantId); + try (ResultSet rs = stmt.executeQuery()) { + if (log.isDebugEnabled()) { + log.debug("Successfully retrieved basic details of the identity server applications"); + } + return DAOUtil.loadApplications(rs); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to get identity server applications for application release"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while getting identity server applications while executing query. Executed query: " + sql; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public boolean isSPApplicationExist(int identityServerId, String spUID, int appId, int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT AP_APP_ID AS ID " + + "FROM AP_IS_SP_APP_MAPPING SP_MAPPING " + + "WHERE " + + "SP_UID = ? AND AP_APP_ID = ? " + + "AND IS_ID = ? AND " + + "TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setString(1, spUID); + stmt.setInt(2, appId); + stmt.setInt(3, identityServerId); + stmt.setInt(4, tenantId); + try (ResultSet rs = stmt.executeQuery()){ + return rs.next(); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to check whether the existence of " + + "sp application with id " + appId + " for service provider which has UID " + spUID; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to check whether the existence of service provider application " + + "with id " + appId + " for service provider which has UID " + spUID + ". executed query " + sql; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public void detachSPApplication(int identityServerId, String spUID, int appId, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to map an application wit identity server:service provider"); + log.debug("Application Details : "); + log.debug("App ID : " + appId + " SP UID : " + spUID + " IS ID : " + identityServerId); + } + String sql = "DELETE FROM AP_IS_SP_APP_MAPPING " + + "WHERE SP_UID = ? " + + "AND AP_APP_ID = ? " + + "AND IS_ID = ? " + + "AND TENANT_ID = ? "; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setString(1, spUID); + stmt.setInt(2, appId); + stmt.setInt(3, identityServerId); + stmt.setInt(4, tenantId); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to create an sp application mapping which has " + + "application id " + appId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to create an application which has application id " + + appId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int attachSPApplication(int identityServerId, String spUID, int appId, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to map an application wit identity server:service provider"); + log.debug("Application Details : "); + log.debug("App ID : " + appId + " SP UID : " + spUID + " IS ID : " + identityServerId); + } + String sql = "INSERT INTO AP_IS_SP_APP_MAPPING " + + "(SP_UID, " + + "AP_APP_ID, " + + "IS_ID, TENANT_ID) " + + "VALUES (?, ?, ?, ?)"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setString(1, spUID); + stmt.setInt(2, appId); + stmt.setInt(3, identityServerId); + stmt.setInt(4, tenantId); + stmt.executeUpdate(); + try (ResultSet rs = stmt.getGeneratedKeys()) { + if (rs.next()) { + return rs.getInt(1); + } + return -1; + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to create an sp application mapping which has " + + "application id " + appId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to create an application which has application id " + + appId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public void deleteApplicationFromServiceProviders(int applicationId, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to delete application with the id: " + applicationId + " from service providers"); + } + String sql = "DELETE FROM AP_IS_SP_APP_MAPPING WHERE AP_APP_ID = ? AND TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setInt(1, applicationId); + stmt.setInt(2, tenantId); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to create an sp application mapping which has " + + "application id " + applicationId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to create an application which has application id " + + applicationId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public void deleteIdentityServer(int id, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to delete identity server with the id: " + id); + } + String sql = "DELETE FROM AP_IDENTITY_SERVER WHERE ID = ? AND TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setInt(1, id); + stmt.setInt(2, tenantId); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to delete an identity server with the id " + id; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to delete an identity server which has the id " + + id; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + +} diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/spapplication/SQLServerSPApplicationDAOImpl.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/spapplication/SQLServerSPApplicationDAOImpl.java new file mode 100644 index 0000000000..619b3214de --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/dao/impl/application/spapplication/SQLServerSPApplicationDAOImpl.java @@ -0,0 +1,487 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.core.dao.impl.application.spapplication; + +import io.entgra.application.mgt.common.dto.IdentityServerDTO; +import io.entgra.application.mgt.common.dto.ApplicationDTO; +import io.entgra.application.mgt.common.exception.DBConnectionException; +import io.entgra.application.mgt.core.dao.SPApplicationDAO; +import io.entgra.application.mgt.core.dao.impl.AbstractDAOImpl; +import io.entgra.application.mgt.core.exception.ApplicationManagementDAOException; +import io.entgra.application.mgt.core.exception.UnexpectedServerErrorException; +import io.entgra.application.mgt.core.util.DAOUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; + +public class SQLServerSPApplicationDAOImpl extends AbstractDAOImpl implements SPApplicationDAO { + + private static final Log log = LogFactory.getLog(SQLServerSPApplicationDAOImpl.class); + + @Override + public List getIdentityServers(int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT ID, PROVIDER_NAME, NAME, DESCRIPTION, URL, API_PARAMS, USERNAME, PASSWORD, TENANT_ID " + + "FROM AP_IDENTITY_SERVER " + + "WHERE TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setInt(1, tenantId); + try (ResultSet rs = stmt.executeQuery()){ + if (log.isDebugEnabled()) { + log.debug("Successfully retrieved available identity servers" ); + } + return DAOUtil.loadIdentityServers(rs); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to retrieve available identity servers"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to retrieve available identity servers"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public IdentityServerDTO getIdentityServerById(int id, int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT ID, PROVIDER_NAME, NAME, DESCRIPTION, URL, API_PARAMS, USERNAME, PASSWORD, TENANT_ID " + + "FROM AP_IDENTITY_SERVER " + + "WHERE TENANT_ID = ? AND " + + "ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setInt(1, tenantId); + stmt.setInt(2, id); + try (ResultSet rs = stmt.executeQuery()){ + if (log.isDebugEnabled()) { + log.debug("Successfully retrieved available identity servers" ); + } + return DAOUtil.loadIdentityServer(rs); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to retrieve available identity servers"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to retrieve available identity servers"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (UnexpectedServerErrorException e) { + String msg = "Found more than one identity server for id: " + id; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public boolean isExistingIdentityServerUrl(String url, int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT AP_APP.ID AS ID " + + "FROM AP_IDENTITY_SERVER " + + "WHERE " + + "LOWER(URL) = LOWER(?) AND " + + "AP_APP.TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setString(1, url); + stmt.setInt(2, tenantId); + try (ResultSet rs = stmt.executeQuery()){ + return rs.next(); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to check if identity server url: " + url + + " already exist"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to check if identity server with the url " + url + + " already exists."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public boolean isExistingIdentityServerName(String name, int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT AP_APP.ID AS ID " + + "FROM AP_IDENTITY_SERVER " + + "WHERE " + + "LOWER(NAME) = LOWER(?) AND " + + "AP_APP.TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setString(1, name); + stmt.setInt(2, tenantId); + try (ResultSet rs = stmt.executeQuery()){ + return rs.next(); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to check if identity server name: " + name + + " already exist"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to check if identity server with the name " + name + + " already exists."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public void updateIdentityServer(IdentityServerDTO updatedIdentityServerDTO, int tenantId, int identityServerId) + throws ApplicationManagementDAOException { + String sql = "UPDATE AP_IDENTITY_SERVER " + + "SET "; + if (updatedIdentityServerDTO.getName() != null) { + sql += "NAME = ?, "; + } + if (updatedIdentityServerDTO.getUrl() != null) { + sql += "URL = ?, "; + } + if (updatedIdentityServerDTO.getProviderName() != null) { + sql += "PROVIDER_NAME = ?, "; + } + if (updatedIdentityServerDTO.getUsername() != null) { + sql += "USERNAME = ?, "; + } + if (updatedIdentityServerDTO.getPassword() != null) { + sql += "PASSWORD = ?, "; + } + if (updatedIdentityServerDTO.getDescription() != null) { + sql += "DESCRIPTION = ?, "; + } + sql += "API_PARAMS = ? " + + "WHERE ID = ? AND TENANT_ID = ?"; + + try { + int index = 1; + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + if (updatedIdentityServerDTO.getName() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getName()); + } + if (updatedIdentityServerDTO.getUrl() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getUrl()); + } + if (updatedIdentityServerDTO.getProviderName() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getProviderName()); + } + if (updatedIdentityServerDTO.getUsername() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getUsername()); + } + if (updatedIdentityServerDTO.getPassword() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getPassword()); + } + if (updatedIdentityServerDTO.getDescription() != null) { + stmt.setString(index++, updatedIdentityServerDTO.getDescription()); + } + stmt.setString(index++, updatedIdentityServerDTO.constructApiParamsJsonString()); + stmt.setInt(index++, identityServerId); + stmt.setInt(index, tenantId); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to update identity server."; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred when executing SQL to update identity server. Executed query: " + sql; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int createIdentityServer(IdentityServerDTO identityServerDTO, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to create an identity server"); + } + String sql = "INSERT INTO AP_IDENTITY_SERVER " + + "(PROVIDER_NAME, " + + "NAME, " + + "DESCRIPTION, URL, API_PARAMS, USERNAME, PASSWORD, TENANT_ID) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setString(1, identityServerDTO.getProviderName()); + stmt.setString(2, identityServerDTO.getName()); + stmt.setString(3, identityServerDTO.getDescription()); + stmt.setString(4, identityServerDTO.getUrl()); + stmt.setString(5, identityServerDTO.constructApiParamsJsonString()); + stmt.setString(6, identityServerDTO.getUsername()); + stmt.setString(7, identityServerDTO.getPassword()); + stmt.setInt(8, tenantId); + stmt.executeUpdate(); + try (ResultSet rs = stmt.getGeneratedKeys()) { + if (rs.next()) { + return rs.getInt(1); + } + return -1; + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while creating identity server "; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to create an identity server "; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public List getSPApplications(int identityServerId, String spUID, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Getting identity server applications from the database"); + } + String sql = "SELECT " + + "AP_APP.ID AS APP_ID, " + + "AP_APP.NAME AS APP_NAME, " + + "AP_APP.DESCRIPTION AS APP_DESCRIPTION, " + + "AP_APP.TYPE AS APP_TYPE, " + + "AP_APP.STATUS AS APP_STATUS, " + + "AP_APP.SUB_TYPE AS APP_SUB_TYPE, " + + "AP_APP.CURRENCY AS APP_CURRENCY, " + + "AP_APP.RATING AS APP_RATING, " + + "AP_APP.DEVICE_TYPE_ID AS APP_DEVICE_TYPE_ID, " + + "AP_APP_RELEASE.ID AS RELEASE_ID, " + + "AP_APP_RELEASE.DESCRIPTION AS RELEASE_DESCRIPTION, " + + "AP_APP_RELEASE.VERSION AS RELEASE_VERSION, " + + "AP_APP_RELEASE.UUID AS RELEASE_UUID, " + + "AP_APP_RELEASE.RELEASE_TYPE AS RELEASE_TYPE, " + + "AP_APP_RELEASE.INSTALLER_LOCATION AS AP_RELEASE_STORED_LOC, " + + "AP_APP_RELEASE.ICON_LOCATION AS AP_RELEASE_ICON_LOC, " + + "AP_APP_RELEASE.BANNER_LOCATION AS AP_RELEASE_BANNER_LOC, " + + "AP_APP_RELEASE.SC_1_LOCATION AS AP_RELEASE_SC1, " + + "AP_APP_RELEASE.SC_2_LOCATION AS AP_RELEASE_SC2, " + + "AP_APP_RELEASE.SC_3_LOCATION AS AP_RELEASE_SC3, " + + "AP_APP_RELEASE.APP_HASH_VALUE AS RELEASE_HASH_VALUE, " + + "AP_APP_RELEASE.APP_PRICE AS RELEASE_PRICE, " + + "AP_APP_RELEASE.APP_META_INFO AS RELEASE_META_INFO, " + + "AP_APP_RELEASE.PACKAGE_NAME AS PACKAGE_NAME, " + + "AP_APP_RELEASE.SUPPORTED_OS_VERSIONS AS RELEASE_SUP_OS_VERSIONS, " + + "AP_APP_RELEASE.RATING AS RELEASE_RATING, " + + "AP_APP_RELEASE.CURRENT_STATE AS RELEASE_CURRENT_STATE, " + + "AP_APP_RELEASE.RATED_USERS AS RATED_USER_COUNT " + + "FROM AP_APP " + + "LEFT JOIN AP_APP_RELEASE ON " + + "AP_APP.ID = AP_APP_RELEASE.AP_APP_ID AND " + + "AP_APP.TENANT_ID = AP_APP_RELEASE.TENANT_ID " + + "INNER JOIN AP_IS_SP_APP_MAPPING as SP_APPS on SP_APPS.AP_APP_ID = AP_APP.ID " + + "WHERE " + + "SP_APPS.SP_UID = ? " + + "AND SP_APPS.IS_ID = ? " + + "AND AP_APP.TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setString(1, spUID); + stmt.setInt(2, identityServerId); + stmt.setInt(3, tenantId); + try (ResultSet rs = stmt.executeQuery()) { + if (log.isDebugEnabled()) { + log.debug("Successfully retrieved basic details of the identity server applications"); + } + return DAOUtil.loadApplications(rs); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to get identity server applications for application release"; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while getting identity server applications while executing query. Executed query: " + sql; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public boolean isSPApplicationExist(int identityServerId, String spUID, int appId, int tenantId) throws ApplicationManagementDAOException { + String sql = "SELECT AP_APP_ID AS ID " + + "FROM AP_IS_SP_APP_MAPPING SP_MAPPING " + + "WHERE " + + "SP_UID = ? AND AP_APP_ID = ? " + + "AND IS_ID = ? AND " + + "TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + stmt.setString(1, spUID); + stmt.setInt(2, appId); + stmt.setInt(3, identityServerId); + stmt.setInt(4, tenantId); + try (ResultSet rs = stmt.executeQuery()){ + return rs.next(); + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to check whether the existence of " + + "sp application with id " + appId + " for service provider which has UID " + spUID; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing query to check whether the existence of service provider application " + + "with id " + appId + " for service provider which has UID " + spUID + ". executed query " + sql; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public void detachSPApplication(int identityServerId, String spUID, int appId, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to map an application wit identity server:service provider"); + log.debug("Application Details : "); + log.debug("App ID : " + appId + " SP UID : " + spUID + " IS ID : " + identityServerId); + } + String sql = "DELETE FROM AP_IS_SP_APP_MAPPING " + + "WHERE SP_UID = ? " + + "AND AP_APP_ID = ? " + + "AND IS_ID = ? " + + "AND TENANT_ID = ? "; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setString(1, spUID); + stmt.setInt(2, appId); + stmt.setInt(3, identityServerId); + stmt.setInt(4, tenantId); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to create an sp application mapping which has " + + "application id " + appId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to create an application which has application id " + + appId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public int attachSPApplication(int identityServerId, String spUID, int appId, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to map an application wit identity server:service provider"); + log.debug("Application Details : "); + log.debug("App ID : " + appId + " SP UID : " + spUID + " IS ID : " + identityServerId); + } + String sql = "INSERT INTO AP_IS_SP_APP_MAPPING " + + "(SP_UID, " + + "AP_APP_ID, " + + "IS_ID, TENANT_ID) " + + "VALUES (?, ?, ?, ?)"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setString(1, spUID); + stmt.setInt(2, appId); + stmt.setInt(3, identityServerId); + stmt.setInt(4, tenantId); + stmt.executeUpdate(); + try (ResultSet rs = stmt.getGeneratedKeys()) { + if (rs.next()) { + return rs.getInt(1); + } + return -1; + } + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to create an sp application mapping which has " + + "application id " + appId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to create an application which has application id " + + appId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public void deleteApplicationFromServiceProviders(int applicationId, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to delete application with the id: " + applicationId + " from service providers"); + } + String sql = "DELETE FROM AP_IS_SP_APP_MAPPING WHERE AP_APP_ID = ? AND TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setInt(1, applicationId); + stmt.setInt(2, tenantId); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to delete an sp application mapping which has " + + "application id " + applicationId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to delete an application which has application id " + + applicationId; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + + @Override + public void deleteIdentityServer(int id, int tenantId) throws ApplicationManagementDAOException { + if (log.isDebugEnabled()) { + log.debug("Request received in DAO Layer to delete identity server with the id: " + id); + } + String sql = "DELETE FROM AP_IDENTITY_SERVER WHERE ID = ? AND TENANT_ID = ?"; + try { + Connection conn = this.getDBConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setInt(1, id); + stmt.setInt(2, tenantId); + stmt.executeUpdate(); + } + } catch (DBConnectionException e) { + String msg = "Error occurred while obtaining the DB connection to delete an identity server with the id " + id; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while executing SQL to delete an identity server which has the id " + + id; + log.error(msg, e); + throw new ApplicationManagementDAOException(msg, e); + } + } + +} diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/identityserver/serviceprovider/ISServiceProviderApplicationService.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/identityserver/serviceprovider/ISServiceProviderApplicationService.java new file mode 100644 index 0000000000..2f603fae68 --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/identityserver/serviceprovider/ISServiceProviderApplicationService.java @@ -0,0 +1,85 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.core.identityserver.serviceprovider; + +import io.entgra.application.mgt.common.SPApplication; +import io.entgra.application.mgt.common.SPApplicationListResponse; +import io.entgra.application.mgt.common.dto.IdentityServerDTO; +import io.entgra.application.mgt.common.exception.ApplicationManagementException; +import io.entgra.application.mgt.common.exception.InvalidConfigurationException; +import io.entgra.application.mgt.core.config.ConfigurationManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.lang.reflect.Constructor; +import java.util.List; + +public interface ISServiceProviderApplicationService { + + Log log = LogFactory.getLog(ISServiceProviderApplicationService.class); + + static ISServiceProviderApplicationService of(String identityServerName) throws InvalidConfigurationException { + String className = ConfigurationManager.getInstance().getIdentityServerConfiguration(). + getIdentityServerDetailByProviderName(identityServerName).getProviderClassName(); + try { + Class theClass = Class.forName(className); + Constructor constructor = theClass.getConstructor(); + return constructor.newInstance(); + } catch (Exception e) { + String msg = "Unable to get instance of " + className; + log.error(msg, e); + throw new InvalidConfigurationException(msg, e); + } + } + + /** + * Use to get IS Service specific api params + * + * @return IS Service specific api params + */ + List getRequiredApiParams(); + + /** + * Check if service provider application exists + * + * @param identityServer {@link IdentityServerDTO} + * @param spAppId uid of the service provider + * @return if service provider exist + * @throws ApplicationManagementException + */ + boolean isSPApplicationExist(IdentityServerDTO identityServer, String spAppId) throws ApplicationManagementException; + + /** + * Get service provider by identity server id and service provider uid + * @param identityServer {@link IdentityServerDTO} + * @param spAppId uid of service provider to be retrieved + * @return {@link SPApplication} + * @throws ApplicationManagementException + */ + SPApplication retrieveSPApplication(IdentityServerDTO identityServer, String spAppId) throws ApplicationManagementException; + + /** + * Retrieve service provider apps from identity server + * + * @param identityServer {@link IdentityServerDTO} + * @return {@link SPApplicationListResponse} + * @throws ApplicationManagementException + */ + SPApplicationListResponse retrieveSPApplications(IdentityServerDTO identityServer, Integer limit, Integer offset) + throws ApplicationManagementException; +} diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/identityserver/serviceprovider/impl/WSO2IAMSPApplicationService.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/identityserver/serviceprovider/impl/WSO2IAMSPApplicationService.java new file mode 100644 index 0000000000..2dc5a91e27 --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/identityserver/serviceprovider/impl/WSO2IAMSPApplicationService.java @@ -0,0 +1,170 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.core.identityserver.serviceprovider.impl; + +import com.google.gson.Gson; +import io.entgra.application.mgt.common.SPApplication; +import io.entgra.application.mgt.common.SPApplicationListResponse; +import io.entgra.application.mgt.common.dto.IdentityServerDTO; +import io.entgra.application.mgt.common.exception.ApplicationManagementException; +import io.entgra.application.mgt.common.exception.IdentityServerManagementException; +import io.entgra.application.mgt.core.identityserver.serviceprovider.ISServiceProviderApplicationService; +import io.entgra.application.mgt.core.util.Constants; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.wso2.carbon.device.mgt.core.common.util.HttpUtil; +import javax.ws.rs.core.HttpHeaders; +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +public class WSO2IAMSPApplicationService implements ISServiceProviderApplicationService { + + private static final List REQUIRED_API_PARAM_LIST; + private static final String TENANT_DOMAIN = "Tenant domain"; + private static final String SP_APPLICATION_API_CONTEXT = "/t/%s/api/server/v1/applications"; + private static final Log log = LogFactory.getLog(WSO2IAMSPApplicationService.class); + + static { + REQUIRED_API_PARAM_LIST = Collections.singletonList(TENANT_DOMAIN); + } + + public List getRequiredApiParams() { + return REQUIRED_API_PARAM_LIST; + } + + public boolean isSPApplicationExist(IdentityServerDTO identityServer, String spAppId) throws ApplicationManagementException { + SPApplication application = retrieveSPApplication(identityServer, spAppId); + return application != null; + } + + public SPApplication retrieveSPApplication(IdentityServerDTO identityServer, String spAppId) throws ApplicationManagementException { + HttpGet req = new HttpGet(); + String uriString = constructAPIUrl(identityServer); + uriString += Constants.FORWARD_SLASH + spAppId; + req.setURI(HttpUtil.createURI(uriString)); + try (CloseableHttpClient client = HttpClients.createDefault()) { + HttpResponse response = invokeISAPI(identityServer, client, req); + String responseBody = HttpUtil.getResponseString(response); + if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { + return new Gson().fromJson(responseBody, + SPApplication.class); + } + if (response.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_FOUND) { + return null; + } + String msg = constructErrorMessage(response); + log.error(msg); + throw new IdentityServerManagementException(msg); + } catch (IOException e) { + String msg = "Error occurred while calling SP Applications API. Make sure identity server is up and running"; + log.error(msg, e); + throw new IdentityServerManagementException(msg, e); + } + } + + /** + * Construct error message string depending on service providers api response + * (I.E If unauthorized a different message will be returned) + * + * @param response of the service provider api call + * @return constructed error message + */ + private String constructErrorMessage(HttpResponse response) { + String msg = "Error occurred while calling SP Applications API"; + if (response.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + msg += ". Make sure provided identity Server credentials are valid"; + } + return msg; + } + + public SPApplicationListResponse retrieveSPApplications(IdentityServerDTO identityServer, Integer limit, Integer offset) + throws ApplicationManagementException { + HttpGet req = new HttpGet(); + String uriString = constructAPIUrl(identityServer); + uriString += Constants.URI_QUERY_SEPARATOR + Constants.LIMIT_QUERY_PARAM + Constants.QUERY_KEY_VALUE_SEPARATOR + + limit; + uriString += Constants.QUERY_STRING_SEPARATOR + Constants.OFFSET_QUERY_PARAM + Constants.QUERY_KEY_VALUE_SEPARATOR + + offset; + req.setURI(HttpUtil.createURI(uriString)); + try (CloseableHttpClient client = HttpClients.createDefault()) { + HttpResponse response = invokeISAPI(identityServer, client, req); + String responseBody = HttpUtil.getResponseString(response); + if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { + return new Gson().fromJson(responseBody, + SPApplicationListResponse.class); + } + String msg = constructErrorMessage(response); + log.error(msg); + throw new IdentityServerManagementException(msg); + } catch (IOException e) { + String msg = "Error occurred while calling SP Applications API. Make sure identity server is up and running"; + log.error(msg, e); + throw new IdentityServerManagementException(msg, e); + } + } + + /** + * Takes essential prerequisite steps (I.E setting authorization header), + * invokes provided GET request and returns the response + * + * @param identityServer {@link IdentityServerDTO} + * @param client httpClient that should be used to invoke + * @param request GET request to be invoked + * @return response of the invoked api + */ + private HttpResponse invokeISAPI(IdentityServerDTO identityServer, HttpClient client, HttpGet request) throws IOException { + setBasicAuthHeader(identityServer, request); + return client.execute(request); + } + + /** + * Add basic auth header to provided service provider api request by getting the username and password + * from identity server bean + * + * @param identityServer {@link IdentityServerDTO} + * @param request service provider api request + */ + private void setBasicAuthHeader(IdentityServerDTO identityServer, HttpRequestBase request) { + String basicAuthHeader = HttpUtil.getBasicAuthBase64Header(identityServer.getUsername(), + identityServer.getPassword()); + request.setHeader(HttpHeaders.AUTHORIZATION, basicAuthHeader); + } + + /** + * Helps to construct service provider api base url + * + * @param identityServer {@link IdentityServerDTO} + * @return constructed service providers api url + */ + private String constructAPIUrl(IdentityServerDTO identityServer) { + String identityServerUrl = identityServer.getUrl(); + // add "/" at the end, if the server url doesn't contain "/" at the end + if (identityServerUrl.charAt(identityServerUrl.length() - 1) != Constants.FORWARD_SLASH.charAt(0)) { + identityServerUrl += Constants.FORWARD_SLASH; + } + return identityServerUrl + String.format(SP_APPLICATION_API_CONTEXT, identityServer.getApiParams().get(TENANT_DOMAIN)); + } +} \ No newline at end of file diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/impl/ApplicationManagerImpl.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/impl/ApplicationManagerImpl.java index 5b1fb55588..b7fce45b1a 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/impl/ApplicationManagerImpl.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/impl/ApplicationManagerImpl.java @@ -17,6 +17,9 @@ package io.entgra.application.mgt.core.impl; +import io.entgra.application.mgt.common.Base64File; +import io.entgra.application.mgt.core.dao.SPApplicationDAO; +import io.entgra.application.mgt.core.util.ApplicationManagementUtil; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringEscapeUtils; @@ -109,8 +112,7 @@ import java.util.stream.Stream; /** * Default Concrete implementation of Application Management related implementations. */ -public class -ApplicationManagerImpl implements ApplicationManager { +public class ApplicationManagerImpl implements ApplicationManager { private static final Log log = LogFactory.getLog(ApplicationManagerImpl.class); private VisibilityDAO visibilityDAO; @@ -119,6 +121,7 @@ ApplicationManagerImpl implements ApplicationManager { private LifecycleStateDAO lifecycleStateDAO; private SubscriptionDAO subscriptionDAO; private LifecycleStateManager lifecycleStateManager; + private SPApplicationDAO spApplicationDAO; public ApplicationManagerImpl() { initDataAccessObjects(); @@ -131,51 +134,186 @@ ApplicationManagerImpl implements ApplicationManager { this.lifecycleStateDAO = ApplicationManagementDAOFactory.getLifecycleStateDAO(); this.applicationReleaseDAO = ApplicationManagementDAOFactory.getApplicationReleaseDAO(); this.subscriptionDAO = ApplicationManagementDAOFactory.getSubscriptionDAO(); + this.spApplicationDAO = ApplicationManagementDAOFactory.getSPApplicationDAO(); } @Override - public Application createEntApp(ApplicationWrapper applicationWrapper, - ApplicationArtifact applicationArtifact, boolean isPublished) throws ApplicationManagementException { - if (log.isDebugEnabled()) { - log.debug("Ent. Application create request is received. Application name: " + applicationWrapper.getName() - + " Device type: " + applicationWrapper.getDeviceType()); + public Application createApplication(T app, boolean isPublished) throws ApplicationManagementException { + ApplicationDTO applicationDTO = uploadReleaseArtifactIfExist(app); + try { + ConnectionManagerUtil.beginDBTransaction(); + Application application = addAppDataIntoDB(applicationDTO, isPublished); + ConnectionManagerUtil.commitDBTransaction(); + return application; + } catch (DBConnectionException e) { + String msg = "Error occurred while getting database connection."; + log.error(msg, e); + ApplicationManagementUtil.deleteArtifactIfExist(applicationDTO); + throw new ApplicationManagementException(msg, e); + } catch (TransactionManagementException e) { + String msg = "Error occurred while disabling AutoCommit."; + log.error(msg, e); + ApplicationManagementUtil.deleteArtifactIfExist(applicationDTO); + throw new ApplicationManagementException(msg, e); + } catch (ApplicationManagementException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + ApplicationManagementUtil.deleteArtifactIfExist(applicationDTO); + String msg = "Error occurred while adding application with the name " + applicationDTO.getName() + " to database "; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); } - int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); - ApplicationDTO applicationDTO = APIUtil.convertToAppDTO(applicationWrapper); + } - //uploading application artifacts - ApplicationReleaseDTO applicationReleaseDTO = uploadEntAppReleaseArtifacts( - applicationDTO.getApplicationReleaseDTOs().get(0), applicationArtifact, - applicationWrapper.getDeviceType(), tenantId, false); - applicationDTO.getApplicationReleaseDTOs().clear(); - applicationDTO.getApplicationReleaseDTOs().add(applicationReleaseDTO); - return addAppDataIntoDB(applicationDTO, tenantId, isPublished); + @Override + public ApplicationRelease createEntAppRelease(int appId, EntAppReleaseWrapper releaseWrapper, boolean isPublished) + throws ApplicationManagementException { + ApplicationManager applicationManager = APIUtil.getApplicationManager(); + ApplicationArtifact artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIcon(), releaseWrapper.getScreenshots(), + releaseWrapper.getBinaryFile(), releaseWrapper.getBanner()); + ApplicationDTO applicationDTO = applicationManager.getApplication(appId); + DeviceType deviceType = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId()); + ApplicationReleaseDTO releaseDTO = APIUtil.releaseWrapperToReleaseDTO(releaseWrapper); + releaseDTO = uploadEntAppReleaseArtifacts(releaseDTO, artifact, deviceType.getName(), true); + try { + return createRelease(applicationDTO, releaseDTO, ApplicationType.ENTERPRISE, isPublished); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while creating ent app release for application with the name: " + applicationDTO.getName(); + log.error(msg, e); + deleteApplicationArtifacts(Collections.singletonList(releaseDTO.getAppHashValue())); + throw new ApplicationManagementException(msg, e); + } + } + + @Override + public ApplicationRelease createWebAppRelease(int appId, WebAppReleaseWrapper releaseWrapper, boolean isPublished) + throws ApplicationManagementException, ResourceManagementException { + ApplicationManager applicationManager = APIUtil.getApplicationManager(); + ApplicationDTO applicationDTO = applicationManager.getApplication(appId); + ApplicationArtifact artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIcon(), + releaseWrapper.getScreenshots(), null, releaseWrapper.getBanner()); + ApplicationReleaseDTO releaseDTO = APIUtil.releaseWrapperToReleaseDTO(releaseWrapper); + releaseDTO = uploadWebAppReleaseArtifacts(releaseDTO, artifact); + try { + return createRelease(applicationDTO, releaseDTO, ApplicationType.WEB_CLIP, isPublished); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while creating web app release for application with the name: " + applicationDTO.getName(); + log.error(msg, e); + deleteApplicationArtifacts(Collections.singletonList(releaseDTO.getAppHashValue())); + throw new ApplicationManagementException(msg, e); + } } @Override - public Application createWebClip(WebAppWrapper webAppWrapper, ApplicationArtifact applicationArtifact, boolean isPublished) + public ApplicationRelease createPubAppRelease(int appId, PublicAppReleaseWrapper releaseWrapper, boolean isPublished) throws + ResourceManagementException, ApplicationManagementException { + ApplicationManager applicationManager = APIUtil.getApplicationManager(); + ApplicationDTO applicationDTO = applicationManager.getApplication(appId); + DeviceType deviceType = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId()); + ApplicationArtifact artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIcon(), + releaseWrapper.getScreenshots(), null, releaseWrapper.getBanner()); + ApplicationReleaseDTO releaseDTO = APIUtil.releaseWrapperToReleaseDTO(releaseWrapper); + releaseDTO = uploadPubAppReleaseArtifacts(releaseDTO, artifact, deviceType.getName()); + try { + return createRelease(applicationDTO, releaseDTO, ApplicationType.PUBLIC, isPublished); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while creating ent public release for application with the name: " + applicationDTO.getName(); + log.error(msg, e); + deleteApplicationArtifacts(Collections.singletonList(releaseDTO.getAppHashValue())); + throw new ApplicationManagementException(msg, e); + } + } + + @Override + public ApplicationRelease createCustomAppRelease(int appId, CustomAppReleaseWrapper releaseWrapper, boolean isPublished) + throws ResourceManagementException, ApplicationManagementException { + ApplicationManager applicationManager = APIUtil.getApplicationManager(); + ApplicationDTO applicationDTO = applicationManager.getApplication(appId); + DeviceType deviceType = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId()); + ApplicationArtifact artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIcon(), + releaseWrapper.getScreenshots(), releaseWrapper.getBinaryFile(), releaseWrapper.getBanner()); + ApplicationReleaseDTO releaseDTO = APIUtil.releaseWrapperToReleaseDTO(releaseWrapper); + releaseDTO = uploadCustomAppReleaseArtifacts(releaseDTO, artifact, deviceType.getName()); + try { + return createRelease(applicationDTO, releaseDTO, ApplicationType.CUSTOM, isPublished); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while creating custom app release for application with the name: " + applicationDTO.getName(); + log.error(msg, e); + deleteApplicationArtifacts(Collections.singletonList(releaseDTO.getAppHashValue())); + throw new ApplicationManagementException(msg, e); + } + } + + @Override + public ApplicationDTO uploadReleaseArtifactIfExist(T app) throws ApplicationManagementException { + if (ApplicationManagementUtil.isReleaseAvailable(app)) { + return uploadReleaseArtifact(app); + } + return APIUtil.convertToAppDTO(app); + } + + /** + * Upload release artifacts depending on the application wrapper type + * + * @param app Application wrapper bean + * @param Application Wrapper class + * @return ApplicationDTO that is constructed after uploading the artifacts + * @throws ApplicationManagementException if any error occurred while uploading artifacts + */ + private ApplicationDTO uploadReleaseArtifact(T app) throws ApplicationManagementException { + ApplicationArtifact artifact; + ApplicationDTO applicationDTO = APIUtil.convertToAppDTO(app); + ApplicationReleaseDTO releaseDTO = applicationDTO.getApplicationReleaseDTOs().get(0); if (log.isDebugEnabled()) { - log.debug("Web clip create request is received. App name: " + webAppWrapper.getName() + " Device type: " - + Constants.ANY); + log.debug("Ent. Application create request is received. Application name: " + applicationDTO.getName()); } - int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); - ApplicationDTO applicationDTO = APIUtil.convertToAppDTO(webAppWrapper); - ApplicationReleaseDTO applicationReleaseDTO = applicationDTO.getApplicationReleaseDTOs().get(0); - applicationReleaseDTO.setUuid(UUID.randomUUID().toString()); - applicationReleaseDTO.setAppHashValue(DigestUtils.md5Hex(applicationReleaseDTO.getInstallerName())); - //uploading application artifacts try { - applicationDTO.getApplicationReleaseDTOs().clear(); - applicationDTO.getApplicationReleaseDTOs() - .add(addImageArtifacts(applicationReleaseDTO, applicationArtifact, tenantId)); + if (app instanceof ApplicationWrapper) { + ApplicationWrapper wrapper = (ApplicationWrapper) app; + EntAppReleaseWrapper releaseWrapper = wrapper.getEntAppReleaseWrappers().get(0); + artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIcon(), + releaseWrapper.getScreenshots(), releaseWrapper.getBinaryFile(), releaseWrapper.getBanner()); + releaseDTO = uploadEntAppReleaseArtifacts(releaseDTO, + artifact, wrapper.getDeviceType(), false); + } else if (app instanceof PublicAppWrapper) { + PublicAppWrapper wrapper = (PublicAppWrapper) app; + PublicAppReleaseWrapper releaseWrapper = wrapper.getPublicAppReleaseWrappers().get(0); + artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIcon(), + releaseWrapper.getScreenshots(), null, releaseWrapper.getBanner()); + releaseDTO = uploadPubAppReleaseArtifacts(releaseDTO, artifact, wrapper.getDeviceType()); + } else if (app instanceof WebAppWrapper) { + WebAppWrapper wrapper = (WebAppWrapper) app; + WebAppReleaseWrapper releaseWrapper = wrapper.getWebAppReleaseWrappers().get(0); + artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIcon(), + releaseWrapper.getScreenshots(), null, releaseWrapper.getBanner()); + releaseDTO = uploadWebAppReleaseArtifacts(releaseDTO, artifact); + } else if (app instanceof CustomAppWrapper) { + CustomAppWrapper wrapper = (CustomAppWrapper) app; + CustomAppReleaseWrapper releaseWrapper = wrapper.getCustomAppReleaseWrappers().get(0); + artifact = ApplicationManagementUtil.constructApplicationArtifact(releaseWrapper.getIcon(), + releaseWrapper.getScreenshots(), releaseWrapper.getBinaryFile(), releaseWrapper.getBanner()); + try { + releaseDTO = uploadCustomAppReleaseArtifacts(releaseDTO, artifact, wrapper.getDeviceType()); + } catch (ResourceManagementException e) { + String msg = "Error Occurred when uploading artifacts of the web clip: " + wrapper.getName(); + log.error(msg); + throw new ApplicationManagementException(msg, e); + } + } else { + String msg = "Invalid payload found with the request. Hence verify the request payload object."; + log.error(msg); + throw new ApplicationManagementException(msg); + } } catch (ResourceManagementException e) { - String msg = "Error Occured when uploading artifacts of the web clip: " + webAppWrapper.getName(); + String msg = "Error Occurred when uploading artifacts of the web clip: " + applicationDTO.getName(); log.error(msg); throw new ApplicationManagementException(msg, e); } - //insert application data into database - return addAppDataIntoDB(applicationDTO, tenantId, isPublished); + applicationDTO.getApplicationReleaseDTOs().clear(); + applicationDTO.getApplicationReleaseDTOs().add(releaseDTO); + return applicationDTO; } @Override @@ -288,120 +426,190 @@ ApplicationManagerImpl implements ApplicationManager { } } - @Override - public Application createPublicApp(PublicAppWrapper publicAppWrapper, ApplicationArtifact applicationArtifact, boolean isPublished) + /** + * Upload enterprise application release artifact into file system. + * + * @param releaseDTO Application Release + * @param applicationArtifact Application Release artifacts + * @param deviceTypeName Device Type name + * @param isNewRelease New Release or Not + * @return {@link ApplicationReleaseDTO} + * @throws ApplicationManagementException if error occurred while uploading artifacts into file system. + */ + private ApplicationReleaseDTO uploadEntAppReleaseArtifacts(ApplicationReleaseDTO releaseDTO, + ApplicationArtifact applicationArtifact, String deviceTypeName, boolean isNewRelease) throws ApplicationManagementException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); - - if (log.isDebugEnabled()) { - log.debug("Public app creating request is received. App name: " + publicAppWrapper.getName() - + " Device Type: " + publicAppWrapper.getDeviceType()); + try { + ApplicationReleaseDTO applicationReleaseDTO = addApplicationReleaseArtifacts(deviceTypeName, releaseDTO, + applicationArtifact, isNewRelease); + return addImageArtifacts(applicationReleaseDTO, applicationArtifact, tenantId); + } catch (ResourceManagementException e) { + String msg = "Error occurred while uploading application release artifacts."; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); } + } - String publicAppStorePath = ""; - if (DeviceTypes.ANDROID.toString().equalsIgnoreCase(publicAppWrapper.getDeviceType())) { - publicAppStorePath = Constants.GOOGLE_PLAY_STORE_URL; - } else if (DeviceTypes.IOS.toString().equals(publicAppWrapper.getDeviceType())) { - publicAppStorePath = Constants.APPLE_STORE_URL; - } - ApplicationDTO applicationDTO = APIUtil.convertToAppDTO(publicAppWrapper); - ApplicationReleaseDTO applicationReleaseDTO = applicationDTO.getApplicationReleaseDTOs().get(0); - String appInstallerUrl = publicAppStorePath + applicationReleaseDTO.getPackageName(); - applicationReleaseDTO.setInstallerName(appInstallerUrl); - applicationReleaseDTO.setUuid(UUID.randomUUID().toString()); - applicationReleaseDTO.setAppHashValue(DigestUtils.md5Hex(appInstallerUrl)); + /** + * Use to upload/save web app release artifacts (I.E icon) + * + * @param releaseDTO {@link ApplicationReleaseDTO} + * @param applicationArtifact {@link ApplicationArtifact} + * @return constructed {@link ApplicationReleaseDTO} with upload details + * @throws ResourceManagementException if error occurred while uploading + */ + private ApplicationReleaseDTO uploadWebAppReleaseArtifacts(ApplicationReleaseDTO releaseDTO, ApplicationArtifact applicationArtifact) + throws ResourceManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + releaseDTO.setUuid(UUID.randomUUID().toString()); + releaseDTO.setAppHashValue(DigestUtils.md5Hex(releaseDTO.getInstallerName())); + //uploading application artifacts + return addImageArtifacts(releaseDTO, applicationArtifact, tenantId); + } + /** + * Use to upload/save public app release artifacts (I.E icon) + * + * @param releaseDTO {@link ApplicationReleaseDTO} + * @param applicationArtifact {@link ApplicationArtifact} + * @param deviceType Device Type name + * @return constructed {@link ApplicationReleaseDTO} with upload details + * @throws ResourceManagementException if error occurred while uploading + */ + private ApplicationReleaseDTO uploadPubAppReleaseArtifacts(ApplicationReleaseDTO releaseDTO, ApplicationArtifact applicationArtifact, + String deviceType) + throws ResourceManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + String appInstallerUrl = getPublicAppStorePath(deviceType) + releaseDTO.getPackageName(); + releaseDTO.setInstallerName(appInstallerUrl); + releaseDTO.setUuid(UUID.randomUUID().toString()); + releaseDTO.setAppHashValue(DigestUtils.md5Hex(appInstallerUrl)); + //uploading application artifacts + return addImageArtifacts(releaseDTO, applicationArtifact, tenantId); + } + + public void validatePublicAppReleasePackageName(String packageName) throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); try { ConnectionManagerUtil.openDBConnection(); List exitingPubAppReleases = applicationReleaseDAO - .getReleaseByPackages(Collections.singletonList(applicationReleaseDTO.getPackageName()), tenantId); + .getReleaseByPackages(Collections.singletonList(packageName), tenantId); if (!exitingPubAppReleases.isEmpty()){ - String msg = "Public app release exists for package name " + applicationReleaseDTO.getPackageName() + String msg = "Public app release exists for package name " + packageName + ". Hence you can't add new public app for package name " - + applicationReleaseDTO.getPackageName(); + + packageName; log.error(msg); throw new BadRequestException(msg); } } catch (ApplicationManagementDAOException e) { - String msg = "Error Occured when fetching release: " + publicAppWrapper.getName(); + String msg = "Error Occurred when fetching release: " + packageName; log.error(msg); throw new ApplicationManagementException(msg, e); } finally { ConnectionManagerUtil.closeDBConnection(); } + } - try { - //uploading application artifacts - applicationReleaseDTO = addImageArtifacts(applicationReleaseDTO, applicationArtifact, tenantId); - applicationDTO.getApplicationReleaseDTOs().clear(); - applicationDTO.getApplicationReleaseDTOs().add(applicationReleaseDTO); - } catch (ResourceManagementException e) { - String msg = "Error Occured when uploading artifacts of the public app: " + publicAppWrapper.getName(); - log.error(msg, e); + /** + * Use to upload/save public app release artifacts (I.E icon) + * + * @param releaseDTO {@link ApplicationReleaseDTO} + * @param applicationArtifact {@link ApplicationArtifact} + * @param deviceType Device Type name + * @return constructed {@link ApplicationReleaseDTO} with upload details + * @throws ResourceManagementException if error occurred while uploading + */ + private ApplicationReleaseDTO uploadCustomAppReleaseArtifacts(ApplicationReleaseDTO releaseDTO, ApplicationArtifact applicationArtifact, + String deviceType) + throws ResourceManagementException, ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + ApplicationStorageManager applicationStorageManager = APIUtil.getApplicationStorageManager(); + byte[] content = getByteContentOfApp(applicationArtifact); + String md5OfApp = generateMD5OfApp(applicationArtifact, content); + validateReleaseBinaryFileHash(md5OfApp); + releaseDTO.setUuid(UUID.randomUUID().toString()); + releaseDTO.setAppHashValue(md5OfApp); + releaseDTO.setInstallerName(applicationArtifact.getInstallerName()); + + try (ByteArrayInputStream binaryDuplicate = new ByteArrayInputStream(content)) { + applicationStorageManager.uploadReleaseArtifact(releaseDTO, deviceType, + binaryDuplicate, tenantId); + } catch (IOException e) { + String msg = "Error occurred when uploading release artifact into the server"; + log.error(msg); throw new ApplicationManagementException(msg, e); } - //insert application data into database - return addAppDataIntoDB(applicationDTO, tenantId, isPublished); + return addImageArtifacts(releaseDTO, applicationArtifact, tenantId); } - @Override - public Application createCustomApp(CustomAppWrapper customAppWrapper, ApplicationArtifact applicationArtifact, boolean isPublished) + public void validateReleaseBinaryFileHash(String hash) throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); try { - int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); - ApplicationStorageManager applicationStorageManager = APIUtil.getApplicationStorageManager(); - byte[] content = IOUtils.toByteArray(applicationArtifact.getInstallerStream()); - String md5OfApp = StorageManagementUtil.getMD5(new ByteArrayInputStream(content)); - if (md5OfApp == null) { - String msg = - "Error occurred while getting md5sum value of custom app. Application name: " + customAppWrapper - .getName() + " Device type: " + customAppWrapper.getDeviceType(); + ConnectionManagerUtil.openDBConnection(); + if (this.applicationReleaseDAO.verifyReleaseExistenceByHash(hash, tenantId)) { + String msg = "Application release already exists"; log.error(msg); - throw new ApplicationManagementException(msg); - } - try { - ConnectionManagerUtil.openDBConnection(); - if (this.applicationReleaseDAO.verifyReleaseExistenceByHash(md5OfApp, tenantId)) { - String msg = "Application release exists for the uploaded binary file. Application name: " - + customAppWrapper.getName() + " Device type: " + customAppWrapper.getDeviceType(); - log.error(msg); - throw new BadRequestException(msg); - } - } catch (ApplicationManagementDAOException e) { - String msg = "Error occurred while adding application data into the database. Application name: " - + customAppWrapper.getName() + " Device type: " + customAppWrapper.getDeviceType(); - log.error(msg, e); - throw new ApplicationManagementException(msg, e); - } finally { - ConnectionManagerUtil.closeDBConnection(); + throw new BadRequestException(msg); } + } catch (ApplicationManagementDAOException e) { + String msg = "Error occurred while checking if release already exists"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } - ApplicationDTO applicationDTO = APIUtil.convertToAppDTO(customAppWrapper); - ApplicationReleaseDTO applicationReleaseDTO = applicationDTO.getApplicationReleaseDTOs().get(0); - applicationReleaseDTO.setUuid(UUID.randomUUID().toString()); - applicationReleaseDTO.setAppHashValue(md5OfApp); - applicationReleaseDTO.setInstallerName(applicationArtifact.getInstallerName()); - try (ByteArrayInputStream binaryDuplicate = new ByteArrayInputStream(content)) { - applicationStorageManager.uploadReleaseArtifact(applicationReleaseDTO, customAppWrapper.getDeviceType(), - binaryDuplicate, tenantId); - } catch (IOException e) { - String msg = "Error occurred when uploading release artifact into the server."; + public String getPublicAppStorePath(String deviceType) { + if (DeviceTypes.ANDROID.toString().equalsIgnoreCase(deviceType)) { + return Constants.GOOGLE_PLAY_STORE_URL; + } else if (DeviceTypes.IOS.toString().equalsIgnoreCase(deviceType)) { + return Constants.APPLE_STORE_URL; + } else { + throw new IllegalArgumentException("No such device with the name " + deviceType); + } + } + + /** + * Helps to byte content of release binary file of application artifact + * This method can be useful when uploading application release binary file or when generating md5hex of release binary + * + * @param artifact {@link ApplicationArtifact} + * @return byte content of application release binary file + * @throws ApplicationManagementException if error occurred while getting byte content + */ + private byte[] getByteContentOfApp(ApplicationArtifact artifact) throws ApplicationManagementException{ + try { + return IOUtils.toByteArray(artifact.getInstallerStream()); + } catch (IOException e) { + String msg = "Error occurred while getting byte content of app binary artifact"; + log.error(msg); + throw new ApplicationManagementException(msg, e); + } + } + + /** + * Useful to generate md5hex string of application release + * + * @param applicationArtifact {@link ApplicationArtifact} + * @param content byte array content of application release binary file + * @return Generated md5hex string + * @throws ApplicationManagementException if any error occurred while generating md5hex string + */ + private String generateMD5OfApp(ApplicationArtifact applicationArtifact, byte[] content) throws ApplicationManagementException { + try { + String md5OfApp = StorageManagementUtil.getMD5(new ByteArrayInputStream(content)); + if (md5OfApp == null) { + String msg = "Error occurred while generating md5sum value of " + applicationArtifact.getInstallerName(); log.error(msg); throw new ApplicationManagementException(msg); } - applicationReleaseDTO = addImageArtifacts(applicationReleaseDTO, applicationArtifact, tenantId); - applicationDTO.getApplicationReleaseDTOs().clear(); - applicationDTO.getApplicationReleaseDTOs().add(applicationReleaseDTO); - return addAppDataIntoDB(applicationDTO, tenantId, isPublished); - } catch (ResourceManagementException e) { - String msg = "Error occurred while uploading application artifact into the server. Application name: " - + customAppWrapper.getName() + " Device type: " + customAppWrapper.getDeviceType(); - log.error(msg, e); - throw new ApplicationManagementException(msg, e); - } catch (IOException e) { - String msg = "Error occurred while getting bytes from application release artifact. Application name: " - + customAppWrapper.getName() + " Device type: " + customAppWrapper.getDeviceType(); - log.error(msg, e); + return md5OfApp; + } catch( ApplicationStorageManagementException e) { + String msg = "Error occurred while generating md5sum value of " + applicationArtifact.getInstallerName(); + log.error(msg); throw new ApplicationManagementException(msg, e); } } @@ -410,10 +618,11 @@ ApplicationManagerImpl implements ApplicationManager { * Delete Application release artifacts * * @param directoryPaths Directory paths - * @param tenantId Tenant Id * @throws ApplicationManagementException if error occurred while deleting application release artifacts. */ - private void deleteApplicationArtifacts(List directoryPaths, int tenantId) throws ApplicationManagementException { + @Override + public void deleteApplicationArtifacts(List directoryPaths) throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); ApplicationStorageManager applicationStorageManager = APIUtil.getApplicationStorageManager(); try { applicationStorageManager.deleteAllApplicationReleaseArtifacts(directoryPaths, tenantId); @@ -437,7 +646,7 @@ ApplicationManagerImpl implements ApplicationManager { * @throws ApplicationManagementException if error occurred while handling application release data. */ private ApplicationReleaseDTO addApplicationReleaseArtifacts(String deviceType, - ApplicationReleaseDTO applicationReleaseDTO, ApplicationArtifact applicationArtifact, boolean isNewRelease) + ApplicationReleaseDTO applicationReleaseDTO, ApplicationArtifact applicationArtifact, boolean isNewRelease) throws ResourceManagementException, ApplicationManagementException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); ApplicationStorageManager applicationStorageManager = APIUtil.getApplicationStorageManager(); @@ -533,7 +742,7 @@ ApplicationManagerImpl implements ApplicationManager { * @throws ApplicationManagementException if error occurred while handling application release data. */ private ApplicationReleaseDTO updateEntAppReleaseArtifact(String deviceType, - ApplicationReleaseDTO applicationReleaseDTO, ApplicationArtifact applicationArtifact) + ApplicationReleaseDTO applicationReleaseDTO, ApplicationArtifact applicationArtifact) throws ResourceManagementException, ApplicationManagementException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); ApplicationStorageManager applicationStorageManager = APIUtil.getApplicationStorageManager(); @@ -628,7 +837,7 @@ ApplicationManagerImpl implements ApplicationManager { * @throws ResourceManagementException if error occurred while uploading image artifacts into file system. */ private ApplicationReleaseDTO addImageArtifacts(ApplicationReleaseDTO applicationReleaseDTO, - ApplicationArtifact applicationArtifact, int tenantId) throws ResourceManagementException { + ApplicationArtifact applicationArtifact, int tenantId) throws ResourceManagementException { ApplicationStorageManager applicationStorageManager = APIUtil.getApplicationStorageManager(); applicationReleaseDTO.setIconName(applicationArtifact.getIconName()); @@ -665,7 +874,7 @@ ApplicationManagerImpl implements ApplicationManager { * @throws ResourceManagementException if error occurred while uploading application release artifacts into the file system. */ private ApplicationReleaseDTO updateImageArtifacts(ApplicationReleaseDTO applicationReleaseDTO, - ApplicationArtifact applicationArtifact, int tenantId) throws ResourceManagementException{ + ApplicationArtifact applicationArtifact, int tenantId) throws ResourceManagementException{ ApplicationStorageManager applicationStorageManager = APIUtil.getApplicationStorageManager(); if (!StringUtils.isEmpty(applicationArtifact.getIconName())) { @@ -784,7 +993,6 @@ ApplicationManagerImpl implements ApplicationManager { applications.add(application); } } - Pagination pagination = new Pagination(); pagination.setCount(applicationDAO.getApplicationCount(filter, deviceType.getId(), tenantId)); pagination.setSize(applications.size()); @@ -851,7 +1059,6 @@ ApplicationManagerImpl implements ApplicationManager { } return true; } - /** * To check whether the application is whether hideable or not * @@ -859,7 +1066,8 @@ ApplicationManagerImpl implements ApplicationManager { * @return true if application releases are in hideable state (i.e Retired), otherwise returns false * @throws ApplicationManagementException if error occurred while getting application release end state. */ - private boolean isHideableApp(List applicationReleaseDTOs) + @Override + public boolean isHideableApp(List applicationReleaseDTOs) throws ApplicationManagementException { try { for (ApplicationReleaseDTO applicationReleaseDTO : applicationReleaseDTOs) { @@ -883,7 +1091,8 @@ ApplicationManagerImpl implements ApplicationManager { * @throws ApplicationManagementException if error occurred while checking whether the application release is in * deletable state or not. */ - private boolean isDeletableApp(List applicationReleaseDTOs) + @Override + public boolean isDeletableApp(List applicationReleaseDTOs) throws ApplicationManagementException { try { for (ApplicationReleaseDTO applicationReleaseDTO : applicationReleaseDTOs) { @@ -964,7 +1173,7 @@ ApplicationManagerImpl implements ApplicationManager { * @throws UserStoreException if error occurred when checking whether user has assigned at least one filtering role. */ private boolean hasAppUnrestrictedRole(List appUnrestrictedRoles, List filteringUnrestrictedRoles, - String userName) throws BadRequestException, UserStoreException { + String userName) throws BadRequestException, UserStoreException { if (!hasUserRole(filteringUnrestrictedRoles, userName)) { String msg = "At least one filtering role is not assigned for the user: " + userName + ". Hence user " + userName @@ -982,44 +1191,33 @@ ApplicationManagerImpl implements ApplicationManager { return false; } - /*** - * This method is responsible to add application data into APPM database. However, before call this method it is - * required to do the validation of request and check the existence of application releaseDTO. - * - * @param applicationDTO Application DTO object. - * @param tenantId Tenant Id - * @return {@link Application} - * @throws ApplicationManagementException which throws if error occurs while during application management. - */ - private Application addAppDataIntoDB(ApplicationDTO applicationDTO, int tenantId, boolean isPublished) throws ApplicationManagementException { - ApplicationStorageManager applicationStorageManager = APIUtil.getApplicationStorageManager(); - List unrestrictedRoles = applicationDTO.getUnrestrictedRoles(); - ApplicationReleaseDTO applicationReleaseDTO = applicationDTO.getApplicationReleaseDTOs().get(0); - List categories = applicationDTO.getAppCategories(); - List tags = applicationDTO.getTags(); - List applicationReleaseEntities = new ArrayList<>(); + @Override + public Application addAppDataIntoDB(ApplicationDTO applicationDTO, boolean isPublished) throws + ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + ApplicationReleaseDTO applicationReleaseDTO = null; + if (applicationDTO.getApplicationReleaseDTOs().size() > 0) { + applicationReleaseDTO = applicationDTO.getApplicationReleaseDTOs().get(0); + } try { - ConnectionManagerUtil.beginDBTransaction(); // Insert to application table int appId = this.applicationDAO.createApplication(applicationDTO, tenantId); if (appId == -1) { - log.error("Application data storing is Failed."); - ConnectionManagerUtil.rollbackDBTransaction(); - deleteApplicationArtifacts(Collections.singletonList(applicationReleaseDTO.getAppHashValue()), - tenantId); - return null; + String msg = "Application data storing is Failed."; + log.error(msg); + throw new ApplicationManagementDAOException(msg); } else { if (log.isDebugEnabled()) { log.debug("New ApplicationDTO entry added to AP_APP table. App Id:" + appId); } //add application categories - List categoryIds = applicationDAO.getCategoryIdsForCategoryNames(categories, tenantId); + List categoryIds = applicationDAO.getCategoryIdsForCategoryNames(applicationDTO.getAppCategories(), tenantId); this.applicationDAO.addCategoryMapping(categoryIds, appId, tenantId); //adding application unrestricted roles - if (unrestrictedRoles != null && !unrestrictedRoles.isEmpty()) { - this.visibilityDAO.addUnrestrictedRoles(unrestrictedRoles, appId, tenantId); + if (applicationDTO.getUnrestrictedRoles() != null && !applicationDTO.getUnrestrictedRoles().isEmpty()) { + this.visibilityDAO.addUnrestrictedRoles(applicationDTO.getUnrestrictedRoles(), appId, tenantId); if (log.isDebugEnabled()) { log.debug("New restricted roles to app ID mapping added to AP_UNRESTRICTED_ROLE table." + " App Id:" + appId); @@ -1027,7 +1225,7 @@ ApplicationManagerImpl implements ApplicationManager { } //adding application tags - if (tags != null && !tags.isEmpty()) { + if (applicationDTO.getTags() != null && !applicationDTO.getTags().isEmpty()) { List registeredTags = applicationDAO.getAllTags(tenantId); List registeredTagNames = new ArrayList<>(); List tagIds = new ArrayList<>(); @@ -1035,16 +1233,16 @@ ApplicationManagerImpl implements ApplicationManager { for (TagDTO tagDTO : registeredTags) { registeredTagNames.add(tagDTO.getTagName()); } - List newTags = getDifference(tags, registeredTagNames); + List newTags = getDifference(applicationDTO.getTags(), registeredTagNames); if (!newTags.isEmpty()) { this.applicationDAO.addTags(newTags, tenantId); if (log.isDebugEnabled()) { log.debug("New tags entry added to AP_APP_TAG table. App Id:" + appId); } - tagIds = this.applicationDAO.getTagIdsForTagNames(tags, tenantId); + tagIds = this.applicationDAO.getTagIdsForTagNames(applicationDTO.getTags(), tenantId); } else { for (TagDTO tagDTO : registeredTags) { - for (String tagName : tags) { + for (String tagName : applicationDTO.getTags()) { if (tagName.equals(tagDTO.getTagName())) { tagIds.add(tagDTO.getId()); break; @@ -1058,122 +1256,90 @@ ApplicationManagerImpl implements ApplicationManager { if (log.isDebugEnabled()) { log.debug("Creating a new release. App Id:" + appId); } - - String lifeCycleState = lifecycleStateManager.getInitialState(); - String[] publishStates= {"IN-REVIEW", "APPROVED", "PUBLISHED"}; - - applicationReleaseDTO.setCurrentState(lifeCycleState); - applicationReleaseDTO = this.applicationReleaseDAO.createRelease(applicationReleaseDTO, appId, tenantId); - LifecycleState lifecycleState = getLifecycleStateInstance(lifeCycleState, lifeCycleState); - this.lifecycleStateDAO.addLifecycleState(lifecycleState, applicationReleaseDTO.getId(), tenantId); - - if(isPublished){ - for (String state: publishStates) { - LifecycleChanger lifecycleChanger = new LifecycleChanger(); - lifecycleChanger.setAction(state); - lifecycleChanger.setReason("Updated to " + state); - this.changeLifecycleState(applicationReleaseDTO, lifecycleChanger); + List applicationReleaseEntities = new ArrayList<>(); + if (applicationReleaseDTO != null) { + String lifeCycleState = lifecycleStateManager.getInitialState(); + String[] publishStates= {"IN-REVIEW", "APPROVED", "PUBLISHED"}; + + applicationReleaseDTO.setCurrentState(lifeCycleState); + applicationReleaseDTO = this.applicationReleaseDAO.createRelease(applicationReleaseDTO, appId, tenantId); + LifecycleState lifecycleState = getLifecycleStateInstance(lifeCycleState, lifeCycleState); + this.lifecycleStateDAO.addLifecycleState(lifecycleState, applicationReleaseDTO.getId(), tenantId); + if(isPublished){ + for (String state: publishStates) { + LifecycleChanger lifecycleChanger = new LifecycleChanger(); + lifecycleChanger.setAction(state); + lifecycleChanger.setReason("Updated to " + state); + this.changeLifecycleState(applicationReleaseDTO, lifecycleChanger); + } } + applicationReleaseEntities.add(applicationReleaseDTO); } - - applicationReleaseEntities.add(applicationReleaseDTO); + applicationDTO.setId(appId); applicationDTO.setApplicationReleaseDTOs(applicationReleaseEntities); - Application application = APIUtil.appDtoToAppResponse(applicationDTO); - ConnectionManagerUtil.commitDBTransaction(); - return application; + return APIUtil.appDtoToAppResponse(applicationDTO); } } catch (LifeCycleManagementDAOException e) { - ConnectionManagerUtil.rollbackDBTransaction(); String msg = "Error occurred while adding lifecycle state. application name: " + applicationDTO.getName() + "."; log.error(msg, e); - try { - applicationStorageManager.deleteAllApplicationReleaseArtifacts( - Collections.singletonList(applicationReleaseDTO.getAppHashValue()), tenantId); - } catch (ApplicationStorageManagementException ex) { - String errorLog = - "Error occurred when deleting application artifacts. Application artifacts are tried to " - + "delete because of lifecycle state adding issue in the application creating operation."; - log.error(errorLog, ex); - throw new ApplicationManagementException(errorLog, ex); - } throw new ApplicationManagementException(msg, e); } catch (ApplicationManagementDAOException e) { - ConnectionManagerUtil.rollbackDBTransaction(); String msg = "Error occurred while adding application or application release. application name: " + applicationDTO.getName() + "."; log.error(msg, e); - deleteApplicationArtifacts(Collections.singletonList(applicationReleaseDTO.getAppHashValue()), tenantId); throw new ApplicationManagementException(msg, e); } catch (LifecycleManagementException e) { - ConnectionManagerUtil.rollbackDBTransaction(); String msg = "Error occurred when getting initial lifecycle state. application name: " + applicationDTO.getName() + "."; log.error(msg, e); - deleteApplicationArtifacts(Collections.singletonList(applicationReleaseDTO.getAppHashValue()), tenantId); - throw new ApplicationManagementException(msg, e); - } catch (DBConnectionException e) { - String msg = "Error occurred while getting database connection."; - log.error(msg, e); throw new ApplicationManagementException(msg, e); } catch (VisibilityManagementDAOException e) { - ConnectionManagerUtil.rollbackDBTransaction(); String msg = "Error occurred while adding unrestricted roles. application name: " + applicationDTO.getName() + "."; log.error(msg, e); - deleteApplicationArtifacts(Collections.singletonList(applicationReleaseDTO.getAppHashValue()), tenantId); - throw new ApplicationManagementException(msg, e); - } catch (TransactionManagementException e) { - String msg = "Error occurred while disabling AutoCommit."; - log.error(msg, e); throw new ApplicationManagementException(msg, e); - } finally { - ConnectionManagerUtil.closeDBConnection(); } } @Override - public ApplicationRelease createEntAppRelease(int applicationId, EntAppReleaseWrapper entAppReleaseWrapper, - ApplicationArtifact applicationArtifact, boolean isPublished) throws ApplicationManagementException { + public ApplicationRelease createRelease(ApplicationDTO applicationDTO, ApplicationReleaseDTO applicationReleaseDTO, + ApplicationType type, boolean isPublished) + throws ApplicationManagementException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); if (log.isDebugEnabled()) { - log.debug("Application release creating request is received for the application id: " + applicationId); + log.debug("Application release creating request is received for the application id: " + applicationDTO.getId()); } - ApplicationDTO applicationDTO = getApplication(applicationId); - - if (!ApplicationType.ENTERPRISE.toString().equals(applicationDTO.getType())) { - String msg = "It is possible to add new application release for " + ApplicationType.ENTERPRISE.toString() + if (!type.toString().equals(applicationDTO.getType())) { + String msg = "It is possible to add new application release for " + type + " app type. But you are requesting to add new application release for " + applicationDTO.getType() + " app type."; log.error(msg); throw new BadRequestException(msg); } - DeviceType deviceType = APIUtil.getDeviceTypeData(applicationDTO.getDeviceTypeId()); - if (isInvalidOsVersionRange(entAppReleaseWrapper.getSupportedOsVersions(), deviceType.getName())) { - String msg = "You are trying to add application release which has invalid or unsupported OS versions in " - + "the supportedOsVersions section. Hence, please re-evaluate the request payload."; - log.error(msg); - throw new BadRequestException(msg); - } - ApplicationReleaseDTO applicationReleaseDTO = uploadEntAppReleaseArtifacts( - APIUtil.releaseWrapperToReleaseDTO(entAppReleaseWrapper), applicationArtifact, deviceType.getName(), - tenantId, true); + if (!type.equals(ApplicationType.ENTERPRISE)) { + int applicationReleaseCount = applicationDTO.getApplicationReleaseDTOs().size(); + if (applicationReleaseCount > 0) { + String msg = "Application type of " + applicationDTO.getType() + " can only have one release"; + log.error(msg); + throw new BadRequestException(msg); + } + } try { ConnectionManagerUtil.beginDBTransaction(); String lifeCycleState = lifecycleStateManager.getInitialState(); - String[] publishStates= {"IN-REVIEW", "APPROVED", "PUBLISHED"}; - + String[] publishStates = {"IN-REVIEW", "APPROVED", "PUBLISHED"}; + applicationReleaseDTO.setCurrentState(lifeCycleState); LifecycleState lifecycleState = getLifecycleStateInstance(lifeCycleState, lifeCycleState); applicationReleaseDTO = this.applicationReleaseDAO .createRelease(applicationReleaseDTO, applicationDTO.getId(), tenantId); this.lifecycleStateDAO .addLifecycleState(lifecycleState, applicationReleaseDTO.getId(), tenantId); - if(isPublished){ for (String state: publishStates) { LifecycleChanger lifecycleChanger = new LifecycleChanger(); @@ -1182,29 +1348,28 @@ ApplicationManagerImpl implements ApplicationManager { this.changeLifecycleState(applicationReleaseDTO, lifecycleChanger); } } - ApplicationRelease applicationRelease = APIUtil.releaseDtoToRelease(applicationReleaseDTO); ConnectionManagerUtil.commitDBTransaction(); return applicationRelease; } catch (TransactionManagementException e) { String msg = "Error occurred while staring application release creating transaction for application Id: " - + applicationId; + + applicationDTO.getId(); log.error(msg, e); throw new ApplicationManagementException(msg, e); } catch (DBConnectionException e) { String msg = "Error occurred while adding application release into IoTS app management ApplicationDTO id of" - + " the application release: " + applicationId; + + " the application release: " + applicationDTO.getId(); log.error(msg, e); throw new ApplicationManagementException(msg, e); } catch (LifeCycleManagementDAOException e) { ConnectionManagerUtil.rollbackDBTransaction(); String msg = "Error occurred while adding new application release lifecycle state to the application" - + " release: " + applicationId; + + " release: " + applicationDTO.getId(); log.error(msg, e); throw new ApplicationManagementException(msg, e); } catch (ApplicationManagementDAOException e) { ConnectionManagerUtil.rollbackDBTransaction(); - String msg = "Error occurred while adding new application release for application " + applicationId; + String msg = "Error occurred while adding new application release for application " + applicationDTO.getId(); log.error(msg, e); throw new ApplicationManagementException(msg, e); } finally { @@ -1212,14 +1377,8 @@ ApplicationManagerImpl implements ApplicationManager { } } - /** - * Get Application and all application releases associated to the application that has given application Id - * - * @param applicationId Application Id - * @return {@link ApplicationDTO} - * @throws ApplicationManagementException if error occurred application data from the databse. - */ - private ApplicationDTO getApplication(int applicationId) throws ApplicationManagementException { + @Override + public ApplicationDTO getApplication(int applicationId) throws ApplicationManagementException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); try { ConnectionManagerUtil.openDBConnection(); @@ -1244,31 +1403,6 @@ ApplicationManagerImpl implements ApplicationManager { } } - /** - * Upload enterprise application release artifact into file system. - * - * @param releaseDTO Apllication Release - * @param applicationArtifact Application Release artifacts - * @param deviceTypeName Device Type name - * @param tenantId Tenant Id - * @param isNewRelease New Release or Not - * @return {@link ApplicationReleaseDTO} - * @throws ApplicationManagementException if error occurred while uploading artifacts into file system. - */ - private ApplicationReleaseDTO uploadEntAppReleaseArtifacts(ApplicationReleaseDTO releaseDTO, - ApplicationArtifact applicationArtifact, String deviceTypeName, int tenantId, boolean isNewRelease) - throws ApplicationManagementException { - try { - ApplicationReleaseDTO applicationReleaseDTO = addApplicationReleaseArtifacts(deviceTypeName, releaseDTO, - applicationArtifact, isNewRelease); - return addImageArtifacts(applicationReleaseDTO, applicationArtifact, tenantId); - } catch (ResourceManagementException e) { - String msg = "Error occurred while uploading application release artifacts."; - log.error(msg, e); - throw new ApplicationManagementException(msg, e); - } - } - /** * Check whether given OS range is valid or invalid * @@ -1425,7 +1559,6 @@ ApplicationManagerImpl implements ApplicationManager { } } - @Override public Application getApplicationByUuid(String releaseUuid, String state) throws ApplicationManagementException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); @@ -1604,6 +1737,7 @@ ApplicationManagerImpl implements ApplicationManager { this.applicationDAO.deleteApplicationTags(applicationDTO.getId(), tenantId); this.applicationDAO.deleteAppCategories(applicationDTO.getId(), tenantId); this.visibilityDAO.deleteAppUnrestrictedRoles(applicationDTO.getId(), tenantId); + this.spApplicationDAO.deleteApplicationFromServiceProviders(applicationDTO.getId(), tenantId); this.applicationDAO.deleteApplication(applicationDTO.getId(), tenantId); APIUtil.getApplicationStorageManager().deleteAllApplicationReleaseArtifacts(deletingAppHashVals, tenantId); ConnectionManagerUtil.commitDBTransaction(); @@ -1709,66 +1843,62 @@ ApplicationManagerImpl implements ApplicationManager { ConnectionManagerUtil.closeDBConnection(); } - if (applicationDTO.getApplicationReleaseDTOs().size() == 1) { - deleteApplication(applicationDTO, tenantId); - } else { - for (ApplicationReleaseDTO applicationReleaseDTO : applicationDTO.getApplicationReleaseDTOs()) { - if (releaseUuid.equals(applicationReleaseDTO.getUuid())) { - if (!lifecycleStateManager.isDeletableState(applicationReleaseDTO.getCurrentState())) { - String msg = - "Application state is not in the deletable state. Therefore you are not permitted to " - + "delete the application release."; + for (ApplicationReleaseDTO applicationReleaseDTO : applicationDTO.getApplicationReleaseDTOs()) { + if (releaseUuid.equals(applicationReleaseDTO.getUuid())) { + if (!lifecycleStateManager.isDeletableState(applicationReleaseDTO.getCurrentState())) { + String msg = + "Application state is not in the deletable state. Therefore you are not permitted to " + + "delete the application release."; + log.error(msg); + throw new ForbiddenException(msg); + } + try { + ConnectionManagerUtil.beginDBTransaction(); + List deviceSubscriptionDTOS = subscriptionDAO + .getDeviceSubscriptions(applicationReleaseDTO.getId(), tenantId, null, null); + if (!deviceSubscriptionDTOS.isEmpty()) { + String msg = "Application release which has UUID: " + applicationReleaseDTO.getUuid() + + " either subscribed to device/s or it had subscribed to device/s. Therefore you " + + "are not permitted to delete the application release."; log.error(msg); throw new ForbiddenException(msg); } - try { - ConnectionManagerUtil.beginDBTransaction(); - List deviceSubscriptionDTOS = subscriptionDAO - .getDeviceSubscriptions(applicationReleaseDTO.getId(), tenantId, null, null); - if (!deviceSubscriptionDTOS.isEmpty()) { - String msg = "Application release which has UUID: " + applicationReleaseDTO.getUuid() - + " either subscribed to device/s or it had subscribed to device/s. Therefore you " - + "are not permitted to delete the application release."; - log.error(msg); - throw new ForbiddenException(msg); - } - lifecycleStateDAO.deleteLifecycleStateByReleaseId(applicationReleaseDTO.getId()); - applicationReleaseDAO.deleteRelease(applicationReleaseDTO.getId()); - applicationStorageManager.deleteAllApplicationReleaseArtifacts( - Collections.singletonList(applicationReleaseDTO.getAppHashValue()), tenantId); - ConnectionManagerUtil.commitDBTransaction(); - } catch (DBConnectionException e) { - String msg = "Error occurred while observing the database connection to delete application " - + "release which has the UUID:" + releaseUuid; - log.error(msg, e); - throw new ApplicationManagementException(msg, e); - } catch (TransactionManagementException e) { - String msg = "Database access error is occurred when deleting application release which has " - + "the UUID: " + releaseUuid; - log.error(msg, e); - throw new ApplicationManagementException(msg, e); - } catch (ApplicationManagementDAOException e) { - ConnectionManagerUtil.rollbackDBTransaction(); - String msg = "Error occurred while verifying whether application relase has an subscription or " - + "not. Application release UUID: " + releaseUuid; - log.error(msg, e); - throw new ApplicationManagementException(msg, e); - } catch (ApplicationStorageManagementException e) { - String msg = "Error occurred when deleting the application release artifact from the file " - + "system. Application release UUID: " + releaseUuid; - log.error(msg, e); - throw new ApplicationManagementException(msg, e); - } catch (LifeCycleManagementDAOException e) { - ConnectionManagerUtil.rollbackDBTransaction(); - String msg = "Error occurred when deleting lifecycle data for application release UUID: " - + releaseUuid; - log.error(msg, e); - throw new ApplicationManagementException(msg, e); - } finally { - ConnectionManagerUtil.closeDBConnection(); - } - break; + lifecycleStateDAO.deleteLifecycleStateByReleaseId(applicationReleaseDTO.getId()); + applicationReleaseDAO.deleteRelease(applicationReleaseDTO.getId()); + applicationStorageManager.deleteAllApplicationReleaseArtifacts( + Collections.singletonList(applicationReleaseDTO.getAppHashValue()), tenantId); + ConnectionManagerUtil.commitDBTransaction(); + } catch (DBConnectionException e) { + String msg = "Error occurred while observing the database connection to delete application " + + "release which has the UUID:" + releaseUuid; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (TransactionManagementException e) { + String msg = "Database access error is occurred when deleting application release which has " + + "the UUID: " + releaseUuid; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (ApplicationManagementDAOException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = "Error occurred while verifying whether application relase has an subscription or " + + "not. Application release UUID: " + releaseUuid; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (ApplicationStorageManagementException e) { + String msg = "Error occurred when deleting the application release artifact from the file " + + "system. Application release UUID: " + releaseUuid; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (LifeCycleManagementDAOException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = "Error occurred when deleting lifecycle data for application release UUID: " + + releaseUuid; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); } + break; } } } @@ -1827,7 +1957,7 @@ ApplicationManagerImpl implements ApplicationManager { @Override public void updateApplicationArtifact(String deviceType, String releaseUuid, - ApplicationArtifact applicationArtifact) throws ApplicationManagementException { + ApplicationArtifact applicationArtifact) throws ApplicationManagementException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); boolean isValidDeviceType = false; List deviceTypes; @@ -1893,7 +2023,7 @@ ApplicationManagerImpl implements ApplicationManager { throw new ApplicationManagementException(msg, e); } catch (TransactionManagementException e) { String msg = "Error occured while starting the transaction to update application release artifact which has " - + "application uuid " + releaseUuid + "."; + + "application uuid " + releaseUuid + "."; log.error(msg, e); throw new ApplicationManagementException(msg, e); } catch (DBConnectionException e) { @@ -1931,7 +2061,7 @@ ApplicationManagerImpl implements ApplicationManager { return this.lifecycleStateDAO.getLifecycleStates(applicationReleaseDTO.getId(), tenantId); } catch (DBConnectionException e) { String msg = "Error occurred while obtaining the database connection to get lifecycle state change flow for " - + "application release which has UUID: " + releaseUuid; + + "application release which has UUID: " + releaseUuid; log.error(msg, e); throw new ApplicationManagementException(msg, e); } catch (LifeCycleManagementDAOException e) { @@ -2267,8 +2397,8 @@ ApplicationManagerImpl implements ApplicationManager { if (!getDifference(updatingAppCategries, allCategoryName).isEmpty()){ String msg = "Application update request contains invalid category names. Hence please verify the " + "request payload"; - log.error(msg); - throw new BadRequestException(msg); + log.error(msg); + throw new BadRequestException(msg); } List addingAppCategories = getDifference(updatingAppCategries, appCategories); @@ -2871,7 +3001,7 @@ ApplicationManagerImpl implements ApplicationManager { @Override public ApplicationRelease updateEntAppRelease(String releaseUuid, EntAppReleaseWrapper entAppReleaseWrapper, - ApplicationArtifact applicationArtifact) throws ApplicationManagementException { + ApplicationArtifact applicationArtifact) throws ApplicationManagementException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); try { @@ -2948,7 +3078,7 @@ ApplicationManagerImpl implements ApplicationManager { @Override public ApplicationRelease updatePubAppRelease(String releaseUuid, PublicAppReleaseWrapper publicAppReleaseWrapper, - ApplicationArtifact applicationArtifact) throws ApplicationManagementException { + ApplicationArtifact applicationArtifact) throws ApplicationManagementException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); try { @@ -3017,7 +3147,7 @@ ApplicationManagerImpl implements ApplicationManager { @Override public ApplicationRelease updateWebAppRelease(String releaseUuid, WebAppReleaseWrapper webAppReleaseWrapper, - ApplicationArtifact applicationArtifact) throws ApplicationManagementException { + ApplicationArtifact applicationArtifact) throws ApplicationManagementException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); try { @@ -3082,7 +3212,7 @@ ApplicationManagerImpl implements ApplicationManager { @Override public ApplicationRelease updateCustomAppRelease(String releaseUuid, - CustomAppReleaseWrapper customAppReleaseWrapper, ApplicationArtifact applicationArtifact) + CustomAppReleaseWrapper customAppReleaseWrapper, ApplicationArtifact applicationArtifact) throws ApplicationManagementException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); ApplicationStorageManager applicationStorageManager = APIUtil.getApplicationStorageManager(); @@ -3216,7 +3346,7 @@ ApplicationManagerImpl implements ApplicationManager { * @throws ApplicationManagementException if invalid application release updating payload received. */ private void validateAppReleaseUpdating(T param, ApplicationDTO applicationDTO, - ApplicationArtifact applicationArtifact, String appType) + ApplicationArtifact applicationArtifact, String appType) throws ApplicationManagementException { if (applicationDTO == null) { String msg = "Couldn't found an application for requested UUID."; @@ -3294,7 +3424,7 @@ ApplicationManagerImpl implements ApplicationManager { } @Override - public void validateAppCreatingRequest(T param) throws ApplicationManagementException { + public void validateAppCreatingRequest(T param) throws ApplicationManagementException, RequestValidatingException { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); String userName = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); int deviceTypeId = -1; @@ -3328,17 +3458,12 @@ ApplicationManagerImpl implements ApplicationManager { } DeviceType deviceType = APIUtil.getDeviceTypeData(applicationWrapper.getDeviceType()); deviceTypeId = deviceType.getId(); - - List entAppReleaseWrappers; - entAppReleaseWrappers = applicationWrapper.getEntAppReleaseWrappers(); - - if (entAppReleaseWrappers == null || entAppReleaseWrappers.size() != 1) { - String msg = "Invalid application creating request. Application creating request must have single " - + "application release. Application name:" + applicationWrapper.getName() + "."; - log.error(msg); - throw new BadRequestException(msg); - } unrestrictedRoles = applicationWrapper.getUnrestrictedRoles(); + List releaseWrappers = applicationWrapper.getEntAppReleaseWrappers(); + if (!releaseWrappers.isEmpty()) { + EntAppReleaseWrapper releaseWrapper = releaseWrappers.get(0); + validateEntAppReleaseCreatingRequest(releaseWrapper, applicationWrapper.getDeviceType()); + } } else if (param instanceof WebAppWrapper) { WebAppWrapper webAppWrapper = (WebAppWrapper) param; appName = webAppWrapper.getName(); @@ -3366,17 +3491,12 @@ ApplicationManagerImpl implements ApplicationManager { log.error(msg); throw new BadRequestException(msg); } - - List webAppReleaseWrappers; - webAppReleaseWrappers = webAppWrapper.getWebAppReleaseWrappers(); - - if (webAppReleaseWrappers == null || webAppReleaseWrappers.size() != 1) { - String msg = "Invalid web clip creating request. Web clip creating request must have single " - + "web clip release. Web clip name:" + webAppWrapper.getName() + "."; - log.error(msg); - throw new BadRequestException(msg); - } unrestrictedRoles = webAppWrapper.getUnrestrictedRoles(); + List releaseWrappers = webAppWrapper.getWebAppReleaseWrappers(); + if(!releaseWrappers.isEmpty()) { + WebAppReleaseWrapper releaseWrapper = releaseWrappers.get(0); + validateWebAppReleaseCreatingRequest(releaseWrapper); + } } else if (param instanceof PublicAppWrapper) { PublicAppWrapper publicAppWrapper = (PublicAppWrapper) param; appName = publicAppWrapper.getName(); @@ -3403,17 +3523,12 @@ ApplicationManagerImpl implements ApplicationManager { } DeviceType deviceType = APIUtil.getDeviceTypeData(publicAppWrapper.getDeviceType()); deviceTypeId = deviceType.getId(); - - List publicAppReleaseWrappers; - publicAppReleaseWrappers = publicAppWrapper.getPublicAppReleaseWrappers(); - - if (publicAppReleaseWrappers == null || publicAppReleaseWrappers.size() != 1) { - String msg = "Invalid public app creating request. Request must have single release. Application name:" - + publicAppWrapper.getName() + "."; - log.error(msg); - throw new BadRequestException(msg); - } unrestrictedRoles = publicAppWrapper.getUnrestrictedRoles(); + List releaseWrappers = publicAppWrapper.getPublicAppReleaseWrappers(); + if(!releaseWrappers.isEmpty()) { + PublicAppReleaseWrapper releaseWrapper = releaseWrappers.get(0); + validatePublicAppReleaseCreatingRequest(releaseWrapper, publicAppWrapper.getDeviceType()); + } } else if (param instanceof CustomAppWrapper) { CustomAppWrapper customAppWrapper = (CustomAppWrapper) param; appName = customAppWrapper.getName(); @@ -3440,17 +3555,12 @@ ApplicationManagerImpl implements ApplicationManager { } DeviceType deviceType = APIUtil.getDeviceTypeData(customAppWrapper.getDeviceType()); deviceTypeId = deviceType.getId(); - - List customAppReleaseWrappers; - customAppReleaseWrappers = customAppWrapper.getCustomAppReleaseWrappers(); - - if (customAppReleaseWrappers == null || customAppReleaseWrappers.size() != 1) { - String msg = "Invalid custom app creating request. Application creating request must have single " - + "application release. Application name:" + customAppWrapper.getName() + "."; - log.error(msg); - throw new BadRequestException(msg); - } unrestrictedRoles = customAppWrapper.getUnrestrictedRoles(); + List releaseWrappers = customAppWrapper.getCustomAppReleaseWrappers(); + if(!releaseWrappers.isEmpty()) { + CustomAppReleaseWrapper releaseWrapper = releaseWrappers.get(0); + validateCustomAppReleaseCreatingRequest(releaseWrapper, customAppWrapper.getDeviceType()); + } } else { String msg = "Invalid payload found with the request. Hence verify the request payload object."; log.error(msg); @@ -3623,9 +3733,65 @@ ApplicationManagerImpl implements ApplicationManager { } } + @Override + public void validateEntAppReleaseCreatingRequest(EntAppReleaseWrapper releaseWrapper, String deviceType) + throws RequestValidatingException, ApplicationManagementException { + validateReleaseCreatingRequest(releaseWrapper, deviceType); + validateBinaryArtifact(releaseWrapper.getBinaryFile()); + validateImageArtifacts(releaseWrapper.getIcon(), releaseWrapper.getScreenshots()); + } + + @Override + public void validateCustomAppReleaseCreatingRequest(CustomAppReleaseWrapper releaseWrapper, String deviceType) + throws RequestValidatingException, ApplicationManagementException { + validateReleaseCreatingRequest(releaseWrapper, deviceType); + validateBinaryArtifact(releaseWrapper.getBinaryFile()); + validateImageArtifacts(releaseWrapper.getIcon(), releaseWrapper.getScreenshots()); + } + + @Override + public void validateWebAppReleaseCreatingRequest(WebAppReleaseWrapper releaseWrapper) + throws RequestValidatingException, ApplicationManagementException { + validateReleaseCreatingRequest(releaseWrapper, Constants.ANY); + validateImageArtifacts(releaseWrapper.getIcon(), releaseWrapper.getScreenshots()); + } + + @Override + public void validatePublicAppReleaseCreatingRequest(PublicAppReleaseWrapper releaseWrapper, String deviceType) + throws RequestValidatingException, ApplicationManagementException { + validateReleaseCreatingRequest(releaseWrapper, deviceType); + validateImageArtifacts(releaseWrapper.getIcon(), releaseWrapper.getScreenshots()); + validatePublicAppReleasePackageName(releaseWrapper.getPackageName()); + } + + @Override + public void validateImageArtifacts(Base64File iconFile, List screenshots) + throws RequestValidatingException { + if (iconFile == null) { + String msg = "Icon file is not found with the application release creating request."; + log.error(msg); + throw new RequestValidatingException(msg); + } + if (screenshots == null || screenshots.isEmpty()) { + String msg = "Screenshots are not found with the application release creating request."; + log.error(msg); + throw new RequestValidatingException(msg); + } + } + + @Override + public void validateBase64File(Base64File file) throws RequestValidatingException { + if (StringUtils.isEmpty(file.getBase64String())) { + throw new RequestValidatingException("Base64File in the payload doesn't contain base64 string"); + } + if (StringUtils.isEmpty(file.getName())) { + throw new RequestValidatingException("Base64File in the payload doesn't contain file name"); + } + } + @Override public void validateImageArtifacts(Attachment iconFile, Attachment bannerFile, - List attachmentList) throws RequestValidatingException { + List attachmentList) throws RequestValidatingException { if (iconFile == null) { String msg = "Icon file is not found with the application release creating request."; log.error(msg); @@ -3638,6 +3804,16 @@ ApplicationManagerImpl implements ApplicationManager { } } + @Override + public void validateBinaryArtifact(Base64File binaryFile) throws RequestValidatingException { + if (binaryFile == null) { + String msg = "Binary file is not found with the application release creating request for ENTERPRISE app " + + "creating request."; + log.error(msg); + throw new RequestValidatingException(msg); + } + } + @Override public void validateBinaryArtifact(Attachment binaryFile) throws RequestValidatingException { if (binaryFile == null) { @@ -3747,18 +3923,18 @@ ApplicationManagerImpl implements ApplicationManager { String artifactDownloadURL = APIUtil.getArtifactDownloadBaseURL() + tenantId + Constants.FORWARD_SLASH + applicationReleaseDTO.getUuid() + Constants.FORWARD_SLASH + Constants.APP_ARTIFACT + Constants.FORWARD_SLASH + - applicationReleaseDTO.getInstallerName(); + applicationReleaseDTO.getInstallerName(); String plistContent = "<!DOCTYPE plist PUBLIC "-//Apple//DTDPLIST1.0//EN" "" + - "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="" + - "1.0"><dict><key>items</key><array><dict><" + - "key>assets</key><array><dict><key>kind</key><" + - "string>software-package</string><key>url</key><string>" + - "$downloadURL</string></dict></array><key>metadata<" + - "/key><dict><key>bundle-identifier</key><string>" + - "$packageName</string><key>bundle-version</key><string>" + - "$bundleVersion</string><key>kind</key><string>" + - "software</string><key>title</key><string>$appName<" + - "/string></dict></dict></array></dict></plist>"; + "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="" + + "1.0"><dict><key>items</key><array><dict><" + + "key>assets</key><array><dict><key>kind</key><" + + "string>software-package</string><key>url</key><string>" + + "$downloadURL</string></dict></array><key>metadata<" + + "/key><dict><key>bundle-identifier</key><string>" + + "$packageName</string><key>bundle-version</key><string>" + + "$bundleVersion</string><key>kind</key><string>" + + "software</string><key>title</key><string>$appName<" + + "/string></dict></dict></array></dict></plist>"; plistContent = plistContent.replace("$downloadURL", artifactDownloadURL) .replace("$packageName", applicationReleaseDTO.getPackageName()) .replace("$bundleVersion", applicationReleaseDTO.getVersion()) diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/impl/SPApplicationManagerImpl.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/impl/SPApplicationManagerImpl.java new file mode 100644 index 0000000000..8382f428b5 --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/impl/SPApplicationManagerImpl.java @@ -0,0 +1,699 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.core.impl; + +import io.entgra.application.mgt.common.IdentityServerResponse; +import io.entgra.application.mgt.common.SPApplicationListResponse; +import io.entgra.application.mgt.common.dto.IdentityServerDTO; +import io.entgra.application.mgt.common.SPApplication; +import io.entgra.application.mgt.common.dto.ApplicationDTO; +import io.entgra.application.mgt.common.dto.IdentityServiceProviderDTO; +import io.entgra.application.mgt.common.exception.ApplicationManagementException; +import io.entgra.application.mgt.common.exception.DBConnectionException; +import io.entgra.application.mgt.common.exception.TransactionManagementException; +import io.entgra.application.mgt.common.response.Application; +import io.entgra.application.mgt.common.services.ApplicationManager; +import io.entgra.application.mgt.common.services.SPApplicationManager; +import io.entgra.application.mgt.core.config.ConfigurationManager; +import io.entgra.application.mgt.core.config.IdentityServiceProvider; +import io.entgra.application.mgt.core.dao.ApplicationDAO; +import io.entgra.application.mgt.core.dao.SPApplicationDAO; +import io.entgra.application.mgt.core.dao.VisibilityDAO; +import io.entgra.application.mgt.core.dao.common.ApplicationManagementDAOFactory; +import io.entgra.application.mgt.core.exception.ApplicationManagementDAOException; +import io.entgra.application.mgt.core.exception.BadRequestException; +import io.entgra.application.mgt.core.exception.NotFoundException; +import io.entgra.application.mgt.core.identityserver.serviceprovider.ISServiceProviderApplicationService; +import io.entgra.application.mgt.core.internal.DataHolder; +import io.entgra.application.mgt.core.lifecycle.LifecycleStateManager; +import io.entgra.application.mgt.core.util.APIUtil; +import io.entgra.application.mgt.core.util.ApplicationManagementUtil; +import io.entgra.application.mgt.core.util.ConnectionManagerUtil; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.validator.routines.UrlValidator; +import org.wso2.carbon.context.PrivilegedCarbonContext; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class SPApplicationManagerImpl implements SPApplicationManager { + + private static final Log log = LogFactory.getLog(SPApplicationManagerImpl.class); + private ApplicationDAO applicationDAO; + private SPApplicationDAO spApplicationDAO; + private VisibilityDAO visibilityDAO; + private final LifecycleStateManager lifecycleStateManager; + + public SPApplicationManagerImpl() { + initDataAccessObjects(); + lifecycleStateManager = DataHolder.getInstance().getLifecycleStateManager(); + } + + private void initDataAccessObjects() { + this.applicationDAO = ApplicationManagementDAOFactory.getApplicationDAO(); + this.visibilityDAO = ApplicationManagementDAOFactory.getVisibilityDAO(); + this.spApplicationDAO = ApplicationManagementDAOFactory.getSPApplicationDAO(); + } + + @Override + public IdentityServerResponse getIdentityServerResponse(int identityServerId) throws ApplicationManagementException { + IdentityServerDTO identityServerDTO = getIdentityServer(identityServerId); + return APIUtil.identityServerDtoToIdentityServerResponse(identityServerDTO); + } + + /** + * This is similar to getIdentityServerFromDB method except throws {@link NotFoundException} if identity server + * does not exist for the given id + * + * @param identityServerId id of identity server + * @return {@link IdentityServerDTO} + */ + private IdentityServerDTO getIdentityServer(int identityServerId) throws ApplicationManagementException { + IdentityServerDTO identityServerDTO = getIdentityServerFromDB(identityServerId); + if (identityServerDTO == null) { + String msg = "Identity server with the id: " + identityServerId + " does not exist"; + log.error(msg); + throw new NotFoundException(msg); + } + return identityServerDTO; + } + + /** + * Use to get {@link IdentityServerDTO} bean from database. Returns null if does not exist + * + * @param identityServerId id of identity server + * @return {@link IdentityServerDTO} + */ + private IdentityServerDTO getIdentityServerFromDB(int identityServerId) throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + try { + ConnectionManagerUtil.openDBConnection(); + return spApplicationDAO.getIdentityServerById(identityServerId, tenantId); + } catch (DBConnectionException e) { + String msg = "Error occurred when getting database connection to get identity server with the id: " + identityServerId; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (ApplicationManagementDAOException e) { + String msg = + "DAO exception while getting identity server with the id " + identityServerId ; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + @Override + public List getIdentityServers() throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + try { + ConnectionManagerUtil.openDBConnection(); + return spApplicationDAO.getIdentityServers(tenantId).stream(). + map(APIUtil::identityServerDtoToIdentityServerResponse).collect(Collectors.toList()); + } catch (DBConnectionException e) { + String msg = "Error occurred when getting database connection to get identity servers"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (ApplicationManagementDAOException e) { + String msg = + "DAO exception while getting identity servers"; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + @Override + public IdentityServerResponse createIdentityServer(IdentityServerDTO identityServerDTO) throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + validateIdentityServerCreateRequest(identityServerDTO); + try { + ConnectionManagerUtil.beginDBTransaction(); + int id = spApplicationDAO.createIdentityServer(identityServerDTO, tenantId); + identityServerDTO.setId(id); + ConnectionManagerUtil.commitDBTransaction(); + return APIUtil.identityServerDtoToIdentityServerResponse(identityServerDTO); + } catch (ApplicationManagementDAOException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = "Error occurred while creating identity server " + identityServerDTO.getName(); + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + @Override + public IdentityServerResponse updateIdentityServer(IdentityServerDTO updateIdentityServerDTO, int id) + throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + IdentityServerDTO existingIdentityServerDTO = getIdentityServer(id); + validateIdentityServerUpdateRequest(updateIdentityServerDTO, existingIdentityServerDTO); + Map updatedApiParams = constructUpdatedApiParams(updateIdentityServerDTO, existingIdentityServerDTO); + updateIdentityServerDTO.setApiParams(updatedApiParams); + try { + ConnectionManagerUtil.beginDBTransaction(); + spApplicationDAO.updateIdentityServer(updateIdentityServerDTO, tenantId, id); + ConnectionManagerUtil.commitDBTransaction(); + } catch (ApplicationManagementDAOException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = "Error occurred while creating identity server " + updateIdentityServerDTO.getName(); + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + return getIdentityServerResponse(id); + } + + @Override + public void deleteIdentityServer(int id) throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + validateIdentityServerDeleteRequest(id); + try { + ConnectionManagerUtil.beginDBTransaction(); + spApplicationDAO.deleteIdentityServer(id, tenantId); + ConnectionManagerUtil.commitDBTransaction(); + } catch (ApplicationManagementDAOException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = "Error occurred while creating identity server with the id " + id; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + /** + * Validate the identity server delete request + * + * @param identityServerId identity server id + * @throws BadRequestException if provided identity server id is invalid + */ + private void validateIdentityServerDeleteRequest(int identityServerId) throws ApplicationManagementException { + IdentityServerDTO identityServerDTO = getIdentityServerFromDB(identityServerId); + if (identityServerDTO == null) { + String msg = "Identity server with the id: " + identityServerId + " does not exist to delete"; + log.error(msg); + throw new BadRequestException(msg); + } + } + + /** + * This method is useful to re-construct the api params Map using updated identity server bean {@link IdentityServerDTO} + * For example updated identity server bean may contain only updated api param, in which case the existing api param values + * should be re-added to updated identity server bean + * + * @param updatedIdentityServerDTO updated identity server request payload + * @param existingIdentityServerDTO corresponding existing identity server of updated identity server + * @return Constructed api param map + */ + private Map constructUpdatedApiParams(IdentityServerDTO updatedIdentityServerDTO, + IdentityServerDTO existingIdentityServerDTO) { + Map updatedApiParams = updatedIdentityServerDTO.getApiParams(); + Map existingApiParams = existingIdentityServerDTO.getApiParams(); + if (updatedIdentityServerDTO.getProviderName().equals(existingIdentityServerDTO.getProviderName())) { + existingApiParams.putAll(updatedApiParams); + return existingApiParams; + } + return updatedApiParams; + } + + /** + * Validate the identity server update request payload + * + * @param updateIdentityServerDTO of identity server update request + * @throws BadRequestException if any invalid payload found + */ + private void validateIdentityServerUpdateRequest(IdentityServerDTO updateIdentityServerDTO, + IdentityServerDTO existingIdentityServerDTO) throws ApplicationManagementException { + if (updateIdentityServerDTO.getProviderName() != null && + isIdentityServiceProviderNotConfigured(updateIdentityServerDTO.getProviderName())) { + String msg = "No such providers configured. Provider name: " + updateIdentityServerDTO.getProviderName(); + log.error(msg); + throw new BadRequestException(msg); + } + if (updateIdentityServerDTO.getName() != null) { + if (!updateIdentityServerDTO.getName().equalsIgnoreCase(existingIdentityServerDTO.getName()) + && isIdentityServerNameExist(updateIdentityServerDTO.getName())) { + String msg = "Identity server already exist with the given name. Identity server name: " + updateIdentityServerDTO.getName(); + log.error(msg); + throw new BadRequestException(msg); + } + } + if (updateIdentityServerDTO.getUrl() != null) { + validateIdentityServerUrl(updateIdentityServerDTO.getUrl()); + if(!updateIdentityServerDTO.getUrl().equalsIgnoreCase(existingIdentityServerDTO.getUrl()) && + isIdentityServerUrlExist(updateIdentityServerDTO.getUrl())) { + String msg = "Identity server already exist with the given url. Identity server url: " + updateIdentityServerDTO.getUrl(); + log.error(msg); + throw new BadRequestException(msg); + } + } + validateUpdateIdentityServerRequestApiParam(updateIdentityServerDTO, existingIdentityServerDTO); + } + + + /** + * Validate the identity server create request payload + * + * @param identityServerDTO of identity server create request + * @throws BadRequestException if any invalid payload found + */ + private void validateIdentityServerCreateRequest(IdentityServerDTO identityServerDTO) throws ApplicationManagementException { + if (identityServerDTO.getUsername() == null) { + String msg = "Identity server username can not be null"; + log.error(msg); + throw new BadRequestException(msg); + } + if (identityServerDTO.getPassword() == null) { + String msg = "Identity server password can not be null"; + log.error(msg); + throw new BadRequestException(msg); + } + if (identityServerDTO.getName() == null) { + String msg = "Identity server name can not be null"; + log.error(msg); + throw new BadRequestException(msg); + } + if (identityServerDTO.getUrl() == null) { + String msg = "Identity server url can not be null"; + log.error(msg); + throw new BadRequestException(msg); + } + if (isIdentityServiceProviderNotConfigured(identityServerDTO.getProviderName())) { + String msg = "No such providers configured. Provider name: " + identityServerDTO.getProviderName(); + log.error(msg); + throw new BadRequestException(msg); + } + if (isIdentityServerNameExist(identityServerDTO.getName())) { + String msg = "Identity server already exist with the given name. Identity server name: " + identityServerDTO.getName(); + log.error(msg); + throw new BadRequestException(msg); + } + if (isIdentityServerUrlExist(identityServerDTO.getUrl())) { + String msg = "Identity server already exist with the given url. Identity server url: " + identityServerDTO.getUrl(); + log.error(msg); + throw new BadRequestException(msg); + } + validateCreateIdentityServerRequestApiParams(identityServerDTO); + validateIdentityServerUrl(identityServerDTO.getUrl()); + } + + /** + * Validate provided identity server url (For example make sure it uses http/https protocol) + * + * @param url url of the identity server + * @throws BadRequestException if url is invalid + */ + private void validateIdentityServerUrl(String url) throws BadRequestException { + String[] schemes = {"http","https"}; + UrlValidator urlValidator = new UrlValidator(schemes, UrlValidator.ALLOW_LOCAL_URLS); + if (!urlValidator.isValid(url)) { + String msg = "Identity server url is not a valid url"; + log.error(msg); + throw new BadRequestException(msg); + } + } + + /** + * Validate provided api params map in a identity server updated request + * For example the updated api param map may not contain all the required api params + * + * @param updatedIdentityServerDto Identity server update request payload bean + * @param existingIdentityServerDTO Corresponding existing identity server bean of the updated identity server + * @throws ApplicationManagementException if any api param is invalid + */ + private void validateUpdateIdentityServerRequestApiParam(IdentityServerDTO updatedIdentityServerDto, + IdentityServerDTO existingIdentityServerDTO) throws ApplicationManagementException { + ISServiceProviderApplicationService serviceProviderApplicationService = + ISServiceProviderApplicationService.of(existingIdentityServerDTO.getProviderName()); + List requiredApiParams = serviceProviderApplicationService.getRequiredApiParams(); + if (!updatedIdentityServerDto.getProviderName().equals(existingIdentityServerDTO.getProviderName())) { + validateAllRequiredParamsExists(updatedIdentityServerDto, requiredApiParams); + } + validateIfAnyInvalidParamExists(updatedIdentityServerDto, requiredApiParams); + } + + /** + * Validate api params map of identity server create request payload + * For example the api param map may not contain all the required api params + * + * @param identityServerDTO {@link IdentityServerDTO} + * @throws ApplicationManagementException if any api param is invalid + */ + private void validateCreateIdentityServerRequestApiParams(IdentityServerDTO identityServerDTO) throws ApplicationManagementException { + ISServiceProviderApplicationService serviceProviderApplicationService = + ISServiceProviderApplicationService.of(identityServerDTO.getProviderName()); + List requiredApiParams = serviceProviderApplicationService.getRequiredApiParams(); + validateAllRequiredParamsExists(identityServerDTO, requiredApiParams); + validateIfAnyInvalidParamExists(identityServerDTO, requiredApiParams); + } + + /** + * Make sure if all required api params exists for the given identity server bean + * + * @param identityServerDTO {@link IdentityServerDTO} + * @param requiredApiParams all mandatory api params + * @throws BadRequestException if a required api param does not exist + */ + private void validateAllRequiredParamsExists(IdentityServerDTO identityServerDTO, List requiredApiParams) + throws BadRequestException { + for (String param : requiredApiParams) { + if (identityServerDTO.getApiParams().get(param) == null) { + String msg = param + " api parameter is required for " + identityServerDTO.getProviderName() + ". " + + "Required api parameters: " + StringUtils.join(requiredApiParams, ","); + log.error(msg); + throw new BadRequestException(msg); + } + } + } + + /** + * Make sure if all api params are valid + * For example it may contain an unwanted api param + * + * @param identityServerDTO {@link IdentityServerDTO} + * @param requiredApiParams all required api params + * @throws BadRequestException if an unwanted api param exist + */ + private void validateIfAnyInvalidParamExists(IdentityServerDTO identityServerDTO, List requiredApiParams) + throws BadRequestException { + for (String param : identityServerDTO.getApiParamKeys()) { + if (!requiredApiParams.contains(param)) { + String msg = "Invalid api parameter. " + param + " is not required for " + identityServerDTO.getProviderName() + ". " + + "Required api parameters: " + StringUtils.join(requiredApiParams, ","); + throw new BadRequestException(msg); + } + } + } + + /** + * If the given providerName does not exist in the identity server config file + * + * @param providerName Name of the identity service provider + * @return if provider name exist in identity server config + */ + private boolean isIdentityServiceProviderNotConfigured(String providerName) { + List identityServiceProviders = ConfigurationManager.getInstance().getIdentityServerConfiguration(). + getIdentityServiceProviders(); + return identityServiceProviders.stream().noneMatch(provider -> provider.getProviderName().equals(providerName)); + } + + @Override + public boolean isIdentityServerNameExist(String name) throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + try { + ConnectionManagerUtil.openDBConnection(); + return spApplicationDAO.isExistingIdentityServerName(name, tenantId); + } catch (ApplicationManagementDAOException | DBConnectionException e) { + String msg = "Error occurred while checking if identity server with the name " + name + " exists."; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + @Override + public boolean isIdentityServerUrlExist(String url) throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + try { + ConnectionManagerUtil.openDBConnection(); + return spApplicationDAO.isExistingIdentityServerUrl(url, tenantId); + } catch (ApplicationManagementDAOException | DBConnectionException e) { + String msg = "Error occurred while checking if identity server with the url " + url + " exists."; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + @Override + public SPApplicationListResponse retrieveSPApplicationFromIdentityServer(int identityServerId, Integer offset, Integer limit) + throws ApplicationManagementException { + IdentityServerDTO identityServer = getIdentityServer(identityServerId); + ISServiceProviderApplicationService serviceProviderApplicationService = ISServiceProviderApplicationService.of(identityServer.getProviderName()); + SPApplicationListResponse spApplicationListResponse = serviceProviderApplicationService.retrieveSPApplications(identityServer, offset, limit); + addExistingApps(identityServerId, spApplicationListResponse.getApplications()); + return spApplicationListResponse; + } + + /** + * This method adds existing consumer applications of service providers to the SPApplication bean + * + * @param identityServerId identity server id of the service provider + * @param spApplications Service providers list to which the existing applications should be added + * @throws ApplicationManagementException if error occurred while adding existing applications + */ + private void addExistingApps(int identityServerId, List spApplications) throws ApplicationManagementException { + for (SPApplication spApplication : spApplications) { + List existingApplications = getSPApplications(identityServerId, spApplication.getId()); + spApplication.setExistingApplications(existingApplications); + } + } + + @Override + public List getSPApplications(int identityServerId, String spUID) throws + ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + ApplicationManager applicationManager = APIUtil.getApplicationManager(); + List applications = new ArrayList<>(); + + try { + ConnectionManagerUtil.openDBConnection(); + List appDTOs = spApplicationDAO.getSPApplications(identityServerId, spUID, tenantId); + for (ApplicationDTO applicationDTO : appDTOs) { + if (lifecycleStateManager.getEndState().equals(applicationDTO.getStatus())) { + continue; + } + boolean isHideableApp = applicationManager.isHideableApp(applicationDTO.getApplicationReleaseDTOs()); + boolean isDeletableApp = applicationManager.isDeletableApp(applicationDTO.getApplicationReleaseDTOs()); + + //Set application categories, tags and unrestricted roles to the application DTO. + applicationDTO + .setUnrestrictedRoles(visibilityDAO.getUnrestrictedRoles(applicationDTO.getId(), tenantId)); + applicationDTO.setAppCategories(applicationDAO.getAppCategories(applicationDTO.getId(), tenantId)); + applicationDTO.setTags(applicationDAO.getAppTags(applicationDTO.getId(), tenantId)); + + applicationDTO.setApplicationReleaseDTOs(applicationDTO.getApplicationReleaseDTOs()); + Application application = APIUtil.appDtoToAppResponse(applicationDTO); + application.setDeletableApp(isDeletableApp); + application.setHideableApp(isHideableApp); + applications.add(application); + } + + return applications; + } catch (DBConnectionException e) { + String msg = "Error occurred when getting database connection to get applications by filtering from " + + "requested filter."; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } catch (ApplicationManagementDAOException e) { + String msg = + "DAO exception while getting applications of tenant " + tenantId ; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + public void validateAttachAppsRequest(int identityServerId, String serviceProviderId, List appIds) throws ApplicationManagementException { + validateServiceProviderUID(identityServerId, serviceProviderId); + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + try { + ConnectionManagerUtil.openDBConnection(); + for (int appId : appIds) { + try { + ApplicationDTO appDTO = applicationDAO.getApplication(appId, tenantId); + if (appDTO == null) { + String msg = "Payload contains invalid an app id. " + "No app exist with the appId: " + appId + "."; + throw new BadRequestException(msg); + } + } catch (ApplicationManagementDAOException e) { + String msg = "Error occurred while trying to retrieve application with the id:" + appId; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } + } + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + public void validateDetachAppsRequest(int identityServerId, String spId, List appIds) throws ApplicationManagementException { + validateServiceProviderUID(identityServerId, spId); + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + try { + ConnectionManagerUtil.openDBConnection(); + for (int id : appIds) { + try { + boolean isSPAppExist = spApplicationDAO.isSPApplicationExist(identityServerId, spId, id, tenantId); + if (!isSPAppExist) { + String msg = "No service provider app exist with the appId: " + id + " for service provider with the " + + "UID " + spId; + throw new ApplicationManagementException(msg); + } + } catch (ApplicationManagementDAOException e) { + String msg = "Error occurred while checking if application exists with the id:" + id; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } + } + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + @Override + public List getIdentityServiceProviders() throws ApplicationManagementException { + List identityServiceProviders = ConfigurationManager.getInstance(). + getIdentityServerConfiguration().getIdentityServiceProviders(); + List identityServiceProviderDTOS = new ArrayList<>(); + for (IdentityServiceProvider identityServiceProvider : identityServiceProviders) { + try { + identityServiceProviderDTOS.add(APIUtil.identityServiceProviderToDTO(identityServiceProvider)); + } catch (ApplicationManagementException e) { + String msg = "Identity service provider configuration file is invalid. Hence failed to proceed."; + log.error(msg); + throw new ApplicationManagementException(msg, e); + } + } + return identityServiceProviderDTOS; + } + + /** + * Responsible for validating service provider in requests + * + * @param identityServerId identity server id of the service provider + * @param spUID uid of the service provider + * @throws ApplicationManagementException if invalid service provider + */ + private void validateServiceProviderUID(int identityServerId, String spUID) throws + ApplicationManagementException { + IdentityServerDTO identityServer = getIdentityServer(identityServerId); + ISServiceProviderApplicationService serviceProviderApplicationService = ISServiceProviderApplicationService.of(identityServer.getProviderName()); + try { + boolean isSPAppExists = serviceProviderApplicationService. + isSPApplicationExist(identityServer, spUID); + if (!isSPAppExists) { + String errMsg = "Service provider with the uid " + spUID + " does not exist."; + log.error(errMsg); + throw new BadRequestException(errMsg); + } + } catch (ApplicationManagementException e) { + String errMsg = "Error occurred while trying to validate service provider uid"; + log.error(errMsg, e); + throw new ApplicationManagementException(errMsg, e); + } + } + + + public void attachSPApplications(int identityServerId, String spUID, List appIds) throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + try { + ConnectionManagerUtil.beginDBTransaction(); + for (int appId : appIds) { + spApplicationDAO.attachSPApplication(identityServerId, spUID, appId, tenantId); + } + ConnectionManagerUtil.commitDBTransaction(); + } catch (ApplicationManagementDAOException e){ + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = + "DAO exception while getting applications of tenant " + tenantId; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + public void detachSPApplications(int identityServerId, String spUID, List appIds) throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + try { + ConnectionManagerUtil.beginDBTransaction(); + for (int id : appIds) { + spApplicationDAO.detachSPApplication(identityServerId, spUID, id, tenantId); + } + ConnectionManagerUtil.commitDBTransaction(); + } catch (ApplicationManagementDAOException e){ + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = + "DAO exception while getting applications of tenant " + tenantId; + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + @Override + public Application createSPApplication(T app, int identityServerId, String spId, boolean isPublished) throws ApplicationManagementException { + validateServiceProviderUID(identityServerId, spId); + ApplicationManager applicationManager = ApplicationManagementUtil.getApplicationManagerInstance(); + ApplicationDTO applicationDTO = applicationManager.uploadReleaseArtifactIfExist(app); + if (log.isDebugEnabled()) { + log.debug("Application release create request is received. Application name: " + applicationDTO.getName() + + " Device type ID: " + applicationDTO.getDeviceTypeId()); + } + try { + ConnectionManagerUtil.beginDBTransaction(); + Application createdApp = applicationManager.addAppDataIntoDB(applicationDTO, isPublished); + attachCreatedSPApplication(createdApp, identityServerId, spId); + ConnectionManagerUtil.commitDBTransaction(); + return createdApp; + } catch (DBConnectionException e) { + String msg = "Error occurred while getting database connection."; + log.error(msg, e); + ApplicationManagementUtil.deleteArtifactIfExist(applicationDTO); + throw new ApplicationManagementException(msg, e); + } catch (TransactionManagementException e) { + String msg = "Error occurred while disabling AutoCommit."; + log.error(msg, e); + ApplicationManagementUtil.deleteArtifactIfExist(applicationDTO); + throw new ApplicationManagementException(msg, e); + } catch (ApplicationManagementException e) { + ConnectionManagerUtil.rollbackDBTransaction(); + String msg = "Error occurred while creating and attaching application with the name " + applicationDTO.getName() ; + log.error(msg, e); + ApplicationManagementUtil.deleteArtifactIfExist(applicationDTO); + throw new ApplicationManagementException(msg, e); + } finally { + ConnectionManagerUtil.closeDBConnection(); + } + } + + public void attachCreatedSPApplication(Application createdApp, int identityServerId, String spUID) throws ApplicationManagementException { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + try { + spApplicationDAO.attachSPApplication(identityServerId, spUID, createdApp.getId(), tenantId); + } catch (ApplicationManagementDAOException e) { + String msg = "Error occurred while attaching application with the id " + createdApp.getId(); + log.error(msg, e); + throw new ApplicationManagementException(msg, e); + } + } + +} diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/internal/ApplicationManagementServiceComponent.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/internal/ApplicationManagementServiceComponent.java index e56f73e1cb..be8cd12d46 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/internal/ApplicationManagementServiceComponent.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/internal/ApplicationManagementServiceComponent.java @@ -17,6 +17,7 @@ */ package io.entgra.application.mgt.core.internal; +import io.entgra.application.mgt.common.services.SPApplicationManager; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.osgi.framework.BundleContext; @@ -88,6 +89,10 @@ public class ApplicationManagementServiceComponent { DataHolder.getInstance().setLifecycleStateManger(lifecycleStateManager); bundleContext.registerService(LifecycleStateManager.class.getName(), lifecycleStateManager, null); + SPApplicationManager SPApplicationManager = ApplicationManagementUtil.getSPApplicationManagerInstance(); + DataHolder.getInstance().setISApplicationManager(SPApplicationManager); + bundleContext.registerService(SPApplicationManager.class.getName(), SPApplicationManager, null); + ApplicationManager applicationManager = ApplicationManagementUtil.getApplicationManagerInstance(); applicationManager .addApplicationCategories(ConfigurationManager.getInstance().getConfiguration().getAppCategories()); diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/internal/DataHolder.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/internal/DataHolder.java index 3c675db85a..f7bc6e1d8c 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/internal/DataHolder.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/internal/DataHolder.java @@ -20,6 +20,7 @@ package io.entgra.application.mgt.core.internal; import io.entgra.application.mgt.common.services.ApplicationManager; import io.entgra.application.mgt.common.services.ApplicationStorageManager; import io.entgra.application.mgt.common.services.AppmDataHandler; +import io.entgra.application.mgt.common.services.SPApplicationManager; import io.entgra.application.mgt.common.services.ReviewManager; import io.entgra.application.mgt.common.services.SubscriptionManager; import io.entgra.application.mgt.core.lifecycle.LifecycleStateManager; @@ -36,6 +37,8 @@ public class DataHolder { private RealmService realmService; + private SPApplicationManager SPApplicationManager; + private ApplicationManager applicationManager; private ReviewManager reviewManager; @@ -131,4 +134,12 @@ public class DataHolder { public void setTaskService(TaskService taskService) { this.taskService = taskService; } + + public SPApplicationManager getISApplicationManager() { + return SPApplicationManager; + } + + public void setISApplicationManager(SPApplicationManager SPApplicationManager) { + this.SPApplicationManager = SPApplicationManager; + } } diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/APIUtil.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/APIUtil.java index 45f1320176..0821341aa2 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/APIUtil.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/APIUtil.java @@ -18,6 +18,12 @@ package io.entgra.application.mgt.core.util; +import io.entgra.application.mgt.common.IdentityServerResponse; +import io.entgra.application.mgt.common.dto.IdentityServerDTO; +import io.entgra.application.mgt.common.dto.IdentityServiceProviderDTO; +import io.entgra.application.mgt.common.exception.InvalidConfigurationException; +import io.entgra.application.mgt.core.config.IdentityServiceProvider; +import io.entgra.application.mgt.core.identityserver.serviceprovider.ISServiceProviderApplicationService; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -59,12 +65,31 @@ public class APIUtil { private static Log log = LogFactory.getLog(APIUtil.class); + private static volatile SPApplicationManager SPApplicationManager; private static volatile ApplicationManager applicationManager; private static volatile ApplicationStorageManager applicationStorageManager; private static volatile SubscriptionManager subscriptionManager; private static volatile ReviewManager reviewManager; private static volatile AppmDataHandler appmDataHandler; + public static SPApplicationManager getSPApplicationManager() { + if (SPApplicationManager == null) { + synchronized (APIUtil.class) { + if (SPApplicationManager == null) { + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + SPApplicationManager = + (SPApplicationManager) ctx.getOSGiService(SPApplicationManager.class, null); + if (SPApplicationManager == null) { + String msg = "ApplicationDTO Manager service has not initialized."; + log.error(msg); + throw new IllegalStateException(msg); + } + } + } + } + return SPApplicationManager; + } + public static ApplicationManager getApplicationManager() { if (applicationManager == null) { synchronized (APIUtil.class) { @@ -231,6 +256,7 @@ public class APIUtil { public static ApplicationDTO convertToAppDTO(T param) throws BadRequestException, UnexpectedServerErrorException { ApplicationDTO applicationDTO = new ApplicationDTO(); + List applicationReleaseEntities; if (param instanceof ApplicationWrapper){ ApplicationWrapper applicationWrapper = (ApplicationWrapper) param; @@ -244,7 +270,7 @@ public class APIUtil { applicationDTO.setTags(applicationWrapper.getTags()); applicationDTO.setUnrestrictedRoles(applicationWrapper.getUnrestrictedRoles()); applicationDTO.setDeviceTypeId(deviceType.getId()); - List applicationReleaseEntities = applicationWrapper.getEntAppReleaseWrappers() + applicationReleaseEntities = applicationWrapper.getEntAppReleaseWrappers() .stream().map(APIUtil::releaseWrapperToReleaseDTO).collect(Collectors.toList()); applicationDTO.setApplicationReleaseDTOs(applicationReleaseEntities); } else if (param instanceof WebAppWrapper){ @@ -257,7 +283,7 @@ public class APIUtil { applicationDTO.setType(webAppWrapper.getType()); applicationDTO.setTags(webAppWrapper.getTags()); applicationDTO.setUnrestrictedRoles(webAppWrapper.getUnrestrictedRoles()); - List applicationReleaseEntities = webAppWrapper.getWebAppReleaseWrappers() + applicationReleaseEntities = webAppWrapper.getWebAppReleaseWrappers() .stream().map(APIUtil::releaseWrapperToReleaseDTO).collect(Collectors.toList()); applicationDTO.setApplicationReleaseDTOs(applicationReleaseEntities); } else if (param instanceof PublicAppWrapper) { @@ -272,7 +298,7 @@ public class APIUtil { applicationDTO.setTags(publicAppWrapper.getTags()); applicationDTO.setUnrestrictedRoles(publicAppWrapper.getUnrestrictedRoles()); applicationDTO.setDeviceTypeId(deviceType.getId()); - List applicationReleaseEntities = publicAppWrapper.getPublicAppReleaseWrappers() + applicationReleaseEntities = publicAppWrapper.getPublicAppReleaseWrappers() .stream().map(APIUtil::releaseWrapperToReleaseDTO).collect(Collectors.toList()); applicationDTO.setApplicationReleaseDTOs(applicationReleaseEntities); } else if (param instanceof CustomAppWrapper){ @@ -287,7 +313,7 @@ public class APIUtil { applicationDTO.setTags(customAppWrapper.getTags()); applicationDTO.setUnrestrictedRoles(customAppWrapper.getUnrestrictedRoles()); applicationDTO.setDeviceTypeId(deviceType.getId()); - List applicationReleaseEntities = customAppWrapper.getCustomAppReleaseWrappers() + applicationReleaseEntities = customAppWrapper.getCustomAppReleaseWrappers() .stream().map(APIUtil::releaseWrapperToReleaseDTO).collect(Collectors.toList()); applicationDTO.setApplicationReleaseDTOs(applicationReleaseEntities); } @@ -343,6 +369,32 @@ public class APIUtil { return applicationReleaseDTO; } + public static IdentityServiceProviderDTO identityServiceProviderToDTO(IdentityServiceProvider identityServiceProvider) + throws InvalidConfigurationException { + ISServiceProviderApplicationService serviceProviderApplicationService = + ISServiceProviderApplicationService.of(identityServiceProvider.getProviderName()); + IdentityServiceProviderDTO identityServiceProviderDTO = new IdentityServiceProviderDTO(); + identityServiceProviderDTO.setName(identityServiceProvider.getProviderName()); + identityServiceProviderDTO.setRequiredApiParams(serviceProviderApplicationService.getRequiredApiParams()); + return identityServiceProviderDTO; + } + + public static IdentityServerResponse identityServerDtoToIdentityServerResponse(IdentityServerDTO identityServerDTO) { + IdentityServerResponse identityServer = new IdentityServerResponse(); + identityServer.setId(identityServerDTO.getId()); + identityServer.setProviderName(identityServerDTO.getProviderName()); + identityServer.setName(identityServerDTO.getName()); + identityServer.setDescription(identityServerDTO.getDescription()); + identityServer.setUrl(identityServerDTO.getUrl()); + identityServer.setApiParamList(identityServerDTO.getApiParams()); + identityServer.setUsername(identityServerDTO.getUsername()); + IdentityServiceProvider identityServiceProvider = ConfigurationManager.getInstance().getIdentityServerConfiguration() + .getIdentityServerDetailByProviderName(identityServerDTO.getProviderName()); + String serviceProviderAppsUrl = identityServerDTO.getUrl() + identityServiceProvider.getServiceProvidersPageUri(); + identityServer.setServiceProviderAppsUrl(serviceProviderAppsUrl); + return identityServer; + } + public static Application appDtoToAppResponse(ApplicationDTO applicationDTO) throws ApplicationManagementException { Application application = new Application(); @@ -363,7 +415,9 @@ public class APIUtil { application.setUnrestrictedRoles(applicationDTO.getUnrestrictedRoles()); application.setRating(applicationDTO.getAppRating()); application.setFavourite(applicationDTO.isFavourite()); - application.setInstallerName(applicationDTO.getApplicationReleaseDTOs().get(0).getInstallerName()); + if (applicationDTO.getApplicationReleaseDTOs() != null && !applicationDTO.getApplicationReleaseDTOs().isEmpty()) { + application.setInstallerName(applicationDTO.getApplicationReleaseDTOs().get(0).getInstallerName()); + } List applicationReleases = new ArrayList<>(); if (ApplicationType.PUBLIC.toString().equals(applicationDTO.getType()) && application.getCategories() .contains("GooglePlaySyncedApp")) { diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/ApplicationManagementUtil.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/ApplicationManagementUtil.java index 11d8adb2ce..f0ef6c4b29 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/ApplicationManagementUtil.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/ApplicationManagementUtil.java @@ -17,6 +17,24 @@ */ package io.entgra.application.mgt.core.util; +import io.entgra.application.mgt.common.ApplicationArtifact; +import io.entgra.application.mgt.common.Base64File; +import io.entgra.application.mgt.common.FileDataHolder; +import io.entgra.application.mgt.common.dto.ApplicationDTO; +import io.entgra.application.mgt.common.dto.ApplicationReleaseDTO; +import io.entgra.application.mgt.common.exception.ApplicationManagementException; +import io.entgra.application.mgt.common.exception.RequestValidatingException; +import io.entgra.application.mgt.common.exception.ResourceManagementException; +import io.entgra.application.mgt.common.services.SPApplicationManager; +import io.entgra.application.mgt.common.wrapper.ApplicationWrapper; +import io.entgra.application.mgt.common.wrapper.CustomAppReleaseWrapper; +import io.entgra.application.mgt.common.wrapper.CustomAppWrapper; +import io.entgra.application.mgt.common.wrapper.EntAppReleaseWrapper; +import io.entgra.application.mgt.common.wrapper.PublicAppReleaseWrapper; +import io.entgra.application.mgt.common.wrapper.PublicAppWrapper; +import io.entgra.application.mgt.common.wrapper.WebAppReleaseWrapper; +import io.entgra.application.mgt.common.wrapper.WebAppWrapper; +import io.entgra.application.mgt.core.exception.BadRequestException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import io.entgra.application.mgt.common.exception.InvalidConfigurationException; @@ -27,8 +45,15 @@ import io.entgra.application.mgt.common.services.SubscriptionManager; import io.entgra.application.mgt.core.config.ConfigurationManager; import io.entgra.application.mgt.core.config.Extension; import io.entgra.application.mgt.core.lifecycle.LifecycleStateManager; +import org.wso2.carbon.device.mgt.core.common.util.FileUtil; +import java.io.InputStream; import java.lang.reflect.Constructor; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; /** * This DAOUtil class is responsible for making sure single instance of each Extension Manager is used throughout for @@ -38,6 +63,97 @@ public class ApplicationManagementUtil { private static Log log = LogFactory.getLog(ApplicationManagementUtil.class); + /** + * Construct ApplicationArtifact from given base64 artifact files + * + * @param iconBase64 icon of the application + * @param screenshotsBase64 screenshots of the application + * @param binaryFileBase64 binary file of the application + * @param bannerFileBase64 banner of the application + * @return ApplicationArtifact the give base64 release artifact files + * @throws BadRequestException if any invalid payload is found + */ + public static ApplicationArtifact constructApplicationArtifact(Base64File iconBase64, List screenshotsBase64, + Base64File binaryFileBase64, Base64File bannerFileBase64) + throws BadRequestException { + ApplicationArtifact applicationArtifact = new ApplicationArtifact(); + ApplicationManager applicationManager = APIUtil.getApplicationManager(); + if (binaryFileBase64 != null) { + try { + applicationManager.validateBase64File(binaryFileBase64); + } catch (RequestValidatingException e) { + String msg = "Invalid base64 binary file payload found"; + log.error(msg, e); + throw new BadRequestException(msg, e); + } + FileDataHolder binaryFile = base64FileToFileDataHolder(binaryFileBase64); + applicationArtifact.setInstallerName(binaryFile.getName()); + applicationArtifact.setInstallerStream(binaryFile.getFile()); + } + if (iconBase64 != null) { + try { + applicationManager.validateBase64File(iconBase64); + } catch (RequestValidatingException e) { + String msg = "Invalid base64 icon file payload found"; + log.error(msg, e); + throw new BadRequestException(msg, e); + } + FileDataHolder iconFile = base64FileToFileDataHolder(iconBase64); + applicationArtifact.setIconName(iconFile.getName()); + applicationArtifact.setIconStream(iconFile.getFile()); + } + if (bannerFileBase64 != null) { + try { + applicationManager.validateBase64File(bannerFileBase64); + } catch (RequestValidatingException e) { + String msg = "Invalid base64 banner file payload found"; + log.error(msg, e); + throw new BadRequestException(msg, e); + } + FileDataHolder bannerFile = base64FileToFileDataHolder(bannerFileBase64); + applicationArtifact.setBannerName(bannerFile.getName()); + applicationArtifact.setBannerStream(bannerFile.getFile()); + } + + if (screenshotsBase64 != null) { + Map screenshotData = new TreeMap<>(); + // This is to handle cases in which multiple screenshots have the same name + Map screenshotNameCount = new HashMap<>(); + for (Base64File screenshot : screenshotsBase64) { + try { + applicationManager.validateBase64File(screenshot); + } catch (RequestValidatingException e) { + String msg = "Invalid base64 screenshot file payload found"; + log.error(msg, e); + throw new BadRequestException(msg, e); + } + FileDataHolder screenshotFile = base64FileToFileDataHolder(screenshot); + String screenshotName = screenshotFile.getName(); + screenshotNameCount.put(screenshotName, screenshotNameCount.getOrDefault(screenshotName, 0) + 1); + screenshotName = FileUtil.generateDuplicateFileName(screenshotName, screenshotNameCount.get(screenshotName)); + screenshotData.put(screenshotName, screenshotFile.getFile()); + } + applicationArtifact.setScreenshots(screenshotData); + } + return applicationArtifact; + } + + /** + * + * @param base64File Base64File that should be converted to FileDataHolder bean + * @return FileDataHolder bean which contains input stream and name of the file + */ + public static FileDataHolder base64FileToFileDataHolder(Base64File base64File) { + InputStream stream = FileUtil.base64ToInputStream(base64File.getBase64String()); + return new FileDataHolder(base64File.getName(), stream); + } + + public static SPApplicationManager getSPApplicationManagerInstance() throws InvalidConfigurationException { + ConfigurationManager configurationManager = ConfigurationManager.getInstance(); + Extension extension = configurationManager.getExtension(Extension.Name.SPApplicationManager); + return getInstance(extension, SPApplicationManager.class); + } + public static ApplicationManager getApplicationManagerInstance() throws InvalidConfigurationException { ConfigurationManager configurationManager = ConfigurationManager.getInstance(); Extension extension = configurationManager.getExtension(Extension.Name.ApplicationManager); @@ -69,7 +185,48 @@ public class ApplicationManagementUtil { return getInstance(extension, LifecycleStateManager.class); } - private static T getInstance(Extension extension, Class cls) throws InvalidConfigurationException { + /** + * This is useful to delete application artifacts if any error occurred while creating release/application + * after uploading the artifacts + * + * @param app ApplicationDTO of the application of which the artifacts should be deleted + * @throws ApplicationManagementException if error occurred while deleting artifacts + */ + public static void deleteArtifactIfExist(ApplicationDTO app) throws ApplicationManagementException { + ApplicationManager applicationManager = ApplicationManagementUtil.getApplicationManagerInstance(); + if (!app.getApplicationReleaseDTOs().isEmpty()) { + applicationManager.deleteApplicationArtifacts(Collections.singletonList(app.getApplicationReleaseDTOs().get(0).getAppHashValue())); + } + } + + /** + * Check if application release available for a given application wrapper. This is useful since + * if a release is available for an application that needs to handled separately + * + * @param appWrapper Application wrapper bean of the application + * @return if release is available or not + */ + public static boolean isReleaseAvailable(T appWrapper) { + if (appWrapper instanceof ApplicationWrapper) { + List entAppReleaseWrappers = ((ApplicationWrapper) appWrapper).getEntAppReleaseWrappers(); + return entAppReleaseWrappers != null && !entAppReleaseWrappers.isEmpty(); + } + if (appWrapper instanceof PublicAppWrapper) { + List publicAppReleaseWrappers = ((PublicAppWrapper) appWrapper).getPublicAppReleaseWrappers(); + return publicAppReleaseWrappers != null && !publicAppReleaseWrappers.isEmpty(); + } + if (appWrapper instanceof WebAppWrapper) { + List webAppReleaseWrappers = ((WebAppWrapper) appWrapper).getWebAppReleaseWrappers(); + return webAppReleaseWrappers != null && !webAppReleaseWrappers.isEmpty(); + } + if (appWrapper instanceof CustomAppWrapper) { + List customAppReleaseWrappers = ((CustomAppWrapper) appWrapper).getCustomAppReleaseWrappers(); + return customAppReleaseWrappers != null && !((CustomAppWrapper) appWrapper).getCustomAppReleaseWrappers().isEmpty(); + } + throw new IllegalArgumentException("Provided bean does not belong to an Application Wrapper"); + } + + public static T getInstance(Extension extension, Class cls) throws InvalidConfigurationException { try { Class theClass = Class.forName(extension.getClassName()); if (extension.getParameters() != null && extension.getParameters().size() > 0) { diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/Constants.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/Constants.java index 299db3ea44..a69f28e5df 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/Constants.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/Constants.java @@ -31,10 +31,15 @@ import java.util.Map; public class Constants { public static final String APPLICATION_CONFIG_XML_FILE = "application-mgt.xml"; + public static final String IDENTITY_SERVERS_CONFIG_XML_FILE = "identity-service-provider-config.xml"; public static final String DEFAULT_CONFIG_FILE_LOCATION = CarbonUtils.getCarbonConfigDirPath() + File.separator + Constants.APPLICATION_CONFIG_XML_FILE; + public static final String DEFAULT_IDENTITY_SERVERS_CONFIG_FILE_LOCATION = CarbonUtils.getCarbonConfigDirPath() + File.separator + + IDENTITY_SERVERS_CONFIG_XML_FILE; public static final String DEFAULT_VERSION = "1.0.0"; + public static final String SCREENSHOT_NAME = "screenshot"; + public static final String ICON_NAME = "icon"; public static final String PAYLOAD = "Payload"; public static final String PLIST_NAME = "Info.plist"; public static final String CF_BUNDLE_VERSION = "CFBundleVersion"; @@ -48,8 +53,20 @@ public class Constants { public static final String OPERATION_STATUS_UPDATE_API_BASE = "/api/device-mgt/v1.0/devices"; public static final String OPERATION_STATUS_UPDATE_API_URI = "/operation"; + public static final String LIMIT_QUERY_PARAM = "limit"; + public static final String OFFSET_QUERY_PARAM = "offset"; + public static final String IS_APPS_API_CONTEXT_PATH = "identity-server-applications"; + public static final String IS_APPS_API_BASE_PATH = "identity-server-applications"; + public static final Double IS_APP_DEFAULT_PRICE = 0.0; + public static final String SP_APP_CATEGORY = "SPApp"; + public static final String IS_APP_RELEASE_TYPE = "stable"; + public static final String IS_APP_DEFAULT_PAYMENT_CURRENCY = "$"; + public static final String IS_APP_DEFAULT_VERSION = "1.0"; public static final String COLON = ":"; public static final String FORWARD_SLASH = "/"; + public static final String URI_QUERY_SEPARATOR = "?"; + public static final String QUERY_STRING_SEPARATOR = "&"; + public static final String QUERY_KEY_VALUE_SEPARATOR = "="; public static final String ANY = "ANY"; public static final String DEFAULT_PCK_NAME = "default.app.com"; public static final String ALL = "ALL"; diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/DAOUtil.java b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/DAOUtil.java index 6acfa182a1..88e53bfe6b 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/DAOUtil.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/main/java/io/entgra/application/mgt/core/util/DAOUtil.java @@ -19,6 +19,7 @@ package io.entgra.application.mgt.core.util; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import io.entgra.application.mgt.common.dto.IdentityServerDTO; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONException; @@ -38,11 +39,10 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; import java.util.ArrayList; -import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -86,10 +86,16 @@ public class DAOUtil { application.setAppRating(rs.getDouble("APP_RATING")); application.setDeviceTypeId(rs.getInt("APP_DEVICE_TYPE_ID")); application.setPackageName(rs.getString("PACKAGE_NAME")); - application.getApplicationReleaseDTOs().add(constructAppReleaseDTO(rs)); + ApplicationReleaseDTO releaseDTO = constructAppReleaseDTO(rs); + if (releaseDTO != null) { + application.getApplicationReleaseDTOs().add(constructAppReleaseDTO(rs)); + } } else { if (application != null && application.getApplicationReleaseDTOs() != null) { - application.getApplicationReleaseDTOs().add(constructAppReleaseDTO(rs)); + ApplicationReleaseDTO releaseDTO = constructAppReleaseDTO(rs); + if (releaseDTO != null) { + application.getApplicationReleaseDTOs().add(constructAppReleaseDTO(rs)); + } } } hasNext = rs.next(); @@ -139,28 +145,79 @@ public class DAOUtil { */ public static ApplicationReleaseDTO constructAppReleaseDTO(ResultSet rs) throws SQLException { ApplicationReleaseDTO appRelease = new ApplicationReleaseDTO(); - appRelease.setId(rs.getInt("RELEASE_ID")); - appRelease.setDescription(rs.getString("RELEASE_DESCRIPTION")); - appRelease.setUuid(rs.getString("RELEASE_UUID")); - appRelease.setReleaseType(rs.getString("RELEASE_TYPE")); - appRelease.setVersion(rs.getString("RELEASE_VERSION")); - appRelease.setInstallerName(rs.getString("AP_RELEASE_STORED_LOC")); - appRelease.setIconName(rs.getString("AP_RELEASE_ICON_LOC")); - appRelease.setBannerName(rs.getString("AP_RELEASE_BANNER_LOC")); - appRelease.setScreenshotName1(rs.getString("AP_RELEASE_SC1")); - appRelease.setScreenshotName2(rs.getString("AP_RELEASE_SC2")); - appRelease.setScreenshotName3(rs.getString("AP_RELEASE_SC3")); - appRelease.setAppHashValue(rs.getString("RELEASE_HASH_VALUE")); - appRelease.setPrice(rs.getDouble("RELEASE_PRICE")); - appRelease.setMetaData(rs.getString("RELEASE_META_INFO")); - appRelease.setPackageName(rs.getString("PACKAGE_NAME")); - appRelease.setSupportedOsVersions(rs.getString("RELEASE_SUP_OS_VERSIONS")); - appRelease.setRating(rs.getDouble("RELEASE_RATING")); - appRelease.setCurrentState(rs.getString("RELEASE_CURRENT_STATE")); - appRelease.setRatedUsers(rs.getInt("RATED_USER_COUNT")); - return appRelease; + if (rs.getString("RELEASE_UUID") != null) { + appRelease.setId(rs.getInt("RELEASE_ID")); + appRelease.setDescription(rs.getString("RELEASE_DESCRIPTION")); + appRelease.setUuid(rs.getString("RELEASE_UUID")); + appRelease.setReleaseType(rs.getString("RELEASE_TYPE")); + appRelease.setVersion(rs.getString("RELEASE_VERSION")); + appRelease.setInstallerName(rs.getString("AP_RELEASE_STORED_LOC")); + appRelease.setIconName(rs.getString("AP_RELEASE_ICON_LOC")); + appRelease.setBannerName(rs.getString("AP_RELEASE_BANNER_LOC")); + appRelease.setScreenshotName1(rs.getString("AP_RELEASE_SC1")); + appRelease.setScreenshotName2(rs.getString("AP_RELEASE_SC2")); + appRelease.setScreenshotName3(rs.getString("AP_RELEASE_SC3")); + appRelease.setAppHashValue(rs.getString("RELEASE_HASH_VALUE")); + appRelease.setPrice(rs.getDouble("RELEASE_PRICE")); + appRelease.setMetaData(rs.getString("RELEASE_META_INFO")); + appRelease.setPackageName(rs.getString("PACKAGE_NAME")); + appRelease.setSupportedOsVersions(rs.getString("RELEASE_SUP_OS_VERSIONS")); + appRelease.setRating(rs.getDouble("RELEASE_RATING")); + appRelease.setCurrentState(rs.getString("RELEASE_CURRENT_STATE")); + appRelease.setRatedUsers(rs.getInt("RATED_USER_COUNT")); + return appRelease; + } + return null; } + /** + * To create application object from the result set retrieved from the Database. + * + * @param rs ResultSet + * @return IdentityServerDTO that is retrieved from the Database. + * @throws SQLException SQL Exception + * @throws JSONException JSONException. + */ + public static IdentityServerDTO loadIdentityServer(ResultSet rs) + throws SQLException, JSONException, UnexpectedServerErrorException { + List identityServerDTOS = loadIdentityServers(rs); + if (identityServerDTOS.isEmpty()) { + return null; + } + if (identityServerDTOS.size() > 1) { + String msg = "Internal server error. Found more than one identity server for requested ID"; + log.error(msg); + throw new UnexpectedServerErrorException(msg); + } + return identityServerDTOS.get(0); + } + + /** + * To create application object from the result set retrieved from the Database. + * + * @param rs ResultSet + * @return List of Identity Servers that is retrieved from the Database. + * @throws SQLException SQL Exception + * @throws JSONException JSONException. + */ + public static List loadIdentityServers(ResultSet rs) throws SQLException, JSONException { + List identityServerDTOS = new ArrayList<>(); + while (rs.next()) { + IdentityServerDTO identityServerDTO = new IdentityServerDTO(); + identityServerDTO.setId(rs.getInt("ID")); + identityServerDTO.setProviderName(rs.getString("PROVIDER_NAME")); + identityServerDTO.setName(rs.getString("NAME")); + identityServerDTO.setDescription(rs.getString("DESCRIPTION")); + identityServerDTO.setUrl(rs.getString("URL")); + String apiParamsJson = rs.getString("API_PARAMS"); + Map apiParams = new Gson().fromJson(apiParamsJson, new TypeToken>() {}.getType()); + identityServerDTO.setApiParams(apiParams); + identityServerDTO.setUsername(rs.getString("USERNAME")); + identityServerDTO.setPassword(rs.getString("PASSWORD")); + identityServerDTOS.add(identityServerDTO); + } + return identityServerDTOS; + } /** * To create application object from the result set retrieved from the Database. diff --git a/components/application-mgt/io.entgra.application.mgt.core/src/test/java/io/entgra/application/mgt/core/management/ApplicationManagementTest.java b/components/application-mgt/io.entgra.application.mgt.core/src/test/java/io/entgra/application/mgt/core/management/ApplicationManagementTest.java index bab8ef199e..5d9f59bd21 100644 --- a/components/application-mgt/io.entgra.application.mgt.core/src/test/java/io/entgra/application/mgt/core/management/ApplicationManagementTest.java +++ b/components/application-mgt/io.entgra.application.mgt.core/src/test/java/io/entgra/application/mgt/core/management/ApplicationManagementTest.java @@ -121,7 +121,7 @@ public class ApplicationManagementTest extends BaseTestCase { applicationArtifact.setScreenshots(screenshots); ApplicationManager manager = new ApplicationManagerImpl(); - manager.createEntApp(applicationWrapper, applicationArtifact, false); + manager.createApplication(applicationWrapper, false); } @DataProvider(name = "applicationIdDataProvider") diff --git a/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/java/io/entgra/application/mgt/publisher/api/services/ApplicationManagementPublisherAPI.java b/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/java/io/entgra/application/mgt/publisher/api/services/ApplicationManagementPublisherAPI.java index 772ac1a33d..5abce176c6 100644 --- a/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/java/io/entgra/application/mgt/publisher/api/services/ApplicationManagementPublisherAPI.java +++ b/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/java/io/entgra/application/mgt/publisher/api/services/ApplicationManagementPublisherAPI.java @@ -17,6 +17,7 @@ */ package io.entgra.application.mgt.publisher.api.services; +import io.entgra.application.mgt.common.Base64File; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; @@ -27,8 +28,6 @@ import io.swagger.annotations.ExtensionProperty; import io.swagger.annotations.Info; import io.swagger.annotations.SwaggerDefinition; import io.swagger.annotations.Tag; -import org.apache.cxf.jaxrs.ext.multipart.Attachment; -import org.apache.cxf.jaxrs.ext.multipart.Multipart; import org.wso2.carbon.apimgt.annotations.api.Scope; import org.wso2.carbon.apimgt.annotations.api.Scopes; import io.entgra.application.mgt.common.ApplicationList; @@ -284,7 +283,7 @@ public interface ApplicationManagementPublisherAPI { @POST @Path("/ent-app") @Produces(MediaType.APPLICATION_JSON) - @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) + @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON, @@ -318,47 +317,17 @@ public interface ApplicationManagementPublisherAPI { name = "application", value = "The application that need to be created.", required = true) - @Multipart("application") ApplicationWrapper application, + ApplicationWrapper application, @ApiParam( name = "isPublished", value = "Published state of the application" ) - @QueryParam("is-Published") boolean isPublished, - @ApiParam( - name = "binaryFile", - value = "Binary file of uploading application", - required = true) - @Multipart(value = "binaryFile") Attachment binaryFile, - @ApiParam( - name = "icon", - value = "Icon of the uploading application", - required = true) - @Multipart(value = "icon") Attachment iconFile, - @ApiParam( - name = "banner", - value = "Banner of the uploading application") - @Multipart(value = "banner") Attachment bannerFile, - @ApiParam( - name = "screenshot1", - value = "Screen Shots of the uploading application", - required = true) - @Multipart(value = "screenshot1") Attachment screenshot1, - @ApiParam( - name = "screenshot2", - value = "Screen Shots of the uploading application", - required = false) - @Multipart(value = "screenshot2") Attachment screenshot2, - @ApiParam( - name = "screenshot3", - value = "Screen Shots of the uploading application", - required = false) - @Multipart(value = "screenshot3") Attachment screenshot3 - ); + @QueryParam("isPublished") boolean isPublished); @POST @Path("/web-app") @Produces(MediaType.APPLICATION_JSON) - @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) + @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON, @@ -392,42 +361,18 @@ public interface ApplicationManagementPublisherAPI { name = "webapp", value = "The web app that need to be created.", required = true) - @Multipart("webapp") WebAppWrapper webAppWrapper, + WebAppWrapper webAppWrapper, @ApiParam( name = "isPublished", value = "Published state of the application" ) - @QueryParam("is-Published") boolean isPublished, - @ApiParam( - name = "icon", - value = "Icon of the uploading web app", - required = true) - @Multipart(value = "icon") Attachment iconFile, - @ApiParam( - name = "banner", - value = "Banner of the uploading web app") - @Multipart(value = "banner") Attachment bannerFile, - @ApiParam( - name = "screenshot1", - value = "Screen Shots of the uploading web app", - required = true) - @Multipart(value = "screenshot1") Attachment screenshot1, - @ApiParam( - name = "screenshot2", - value = "Screen Shots of the uploading web app", - required = false) - @Multipart(value = "screenshot2") Attachment screenshot2, - @ApiParam( - name = "screenshot3", - value = "Screen Shots of the uploading web app", - required = false) - @Multipart(value = "screenshot3") Attachment screenshot3 + @QueryParam("isPublished") boolean isPublished ); @POST @Path("/public-app") @Produces(MediaType.APPLICATION_JSON) - @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) + @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON, @@ -461,40 +406,18 @@ public interface ApplicationManagementPublisherAPI { name = "public-app", value = "The public app that need to be created.", required = true) - @Multipart("public-app") PublicAppWrapper publicAppWrapper, + PublicAppWrapper publicAppWrapper, @ApiParam( name = "isPublished", value = "Published state of the application" ) - @QueryParam("is-Published") boolean isPublished, - @ApiParam( - name = "icon", - value = "Icon of the uploading public app", - required = true) - @Multipart(value = "icon") Attachment iconFile, - @ApiParam( - name = "banner", - value = "Banner of the uploading public app") - @Multipart(value = "banner") Attachment bannerFile, - @ApiParam( - name = "screenshot1", - value = "Screen Shots of the uploading public app", - required = true) - @Multipart(value = "screenshot1") Attachment screenshot1, - @ApiParam( - name = "screenshot2", - value = "Screen Shots of the uploading public app") - @Multipart(value = "screenshot2") Attachment screenshot2, - @ApiParam( - name = "screenshot3", - value = "Screen Shots of the uploading public app") - @Multipart(value = "screenshot3") Attachment screenshot3 + @QueryParam("isPublished") boolean isPublished ); @POST @Path("/custom-app") @Produces(MediaType.APPLICATION_JSON) - @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) + @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON, @@ -528,53 +451,79 @@ public interface ApplicationManagementPublisherAPI { name = "application", value = "The application that need to be created.", required = true) - @Multipart("application") CustomAppWrapper customAppWrapper, + CustomAppWrapper customAppWrapper, @ApiParam( name = "isPublished", value = "Published state of the application" ) - @QueryParam("is-Published") boolean isPublished, + @QueryParam("isPublished") boolean isPublished + ); + + @POST + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @Path("/{deviceType}/ent-app/{appId}") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Create an application", + notes = "This will create a new application", + tags = "ApplicationDTO Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:update") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 201, + message = "OK. \n Successfully created an application.", + response = ApplicationRelease.class), + @ApiResponse( + code = 400, + message = "Bad Request. \n " + + "ApplicationDTO creating payload contains unacceptable or vulnerable data"), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error occurred while creating the application.", + response = ErrorResponse.class) + }) + Response createEntAppRelease( @ApiParam( - name = "binaryFile", - value = "Binary file of uploading application", + name = "deviceType", + value = "Device type that application is compatible with.", required = true) - @Multipart(value = "binaryFile") Attachment binaryFile, + @PathParam("deviceType") String deviceType, @ApiParam( - name = "icon", - value = "Icon of the uploading application", + name = "appId", + value = "Id of the application.", required = true) - @Multipart(value = "icon") Attachment iconFile, - @ApiParam( - name = "banner", - value = "Banner of the uploading application") - @Multipart(value = "banner") Attachment bannerFile, + @PathParam("appId") int appId, @ApiParam( - name = "screenshot1", - value = "Screen Shots of the uploading application", + name = "applicationRelease", + value = "The application release that need to be created.", required = true) - @Multipart(value = "screenshot1") Attachment screenshot1, - @ApiParam( - name = "screenshot2", - value = "Screen Shots of the uploading application", - required = false) - @Multipart(value = "screenshot2") Attachment screenshot2, + EntAppReleaseWrapper entAppReleaseWrapper, @ApiParam( - name = "screenshot3", - value = "Screen Shots of the uploading application", - required = false) - @Multipart(value = "screenshot3") Attachment screenshot3 + name = "isPublished", + value = "Published state of the application" + ) + @QueryParam("isPublished") boolean isPublished ); @POST @Produces(MediaType.APPLICATION_JSON) - @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) - @Path("/{deviceType}/ent-app/{appId}") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/{deviceType}/public-app/{appId}") @ApiOperation( consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON, httpMethod = "POST", value = "Create an application", - notes = "This will create a new application", + notes = "This will create a new public application release", tags = "ApplicationDTO Management", extensions = { @Extension(properties = { @@ -597,7 +546,7 @@ public interface ApplicationManagementPublisherAPI { message = "Internal Server Error. \n Error occurred while creating the application.", response = ErrorResponse.class) }) - Response createEntAppRelease( + Response createPubAppRelease( @ApiParam( name = "deviceType", value = "Device type that application is compatible with.", @@ -612,47 +561,123 @@ public interface ApplicationManagementPublisherAPI { name = "applicationRelease", value = "The application release that need to be created.", required = true) - @Multipart("applicationRelease") EntAppReleaseWrapper entAppReleaseWrapper, + PublicAppReleaseWrapper publicAppReleaseWrapper, @ApiParam( name = "isPublished", value = "Published state of the application" ) - @QueryParam("is-Published") boolean isPublished, + @QueryParam("isPublished") boolean isPublished + ); + + @POST + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @Path("/web-app/{appId}") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Create an application", + notes = "This will create a new web application release", + tags = "ApplicationDTO Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:update") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 201, + message = "OK. \n Successfully created an application.", + response = ApplicationRelease.class), + @ApiResponse( + code = 400, + message = "Bad Request. \n " + + "ApplicationDTO creating payload contains unacceptable or vulnerable data"), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error occurred while creating the application.", + response = ErrorResponse.class) + }) + Response createWebAppRelease( @ApiParam( - name = "binaryFile", - value = "Binary file of uploading application", + name = "appId", + value = "Id of the application.", required = true) - @Multipart(value = "binaryFile") Attachment binaryFile, + @PathParam("appId") int appId, @ApiParam( - name = "icon", - value = "Icon of the uploading application", + name = "applicationRelease", + value = "The application release that need to be created.", required = true) - @Multipart(value = "icon") Attachment iconFile, + WebAppReleaseWrapper webAppReleaseWrapper, @ApiParam( - name = "banner", - value = "Banner of the uploading application") - @Multipart(value = "banner") Attachment bannerFile, + name = "isPublished", + value = "Published state of the application" + ) + @QueryParam("isPublished") boolean isPublished + ); + + @POST + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @Path("/{deviceType}/custom-app/{appId}") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Create an application", + notes = "This will create a new custom application release", + tags = "ApplicationDTO Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:update") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 201, + message = "OK. \n Successfully created an application.", + response = ApplicationRelease.class), + @ApiResponse( + code = 400, + message = "Bad Request. \n " + + "ApplicationDTO creating payload contains unacceptable or vulnerable data"), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error occurred while creating the application.", + response = ErrorResponse.class) + }) + Response createCustomAppRelease( @ApiParam( - name = "screenshot1", - value = "Screen Shots of the uploading application", + name = "deviceType", + value = "Device type that application is compatible with.", + required = true) + @PathParam("deviceType") String deviceType, + @ApiParam( + name = "appId", + value = "Id of the application.", required = true) - @Multipart(value = "screenshot1") Attachment screenshot1, + @PathParam("appId") int appId, @ApiParam( - name = "screenshot2", - value = "Screen Shots of the uploading application", - required = false) - @Multipart(value = "screenshot2") Attachment screenshot2, + name = "applicationRelease", + value = "The application release that need to be created.", + required = true) + CustomAppReleaseWrapper customAppReleaseWrapper, @ApiParam( - name = "screenshot3", - value = "Screen Shots of the uploading application", - required = false) - @Multipart(value = "screenshot3") Attachment screenshot3 + name = "isPublished", + value = "Published state of the application" + ) + @QueryParam("isPublished") boolean isPublished ); @PUT @Path("/image-artifacts/{uuid}") @Produces(MediaType.APPLICATION_JSON) - @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) + @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( consumes = MediaType.MULTIPART_FORM_DATA, produces = MediaType.APPLICATION_JSON, @@ -688,23 +713,15 @@ public interface ApplicationManagementPublisherAPI { @ApiParam( name = "icon", value = "Icon of the uploading application") - @Multipart(value = "icon") Attachment iconFile, + Base64File iconFile, @ApiParam( name = "banner", value = "Banner of the uploading application") - @Multipart(value = "banner") Attachment bannerFile, + Base64File bannerFile, @ApiParam( name = "screenshot1", value = "Screen Shots of the uploading application") - @Multipart(value = "screenshot1") Attachment screenshot1, - @ApiParam( - name = "screenshot2", - value = "Screen Shots of the uploading application") - @Multipart(value = "screenshot2") Attachment screenshot2, - @ApiParam( - name = "screenshot3", - value = "Screen Shots of the uploading application") - @Multipart(value = "screenshot3") Attachment screenshot3 + List screenshots ); @GET @@ -754,7 +771,7 @@ public interface ApplicationManagementPublisherAPI { @PUT @Path("/ent-app-artifacts/{deviceType}/{appId}/{uuid}") @Produces(MediaType.APPLICATION_JSON) - @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) + @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( consumes = MediaType.MULTIPART_FORM_DATA, produces = MediaType.APPLICATION_JSON, @@ -797,13 +814,13 @@ public interface ApplicationManagementPublisherAPI { value = "UUID of the application", required = true) @PathParam("uuid") String applicationUUID, - @Multipart("binaryFile") Attachment binaryFile + Base64File binaryFile ); @PUT @Path("/ent-app-release/{uuid}") @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.MULTIPART_FORM_DATA) + @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( consumes = MediaType.MULTIPART_FORM_DATA, produces = MediaType.APPLICATION_JSON, @@ -842,39 +859,12 @@ public interface ApplicationManagementPublisherAPI { name = "entAppReleaseWrapper", value = "Application release wrapper which is going to update.", required = true) - @Multipart( - value = "entAppReleaseWrapper", - type = "application/json") EntAppReleaseWrapper entAppReleaseWrapper, - @ApiParam( - name = "binaryFile", - value = "Application installer file.", - required = true) - @Multipart(value = "binaryFile") Attachment binaryFile, - @ApiParam( - name = "icon", - value = "Icon file of the application release.") - @Multipart(value = "icon") Attachment iconFile, - @ApiParam( - name = "banner", - value = "banner file of the application release.") - @Multipart(value = "banner") Attachment bannerFile, - @ApiParam( - name = "screenshot1", - value = "First screenshot of the uploading application") - @Multipart(value = "screenshot1") Attachment screenshot1, - @ApiParam( - name = "screenshot2", - value = "Second screenshot 2 of the uploading application") - @Multipart(value = "screenshot2") Attachment screenshot2, - @ApiParam( - name = "screenshot3", - value = "Third screenshot of the uploading application") - @Multipart(value = "screenshot3") Attachment screenshot3); + EntAppReleaseWrapper entAppReleaseWrapper); @PUT @Path("/public-app-release/{uuid}") @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.MULTIPART_FORM_DATA) + @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( consumes = MediaType.MULTIPART_FORM_DATA, produces = MediaType.APPLICATION_JSON, @@ -913,34 +903,12 @@ public interface ApplicationManagementPublisherAPI { name = "pubAppReleaseWrapper", value = "Application release wrapper which is going to update.", required = true) - @Multipart( - value = "pubAppReleaseWrapper", - type = "application/json") PublicAppReleaseWrapper publicAppReleaseWrapper, - @ApiParam( - name = "icon", - value = "Icon file of the application release.") - @Multipart(value = "icon") Attachment iconFile, - @ApiParam( - name = "banner", - value = "banner file of the application release.") - @Multipart(value = "banner") Attachment bannerFile, - @ApiParam( - name = "screenshot1", - value = "First screenshot of the uploading application") - @Multipart(value = "screenshot1") Attachment screenshot1, - @ApiParam( - name = "screenshot2", - value = "Second screenshot 2 of the uploading application") - @Multipart(value = "screenshot2") Attachment screenshot2, - @ApiParam( - name = "screenshot3", - value = "Third screenshot of the uploading application") - @Multipart(value = "screenshot3") Attachment screenshot3); + PublicAppReleaseWrapper publicAppReleaseWrapper); @PUT @Path("/web-app-release/{uuid}") @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.MULTIPART_FORM_DATA) + @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( consumes = MediaType.MULTIPART_FORM_DATA, produces = MediaType.APPLICATION_JSON, @@ -979,34 +947,13 @@ public interface ApplicationManagementPublisherAPI { name = "pubAppReleaseWrapper", value = "Application release wrapper which is going to update.", required = true) - @Multipart( - value = "pubAppReleaseWrapper", - type = "application/json") WebAppReleaseWrapper webAppReleaseWrapper, - @ApiParam( - name = "icon", - value = "Icon file of the application release.") - @Multipart(value = "icon") Attachment iconFile, - @ApiParam( - name = "banner", - value = "banner file of the application release.") - @Multipart(value = "banner") Attachment bannerFile, - @ApiParam( - name = "screenshot1", - value = "First screenshot of the uploading application") - @Multipart(value = "screenshot1") Attachment screenshot1, - @ApiParam( - name = "screenshot2", - value = "Second screenshot 2 of the uploading application") - @Multipart(value = "screenshot2") Attachment screenshot2, - @ApiParam( - name = "screenshot3", - value = "Third screenshot of the uploading application") - @Multipart(value = "screenshot3") Attachment screenshot3); + WebAppReleaseWrapper webAppReleaseWrapper + ); @PUT @Path("/custom-app-release/{uuid}") @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.MULTIPART_FORM_DATA) + @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( consumes = MediaType.MULTIPART_FORM_DATA, produces = MediaType.APPLICATION_JSON, @@ -1045,34 +992,7 @@ public interface ApplicationManagementPublisherAPI { name = "entAppReleaseWrapper", value = "Application release wrapper which is going to update.", required = true) - @Multipart( - value = "entAppReleaseWrapper", - type = "application/json") CustomAppReleaseWrapper customAppReleaseWrapper, - @ApiParam( - name = "binaryFile", - value = "Application installer file.", - required = true) - @Multipart(value = "binaryFile") Attachment binaryFile, - @ApiParam( - name = "icon", - value = "Icon file of the application release.") - @Multipart(value = "icon") Attachment iconFile, - @ApiParam( - name = "banner", - value = "banner file of the application release.") - @Multipart(value = "banner") Attachment bannerFile, - @ApiParam( - name = "screenshot1", - value = "First screenshot of the uploading application") - @Multipart(value = "screenshot1") Attachment screenshot1, - @ApiParam( - name = "screenshot2", - value = "Second screenshot 2 of the uploading application") - @Multipart(value = "screenshot2") Attachment screenshot2, - @ApiParam( - name = "screenshot3", - value = "Third screenshot of the uploading application") - @Multipart(value = "screenshot3") Attachment screenshot3); + CustomAppReleaseWrapper customAppReleaseWrapper); @GET @Path("/life-cycle/state-changes/{uuid}") @@ -1437,7 +1357,7 @@ public interface ApplicationManagementPublisherAPI { name = "appId", value = "application Id", required = true) - List tagNames + List tagNames ); @GET diff --git a/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/java/io/entgra/application/mgt/publisher/api/services/SPApplicationService.java b/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/java/io/entgra/application/mgt/publisher/api/services/SPApplicationService.java new file mode 100644 index 0000000000..995c892aa5 --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/java/io/entgra/application/mgt/publisher/api/services/SPApplicationService.java @@ -0,0 +1,393 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.publisher.api.services; + +import io.entgra.application.mgt.common.dto.IdentityServerDTO; +import io.entgra.application.mgt.common.wrapper.ApplicationWrapper; +import io.entgra.application.mgt.common.wrapper.CustomAppWrapper; +import io.entgra.application.mgt.common.wrapper.PublicAppWrapper; +import io.entgra.application.mgt.common.wrapper.WebAppWrapper; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.Extension; +import io.swagger.annotations.ExtensionProperty; +import io.swagger.annotations.Info; +import io.swagger.annotations.SwaggerDefinition; +import io.swagger.annotations.Tag; +import org.wso2.carbon.apimgt.annotations.api.Scope; +import org.wso2.carbon.apimgt.annotations.api.Scopes; + +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.List; + +@SwaggerDefinition( + info = @Info( + version = "1.0.0", + title = "Service Provider Application Management Service", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = "name", value = "SPApplicationService"), + @ExtensionProperty(name = "context", value = "/api/application-mgt-publisher/v1.0/identity-server-applications"), + }) + } + ), + tags = { + @Tag(name = "application_management, device_management", description = "App publisher related APIs") + } +) +@Scopes( + scopes = { + @Scope( + name = "view a service provider applications", + description = "Get service provider application details", + key = "perm:app:publisher:service-provider:view", + roles = {"Internal/devicemgt-user"}, + permissions = {"/app-mgt/publisher/service-provider/application/view"} + ), + @Scope( + name = "Create new identity server", + description = "Connect to new identity server", + key = "perm:app:publisher:service-provider:connect", + roles = {"Internal/devicemgt-user"}, + permissions = {"/app-mgt/publisher/service-provider/application/connect"} + ), + @Scope( + name = "Create a service provider application", + description = "Create an application and attach (map) to service provider", + key = "perm:app:publisher:service-provider:create", + roles = {"Internal/devicemgt-user"}, + permissions = {"/app-mgt/publisher/service-provider/application/create"} + ), + @Scope( + name = "Attach a service provider application", + description = "Map an application to service provider", + key = "perm:app:publisher:service-provider:attach", + roles = {"Internal/devicemgt-user"}, + permissions = {"/app-mgt/publisher/service-provider/application/attach"} + ), + @Scope( + name = "Detach a service provider application", + description = "Remove an application from service provider", + key = "perm:app:publisher:service-provider:detach", + roles = {"Internal/devicemgt-user"}, + permissions = {"/app-mgt/publisher/service-provider/application/detach"} + ) + } +) +@Path("/identity-server-applications") +@Api(value = "SPApplication Management") +@Produces(MediaType.APPLICATION_JSON) +public interface SPApplicationService { + + String SCOPE = "scope"; + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("/identity-servers/identity-service-providers") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "get available identity service providers", + tags = "Identity Server Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:service-provider:view") + }) + } + ) + Response getIdentityServiceProviders(); + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("/identity-servers") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "get all identity servers", + tags = "Identity Server Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:service-provider:view") + }) + } + ) + Response getIdentityServers(); + + @Path("/identity-servers/{id}") + @DELETE + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "DELETE", + value = "get identity server by id", + tags = "Identity Server Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:service-provider:connect") + }) + } + ) + Response deleteIdentityServer(@PathParam("id") int id); + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("/identity-servers/{id}") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "get identity server by id", + tags = "Identity Server Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:service-provider:view") + }) + } + ) + Response getIdentityServer(@PathParam("id") int id); + + @POST + @Produces(MediaType.APPLICATION_JSON) + @Path("/identity-servers") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "create new identity server", + tags = "Identity Server Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:service-provider:connect") + }) + } + ) + Response createIdentityServer(IdentityServerDTO identityServerDTO); + + @PUT + @Produces(MediaType.APPLICATION_JSON) + @Path("/identity-servers/{id}") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "PUT", + value = "edit existing identity server", + tags = "Identity Server Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:service-provider:connect") + }) + } + ) + Response updateIdentityServer(IdentityServerDTO identityServerDTO, @PathParam("id") int id); + + @GET + @Path("/identity-servers/identity-server-name") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Check if identity server name is already exists", + tags = "Identity Server Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:service-provider:view") + }) + } + ) + Response isIdentityServerNameExists( + @QueryParam("identityServerName") String identityServerName); + + @GET + @Path("/identity-servers/identity-server-url") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Check if identity server url is already exists", + tags = "Identity Server Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:service-provider:view") + }) + } + ) + Response isIdentityServerUrlExists( + @QueryParam("identityServerUrl") String identityServerUrl); + + /** + * This method is used to register an APIM application for tenant domain. + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("{identity-server-id}/service-providers") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "get service providers by identity server id", + notes = "This will get service providers with the existing applications", + tags = "Service Provider Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:service-provider:view") + }) + } + ) + Response getServiceProviders(@QueryParam("limit") Integer limit, @QueryParam("offset") Integer offset, + @PathParam("identity-server-id") int identityServerId); + + @Path("/{identity-server-id}/service-provider/{service-provider-id}/attach") + @POST + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "map application to service provider", + notes = "This will map a given list application ids with the given service provider id", + tags = "Service Provider Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:service-provider:attach") + }) + } + ) + Response attachApps(@PathParam("identity-server-id") int identityServerId, + @PathParam("service-provider-id") String serviceProviderId, List appIds); + + /** + * This method is used to register an APIM application for tenant domain. + */ + @Path("/{identity-server-id}/service-provider/{service-provider-id}/detach") + @POST + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Remove mapping with service provider of the given application ids", + notes = "This will remove applications from service provider", + tags = "Service Provider Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:service-provider:detach") + }) + } + ) + Response detachApps(@PathParam("identity-server-id") int identityServerId, + @PathParam("service-provider-id") String serviceProviderId, List appIds); + + /** + * This method is used to register an APIM application for tenant domain. + */ + @Path("/{identity-server-id}/service-provider/{service-provider-id}/create/ent-app") + @POST + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Create enterprise application and attach to service provider", + notes = "This will get create an enterprise application and map with service provider", + tags = "Service Provider Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:service-provider:create") + }) + } + ) + Response createEntApp(@PathParam("identity-server-id") int identityServerId, + @PathParam("service-provider-id") String serviceProviderId, ApplicationWrapper app, + @ApiParam( + name = "isPublished", + value = "Published state of the application" + ) + @QueryParam("isPublished") boolean isPublished); + + /** + * This method is used to register an APIM application for tenant domain. + */ + @Path("/{identity-server-id}/service-provider/{service-provider-id}/create/public-app") + @POST + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Create public application and attach to service provider", + notes = "This will get create a public application and map with service provider", + tags = "Service Provider Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:service-provider:create") + }) + } + ) + Response createPubApp(@PathParam("identity-server-id") int identityServerId, + @PathParam("service-provider-id") String serviceProviderId, PublicAppWrapper app, + @ApiParam( + name = "isPublished", + value = "Published state of the application" + ) + @QueryParam("isPublished") boolean isPublished); + + @Path("/{identity-server-id}/service-provider/{service-provider-id}/create/web-app") + @POST + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Create web application and attach to service provider", + notes = "This will get create a web application and map with service provider", + tags = "Service Provider Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:service-provider:create") + }) + } + ) + Response createWebApp(@PathParam("identity-server-id") int identityServerId, + @PathParam("service-provider-id") String serviceProviderId, WebAppWrapper app, + @ApiParam( + name = "isPublished", + value = "Published state of the application" + ) + @QueryParam("isPublished") boolean isPublished); + + @Path("/{identity-server-id}/service-provider/{service-provider-id}/create/custom-app") + @POST + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Create custom application and attach to service provider", + notes = "This will get create an custom application and map with service provider", + tags = "Service Provider Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = SCOPE, value = "perm:app:publisher:service-provider:create") + }) + } + ) + Response createCustomApp(@PathParam("identity-server-id") int identityServerId, + @PathParam("service-provider-id") String serviceProviderId, CustomAppWrapper app, + @ApiParam( + name = "isPublished", + value = "Published state of the application" + ) + @QueryParam("isPublished") boolean isPublished); +} diff --git a/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/java/io/entgra/application/mgt/publisher/api/services/impl/ApplicationManagementPublisherAPIImpl.java b/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/java/io/entgra/application/mgt/publisher/api/services/impl/ApplicationManagementPublisherAPIImpl.java index 155348284f..078af292d9 100644 --- a/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/java/io/entgra/application/mgt/publisher/api/services/impl/ApplicationManagementPublisherAPIImpl.java +++ b/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/java/io/entgra/application/mgt/publisher/api/services/impl/ApplicationManagementPublisherAPIImpl.java @@ -16,11 +16,15 @@ */ package io.entgra.application.mgt.publisher.api.services.impl; +import io.entgra.application.mgt.common.ApplicationArtifact; +import io.entgra.application.mgt.common.ApplicationList; +import io.entgra.application.mgt.common.Base64File; +import io.entgra.application.mgt.common.Filter; +import io.entgra.application.mgt.common.LifecycleChanger; +import io.entgra.application.mgt.common.exception.ResourceManagementException; +import io.entgra.application.mgt.core.util.ApplicationManagementUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.cxf.jaxrs.ext.multipart.Attachment; -import org.apache.cxf.jaxrs.ext.multipart.Multipart; -import io.entgra.application.mgt.common.*; import io.entgra.application.mgt.common.LifecycleState; import io.entgra.application.mgt.common.exception.LifecycleManagementException; import io.entgra.application.mgt.common.exception.RequestValidatingException; @@ -42,19 +46,12 @@ import io.entgra.application.mgt.core.exception.BadRequestException; import io.entgra.application.mgt.core.exception.ForbiddenException; import io.entgra.application.mgt.core.exception.UnexpectedServerErrorException; import io.entgra.application.mgt.core.util.APIUtil; -import io.entgra.application.mgt.core.util.Constants; import io.entgra.application.mgt.publisher.api.services.ApplicationManagementPublisherAPI; import io.entgra.application.mgt.common.exception.ApplicationManagementException; import io.entgra.application.mgt.common.services.ApplicationManager; import io.entgra.application.mgt.core.exception.NotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import javax.activation.DataHandler; import javax.validation.Valid; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -169,36 +166,12 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem } @POST - @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) + @Consumes(MediaType.APPLICATION_JSON) @Path("/ent-app") public Response createEntApp( - @Multipart("application") ApplicationWrapper applicationWrapper, - @QueryParam("is-published") boolean isPublished, - @Multipart("binaryFile") Attachment binaryFile, - @Multipart("icon") Attachment iconFile, - @Multipart(value = "banner", required = false) Attachment bannerFile, - @Multipart("screenshot1") Attachment screenshot1, - @Multipart("screenshot2") Attachment screenshot2, - @Multipart("screenshot3") Attachment screenshot3) { - ApplicationManager applicationManager = APIUtil.getApplicationManager(); - List attachmentList = constructAttachmentList(screenshot1, screenshot2, screenshot3); + ApplicationWrapper applicationWrapper, @QueryParam("is-published") boolean isPublished) { try { - applicationManager.validateAppCreatingRequest(applicationWrapper); - applicationManager.validateReleaseCreatingRequest(applicationWrapper.getEntAppReleaseWrappers().get(0), - applicationWrapper.getDeviceType()); - applicationManager.validateBinaryArtifact(binaryFile); - applicationManager.validateImageArtifacts(iconFile, bannerFile, attachmentList); - - // Created new Ent App - Application application = applicationManager.createEntApp(applicationWrapper, - constructApplicationArtifact(binaryFile, iconFile, bannerFile, attachmentList), isPublished); - if (application != null) { - return Response.status(Response.Status.CREATED).entity(application).build(); - } else { - String msg = "Application creation is failed"; - log.error(msg); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); - } + return createApplication(applicationWrapper, isPublished); } catch (BadRequestException e) { String msg = "Found incompatible payload with ent. app creating request."; log.error(msg, e); @@ -215,34 +188,12 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem } @POST - @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) + @Consumes(MediaType.APPLICATION_JSON) @Path("/web-app") public Response createWebApp( - @Multipart("webapp") WebAppWrapper webAppWrapper, - @QueryParam("is-published") boolean isPublished, - @Multipart("icon") Attachment iconFile, - @Multipart(value = "banner", required = false) Attachment bannerFile, - @Multipart("screenshot1") Attachment screenshot1, - @Multipart("screenshot2") Attachment screenshot2, - @Multipart("screenshot3") Attachment screenshot3) { - ApplicationManager applicationManager = APIUtil.getApplicationManager(); - List attachmentList = constructAttachmentList(screenshot1, screenshot2, screenshot3); + WebAppWrapper webAppWrapper, @QueryParam("is-published") boolean isPublished) { try { - applicationManager.validateAppCreatingRequest(webAppWrapper); - applicationManager - .validateReleaseCreatingRequest(webAppWrapper.getWebAppReleaseWrappers().get(0), Constants.ANY); - applicationManager.validateImageArtifacts(iconFile, bannerFile, attachmentList); - - // Created new Web App - Application application = applicationManager.createWebClip(webAppWrapper, - constructApplicationArtifact(null, iconFile, bannerFile, attachmentList), isPublished); - if (application != null) { - return Response.status(Response.Status.CREATED).entity(application).build(); - } else { - String msg = "Web app creation is failed"; - log.error(msg); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); - } + return createApplication(webAppWrapper, isPublished); } catch (BadRequestException e) { String msg = "Found incompatible payload with web app creating request."; log.error(msg, e); @@ -259,34 +210,12 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem } @POST - @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) + @Consumes(MediaType.APPLICATION_JSON) @Path("/public-app") public Response createPubApp( - @Multipart("public-app") PublicAppWrapper publicAppWrapper, - @QueryParam("is-published") boolean isPublished, - @Multipart("icon") Attachment iconFile, - @Multipart(value = "banner", required = false) Attachment bannerFile, - @Multipart("screenshot1") Attachment screenshot1, - @Multipart("screenshot2") Attachment screenshot2, - @Multipart("screenshot3") Attachment screenshot3) { - ApplicationManager applicationManager = APIUtil.getApplicationManager(); - List attachmentList = constructAttachmentList(screenshot1, screenshot2, screenshot3); + PublicAppWrapper publicAppWrapper, @QueryParam("is-published") boolean isPublished) { try { - applicationManager.validateAppCreatingRequest(publicAppWrapper); - applicationManager.validateReleaseCreatingRequest(publicAppWrapper.getPublicAppReleaseWrappers().get(0), - publicAppWrapper.getDeviceType()); - applicationManager.validateImageArtifacts(iconFile, bannerFile, attachmentList); - - // Created new Public App - Application application = applicationManager.createPublicApp(publicAppWrapper, - constructApplicationArtifact(null, iconFile, bannerFile, attachmentList), isPublished); - if (application != null) { - return Response.status(Response.Status.CREATED).entity(application).build(); - } else { - String msg = "Public app creation is failed"; - log.error(msg); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); - } + return createApplication(publicAppWrapper, isPublished); } catch (BadRequestException e) { String msg = "Found incompatible payload with pub app creating request."; log.error(msg, e); @@ -303,36 +232,12 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem } @POST - @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) + @Consumes(MediaType.APPLICATION_JSON) @Path("/custom-app") public Response createCustomApp( - @Multipart("application") CustomAppWrapper customAppWrapper, - @QueryParam("is-published") boolean isPublished, - @Multipart("binaryFile") Attachment binaryFile, - @Multipart("icon") Attachment iconFile, - @Multipart(value = "banner", required = false) Attachment bannerFile, - @Multipart("screenshot1") Attachment screenshot1, - @Multipart("screenshot2") Attachment screenshot2, - @Multipart("screenshot3") Attachment screenshot3) { - ApplicationManager applicationManager = APIUtil.getApplicationManager(); - List attachmentList = constructAttachmentList(screenshot1, screenshot2, screenshot3); + CustomAppWrapper customAppWrapper, @QueryParam("is-published") boolean isPublished) { try { - applicationManager.validateAppCreatingRequest(customAppWrapper); - applicationManager.validateReleaseCreatingRequest(customAppWrapper.getCustomAppReleaseWrappers().get(0), - customAppWrapper.getDeviceType()); - applicationManager.validateBinaryArtifact(binaryFile); - applicationManager.validateImageArtifacts(iconFile, bannerFile, attachmentList); - - // Created new Custom App - Application application = applicationManager.createCustomApp(customAppWrapper, - constructApplicationArtifact(binaryFile, iconFile, bannerFile, attachmentList), isPublished); - if (application != null) { - return Response.status(Response.Status.CREATED).entity(application).build(); - } else { - String msg = "Custom app creation is failed"; - log.error(msg); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); - } + return createApplication(customAppWrapper, isPublished); } catch (BadRequestException e) { String msg = "Found incompatible payload with custom app creating request."; log.error(msg, e); @@ -349,50 +254,113 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem } @POST - @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) + @Consumes(MediaType.APPLICATION_JSON) @Path("/{deviceType}/ent-app/{appId}") public Response createEntAppRelease( - @PathParam("deviceType") String deviceType, + @PathParam("deviceType") String deviceTypeName, @PathParam("appId") int appId, - @Multipart("applicationRelease") EntAppReleaseWrapper entAppReleaseWrapper, - @QueryParam("is-published") boolean isPublished, - @Multipart("binaryFile") Attachment binaryFile, - @Multipart("icon") Attachment iconFile, - @Multipart(value = "banner", required = false) Attachment bannerFile, - @Multipart("screenshot1") Attachment screenshot1, - @Multipart("screenshot2") Attachment screenshot2, - @Multipart("screenshot3") Attachment screenshot3) { - ApplicationManager applicationManager = APIUtil.getApplicationManager(); - List attachmentList = constructAttachmentList(screenshot1, screenshot2, screenshot3); + EntAppReleaseWrapper entAppReleaseWrapper, + @QueryParam("isPublished") boolean isPublished) { try { - applicationManager.validateReleaseCreatingRequest(entAppReleaseWrapper, deviceType); - applicationManager.validateBinaryArtifact(binaryFile); - applicationManager.validateImageArtifacts(iconFile, bannerFile, attachmentList); + ApplicationManager applicationManager = APIUtil.getApplicationManager(); + applicationManager.validateEntAppReleaseCreatingRequest(entAppReleaseWrapper, deviceTypeName); + ApplicationRelease release = applicationManager.createEntAppRelease(appId, entAppReleaseWrapper, isPublished); + return Response.status(Response.Status.CREATED).entity(release).build(); + } catch (RequestValidatingException e) { + String msg = "Error occurred while validating binaryArtifact"; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while creating application release for the application with the id " + appId; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } - // Created new Ent App release - ApplicationRelease release = applicationManager.createEntAppRelease(appId, entAppReleaseWrapper, - constructApplicationArtifact(binaryFile, iconFile, bannerFile, attachmentList), isPublished); - if (release != null) { - return Response.status(Response.Status.CREATED).entity(release).build(); - } else { - log.error("ApplicationDTO Creation Failed"); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); - } - } catch (BadRequestException e) { - String msg = "Found incompatible payload with enterprise app release creating request."; + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Path("/{deviceType}/public-app/{appId}") + @Override + public Response createPubAppRelease( + @PathParam("deviceType") String deviceTypeName, + @PathParam("appId") int appId, + PublicAppReleaseWrapper publicAppReleaseWrapper, @QueryParam("isPublished") boolean isPublished) { + + try { + ApplicationManager applicationManager = APIUtil.getApplicationManager(); + applicationManager.validatePublicAppReleaseCreatingRequest(publicAppReleaseWrapper, deviceTypeName); + ApplicationRelease applicationRelease = applicationManager.createPubAppRelease(appId, publicAppReleaseWrapper, isPublished); + return Response.status(Response.Status.CREATED).entity(applicationRelease).build(); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while creating application release for the application with the id " + appId; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } catch (ResourceManagementException e) { + String msg = "Error occurred while uploading application release artifacts"; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } catch (RequestValidatingException e) { + String msg = "Invalid payload found in public app release create request"; log.error(msg, e); return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Path("/web-app/{appId}") + @Override + public Response createWebAppRelease( + @PathParam("appId") int appId, + WebAppReleaseWrapper webAppReleaseWrapper, @QueryParam("isPublished") boolean isPublished) { + try { + ApplicationManager applicationManager = APIUtil.getApplicationManager(); + applicationManager.validateWebAppReleaseCreatingRequest(webAppReleaseWrapper); + ApplicationRelease applicationRelease= applicationManager.createWebAppRelease(appId, webAppReleaseWrapper, isPublished); + return Response.status(Response.Status.CREATED).entity(applicationRelease).build(); + } catch (ResourceManagementException e) { + String msg = "Error occurred while uploading application release artifacts"; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } catch (ApplicationManagementException e) { - String msg = "Error occurred while creating the application"; + String msg = "Error occurred while creating application release for the application with the id " + appId; log.error(msg, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } catch (RequestValidatingException e) { - String msg = "Error occurred while handling the application creating request"; + String msg = "Invalid payload found in web app release create request"; log.error(msg, e); return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); } } + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Path("/{deviceType}/custom-app/{appId}") + @Override + public Response createCustomAppRelease( + @PathParam("deviceType") String deviceTypeName, + @PathParam("appId") int appId, + CustomAppReleaseWrapper customAppReleaseWrapper, @QueryParam("isPublished") boolean isPublished) { + try { + ApplicationManager applicationManager = APIUtil.getApplicationManager(); + applicationManager.validateCustomAppReleaseCreatingRequest(customAppReleaseWrapper, deviceTypeName); + ApplicationRelease release = applicationManager.createCustomAppRelease(appId, customAppReleaseWrapper, isPublished); + return Response.status(Response.Status.CREATED).entity(release).build(); + } catch (RequestValidatingException e) { + String msg = "Error occurred while validating binaryArtifact"; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (ResourceManagementException e) { + String msg = "Error occurred while uploading application release artifacts"; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while creating application release for the application with the id " + appId; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } + @Override @GET @Path("/device-type/{deviceType}/app-name") @@ -421,21 +389,20 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem @Override @PUT - @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) + @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/image-artifacts/{uuid}") public Response updateApplicationImageArtifacts( @PathParam("uuid") String applicationReleaseUuid, - @Multipart(value = "icon", required = false) Attachment iconFile, - @Multipart(value = "banner", required = false) Attachment bannerFile, - @Multipart(value = "screenshot1", required = false) Attachment screenshot1, - @Multipart(value = "screenshot2", required = false) Attachment screenshot2, - @Multipart(value = "screenshot3", required = false) Attachment screenshot3) { + Base64File iconFile, + Base64File bannerFile, + List screenshots) { try { - List attachments = constructAttachmentList(screenshot1, screenshot2, screenshot3); + ApplicationArtifact artifact = ApplicationManagementUtil.constructApplicationArtifact(iconFile, screenshots, + null, bannerFile); ApplicationManager applicationManager = APIUtil.getApplicationManager(); applicationManager.updateApplicationImageArtifact(applicationReleaseUuid, - constructApplicationArtifact(null, iconFile, bannerFile, attachments)); + artifact); return Response.status(Response.Status.OK) .entity("Successfully uploaded artifacts for the application " + applicationReleaseUuid).build(); } catch (NotFoundException e) { @@ -454,18 +421,19 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem @Override @PUT - @Consumes({"multipart/mixed", MediaType.MULTIPART_FORM_DATA}) + @Consumes(MediaType.APPLICATION_JSON) @Path("/ent-app-artifact/{deviceType}/{uuid}") public Response updateApplicationArtifact( @PathParam("deviceType") String deviceType, @PathParam("uuid") String applicationReleaseUuid, - @Multipart("binaryFile") Attachment binaryFile) { + Base64File binaryFile) { try { ApplicationManager applicationManager = APIUtil.getApplicationManager(); applicationManager.validateBinaryArtifact(binaryFile); applicationManager.updateApplicationArtifact(deviceType, applicationReleaseUuid, - constructApplicationArtifact(binaryFile, null, null, null)); + ApplicationManagementUtil.constructApplicationArtifact(null, null, + binaryFile, null)); return Response.status(Response.Status.OK) .entity("Successfully uploaded artifacts for the application release. UUID is " + applicationReleaseUuid).build(); @@ -522,19 +490,13 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem @Path("/ent-app-release/{uuid}") public Response updateEntAppRelease( @PathParam("uuid") String applicationUUID, - @Multipart("applicationRelease") EntAppReleaseWrapper entAppReleaseWrapper, - @Multipart(value = "binaryFile", required = false) Attachment binaryFile, - @Multipart(value = "icon", required = false) Attachment iconFile, - @Multipart(value = "banner", required = false) Attachment bannerFile, - @Multipart(value = "screenshot1", required = false) Attachment screenshot1, - @Multipart(value = "screenshot2", required = false) Attachment screenshot2, - @Multipart(value = "screenshot3", required = false) Attachment screenshot3) { + EntAppReleaseWrapper entAppReleaseWrapper) { ApplicationManager applicationManager = APIUtil.getApplicationManager(); - List screenshots = constructAttachmentList(screenshot1, screenshot2, screenshot3); try { + ApplicationArtifact artifact = ApplicationManagementUtil.constructApplicationArtifact(entAppReleaseWrapper.getIcon(), + entAppReleaseWrapper.getScreenshots(), entAppReleaseWrapper.getBinaryFile(), entAppReleaseWrapper.getBanner()); ApplicationRelease applicationRelease = applicationManager - .updateEntAppRelease(applicationUUID, entAppReleaseWrapper, - constructApplicationArtifact(binaryFile, iconFile, bannerFile, screenshots)); + .updateEntAppRelease(applicationUUID, entAppReleaseWrapper, artifact); if (applicationRelease == null) { String msg ="Ent app release updating is failed. Please contact the administrator. Application release " + "UUID: " + applicationUUID; @@ -569,18 +531,13 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem @Path("/public-app-release/{uuid}") public Response updatePubAppRelease( @PathParam("uuid") String applicationUUID, - @Multipart("applicationRelease") PublicAppReleaseWrapper publicAppReleaseWrapper, - @Multipart(value = "icon", required = false) Attachment iconFile, - @Multipart(value = "banner", required = false) Attachment bannerFile, - @Multipart(value = "screenshot1", required = false) Attachment screenshot1, - @Multipart(value = "screenshot2", required = false) Attachment screenshot2, - @Multipart(value = "screenshot3", required = false) Attachment screenshot3) { + PublicAppReleaseWrapper publicAppReleaseWrapper) { ApplicationManager applicationManager = APIUtil.getApplicationManager(); - List screenshots = constructAttachmentList(screenshot1, screenshot2, screenshot3); try { + ApplicationArtifact artifact = ApplicationManagementUtil.constructApplicationArtifact(publicAppReleaseWrapper.getIcon(), + publicAppReleaseWrapper.getScreenshots(), null, publicAppReleaseWrapper.getBanner()); ApplicationRelease applicationRelease = applicationManager - .updatePubAppRelease(applicationUUID, publicAppReleaseWrapper, - constructApplicationArtifact(null, iconFile, bannerFile, screenshots)); + .updatePubAppRelease(applicationUUID, publicAppReleaseWrapper, artifact); if (applicationRelease == null) { String msg ="Public app release updating is failed. Please contact the administrator. " + "Application release UUID: " + applicationUUID + ", Supported device type:"; @@ -614,18 +571,13 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem @Path("/web-app-release/{uuid}") public Response updateWebAppRelease( @PathParam("uuid") String applicationUUID, - @Multipart("applicationRelease") WebAppReleaseWrapper webAppReleaseWrapper, - @Multipart(value = "icon", required = false) Attachment iconFile, - @Multipart(value = "banner", required = false) Attachment bannerFile, - @Multipart(value = "screenshot1", required = false) Attachment screenshot1, - @Multipart(value = "screenshot2", required = false) Attachment screenshot2, - @Multipart(value = "screenshot3", required = false) Attachment screenshot3) { + WebAppReleaseWrapper webAppReleaseWrapper) { ApplicationManager applicationManager = APIUtil.getApplicationManager(); - List screenshots = constructAttachmentList(screenshot1, screenshot2, screenshot3); try { + ApplicationArtifact artifact = ApplicationManagementUtil.constructApplicationArtifact(webAppReleaseWrapper.getIcon(), + webAppReleaseWrapper.getScreenshots(), null, webAppReleaseWrapper.getBanner()); ApplicationRelease applicationRelease = applicationManager - .updateWebAppRelease(applicationUUID, webAppReleaseWrapper, - constructApplicationArtifact(null, iconFile, bannerFile, screenshots)); + .updateWebAppRelease(applicationUUID, webAppReleaseWrapper, artifact); if (applicationRelease == null) { String msg ="web app release updating is failed. Please contact the administrator. Application " + "release UUID: " + applicationUUID; @@ -658,19 +610,13 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem @Path("/custom-app-release/{uuid}") public Response updateCustomAppRelease( @PathParam("uuid") String applicationUUID, - @Multipart("applicationRelease") CustomAppReleaseWrapper customAppReleaseWrapper, - @Multipart(value = "binaryFile", required = false) Attachment binaryFile, - @Multipart(value = "icon", required = false) Attachment iconFile, - @Multipart(value = "banner", required = false) Attachment bannerFile, - @Multipart(value = "screenshot1", required = false) Attachment screenshot1, - @Multipart(value = "screenshot2", required = false) Attachment screenshot2, - @Multipart(value = "screenshot3", required = false) Attachment screenshot3) { + CustomAppReleaseWrapper customAppReleaseWrapper) { ApplicationManager applicationManager = APIUtil.getApplicationManager(); - List screenshots = constructAttachmentList(screenshot1, screenshot2, screenshot3); try { + ApplicationArtifact artifact = ApplicationManagementUtil.constructApplicationArtifact(customAppReleaseWrapper.getIcon(), + customAppReleaseWrapper.getScreenshots(), customAppReleaseWrapper.getBinaryFile(), customAppReleaseWrapper.getBanner()); ApplicationRelease applicationRelease = applicationManager - .updateCustomAppRelease(applicationUUID, customAppReleaseWrapper, - constructApplicationArtifact(binaryFile, iconFile, bannerFile, screenshots)); + .updateCustomAppRelease(applicationUUID, customAppReleaseWrapper, artifact); if (applicationRelease == null) { String msg ="Custom app release updating is failed. Please contact the administrator. Application " + "release UUID: " + applicationUUID; @@ -919,134 +865,16 @@ public class ApplicationManagementPublisherAPIImpl implements ApplicationManagem } } - /*** - * Construct the screenshot list by evaluating the availability of each screenshot. - * - * @param screenshot1 First Screenshot - * @param screenshot2 Second Screenshot - * @param screenshot3 Third Screenshot - * @return List of {@link Attachment} - */ - private List constructAttachmentList(Attachment screenshot1, Attachment screenshot2, - Attachment screenshot3) { - List attachments = new ArrayList<>(); - if (screenshot1 != null) { - attachments.add(screenshot1); - } - if (screenshot2 != null) { - attachments.add(screenshot2); - } - if (screenshot3 != null) { - attachments.add(screenshot3); - } - return attachments; - } - - /*** - * This method can be used to construct {@link ApplicationArtifact} - * - * @param binaryFile binary file of the application release - * @param iconFile icon file of the application release - * @param bannerFile banner file of the application release - * @param attachmentList list of screenshot of the application release - * @return {@link ApplicationArtifact} - * @throws ApplicationManagementException if an error occurs when reading the attached data. - */ - private ApplicationArtifact constructApplicationArtifact(Attachment binaryFile, Attachment iconFile, - Attachment bannerFile, List attachmentList) throws ApplicationManagementException { - try { - ApplicationArtifact applicationArtifact = new ApplicationArtifact(); - DataHandler dataHandler; - if (binaryFile != null) { - dataHandler = binaryFile.getDataHandler(); - InputStream installerStream = dataHandler.getInputStream(); - String installerFileName = dataHandler.getName(); - if (installerStream == null) { - String msg = "Stream of the application release installer is null. Hence can't proceed. Please " - + "verify the installer file."; - log.error(msg); - throw new BadRequestException(msg); - } - if (installerFileName == null) { - String msg = "Installer file name retrieving is failed.. Hence can't proceed. Please verify the " - + "installer file."; - log.error(msg); - throw new BadRequestException(msg); - } - applicationArtifact.setInstallerName(installerFileName.replaceAll("\\s", "")); - applicationArtifact.setInstallerStream(installerStream); - } - - if (iconFile != null) { - dataHandler = iconFile.getDataHandler(); - String iconFileName = dataHandler.getName(); - InputStream iconStream = dataHandler.getInputStream(); - - if (iconStream == null) { - String msg = "Stream of the application release icon is null. Hence can't proceed. Please " - + "verify the uploaded icon file."; - log.error(msg); - throw new BadRequestException(msg); - } - if (iconFileName == null) { - String msg = "Icon file name retrieving is failed.. Hence can't proceed. Please verify the " - + "icon file."; - log.error(msg); - throw new BadRequestException(msg); - } - applicationArtifact.setIconName(iconFileName); - applicationArtifact.setIconStream(iconStream); - } - - if (bannerFile != null) { - dataHandler = bannerFile.getDataHandler(); - String bannerFileName = dataHandler.getName(); - InputStream bannerStream = dataHandler.getInputStream(); - if (bannerStream == null) { - String msg = "Stream of the application release banner is null. Hence can't proceed. Please " - + "verify the uploaded banner file."; - log.error(msg); - throw new BadRequestException(msg); - } - if (bannerFileName == null) { - String msg = "Banner file name retrieving is failed.. Hence can't proceed. Please verify the " - + "banner file."; - log.error(msg); - throw new BadRequestException(msg); - } - applicationArtifact.setBannerName(bannerFileName); - applicationArtifact.setBannerStream(bannerStream); - } - - if (attachmentList != null && !attachmentList.isEmpty()) { - Map screenshotData = new TreeMap<>(); - for (Attachment sc : attachmentList) { - dataHandler = sc.getDataHandler(); - String screenshotFileName = dataHandler.getName(); - InputStream screenshotStream = dataHandler.getInputStream(); - if (screenshotStream == null) { - String msg = - "Stream of one of the application release screenshot is null. Hence can't proceed. Please " - + "verify the uploaded screenshots."; - log.error(msg); - throw new BadRequestException(msg); - } - if (screenshotFileName == null) { - String msg = - "Screenshot file name retrieving is failed for one screenshot. Hence can't proceed. " - + "Please verify the screenshots."; - log.error(msg); - throw new BadRequestException(msg); - } - screenshotData.put(screenshotFileName, screenshotStream); - } - applicationArtifact.setScreenshots(screenshotData); - } - return applicationArtifact; - } catch (IOException e) { - String msg = "Error occurred when reading attachment data."; - log.error(msg, e); - throw new ApplicationManagementException(msg); + public Response createApplication(T appWrapper, boolean isPublished) throws ApplicationManagementException, RequestValidatingException { + ApplicationManager applicationManager = APIUtil.getApplicationManager(); + applicationManager.validateAppCreatingRequest(appWrapper); + Application application = applicationManager.createApplication(appWrapper, isPublished); + if (application != null) { + return Response.status(Response.Status.CREATED).entity(application).build(); + } else { + String msg = "Application creation is failed"; + log.error(msg); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } } } diff --git a/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/java/io/entgra/application/mgt/publisher/api/services/impl/SPApplicationServiceImpl.java b/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/java/io/entgra/application/mgt/publisher/api/services/impl/SPApplicationServiceImpl.java new file mode 100644 index 0000000000..ec197dd47f --- /dev/null +++ b/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/java/io/entgra/application/mgt/publisher/api/services/impl/SPApplicationServiceImpl.java @@ -0,0 +1,363 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.application.mgt.publisher.api.services.impl; + +import io.entgra.application.mgt.common.IdentityServerResponse; +import io.entgra.application.mgt.common.dto.IdentityServerDTO; +import io.entgra.application.mgt.common.SPApplicationListResponse; +import io.entgra.application.mgt.common.dto.IdentityServiceProviderDTO; +import io.entgra.application.mgt.common.exception.ApplicationManagementException; +import io.entgra.application.mgt.common.exception.RequestValidatingException; +import io.entgra.application.mgt.common.response.Application; +import io.entgra.application.mgt.common.services.SPApplicationManager; +import io.entgra.application.mgt.common.wrapper.ApplicationWrapper; +import io.entgra.application.mgt.common.wrapper.CustomAppWrapper; +import io.entgra.application.mgt.common.wrapper.PublicAppWrapper; +import io.entgra.application.mgt.common.wrapper.WebAppWrapper; +import io.entgra.application.mgt.core.exception.BadRequestException; +import io.entgra.application.mgt.core.exception.NotFoundException; +import io.entgra.application.mgt.core.util.APIUtil; +import io.entgra.application.mgt.publisher.api.services.SPApplicationService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.List; + +@Produces(MediaType.APPLICATION_JSON) +@Path("/identity-server-applications") +public class SPApplicationServiceImpl implements SPApplicationService { + + private static final Log log = LogFactory.getLog(SPApplicationServiceImpl.class); + + @Path("/identity-servers/identity-service-providers") + @GET + @Override + public Response getIdentityServiceProviders() { + SPApplicationManager spAppManager = APIUtil.getSPApplicationManager(); + try { + List identityServiceProviders = spAppManager.getIdentityServiceProviders(); + return Response.status(Response.Status.OK).entity(identityServiceProviders).build(); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while getting identity service providers"; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } + + @Path("/identity-servers") + @GET + @Override + public Response getIdentityServers() { + try { + SPApplicationManager spAppManager = APIUtil.getSPApplicationManager(); + List identityServers = spAppManager.getIdentityServers(); + return Response.status(Response.Status.OK).entity(identityServers).build(); + } catch (ApplicationManagementException e) { + String errMsg = "Error occurred while trying to merge identity server apps with existing apps"; + log.error(errMsg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errMsg).build(); + } + } + + @Path("/identity-servers/{id}") + @DELETE + @Override + public Response deleteIdentityServer(@PathParam("id") int id) { + try { + SPApplicationManager spAppManager = APIUtil.getSPApplicationManager(); + spAppManager.deleteIdentityServer(id); + return Response.status(Response.Status.OK).entity("Successfully deleted identity server").build(); + } catch (NotFoundException e) { + String msg = "Identity server with the id " + id + " does not exist."; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (ApplicationManagementException e) { + String errMsg = "Error occurred while trying to merge identity server apps with existing apps"; + log.error(errMsg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errMsg).build(); + } + } + + @Path("/identity-servers/{id}") + @GET + @Override + public Response getIdentityServer(@PathParam("id") int id) { + try { + SPApplicationManager spAppManager = APIUtil.getSPApplicationManager(); + IdentityServerResponse identityServer = spAppManager.getIdentityServerResponse(id); + return Response.status(Response.Status.OK).entity(identityServer).build(); + } catch (NotFoundException e) { + String msg = "Identity server with the id " + id + " does not exist."; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (ApplicationManagementException e) { + String errMsg = "Error occurred while trying to merge identity server apps with existing apps"; + log.error(errMsg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errMsg).build(); + } + } + + @Path("/identity-servers/{id}") + @PUT + @Override + public Response updateIdentityServer(IdentityServerDTO identityServerDTO, @PathParam("id") int id) { + try { + SPApplicationManager spAppManager = APIUtil.getSPApplicationManager(); + IdentityServerResponse identityServerResponse = spAppManager.updateIdentityServer(identityServerDTO, id); + return Response.status(Response.Status.OK).entity(identityServerResponse).build(); + } catch (NotFoundException e) { + String msg = "Identity server with the id " + id + " does not exist."; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (BadRequestException e) { + String errMsg = "Identity server request payload is invalid"; + log.error(errMsg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(errMsg).build(); + } catch (ApplicationManagementException e) { + String errMsg = "Error occurred while trying to merge identity server apps with existing apps"; + log.error(errMsg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errMsg).build(); + } + } + + + @Path("/identity-servers") + @POST + @Override + public Response createIdentityServer(IdentityServerDTO identityServerDTO) { + try { + SPApplicationManager spAppManager = APIUtil.getSPApplicationManager(); + IdentityServerResponse identityServer = spAppManager.createIdentityServer(identityServerDTO); + return Response.status(Response.Status.CREATED).entity(identityServer).build(); + } catch (BadRequestException e) { + String errMsg = "Identity server request payload is invalid"; + log.error(errMsg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(errMsg).build(); + } catch (ApplicationManagementException e) { + String errMsg = "Error occurred while trying to merge identity server apps with existing apps"; + log.error(errMsg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errMsg).build(); + } + } + + @GET + @Path("/identity-servers/identity-server-name") + @Override + public Response isIdentityServerNameExists( + @QueryParam("identityServerName") String identityServerName) { + try { + if (identityServerName == null) { + String msg = "Invalid identity server name, identityServerName query param cannot be empty/null."; + log.error(msg); + return Response.status(Response.Status.BAD_REQUEST).build(); + } + SPApplicationManager spAppManager = APIUtil.getSPApplicationManager(); + if (spAppManager.isIdentityServerNameExist(identityServerName)) { + return Response.status(Response.Status.CONFLICT).build(); + } + return Response.status(Response.Status.OK).build(); + } catch (BadRequestException e) { + String errMsg = "Identity server request payload is invalid"; + log.error(errMsg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(errMsg).build(); + } catch (ApplicationManagementException e) { + String errMsg = "Error occurred while trying to merge identity server apps with existing apps"; + log.error(errMsg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errMsg).build(); + } + } + + @GET + @Path("/identity-servers/identity-server-url") + @Override + public Response isIdentityServerUrlExists( + @QueryParam("identityServerUrl") String identityServerUrl) { + try { + if (identityServerUrl == null) { + String msg = "Invalid identity server url, identityServerName query param cannot be empty/null."; + log.error(msg); + return Response.status(Response.Status.BAD_REQUEST).build(); + } + SPApplicationManager spAppManager = APIUtil.getSPApplicationManager(); + if (spAppManager.isIdentityServerUrlExist(identityServerUrl)) { + return Response.status(Response.Status.CONFLICT).build(); + } + return Response.status(Response.Status.OK).build(); + } catch (BadRequestException e) { + String errMsg = "Identity server request payload is invalid"; + log.error(errMsg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(errMsg).build(); + } catch (ApplicationManagementException e) { + String errMsg = "Error occurred while trying to merge identity server apps with existing apps"; + log.error(errMsg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errMsg).build(); + } + } + + @Path("/{identity-server-id}/service-providers") + @GET + @Override + public Response getServiceProviders(@DefaultValue("30") @QueryParam("limit") Integer limit,@DefaultValue("0") @QueryParam("offset") Integer offset, + @PathParam("identity-server-id") int identityServerId) { + try { + SPApplicationManager spAppManager = APIUtil.getSPApplicationManager(); + SPApplicationListResponse applications = spAppManager.retrieveSPApplicationFromIdentityServer(identityServerId, limit, offset); + return Response.status(Response.Status.OK).entity(applications).build(); + } catch (NotFoundException e) { + String errMsg = "No Identity server exist with the id: " + identityServerId; + log.error(errMsg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(errMsg).build(); + } catch (ApplicationManagementException e) { + String errMsg = "Error occurred while trying to merge identity server apps with existing apps"; + log.error(errMsg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errMsg).build(); + } + } + + @Path("/{identity-server-id}/service-provider/{service-provider-id}/attach") + @POST + @Override + public Response attachApps(@PathParam("identity-server-id") int identityServerId, + @PathParam("service-provider-id") String serviceProviderId, List appIds) { + SPApplicationManager spApplicationManager = APIUtil.getSPApplicationManager(); + try { + spApplicationManager.validateAttachAppsRequest(identityServerId, serviceProviderId, appIds); + spApplicationManager.attachSPApplications(identityServerId, serviceProviderId, appIds); + } catch (NotFoundException e) { + String msg = "No identity server exist with the id " + identityServerId; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (BadRequestException e) { + String msg = "Invalid appIds provided"; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while attaching apps to service provider with the id" + serviceProviderId; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + return Response.status(Response.Status.OK).build(); + } + + @Path("/{identity-server-id}/service-provider/{service-provider-id}/detach") + @POST + @Override + public Response detachApps(@PathParam("identity-server-id") int identityServerId, + @PathParam("service-provider-id") String serviceProviderId, List appIds) { + SPApplicationManager spApplicationManager = APIUtil.getSPApplicationManager(); + try { + spApplicationManager.validateDetachAppsRequest(identityServerId, serviceProviderId, appIds); + spApplicationManager.detachSPApplications(identityServerId, serviceProviderId, appIds); + } catch (NotFoundException e) { + String msg = "No identity server exist with the id " + identityServerId; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (BadRequestException e) { + String msg = "Invalid appIds provided"; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (ApplicationManagementException e) { + String msg = "Error occurred while attaching apps to service provider with the id" + serviceProviderId; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + return Response.status(Response.Status.OK).build(); + } + + @Path("/{identity-server-id}/service-provider/{service-provider-id}/create/ent-app") + @POST + @Override + public Response createEntApp(@PathParam("identity-server-id") int identityServerId, + @PathParam("service-provider-id") String serviceProviderId, ApplicationWrapper app, + @QueryParam("isPublished") boolean isPublished) { + return createSPApplication(identityServerId, serviceProviderId, app, isPublished); + } + + @Path("/{identity-server-id}/service-provider/{service-provider-id}/create/public-app") + @POST + @Override + public Response createPubApp(@PathParam("identity-server-id") int identityServerId, + @PathParam("service-provider-id") String serviceProviderId, PublicAppWrapper app, + @QueryParam("isPublished") boolean isPublished) { + return createSPApplication(identityServerId, serviceProviderId, app, isPublished); + } + + @Path("/{identity-server-id}/service-provider/{service-provider-id}/create/web-app") + @POST + @Override + public Response createWebApp(@PathParam("identity-server-id") int identityServerId, + @PathParam("service-provider-id") String serviceProviderId, WebAppWrapper app, + @QueryParam("isPublished") boolean isPublished) { + return createSPApplication(identityServerId, serviceProviderId, app, isPublished); + } + + @Path("/{identity-server-id}/service-provider/{service-provider-id}/create/custom-app") + @POST + @Override + public Response createCustomApp(@PathParam("identity-server-id") int identityServerId, + @PathParam("service-provider-id") String serviceProviderId, CustomAppWrapper app, + @QueryParam("isPublished") boolean isPublished) { + return createSPApplication(identityServerId, serviceProviderId, app, isPublished); + } + + /** + * Validates and creates service provider application + * + * @param identityServerId id of the identity server + * @param spUID uid of the service provider + * @param appWrapper application wrapper + * @param application wrapper class + * @return Response + */ + private Response createSPApplication(int identityServerId, String spUID, T appWrapper, boolean isPublished) { + try { + SPApplicationManager spApplicationManager = APIUtil.getSPApplicationManager(); + Application createdApp = spApplicationManager.createSPApplication(appWrapper, identityServerId, spUID, isPublished); + return Response.status(Response.Status.CREATED).entity(createdApp).build(); + } catch (NotFoundException e) { + String msg = "No identity server exist with the id " + identityServerId; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (BadRequestException e) { + String msg = "Found incompatible payload with create service provider app request."; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (RequestValidatingException e) { + String msg = "Found invalid release payload with create service provider app request."; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } + catch (ApplicationManagementException e) { + String msg = "Error occurred while creating service provider app"; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } + +} \ No newline at end of file diff --git a/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/webapp/WEB-INF/cxf-servlet.xml b/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/webapp/WEB-INF/cxf-servlet.xml index 47dcef91e1..da39cd93a8 100644 --- a/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/webapp/WEB-INF/cxf-servlet.xml +++ b/components/application-mgt/io.entgra.application.mgt.publisher.api/src/main/webapp/WEB-INF/cxf-servlet.xml @@ -25,6 +25,7 @@ + @@ -54,6 +55,7 @@ + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/common/Constants.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/common/Constants.java new file mode 100644 index 0000000000..0db16ff451 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/common/Constants.java @@ -0,0 +1,27 @@ +/* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.core.common; + +public class Constants { + public static final String SCHEME_SEPARATOR = "://"; + public static final String COLON = ":"; + public static final String URI_QUERY_SEPARATOR = "?"; + public static final String URI_SEPARATOR = "/"; + public static final String BASIC_AUTH_HEADER_PREFIX = "Basic "; + public static final String BEARER = "Bearer "; +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/common/util/FileUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/common/util/FileUtil.java new file mode 100644 index 0000000000..d90e586412 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/common/util/FileUtil.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2022, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved. + * + * Entgra (pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.core.common.util; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.Base64; + +public class FileUtil { + + /** + * Useful to remove path separator string "," from base64 string + * + * @param base64String base64 string + * @return base64 string without path separator + */ + public static String removePathSeparatorFromBase64String(String base64String) { + String partSeparator = ","; + if (base64String.contains(partSeparator)) { + return base64String.split(partSeparator)[1]; + } + return base64String; + } + + /** + * Useful to convert base64 string to input stream + * + * @param base64 base64 string to be converted + * @return {@link InputStream} of the provided base64 string + */ + public static InputStream base64ToInputStream(String base64) { + base64 = FileUtil.removePathSeparatorFromBase64String(base64); + byte[] base64Bytes = Base64.getDecoder().decode(base64); + return new ByteArrayInputStream(base64Bytes); + } + + /** + * This generates file name with a suffix depending on the duplicate name count, useful when saving + * files with the same name + * + * @param fileNameCount File count + * @return generated file name with suffix + */ + public static String generateDuplicateFileName(String fileName, int fileNameCount) { + String suffix = generateDuplicateFileNameSuffix(fileNameCount); + String fileNameWithoutExtension = extractFileNameWithoutExtension(fileName); + String fileNameWithSuffix = fileNameWithoutExtension + suffix; + fileNameWithSuffix = fileNameWithSuffix + '.' + extractFileExtension(fileName); + return fileNameWithSuffix; + } + + /** + * This generates file name suffix for duplicate file names. For example, + * if it's the first file, the count is 1 in which case the name doesn't have any suffix + * else it adds suffix with (count - 1) + * + * @param fileNameCount File count + * @return generated file name suffix + */ + private static String generateDuplicateFileNameSuffix(int fileNameCount) { + String suffix = ""; + if (fileNameCount < 1) { + throw new IllegalArgumentException("file name count must be above 0"); + } + if (fileNameCount > 1) { + suffix = "(" + (fileNameCount - 1) + ")"; + } + return suffix; + } + + /** + * Use to extract file extension from file name + * + * @param fileName name of the file + * @return extension of the file + */ + private static String extractFileExtension(String fileName) { + return fileName.substring(fileName.lastIndexOf('.') + 1); + } + + /** + * Use to extract the file name without the extension + * For example if you provide "main.java" as the fileName this will return main + * + * @param fileName name of the file + * @return file name without file extension + */ + private static String extractFileNameWithoutExtension(String fileName) { + return fileName.substring(0, fileName.lastIndexOf('.')); + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/common/util/HttpUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/common/util/HttpUtil.java index 5a21aaa122..afd8ad5f44 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/common/util/HttpUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/common/util/HttpUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved. + * Copyright (c) 2022, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved. * * Entgra (pvt) Ltd. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -17,15 +17,13 @@ */ package org.wso2.carbon.device.mgt.core.common.util; +import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang.StringUtils; import org.apache.http.HttpResponse; import org.apache.http.entity.ContentType; import org.apache.http.util.EntityUtils; -import org.wso2.carbon.device.mgt.core.report.mgt.Constants; - -import java.io.BufferedReader; +import org.wso2.carbon.device.mgt.core.common.Constants; import java.io.IOException; -import java.io.InputStreamReader; import java.net.URI; import java.util.ArrayList; import java.util.HashMap; @@ -34,12 +32,47 @@ import java.util.Map; public class HttpUtil { + /** + * Use to create {@link URI} from string + * This does encoding of the provided uri string before creating the URI + * + * @param uriString uri string to be used to create the URI + * @return created URI + */ public static URI createURI(String uriString) { uriString = uriString.replace(" ", "%20"); return URI.create(uriString); } - public static String getRequestSubPathFromEnd(URI requestUri, int position) { + /** + * Use to create basic auth header string for provided credentials + * + * @param userName username credential + * @param password password credential + * @return Basic auth header + */ + public static String getBasicAuthBase64Header(String userName, String password) { + return Constants.BASIC_AUTH_HEADER_PREFIX + getBase64Encode(userName, password); + } + + /** + * Use to get the base64 encoded string of key value pair. + * For example this can be useful when creating basic auth header + * + * @return base64 encoded string of provided key and value + */ + public static String getBase64Encode(String key, String value) { + return new String(Base64.encodeBase64((key + ":" + value).getBytes())); + } + + /** + * Useful to get the sub path in a position from the given uri starting from end of the uri + * + * @param requestUri {@link URI} + * @param position of which the sub path is needed + * @return Sub path of the uri + */ + public static String extractRequestSubPathFromEnd(URI requestUri, int position) { if (requestUri.getPath() != null) { String[] pathList = requestUri.getPath().split("/"); if (pathList.length - 1 >= position) { @@ -49,8 +82,15 @@ public class HttpUtil { return null; } - public static String getRequestSubPath(String fullPath, int position) { - String[] pathList = fullPath.split("/"); + /** + * Useful to get the sub path in a position from the given uri + * + * @param uri uri string from which the sub path should be extracted + * @param position of which the sub path is needed + * @return Sub path of the uri + */ + public static String extractRequestSubPath(String uri, int position) { + String[] pathList = uri.split("/"); if (pathList.length - 1 > position) { String path = pathList[position + 1]; if(path.contains(Constants.URI_QUERY_SEPARATOR)) { @@ -61,14 +101,37 @@ public class HttpUtil { return null; } + /** + * This returns the response body as string + * + * @param response {@link HttpResponse} + * @return Response body string + * @throws IOException if errors while converting response body to string + */ public static String getResponseString(HttpResponse response) throws IOException { return EntityUtils.toString(response.getEntity()); } - public static boolean isQueryParamExist(String param, URI request) { - Map> queryMap = getQueryMap(request); + /** + * Useful to check if a given query param exists in uri + * + * @param param query param to be checked + * @param uri in which query param should be checked + * @return if the provided query parameter exists in uri + */ + public static boolean isQueryParamExist(String param, URI uri) { + Map> queryMap = getQueryMap(uri); return queryMap.containsKey(param); } + + /** + * This is useful to get first query parameter value from a query map. + * For example a query parameter may have multiple values. + * + * @param param query parameter of which the value is needed + * @param queryMap query map which contains query paramters and it's values + * @return First value of provided query parameter + */ public static String getFirstQueryValue(String param, Map> queryMap) { List valueList = queryMap.get(param); String firstValue = null; @@ -77,6 +140,20 @@ public class HttpUtil { } return firstValue; } + + /** + * This constructs a key/value Map from query string of the provided uri. + * In other words this will create a map with query parameters as keys and their + * values as values. + * + * For example if the uri contains "?bar=1&foo=2" this will return a map + * with bar and foo as keys and 1 and 2 as their values + * + * This is similar to getQueryMap(URI uri) method except that this accepts uri string + * + * @param uri of which the query map to be created + * @return Query map of the provided uri + */ public static Map> getQueryMap(String uri) { String query = getQueryFromURIPath(uri); Map> map = new HashMap<>(); @@ -97,8 +174,20 @@ public class HttpUtil { } return map; } - public static Map> getQueryMap(URI request) { - String query = request.getQuery(); + + /** + * This constructs a key/value Map from query string of the provided uri. + * In other words this will create a map with query parameters as keys and their + * values as values. + * + * For example if the uri contains "?bar=1&foo=2" this will return a map + * with bar and foo as keys and 1 and 2 as their values + * + * @param uri of which the query map to be created + * @return Query map of the provided uri + */ + public static Map> getQueryMap(URI uri) { + String query = uri.getQuery(); Map> map = new HashMap<>(); if (query != null) { String[] params = query.split("&"); @@ -117,6 +206,13 @@ public class HttpUtil { } return map; } + + /** + * Get query string from uri path. Return null if no query string exists + * + * @param uri of which query string should be taken + * @return Query string of the provided uri + */ public static String getQueryFromURIPath(String uri) { String query = null; if (uri.length() > "?".length() && uri.contains("?")) { @@ -128,6 +224,12 @@ public class HttpUtil { return query; } + /** + * Get content type of http response + * + * @param response {@link HttpResponse} + * @return Content type + */ public static String getContentType(HttpResponse response) { ContentType contentType = ContentType.getOrDefault(response.getEntity()); return contentType.getMimeType(); diff --git a/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/conf/application-mgt.xml b/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/conf/application-mgt.xml index fa4ce1eb53..428fc0e134 100644 --- a/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/conf/application-mgt.xml +++ b/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/conf/application-mgt.xml @@ -22,6 +22,9 @@ jdbc/APPM_DS + + io.entgra.application.mgt.core.impl.SPApplicationManagerImpl + io.entgra.application.mgt.core.impl.ApplicationManagerImpl diff --git a/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/conf/identity-service-provider-config.xml b/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/conf/identity-service-provider-config.xml new file mode 100644 index 0000000000..bee524c54a --- /dev/null +++ b/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/conf/identity-service-provider-config.xml @@ -0,0 +1,30 @@ + + + + + + + + WSO2 IAM + io.entgra.application.mgt.core.identityserver.serviceprovider.impl.WSO2IAMSPApplicationService + /carbon/application/list-service-providers.jsp + + + + diff --git a/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/conf_templates/templates/repository/conf/application-mgt.xml.j2 b/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/conf_templates/templates/repository/conf/application-mgt.xml.j2 index 21ce676f3f..bd2cc9141c 100644 --- a/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/conf_templates/templates/repository/conf/application-mgt.xml.j2 +++ b/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/conf_templates/templates/repository/conf/application-mgt.xml.j2 @@ -22,6 +22,13 @@ jdbc/APPM_DS + + {% if application_mgt_conf.extension.isapplication_manager is defined %} + {{application_mgt_conf.extension.isapplication_manager}} + {% else %} + io.entgra.application.mgt.core.impl.SPApplicationManagerImpl + {% endif %} + {% if application_mgt_conf.extension.application_manager is defined %} {{application_mgt_conf.extension.application_manager}} diff --git a/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/conf_templates/templates/repository/conf/identity-service-provider-config.xml.j2 b/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/conf_templates/templates/repository/conf/identity-service-provider-config.xml.j2 new file mode 100644 index 0000000000..bee524c54a --- /dev/null +++ b/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/conf_templates/templates/repository/conf/identity-service-provider-config.xml.j2 @@ -0,0 +1,30 @@ + + + + + + + + WSO2 IAM + io.entgra.application.mgt.core.identityserver.serviceprovider.impl.WSO2IAMSPApplicationService + /carbon/application/list-service-providers.jsp + + + + diff --git a/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/dbscripts/cdm/application-mgt/mysql.sql b/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/dbscripts/cdm/application-mgt/mysql.sql index 375621018e..2d77337882 100644 --- a/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/dbscripts/cdm/application-mgt/mysql.sql +++ b/features/application-mgt/io.entgra.application.mgt.server.feature/src/main/resources/dbscripts/cdm/application-mgt/mysql.sql @@ -2,290 +2,271 @@ -- Table AP_APP -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS AP_APP( - ID INTEGER NOT NULL AUTO_INCREMENT, - NAME VARCHAR(350) NOT NULL, - DESCRIPTION VARCHAR(200) NOT NULL, - TYPE VARCHAR(200) NOT NULL, - TENANT_ID INTEGER NOT NULL, - STATUS VARCHAR(45) NOT NULL DEFAULT 'ACTIVE', - SUB_TYPE VARCHAR(45) NOT NULL, - CURRENCY VARCHAR(45) NULL DEFAULT '$', - RATING DOUBLE NULL DEFAULT NULL, - DEVICE_TYPE_ID INTEGER NOT NULL, - PRIMARY KEY (ID) + ID INTEGER NOT NULL AUTO_INCREMENT, + NAME VARCHAR(350) NOT NULL, + DESCRIPTION VARCHAR(200) NOT NULL, + TYPE VARCHAR(200) NOT NULL, + TENANT_ID INTEGER NOT NULL, + STATUS VARCHAR(45) NOT NULL DEFAULT 'ACTIVE', + SUB_TYPE VARCHAR(45) NOT NULL, + CURRENCY VARCHAR(45) NULL DEFAULT '$', + RATING DOUBLE NULL DEFAULT NULL, + DEVICE_TYPE_ID INTEGER NOT NULL, + PRIMARY KEY (ID) ); - -- ----------------------------------------------------- -- Table AP_APP_RELEASE -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS AP_APP_RELEASE( - ID INTEGER NOT NULL AUTO_INCREMENT, - DESCRIPTION VARCHAR(200) NOT NULL, - VERSION VARCHAR(70) NOT NULL, - TENANT_ID INTEGER NOT NULL, - UUID VARCHAR(200) NOT NULL, - RELEASE_TYPE VARCHAR(45) NOT NULL, - PACKAGE_NAME VARCHAR(150) NOT NULL, - APP_PRICE DECIMAL(6, 2) NULL DEFAULT NULL, - INSTALLER_LOCATION VARCHAR(100) NOT NULL, - ICON_LOCATION VARCHAR(100) NOT NULL, - BANNER_LOCATION VARCHAR(100) NULL DEFAULT NULL, - SC_1_LOCATION VARCHAR(100) NOT NULL, - SC_2_LOCATION VARCHAR(100) NULL DEFAULT NULL, - SC_3_LOCATION VARCHAR(100) NULL DEFAULT NULL, - APP_HASH_VALUE VARCHAR(1000) NOT NULL, - SHARED_WITH_ALL_TENANTS BOOLEAN NOT NULL DEFAULT FALSE, - APP_META_INFO VARCHAR(150) NULL DEFAULT NULL, - SUPPORTED_OS_VERSIONS VARCHAR(45) NOT NULL, - RATING DOUBLE NULL DEFAULT NULL, - CURRENT_STATE VARCHAR(45) NOT NULL, - RATED_USERS INTEGER NULL, - AP_APP_ID INTEGER NOT NULL, - PRIMARY KEY (ID), - CONSTRAINT fk_AP_APP_RELEASE_AP_APP1 - FOREIGN KEY (AP_APP_ID) - REFERENCES AP_APP (ID) ON DELETE NO ACTION ON UPDATE NO ACTION + ID INTEGER NOT NULL AUTO_INCREMENT, + DESCRIPTION VARCHAR(200) NOT NULL, + VERSION VARCHAR(70) NOT NULL, + TENANT_ID INTEGER NOT NULL, + UUID VARCHAR(200) NOT NULL, + RELEASE_TYPE VARCHAR(45) NOT NULL, + PACKAGE_NAME VARCHAR(150) NOT NULL, + APP_PRICE DECIMAL(6, 2) NULL DEFAULT NULL, + INSTALLER_LOCATION VARCHAR(100) NOT NULL, + ICON_LOCATION VARCHAR(100) NOT NULL, + BANNER_LOCATION VARCHAR(100) NULL DEFAULT NULL, + SC_1_LOCATION VARCHAR(100) NOT NULL, + SC_2_LOCATION VARCHAR(100) NULL DEFAULT NULL, + SC_3_LOCATION VARCHAR(100) NULL DEFAULT NULL, + APP_HASH_VALUE VARCHAR(1000) NOT NULL, + SHARED_WITH_ALL_TENANTS BOOLEAN NOT NULL DEFAULT FALSE, + APP_META_INFO VARCHAR(150) NULL DEFAULT NULL, + SUPPORTED_OS_VERSIONS VARCHAR(45) NOT NULL, + RATING DOUBLE NULL DEFAULT NULL, + CURRENT_STATE VARCHAR(45) NOT NULL, + RATED_USERS INTEGER NULL, + AP_APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT fk_AP_APP_RELEASE_AP_APP1 FOREIGN KEY (AP_APP_ID) REFERENCES AP_APP (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ); CREATE INDEX fk_AP_APP_RELEASE_AP_APP1_idx ON AP_APP_RELEASE (AP_APP_ID ASC); - -- ----------------------------------------------------- -- Table AP_APP_REVIEW -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS AP_APP_REVIEW( - ID INTEGER NOT NULL AUTO_INCREMENT, - TENANT_ID INTEGER NOT NULL, - COMMENT TEXT NOT NULL, - ROOT_PARENT_ID INTEGER NOT NULL, - IMMEDIATE_PARENT_ID INTEGER NOT NULL, - CREATED_AT BIGINT NOT NULL, - MODIFIED_AT BIGINT NOT NULL, - RATING INTEGER NULL, - USERNAME VARCHAR(45) NOT NULL, - ACTIVE_REVIEW BOOLEAN NOT NULL DEFAULT TRUE, - AP_APP_RELEASE_ID INTEGER NOT NULL, - PRIMARY KEY (ID), - CONSTRAINT fk_AP_APP_COMMENT_AP_APP_RELEASE1 - FOREIGN KEY (AP_APP_RELEASE_ID) - REFERENCES AP_APP_RELEASE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + COMMENT TEXT NOT NULL, + ROOT_PARENT_ID INTEGER NOT NULL, + IMMEDIATE_PARENT_ID INTEGER NOT NULL, + CREATED_AT BIGINT NOT NULL, + MODIFIED_AT BIGINT NOT NULL, + RATING INTEGER NULL, + USERNAME VARCHAR(45) NOT NULL, + ACTIVE_REVIEW BOOLEAN NOT NULL DEFAULT TRUE, + AP_APP_RELEASE_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT fk_AP_APP_COMMENT_AP_APP_RELEASE1 FOREIGN KEY (AP_APP_RELEASE_ID) REFERENCES AP_APP_RELEASE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ); CREATE INDEX fk_AP_APP_COMMENT_AP_APP_RELEASE1_idx ON AP_APP_REVIEW (AP_APP_RELEASE_ID ASC); - -- ----------------------------------------------------- -- Table AP_APP_LIFECYCLE_STATE -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS AP_APP_LIFECYCLE_STATE( - ID INTEGER NOT NULL AUTO_INCREMENT, - CURRENT_STATE VARCHAR(45) NOT NULL, - PREVIOUS_STATE VARCHAR(45) NOT NULL, - TENANT_ID INTEGER NOT NULL, - UPDATED_BY VARCHAR(100) NOT NULL, - UPDATED_AT BIGINT NOT NULL, - AP_APP_RELEASE_ID INTEGER NOT NULL, - REASON TEXT DEFAULT NULL, - PRIMARY KEY (ID), - CONSTRAINT fk_AP_APP_LIFECYCLE_STATE_AP_APP_RELEASE1 - FOREIGN KEY (AP_APP_RELEASE_ID) - REFERENCES AP_APP_RELEASE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION + ID INTEGER NOT NULL AUTO_INCREMENT, + CURRENT_STATE VARCHAR(45) NOT NULL, + PREVIOUS_STATE VARCHAR(45) NOT NULL, + TENANT_ID INTEGER NOT NULL, + UPDATED_BY VARCHAR(100) NOT NULL, + UPDATED_AT BIGINT NOT NULL, + AP_APP_RELEASE_ID INTEGER NOT NULL, + REASON TEXT DEFAULT NULL, + PRIMARY KEY (ID), + CONSTRAINT fk_AP_APP_LIFECYCLE_STATE_AP_APP_RELEASE1 FOREIGN KEY (AP_APP_RELEASE_ID) REFERENCES AP_APP_RELEASE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ); -CREATE INDEX fk_AP_APP_LIFECYCLE_STATE_AP_APP_RELEASE1_idx ON AP_APP_LIFECYCLE_STATE( AP_APP_RELEASE_ID ASC); - +CREATE INDEX fk_AP_APP_LIFECYCLE_STATE_AP_APP_RELEASE1_idx ON AP_APP_LIFECYCLE_STATE(AP_APP_RELEASE_ID ASC); -- ----------------------------------------------------- -- Table AP_APP_TAG -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS AP_APP_TAG( - ID INTEGER NOT NULL AUTO_INCREMENT, - TENANT_ID INTEGER NOT NULL, - TAG VARCHAR(100) NOT NULL, - PRIMARY KEY (ID) + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + TAG VARCHAR(100) NOT NULL, + PRIMARY KEY (ID) ); - -- ----------------------------------------------------- -- Table AP_DEVICE_SUBSCRIPTION -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS AP_DEVICE_SUBSCRIPTION( - ID INTEGER NOT NULL AUTO_INCREMENT, - TENANT_ID INTEGER NOT NULL, - SUBSCRIBED_BY VARCHAR(100) NOT NULL, - SUBSCRIBED_TIMESTAMP TIMESTAMP NOT NULL, - UNSUBSCRIBED BOOLEAN NOT NULL DEFAULT false, - UNSUBSCRIBED_BY VARCHAR(100) NULL DEFAULT NULL, - UNSUBSCRIBED_TIMESTAMP TIMESTAMP NULL DEFAULT NULL, - ACTION_TRIGGERED_FROM VARCHAR(45) NOT NULL, - STATUS VARCHAR(45) NOT NULL, - DM_DEVICE_ID INTEGER NOT NULL, - AP_APP_RELEASE_ID INTEGER NOT NULL, - PRIMARY KEY (ID), - CONSTRAINT fk_AP_DEVICE_SUBSCRIPTION_AP_APP_RELEASE1 - FOREIGN KEY (AP_APP_RELEASE_ID) - REFERENCES AP_APP_RELEASE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + SUBSCRIBED_BY VARCHAR(100) NOT NULL, + SUBSCRIBED_TIMESTAMP TIMESTAMP NOT NULL, + UNSUBSCRIBED BOOLEAN NOT NULL DEFAULT false, + UNSUBSCRIBED_BY VARCHAR(100) NULL DEFAULT NULL, + UNSUBSCRIBED_TIMESTAMP TIMESTAMP NULL DEFAULT NULL, + ACTION_TRIGGERED_FROM VARCHAR(45) NOT NULL, + STATUS VARCHAR(45) NOT NULL, + DM_DEVICE_ID INTEGER NOT NULL, + AP_APP_RELEASE_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT fk_AP_DEVICE_SUBSCRIPTION_AP_APP_RELEASE1 FOREIGN KEY (AP_APP_RELEASE_ID) REFERENCES AP_APP_RELEASE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ); CREATE INDEX fk_AP_DEVICE_SUBSCRIPTION_AP_APP_RELEASE1_idx ON AP_DEVICE_SUBSCRIPTION (AP_APP_RELEASE_ID ASC); - -- ----------------------------------------------------- -- Table AP_GROUP_SUBSCRIPTION -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS AP_GROUP_SUBSCRIPTION( - ID INTEGER NOT NULL AUTO_INCREMENT, - TENANT_ID INTEGER NOT NULL, - SUBSCRIBED_BY VARCHAR(100) NOT NULL, - SUBSCRIBED_TIMESTAMP TIMESTAMP NOT NULL, - UNSUBSCRIBED BOOLEAN NOT NULL DEFAULT false, - UNSUBSCRIBED_BY VARCHAR(100) NULL DEFAULT NULL, - UNSUBSCRIBED_TIMESTAMP TIMESTAMP NULL DEFAULT NULL, - GROUP_NAME VARCHAR(100) NOT NULL, - AP_APP_RELEASE_ID INTEGER NOT NULL, - PRIMARY KEY (ID), - CONSTRAINT fk_AP_GROUP_SUBSCRIPTION_AP_APP_RELEASE1 - FOREIGN KEY (AP_APP_RELEASE_ID) - REFERENCES AP_APP_RELEASE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + SUBSCRIBED_BY VARCHAR(100) NOT NULL, + SUBSCRIBED_TIMESTAMP TIMESTAMP NOT NULL, + UNSUBSCRIBED BOOLEAN NOT NULL DEFAULT false, + UNSUBSCRIBED_BY VARCHAR(100) NULL DEFAULT NULL, + UNSUBSCRIBED_TIMESTAMP TIMESTAMP NULL DEFAULT NULL, + GROUP_NAME VARCHAR(100) NOT NULL, + AP_APP_RELEASE_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT fk_AP_GROUP_SUBSCRIPTION_AP_APP_RELEASE1 FOREIGN KEY (AP_APP_RELEASE_ID) REFERENCES AP_APP_RELEASE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ); CREATE INDEX fk_AP_GROUP_SUBSCRIPTION_AP_APP_RELEASE1_idx ON AP_GROUP_SUBSCRIPTION (AP_APP_RELEASE_ID ASC); - -- ----------------------------------------------------- -- Table AP_ROLE_SUBSCRIPTION -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS AP_ROLE_SUBSCRIPTION( - ID INTEGER NOT NULL AUTO_INCREMENT, - TENANT_ID INTEGER NOT NULL, - ROLE_NAME VARCHAR(100) NOT NULL, - SUBSCRIBED_BY VARCHAR(100) NOT NULL, - SUBSCRIBED_TIMESTAMP TIMESTAMP NOT NULL, - UNSUBSCRIBED BOOLEAN NOT NULL DEFAULT false, - UNSUBSCRIBED_BY VARCHAR(100) NULL DEFAULT NULL, - UNSUBSCRIBED_TIMESTAMP TIMESTAMP NULL DEFAULT NULL, - AP_APP_RELEASE_ID INTEGER NOT NULL, - PRIMARY KEY (ID), - CONSTRAINT fk_AP_ROLE_SUBSCRIPTION_AP_APP_RELEASE1 - FOREIGN KEY (AP_APP_RELEASE_ID) - REFERENCES AP_APP_RELEASE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + ROLE_NAME VARCHAR(100) NOT NULL, + SUBSCRIBED_BY VARCHAR(100) NOT NULL, + SUBSCRIBED_TIMESTAMP TIMESTAMP NOT NULL, + UNSUBSCRIBED BOOLEAN NOT NULL DEFAULT false, + UNSUBSCRIBED_BY VARCHAR(100) NULL DEFAULT NULL, + UNSUBSCRIBED_TIMESTAMP TIMESTAMP NULL DEFAULT NULL, + AP_APP_RELEASE_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT fk_AP_ROLE_SUBSCRIPTION_AP_APP_RELEASE1 FOREIGN KEY (AP_APP_RELEASE_ID) REFERENCES AP_APP_RELEASE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ); CREATE INDEX fk_AP_ROLE_SUBSCRIPTION_AP_APP_RELEASE1_idx ON AP_ROLE_SUBSCRIPTION (AP_APP_RELEASE_ID ASC); - -- ----------------------------------------------------- -- Table AP_UNRESTRICTED_ROLE -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS AP_UNRESTRICTED_ROLE( - ID INTEGER NOT NULL AUTO_INCREMENT, - TENANT_ID INTEGER NOT NULL, - ROLE VARCHAR(45) NOT NULL, - AP_APP_ID INTEGER NOT NULL, - PRIMARY KEY (ID), - CONSTRAINT fk_AP_APP_VISIBILITY_AP_APP1 - FOREIGN KEY (AP_APP_ID) - REFERENCES AP_APP (ID) ON DELETE NO ACTION ON UPDATE NO ACTION + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + ROLE VARCHAR(45) NOT NULL, + AP_APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT fk_AP_APP_VISIBILITY_AP_APP1 FOREIGN KEY (AP_APP_ID) REFERENCES AP_APP (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ); CREATE INDEX fk_AP_APP_VISIBILITY_AP_APP1_idx ON AP_UNRESTRICTED_ROLE (AP_APP_ID ASC); - -- ----------------------------------------------------- -- Table AP_USER_SUBSCRIPTION -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS AP_USER_SUBSCRIPTION( - ID INTEGER NOT NULL AUTO_INCREMENT, - TENANT_ID INTEGER NOT NULL, - USER_NAME VARCHAR(100) NOT NULL, - SUBSCRIBED_BY VARCHAR(100) NOT NULL, - SUBSCRIBED_TIMESTAMP TIMESTAMP NOT NULL, - UNSUBSCRIBED BOOLEAN NOT NULL DEFAULT false, - UNSUBSCRIBED_BY VARCHAR(100) NULL DEFAULT NULL, - UNSUBSCRIBED_TIMESTAMP TIMESTAMP NULL DEFAULT NULL, - AP_APP_RELEASE_ID INTEGER NOT NULL, - PRIMARY KEY (ID), - CONSTRAINT fk_AP_USER_SUBSCRIPTION_AP_APP_RELEASE1 - FOREIGN KEY (AP_APP_RELEASE_ID) - REFERENCES AP_APP_RELEASE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + USER_NAME VARCHAR(100) NOT NULL, + SUBSCRIBED_BY VARCHAR(100) NOT NULL, + SUBSCRIBED_TIMESTAMP TIMESTAMP NOT NULL, + UNSUBSCRIBED BOOLEAN NOT NULL DEFAULT false, + UNSUBSCRIBED_BY VARCHAR(100) NULL DEFAULT NULL, + UNSUBSCRIBED_TIMESTAMP TIMESTAMP NULL DEFAULT NULL, + AP_APP_RELEASE_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT fk_AP_USER_SUBSCRIPTION_AP_APP_RELEASE1 FOREIGN KEY (AP_APP_RELEASE_ID) REFERENCES AP_APP_RELEASE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ); CREATE INDEX fk_AP_USER_SUBSCRIPTION_AP_APP_RELEASE1_idx ON AP_USER_SUBSCRIPTION (AP_APP_RELEASE_ID ASC); - -- ----------------------------------------------------- -- Table AP_APP_CATEGORY -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS AP_APP_CATEGORY( - ID INTEGER NOT NULL AUTO_INCREMENT, - TENANT_ID INTEGER NOT NULL, - CATEGORY VARCHAR(45) NOT NULL, - CATEGORY_ICON VARCHAR(45) NULL, - PRIMARY KEY (ID) + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + CATEGORY VARCHAR(45) NOT NULL, + CATEGORY_ICON VARCHAR(45) NULL, + PRIMARY KEY (ID) ); - -- ----------------------------------------------------- -- Table AP_APP_TAG_MAPPING -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS AP_APP_TAG_MAPPING( -ID INTEGER NOT NULL AUTO_INCREMENT, -TENANT_ID INTEGER NOT NULL, -AP_APP_TAG_ID INTEGER NOT NULL, -AP_APP_ID INTEGER NOT NULL, -PRIMARY KEY (ID), -CONSTRAINT fk_AP_APP_TAG_copy1_AP_APP_TAG1 - FOREIGN KEY (AP_APP_TAG_ID) - REFERENCES AP_APP_TAG (ID) ON DELETE NO ACTION ON UPDATE NO ACTION, -CONSTRAINT fk_AP_APP_TAG_copy1_AP_APP1 - FOREIGN KEY (AP_APP_ID) - REFERENCES AP_APP (ID) ON DELETE NO ACTION ON UPDATE NO ACTION + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + AP_APP_TAG_ID INTEGER NOT NULL, + AP_APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT fk_AP_APP_TAG_copy1_AP_APP_TAG1 FOREIGN KEY (AP_APP_TAG_ID) REFERENCES AP_APP_TAG (ID) ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT fk_AP_APP_TAG_copy1_AP_APP1 FOREIGN KEY (AP_APP_ID) REFERENCES AP_APP (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ); CREATE INDEX fk_AP_APP_TAG_copy1_AP_APP_TAG1_idx ON AP_APP_TAG_MAPPING (AP_APP_TAG_ID ASC); CREATE INDEX fk_AP_APP_TAG_copy1_AP_APP1_idx ON AP_APP_TAG_MAPPING (AP_APP_ID ASC); - -- ----------------------------------------------------- -- Table AP_APP_CATEGORY_MAPPING -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS AP_APP_CATEGORY_MAPPING( -ID INTEGER NOT NULL AUTO_INCREMENT, -TENANT_ID INTEGER NOT NULL, -AP_APP_CATEGORY_ID INTEGER NOT NULL, -AP_APP_ID INTEGER NOT NULL, -PRIMARY KEY (ID), -CONSTRAINT fk_AP_APP_CATEGORY_copy1_AP_APP_CATEGORY1 - FOREIGN KEY (AP_APP_CATEGORY_ID) - REFERENCES AP_APP_CATEGORY (ID) ON DELETE NO ACTION ON UPDATE NO ACTION, -CONSTRAINT fk_AP_APP_CATEGORY_copy1_AP_APP1 - FOREIGN KEY (AP_APP_ID) - REFERENCES AP_APP (ID) ON DELETE NO ACTION ON UPDATE NO ACTION + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + AP_APP_CATEGORY_ID INTEGER NOT NULL, + AP_APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT fk_AP_APP_CATEGORY_copy1_AP_APP_CATEGORY1 FOREIGN KEY (AP_APP_CATEGORY_ID) REFERENCES AP_APP_CATEGORY (ID) ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT fk_AP_APP_CATEGORY_copy1_AP_APP1 FOREIGN KEY (AP_APP_ID) REFERENCES AP_APP (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ); CREATE INDEX fk_AP_APP_CATEGORY_copy1_AP_APP_CATEGORY1_idx ON AP_APP_CATEGORY_MAPPING (AP_APP_CATEGORY_ID ASC); CREATE INDEX fk_AP_APP_CATEGORY_copy1_AP_APP1_idx ON AP_APP_CATEGORY_MAPPING (AP_APP_ID ASC); - -- ----------------------------------------------------- -- Table AP_APP_SUB_OP_MAPPING -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS AP_APP_SUB_OP_MAPPING ( - ID INTEGER NOT NULL AUTO_INCREMENT, - TENANT_ID INTEGER NOT NULL, - OPERATION_ID INTEGER NOT NULL, - AP_DEVICE_SUBSCRIPTION_ID INTEGER NOT NULL, - PRIMARY KEY (ID), - CONSTRAINT fk_AP_APP_SUB_OP_MAPPING_AP_DEVICE_SUBSCRIPTION1 - FOREIGN KEY (AP_DEVICE_SUBSCRIPTION_ID) - REFERENCES AP_DEVICE_SUBSCRIPTION (ID) ON DELETE NO ACTION ON UPDATE NO ACTION + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + OPERATION_ID INTEGER NOT NULL, + AP_DEVICE_SUBSCRIPTION_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + CONSTRAINT fk_AP_APP_SUB_OP_MAPPING_AP_DEVICE_SUBSCRIPTION1 FOREIGN KEY (AP_DEVICE_SUBSCRIPTION_ID) REFERENCES AP_DEVICE_SUBSCRIPTION (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ); CREATE INDEX fk_AP_APP_SUB_OP_MAPPING_AP_DEVICE_SUBSCRIPTION1_idx ON AP_APP_SUB_OP_MAPPING (AP_DEVICE_SUBSCRIPTION_ID ASC); - -- ----------------------------------------------------- -- Table AP_SCHEDULED_SUBSCRIPTION -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS AP_SCHEDULED_SUBSCRIPTION( - ID INTEGER NOT NULL AUTO_INCREMENT, - TASK_NAME VARCHAR(100) NOT NULL, - APPLICATION_UUID VARCHAR(36) NOT NULL, - SUBSCRIBER_LIST TEXT NOT NULL, - STATUS VARCHAR(15) NOT NULL, - SCHEDULED_AT BIGINT NOT NULL, - SCHEDULED_BY VARCHAR(100) NOT NULL, - SCHEDULED_TIMESTAMP TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, - DELETED BOOLEAN, - PRIMARY KEY (ID) + ID INTEGER NOT NULL AUTO_INCREMENT, + TASK_NAME VARCHAR(100) NOT NULL, + APPLICATION_UUID VARCHAR(36) NOT NULL, + SUBSCRIBER_LIST TEXT NOT NULL, + STATUS VARCHAR(15) NOT NULL, + SCHEDULED_AT BIGINT NOT NULL, + SCHEDULED_BY VARCHAR(100) NOT NULL, + SCHEDULED_TIMESTAMP TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, + DELETED BOOLEAN, + PRIMARY KEY (ID) ); - -- ----------------------------------------------------- +-- Table AP_IDENTITY_SERVER +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS AP_IDENTITY_SERVER ( + ID INT AUTO_INCREMENT PRIMARY KEY, + NAME VARCHAR(255) NOT NULL, + DESCRIPTION VARCHAR(255) NOT NULL, + URL VARCHAR(255) NOT NULL, + SP_APPS_URI VARCHAR(255) NOT NULL, + SP_APPS_API VARCHAR(255) NULL, + TENANT_ID INT NOT NULL, + USERNAME VARCHAR(255) NOT NULL, + PASSWORD VARCHAR(255) NOT NULL +) -- ----------------------------------------------------- +-- Table AP_IS_SP_APP_MAPPING +-- -----------------------------------------------------; +CREATE TABLE IF NOT EXISTS AP_IS_SP_APP_MAPPING ( + ID INT AUTO_INCREMENT PRIMARY KEY, + SP_UID VARCHAR(255) NOT NULL, + AP_APP_ID INT NOT NULL, + IS_ID INT NOT NULL, + TENANT_ID INT NOT NULL, + CONSTRAINT AP_IS_SP_APP_MAPPING_AP_APP_ID_fk FOREIGN KEY (AP_APP_ID) REFERENCES AP_APP (ID), + CONSTRAINT AP_IS_SP_APP_MAPPING_AP_IDENTITY_SERVER_ID_fk FOREIGN KEY (IS_ID) REFERENCES AP_IDENTITY_SERVER (ID) +); -- Table AP_APP_FAVOURITES -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS AP_APP_FAVOURITES( - ID INTEGER NOT NULL AUTO_INCREMENT, - AP_APP_ID INTEGER NOT NULL, - USER_NAME VARCHAR(100) NOT NULL, - TENANT_ID INTEGER NOT NULL, - PRIMARY KEY(ID), - CONSTRAINT AP_APP_FAVOURITES_AP_APP_ID_fk - FOREIGN KEY (AP_APP_ID) - REFERENCES AP_APP (ID) -); + ID INTEGER NOT NULL AUTO_INCREMENT, + AP_APP_ID INTEGER NOT NULL, + USER_NAME VARCHAR(100) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY(ID), + CONSTRAINT AP_APP_FAVOURITES_AP_APP_ID_fk FOREIGN KEY (AP_APP_ID) REFERENCES AP_APP (ID) +); \ No newline at end of file diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml index 645f4b3269..a8b1584325 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml @@ -38,6 +38,10 @@ perm:grafana:api:view perm:app:review:view perm:app:review:update + perm:app:publisher:service-provider:view + perm:app:publisher:service-provider:create + perm:app:publisher:service-provider:attach + perm:app:publisher:service-provider:detach perm:app:publisher:view perm:app:publisher:update perm:app:store:view diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf_templates/templates/repository/conf/mdm-ui-config.xml.j2 b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf_templates/templates/repository/conf/mdm-ui-config.xml.j2 index 847ede3df7..292234023c 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf_templates/templates/repository/conf/mdm-ui-config.xml.j2 +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf_templates/templates/repository/conf/mdm-ui-config.xml.j2 @@ -57,6 +57,10 @@ perm:app:review:view perm:app:review:update + perm:app:publisher:service-provider:view + perm:app:publisher:service-provider:create + perm:app:publisher:service-provider:attach + perm:app:publisher:service-provider:detach perm:app:publisher:view perm:app:publisher:update perm:app:store:view