diff --git a/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/ApiAppConfiguration.java b/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/ApiAppConfiguration.java index c553c42a9d6..bff8cdea8be 100644 --- a/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/ApiAppConfiguration.java +++ b/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/ApiAppConfiguration.java @@ -11,7 +11,6 @@ public class ApiAppConfiguration implements Configuration { private boolean configOauthEnabled; private boolean disableLoggerTimer; private boolean disableAuditLogger; - private boolean assetMgtEnabled; private boolean customAttributeValidationEnabled; private List apiApprovedIssuer; private String apiProtectionType; @@ -43,258 +42,259 @@ public class ApiAppConfiguration implements Configuration { private DataFormatConversionConf dataFormatConversionConf; private List plugins; + private AssetMgtConfiguration assetMgtConfiguration; + public boolean isConfigOauthEnabled() { return configOauthEnabled; } - + public void setConfigOauthEnabled(boolean configOauthEnabled) { this.configOauthEnabled = configOauthEnabled; } - + public boolean isDisableLoggerTimer() { return disableLoggerTimer; } - + public void setDisableLoggerTimer(boolean disableLoggerTimer) { this.disableLoggerTimer = disableLoggerTimer; } - + public boolean isDisableAuditLogger() { return disableAuditLogger; } - + public void setDisableAuditLogger(boolean disableAuditLogger) { this.disableAuditLogger = disableAuditLogger; } - - public boolean isAssetMgtEnabled() { - return assetMgtEnabled; - } - - public void setAssetMgtEnabled(boolean assetMgtEnabled) { - this.assetMgtEnabled = assetMgtEnabled; - } - + public boolean isCustomAttributeValidationEnabled() { return customAttributeValidationEnabled; } - + public void setCustomAttributeValidationEnabled(boolean customAttributeValidationEnabled) { this.customAttributeValidationEnabled = customAttributeValidationEnabled; } - + public List getApiApprovedIssuer() { return apiApprovedIssuer; } - + public void setApiApprovedIssuer(List apiApprovedIssuer) { this.apiApprovedIssuer = apiApprovedIssuer; } - + public String getApiProtectionType() { return apiProtectionType; } - + public void setApiProtectionType(String apiProtectionType) { this.apiProtectionType = apiProtectionType; } - + public String getApiClientId() { return apiClientId; } - + public void setApiClientId(String apiClientId) { this.apiClientId = apiClientId; } - + public String getApiClientPassword() { return apiClientPassword; } - + public void setApiClientPassword(String apiClientPassword) { this.apiClientPassword = apiClientPassword; } - + public boolean isEndpointInjectionEnabled() { return endpointInjectionEnabled; } - + public void setEndpointInjectionEnabled(boolean endpointInjectionEnabled) { this.endpointInjectionEnabled = endpointInjectionEnabled; } - + public String getAuthIssuerUrl() { return authIssuerUrl; } - + public void setAuthIssuerUrl(String authIssuerUrl) { this.authIssuerUrl = authIssuerUrl; } - + public String getAuthOpenidConfigurationUrl() { return authOpenidConfigurationUrl; } - + public void setAuthOpenidConfigurationUrl(String authOpenidConfigurationUrl) { this.authOpenidConfigurationUrl = authOpenidConfigurationUrl; } - + public String getAuthOpenidIntrospectionUrl() { return authOpenidIntrospectionUrl; } - + public void setAuthOpenidIntrospectionUrl(String authOpenidIntrospectionUrl) { this.authOpenidIntrospectionUrl = authOpenidIntrospectionUrl; } - + public String getAuthOpenidTokenUrl() { return authOpenidTokenUrl; } - + public void setAuthOpenidTokenUrl(String authOpenidTokenUrl) { this.authOpenidTokenUrl = authOpenidTokenUrl; } - + public String getAuthOpenidRevokeUrl() { return authOpenidRevokeUrl; } - + public void setAuthOpenidRevokeUrl(String authOpenidRevokeUrl) { this.authOpenidRevokeUrl = authOpenidRevokeUrl; } - + public String getSmallryeHealthRootPath() { return smallryeHealthRootPath; } - + public void setSmallryeHealthRootPath(String smallryeHealthRootPath) { this.smallryeHealthRootPath = smallryeHealthRootPath; } - + public List getExclusiveAuthScopes() { return exclusiveAuthScopes; } - + public void setExclusiveAuthScopes(List exclusiveAuthScopes) { this.exclusiveAuthScopes = exclusiveAuthScopes; } - + public List getCorsConfigurationFilters() { return corsConfigurationFilters; } - + public void setCorsConfigurationFilters(List corsConfigurationFilters) { this.corsConfigurationFilters = corsConfigurationFilters; } - + public String getLoggingLevel() { return loggingLevel; } - + public void setLoggingLevel(String loggingLevel) { this.loggingLevel = loggingLevel; } - + public String getLoggingLayout() { return loggingLayout; } - + public void setLoggingLayout(String loggingLayout) { this.loggingLayout = loggingLayout; } - + public String getExternalLoggerConfiguration() { return externalLoggerConfiguration; } - + public void setExternalLoggerConfiguration(String externalLoggerConfiguration) { this.externalLoggerConfiguration = externalLoggerConfiguration; } - + public Boolean getDisableJdkLogger() { return disableJdkLogger; } - + public void setDisableJdkLogger(Boolean disableJdkLogger) { this.disableJdkLogger = disableJdkLogger; } - + public int getMaxCount() { return maxCount; } - + public void setMaxCount(int maxCount) { this.maxCount = maxCount; } - + public List getUserExclusionAttributes() { return userExclusionAttributes; } - + public void setUserExclusionAttributes(List userExclusionAttributes) { this.userExclusionAttributes = userExclusionAttributes; } - + public List getUserMandatoryAttributes() { return userMandatoryAttributes; } - + public void setUserMandatoryAttributes(List userMandatoryAttributes) { this.userMandatoryAttributes = userMandatoryAttributes; } - + public AgamaConfiguration getAgamaConfiguration() { return agamaConfiguration; } - + public void setAgamaConfiguration(AgamaConfiguration agamaConfiguration) { this.agamaConfiguration = agamaConfiguration; } - + public AuditLogConf getAuditLogConf() { return auditLogConf; } - + public void setAuditLogConf(AuditLogConf auditLogConf) { this.auditLogConf = auditLogConf; } - + public DataFormatConversionConf getDataFormatConversionConf() { return dataFormatConversionConf; } - + public void setDataFormatConversionConf(DataFormatConversionConf dataFormatConversionConf) { this.dataFormatConversionConf = dataFormatConversionConf; } - + public List getPlugins() { return plugins; } - + public void setPlugins(List plugins) { this.plugins = plugins; } - + + public AssetMgtConfiguration getAssetMgtConfiguration() { + return assetMgtConfiguration; + } + + public void setAssetMgtConfiguration(AssetMgtConfiguration assetMgtConfiguration) { + this.assetMgtConfiguration = assetMgtConfiguration; + } + @Override public String toString() { return "ApiAppConfiguration [configOauthEnabled=" + configOauthEnabled + ", disableLoggerTimer=" - + disableLoggerTimer + ", disableAuditLogger=" + disableAuditLogger + ", assetMgtEnabled=" - + assetMgtEnabled + ", customAttributeValidationEnabled=" + customAttributeValidationEnabled - + ", apiApprovedIssuer=" + apiApprovedIssuer + ", apiProtectionType=" + apiProtectionType - + ", apiClientId=" + apiClientId + ", apiClientPassword=" + apiClientPassword - + ", endpointInjectionEnabled=" + endpointInjectionEnabled + ", authIssuerUrl=" + authIssuerUrl - + ", authOpenidConfigurationUrl=" + authOpenidConfigurationUrl + ", authOpenidIntrospectionUrl=" - + authOpenidIntrospectionUrl + ", authOpenidTokenUrl=" + authOpenidTokenUrl + ", authOpenidRevokeUrl=" - + authOpenidRevokeUrl + ", smallryeHealthRootPath=" + smallryeHealthRootPath + ", exclusiveAuthScopes=" - + exclusiveAuthScopes + ", corsConfigurationFilters=" + corsConfigurationFilters + ", loggingLevel=" - + loggingLevel + ", loggingLayout=" + loggingLayout + ", externalLoggerConfiguration=" - + externalLoggerConfiguration + ", disableJdkLogger=" + disableJdkLogger + ", maxCount=" + maxCount - + ", userExclusionAttributes=" + userExclusionAttributes + ", userMandatoryAttributes=" - + userMandatoryAttributes + ", agamaConfiguration=" + agamaConfiguration + ", auditLogConf=" - + auditLogConf + ", dataFormatConversionConf=" + dataFormatConversionConf + ", plugins=" + plugins - + "]"; - } - - + + disableLoggerTimer + ", disableAuditLogger=" + disableAuditLogger + + ", customAttributeValidationEnabled=" + customAttributeValidationEnabled + ", apiApprovedIssuer=" + + apiApprovedIssuer + ", apiProtectionType=" + apiProtectionType + ", apiClientId=" + apiClientId + + ", apiClientPassword=" + apiClientPassword + ", endpointInjectionEnabled=" + endpointInjectionEnabled + + ", authIssuerUrl=" + authIssuerUrl + ", authOpenidConfigurationUrl=" + authOpenidConfigurationUrl + + ", authOpenidIntrospectionUrl=" + authOpenidIntrospectionUrl + ", authOpenidTokenUrl=" + + authOpenidTokenUrl + ", authOpenidRevokeUrl=" + authOpenidRevokeUrl + ", smallryeHealthRootPath=" + + smallryeHealthRootPath + ", exclusiveAuthScopes=" + exclusiveAuthScopes + + ", corsConfigurationFilters=" + corsConfigurationFilters + ", loggingLevel=" + loggingLevel + + ", loggingLayout=" + loggingLayout + ", externalLoggerConfiguration=" + externalLoggerConfiguration + + ", disableJdkLogger=" + disableJdkLogger + ", maxCount=" + maxCount + ", userExclusionAttributes=" + + userExclusionAttributes + ", userMandatoryAttributes=" + userMandatoryAttributes + + ", agamaConfiguration=" + agamaConfiguration + ", auditLogConf=" + auditLogConf + + ", dataFormatConversionConf=" + dataFormatConversionConf + ", plugins=" + plugins + + ", assetMgtConfiguration=" + assetMgtConfiguration + "]"; + } + } diff --git a/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/AssetDirMapping.java b/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/AssetDirMapping.java new file mode 100644 index 00000000000..856ecfc02bd --- /dev/null +++ b/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/AssetDirMapping.java @@ -0,0 +1,53 @@ +package io.jans.configapi.model.configuration; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class AssetDirMapping { + + /** + * Relative path to asset base directory + */ + private String directory; + + /** + * List of file extention that are stored in directory + */ + private List type; + + /** + * Description of assets stored in directory + */ + private String description; + + public String getDirectory() { + return directory; + } + + public void setDirectory(String directory) { + this.directory = directory; + } + + public List getType() { + return type; + } + + public void setType(List type) { + this.type = type; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @Override + public String toString() { + return "AssetDirMapping [directory=" + directory + ", type=" + type + ", description=" + description + "]"; + } + +} diff --git a/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/AssetMgtConfiguration.java b/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/AssetMgtConfiguration.java new file mode 100644 index 00000000000..05d96c06d25 --- /dev/null +++ b/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/AssetMgtConfiguration.java @@ -0,0 +1,69 @@ +package io.jans.configapi.model.configuration; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class AssetMgtConfiguration { + + /** + * Flag indicating if asset management functionality is enabled + */ + private boolean assetMgtEnabled; + + /** + * Flag indicating if asset upload to server is enabled + */ + private boolean assetServerUploadEnabled; + + /** + * Base directory on server to upload the asset + */ + private String assetBaseDirectory; + + /** + * Asset type mapped to server directory + */ + private List assetDirMapping; + + + public boolean isAssetMgtEnabled() { + return assetMgtEnabled; + } + + public void setAssetMgtEnabled(boolean assetMgtEnabled) { + this.assetMgtEnabled = assetMgtEnabled; + } + + public boolean isAssetServerUploadEnabled() { + return assetServerUploadEnabled; + } + + public void setAssetServerUploadEnabled(boolean assetServerUploadEnabled) { + this.assetServerUploadEnabled = assetServerUploadEnabled; + } + + public String getAssetBaseDirectory() { + return assetBaseDirectory; + } + + public void setAssetBaseDirectory(String assetBaseDirectory) { + this.assetBaseDirectory = assetBaseDirectory; + } + + public List getAssetDirMapping() { + return assetDirMapping; + } + + public void setAssetDirMapping(List assetDirMapping) { + this.assetDirMapping = assetDirMapping; + } + + @Override + public String toString() { + return "AssetMgtConfiguration [assetMgtEnabled=" + assetMgtEnabled + ", assetServerUploadEnabled=" + + assetServerUploadEnabled + ", assetBaseDirectory=" + assetBaseDirectory + ", assetDirMapping=" + + assetDirMapping + "]"; + } + +} diff --git a/jans-config-api/docs/jans-config-api-swagger.yaml b/jans-config-api/docs/jans-config-api-swagger.yaml index e1d90578d2e..855be6f6b3e 100644 --- a/jans-config-api/docs/jans-config-api-swagger.yaml +++ b/jans-config-api/docs/jans-config-api-swagger.yaml @@ -8090,6 +8090,8 @@ components: creationDate: type: string format: date-time + jansFilePath: + type: string jansModuleProperty: type: array items: @@ -8219,19 +8221,19 @@ components: type: string selected: type: boolean - userCanView: + whitePagesCanView: type: boolean - adminCanEdit: + adminCanAccess: type: boolean - userCanEdit: + userCanAccess: type: boolean - adminCanView: + userCanView: type: boolean - adminCanAccess: + adminCanView: type: boolean - userCanAccess: + userCanEdit: type: boolean - whitePagesCanView: + adminCanEdit: type: boolean baseDn: type: string @@ -9057,8 +9059,6 @@ components: type: boolean lockMessageConfig: $ref: '#/components/schemas/LockMessageConfig' - fapi: - type: boolean allResponseTypesSupported: uniqueItems: true type: array @@ -9068,6 +9068,8 @@ components: - code - token - id_token + fapi: + type: boolean AuthenticationFilter: required: - baseDn @@ -9865,8 +9867,6 @@ components: type: boolean disableAuditLogger: type: boolean - assetMgtEnabled: - type: boolean customAttributeValidationEnabled: type: boolean apiApprovedIssuer: @@ -9930,6 +9930,32 @@ components: type: array items: $ref: '#/components/schemas/PluginConf' + assetMgtConfiguration: + $ref: '#/components/schemas/AssetMgtConfiguration' + AssetDirMapping: + type: object + properties: + directory: + type: string + type: + type: array + items: + type: string + description: + type: string + AssetMgtConfiguration: + type: object + properties: + assetMgtEnabled: + type: boolean + assetServerUploadEnabled: + type: boolean + assetBaseDirectory: + type: string + assetDirMapping: + type: array + items: + $ref: '#/components/schemas/AssetDirMapping' AuditLogConf: type: object properties: @@ -10523,10 +10549,10 @@ components: ttl: type: integer format: int32 - opbrowserState: - type: string persisted: type: boolean + opbrowserState: + type: string SessionIdAccessMap: type: object properties: diff --git a/jans-config-api/mvn b/jans-config-api/mvn new file mode 100644 index 00000000000..e69de29bb2d diff --git a/jans-config-api/plugins/docs/kc-saml-plugin-swagger.yaml b/jans-config-api/plugins/docs/kc-saml-plugin-swagger.yaml index 2e3f092dddc..97ff0349824 100644 --- a/jans-config-api/plugins/docs/kc-saml-plugin-swagger.yaml +++ b/jans-config-api/plugins/docs/kc-saml-plugin-swagger.yaml @@ -1047,6 +1047,10 @@ components: type: string idpUrl: type: string + extIDPTokenUrl: + type: string + extIDPRedirectUrl: + type: string idpMetadataImportUrl: type: string idpRootDir: diff --git a/jans-config-api/plugins/kc-saml-plugin/src/main/java/io/jans/configapi/plugin/saml/model/IdentityProvider.java b/jans-config-api/plugins/kc-saml-plugin/src/main/java/io/jans/configapi/plugin/saml/model/IdentityProvider.java index 80b1ca7b75a..3ea977d613e 100644 --- a/jans-config-api/plugins/kc-saml-plugin/src/main/java/io/jans/configapi/plugin/saml/model/IdentityProvider.java +++ b/jans-config-api/plugins/kc-saml-plugin/src/main/java/io/jans/configapi/plugin/saml/model/IdentityProvider.java @@ -81,25 +81,25 @@ public class IdentityProvider extends Entry implements Serializable { private String providerId; @AttributeName - protected boolean trustEmail; + private boolean trustEmail; @AttributeName - protected boolean storeToken; + private boolean storeToken; @AttributeName - protected boolean addReadTokenRoleOnCreate; + private boolean addReadTokenRoleOnCreate; @AttributeName - protected boolean authenticateByDefault; + private boolean authenticateByDefault; @AttributeName - protected boolean linkOnly; + private boolean linkOnly; @AttributeName - protected String firstBrokerLoginFlowAlias; + private String firstBrokerLoginFlowAlias; @AttributeName - protected String postBrokerLoginFlowAlias; + private String postBrokerLoginFlowAlias; @AttributeName(name = "jansSAMLspMetaDataFN") @Hidden diff --git a/jans-config-api/plugins/kc-saml-plugin/src/main/java/io/jans/configapi/plugin/saml/model/config/SamlAppConfiguration.java b/jans-config-api/plugins/kc-saml-plugin/src/main/java/io/jans/configapi/plugin/saml/model/config/SamlAppConfiguration.java index 5a83ac65232..6271feca0f4 100644 --- a/jans-config-api/plugins/kc-saml-plugin/src/main/java/io/jans/configapi/plugin/saml/model/config/SamlAppConfiguration.java +++ b/jans-config-api/plugins/kc-saml-plugin/src/main/java/io/jans/configapi/plugin/saml/model/config/SamlAppConfiguration.java @@ -25,6 +25,8 @@ public class SamlAppConfiguration implements Configuration { private String spMetadataUrl; private String tokenUrl; private String idpUrl; + private String extIDPTokenUrl; + private String extIDPRedirectUrl; private String idpMetadataImportUrl; private String idpRootDir; @@ -170,6 +172,22 @@ public void setIdpUrl(String idpUrl) { this.idpUrl = idpUrl; } + public String getExtIDPTokenUrl() { + return extIDPTokenUrl; + } + + public void setExtIDPTokenUrl(String extIDPTokenUrl) { + this.extIDPTokenUrl = extIDPTokenUrl; + } + + public String getExtIDPRedirectUrl() { + return extIDPRedirectUrl; + } + + public void setExtIDPRedirectUrl(String extIDPRedirectUrl) { + this.extIDPRedirectUrl = extIDPRedirectUrl; + } + public String getIdpMetadataImportUrl() { return idpMetadataImportUrl; } @@ -201,7 +219,7 @@ public String getIdpMetadataTempDir() { public void setIdpMetadataTempDir(String idpMetadataTempDir) { this.idpMetadataTempDir = idpMetadataTempDir; } - + public String getIdpMetadataFile() { return idpMetadataFile; } @@ -271,9 +289,10 @@ public String toString() { return "SamlAppConfiguration [applicationName=" + applicationName + ", samlTrustRelationshipDn=" + samlTrustRelationshipDn + ", trustedIdpDn=" + trustedIdpDn + ", enabled=" + enabled + ", selectedIdp=" + selectedIdp + ", serverUrl=" + serverUrl + ", realm=" + realm + ", clientId=" + clientId - + ", grantType=" + grantType + ", scope=" + scope + ", username=" - + username + ", spMetadataUrl=" + spMetadataUrl + ", tokenUrl=" + tokenUrl - + ", idpUrl=" + idpUrl + ", idpMetadataImportUrl=" + idpMetadataImportUrl + ", idpRootDir=" + idpRootDir + + ", clientSecret=" + clientSecret + ", grantType=" + grantType + ", scope=" + scope + ", username=" + + username + ", spMetadataUrl=" + spMetadataUrl + ", tokenUrl=" + tokenUrl + + ", idpUrl=" + idpUrl + ", extIDPTokenUrl=" + extIDPTokenUrl + ", extIDPRedirectUrl=" + + extIDPRedirectUrl + ", idpMetadataImportUrl=" + idpMetadataImportUrl + ", idpRootDir=" + idpRootDir + ", idpMetadataDir=" + idpMetadataDir + ", idpMetadataTempDir=" + idpMetadataTempDir + ", idpMetadataFile=" + idpMetadataFile + ", spMetadataDir=" + spMetadataDir + ", spMetadataTempDir=" + spMetadataTempDir + ", spMetadataFile=" + spMetadataFile + ", ignoreValidation=" + ignoreValidation diff --git a/jans-config-api/plugins/kc-saml-plugin/src/main/java/io/jans/configapi/plugin/saml/service/SamlConfigService.java b/jans-config-api/plugins/kc-saml-plugin/src/main/java/io/jans/configapi/plugin/saml/service/SamlConfigService.java index 833b34e7dfd..30efa4a995c 100644 --- a/jans-config-api/plugins/kc-saml-plugin/src/main/java/io/jans/configapi/plugin/saml/service/SamlConfigService.java +++ b/jans-config-api/plugins/kc-saml-plugin/src/main/java/io/jans/configapi/plugin/saml/service/SamlConfigService.java @@ -214,6 +214,34 @@ public String getIdpUrl(String realm) { logger.debug("SAML IDP Url - idpUrl:{}", idpUrl); return idpUrl; } + + public String getExtIDPTokenUrl(String realm, String idpAliasName ) { + logger.debug("Get SAML External IDP Url - realm:{}, idpAliasName:{}", realm, idpAliasName); + final SamlConf samlConf = getSamlConf(); + SamlAppConfiguration samlAppConfiguration = samlConf.getDynamicConf(); + String extIDPTokenUrl = null; + if (samlAppConfiguration != null) { + StringBuilder sb = new StringBuilder(); + sb.append(samlAppConfiguration.getServerUrl()).append(samlAppConfiguration.getExtIDPTokenUrl()); + extIDPTokenUrl = String.format(sb.toString(), realm, idpAliasName); + } + logger.debug("SAML Ext IDP Url - extIDPTokenUrl:{}", extIDPTokenUrl); + return extIDPTokenUrl; + } + + public String getExtIDPRedirectUrl(String realm, String clientId, String redirectUrl, String responseType, String idpAliasName ) { + logger.debug("Get SAML External IDP Redirect Url - realm:{}, clientId:{}, redirectUrl:{}, responseType:{}, idpAliasName:{}", realm, clientId, redirectUrl, responseType, idpAliasName); + final SamlConf samlConf = getSamlConf(); + SamlAppConfiguration samlAppConfiguration = samlConf.getDynamicConf(); + String extIDPRedirectUrl = null; + if (samlAppConfiguration != null) { + StringBuilder sb = new StringBuilder(); + sb.append(samlAppConfiguration.getServerUrl()).append(samlAppConfiguration.getExtIDPRedirectUrl()); + extIDPRedirectUrl = String.format(sb.toString(), realm, clientId, redirectUrl, responseType, idpAliasName); + } + logger.debug("SAML External IDP Redirect - extIDPRedirectUrl:{}", extIDPRedirectUrl); + return extIDPRedirectUrl; + } public String getIdpMetadataImportUrl(String realm) { logger.debug("Get SAML IDP Metadata Import Url - realm:{}", realm); diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/configuration/AppInitializer.java b/jans-config-api/server/src/main/java/io/jans/configapi/configuration/AppInitializer.java index 8d56bcd90dc..cdad0125a01 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/configuration/AppInitializer.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/configuration/AppInitializer.java @@ -8,6 +8,7 @@ import io.jans.as.common.service.common.ApplicationFactory; import io.jans.configapi.model.configuration.ApiAppConfiguration; +import io.jans.configapi.model.configuration.AssetMgtConfiguration; import io.jans.configapi.security.api.ApiProtectionService; import io.jans.configapi.security.service.AuthorizationService; import io.jans.configapi.security.service.OpenIdAuthorizationService; @@ -136,6 +137,12 @@ public ConfigurationFactory getConfigurationFactory() { return configurationFactory; } + @Produces + @ApplicationScoped + public AssetMgtConfiguration getAssetMgtConfiguration() { + return this.configurationFactory.getApiAppConfiguration().getAssetMgtConfiguration(); + } + @Produces @ApplicationScoped @Named(ApplicationFactory.PERSISTENCE_ENTRY_MANAGER_NAME) diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/ApiApplication.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/ApiApplication.java index 88d48f9733c..868c6d95a04 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/ApiApplication.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/ApiApplication.java @@ -158,7 +158,7 @@ public Set> getClasses() { classes.add(ClientAuthResource.class); log.info("appConfiguration:{}",appConfiguration ); - if(appConfiguration!=null && appConfiguration.isAssetMgtEnabled()) { + if(appConfiguration!=null && appConfiguration.getAssetMgtConfiguration()!=null && appConfiguration.getAssetMgtConfiguration().isAssetMgtEnabled()) { classes.add(AssetResource.class); } diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AssetResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AssetResource.java index 49390e0f913..115fe197393 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AssetResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AssetResource.java @@ -44,8 +44,6 @@ import org.slf4j.Logger; import org.jboss.resteasy.annotations.providers.multipart.MultipartForm; -import io.swagger.v3.oas.annotations.Hidden; - @Path(ApiConstants.JANS_ASSETS) @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @@ -154,34 +152,6 @@ public Response getAssetByName( return Response.ok(assets).build(); } - @Hidden - @Operation(summary = "Fetch asset stream by name.", description = "Fetch asset stream by name.", operationId = "get-asset-stream-by-name", tags = { - "Jans Assets" }, security = @SecurityRequirement(name = "oauth2", scopes = { - ApiAccessConstants.JANS_ASSET_READ_ACCESS })) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Ok", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = PagedResult.class), examples = @ExampleObject(name = "Response example", value = "example/assets/get-asset-by-name.json"))), - @ApiResponse(responseCode = "401", description = "Unauthorized"), - @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = ApiError.class, description = "NotFoundException"))), - @ApiResponse(responseCode = "500", description = "InternalServerError", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = ApiError.class, description = "InternalServerError"))) }) - @GET - @Path(ApiConstants.STREAM + ApiConstants.NAME_PARAM_PATH) - @Produces(MediaType.APPLICATION_OCTET_STREAM) - @ProtectedApi(scopes = { ApiAccessConstants.JANS_ASSET_WRITE_ACCESS }) - public Response getAssetStreamByName( - @Parameter(description = "Asset Name") @PathParam(ApiConstants.NAME) @NotNull String name) { - - log.info("Fetch asset stream identified by name:{} ", name); - InputStream assetStream = null; - try { - assetStream = assetService.readAssetStream(name); - log.debug(" Fetched assetStream:{} ", assetStream); - } catch (Exception ex) { - log.error("Application Error while reading asset stream is - status:{}", ex.getMessage()); - throwInternalServerException(APPLICATION_ERROR, ex); - } - return Response.status(Response.Status.OK).entity(assetStream).build(); - } - @Operation(summary = "Upload new asset", description = "Upload new asset", operationId = "post-new-asset", tags = { "Jans Assets" }, security = @SecurityRequirement(name = "oauth2", scopes = { ApiAccessConstants.JANS_ASSET_WRITE_ACCESS })) diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/AssetService.java b/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/AssetService.java index ceabc2f4b11..d45361176f0 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/AssetService.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/service/auth/AssetService.java @@ -12,6 +12,9 @@ import io.jans.as.common.service.common.ApplicationFactory; import io.jans.as.common.util.AttributeConstants; +import io.jans.configapi.model.configuration.ApiAppConfiguration; +import io.jans.configapi.model.configuration.AssetDirMapping; +import io.jans.configapi.model.configuration.AssetMgtConfiguration; import io.jans.configapi.util.ApiConstants; import io.jans.configapi.util.AuthUtil; import io.jans.model.SearchRequest; @@ -31,6 +34,7 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.util.Optional; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -38,6 +42,7 @@ import jakarta.ws.rs.NotFoundException; import jakarta.ws.rs.WebApplicationException; import org.apache.commons.codec.binary.Base64InputStream; +import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; @@ -63,6 +68,9 @@ public class AssetService { @Inject DBDocumentService dbDocumentService; + @Inject + private ApiAppConfiguration appConfiguration; + public String getDnForAsset(String inum) throws Exception { return dbDocumentService.getDnForDocument(inum); } @@ -149,7 +157,7 @@ public Document saveAsset(Document asset, InputStream documentStream) throws Exc ByteArrayOutputStream bos = getByteArrayOutputStream(documentStream); log.trace("Asset ByteArrayOutputStream :{}", bos); - //get asset + // get asset try (InputStream is = new Base64InputStream(getInputStream(bos), true)) { asset = setAssetContent(asset, is); } @@ -169,15 +177,15 @@ public Document saveAsset(Document asset, InputStream documentStream) throws Exc } // copy asset on jans-server - try (InputStream ins = getInputStream(bos)) { - String result = copyAssetOnServer(asset, ins); + if (isAssetServerUploadEnabled()) { + String result = copyAssetOnServer(asset, bos); log.info("Result of asset saved on server :{}", result); - } + } // Get final asset asset = this.getAssetByInum(asset.getInum()); - + log.info("\n * Asset successfully saved :{}", asset); return asset; } @@ -207,34 +215,7 @@ public boolean removeAsset(String inum) throws Exception { return status; } - public InputStream readAssetStream(String assetName) throws Exception { - log.info("Read asset stream from server - assetName:{}", assetName); - String filePath = null; - - if (StringUtils.isBlank(assetName)) { - throw new InvalidConfigurationException("Asset name is null!"); - } - - List assets = this.getAssetByName(assetName); - log.info("assets{} identified by assetName:{}", assets, assetName); - - if (assets == null || assets.isEmpty()) { - throw new NotFoundException("Cannot find asset identified by - " + assetName); - } - - Document asset = assets.get(0); - String assetPath = asset.getDescription(); - filePath = assetPath + File.separator + assetName; - log.info("documentStoreService:{}, filePath:{}", documentStoreService, filePath); - - InputStream stream = dBDocumentStoreProvider.readDocumentAsStream(filePath); - log.info("Read asset stream:{}", stream); - - return stream; - - } - - private Document setAssetContent(Document asset, InputStream documentStream) throws Exception { + private Document setAssetContent(Document asset, InputStream documentStream) throws IOException { log.info(" an asset - asset:{}, documentStream:{}", asset, documentStream); if (asset == null) { throw new InvalidAttributeException(" Asset object is null!!!"); @@ -254,37 +235,6 @@ private Document setAssetContent(Document asset, InputStream documentStream) thr return asset; } - private boolean deleteAssetFromServer(Document asset) { - log.info("Delete asset - asset:{}", asset); - boolean deleteStatus = false; - if (asset == null) { - return deleteStatus; - } - - String path = asset.getDescription(); - String fileName = asset.getDisplayName(); - String documentStoreModuleName = fileName; - log.info("path:{}, fileName:{}, documentStoreModuleName:{}", path, fileName, documentStoreModuleName); - - if (StringUtils.isBlank(path)) { - throw new InvalidConfigurationException("Path to delete the asset is null!"); - } - - if (StringUtils.isBlank(fileName)) { - throw new InvalidConfigurationException("Name of asset to be deleted is null!"); - } - - if (documentStoreService == null) { - throw new InvalidConfigurationException("document Store Service is null!"); - } - - String filePath = path + File.separator + fileName; - log.info("documentStoreService:{}, filePath:{} ", documentStoreService, filePath); - deleteStatus = documentStoreService.removeDocument(filePath); - log.info("Asset deletion status:{}", deleteStatus); - return deleteStatus; - } - private Document updateRevision(Document asset) { log.debug("Update asset revision - asset:{}", asset); try { @@ -309,7 +259,7 @@ private Document updateRevision(Document asset) { return asset; } - private String copyAssetOnServer(Document asset, InputStream stream) { + private String copyAssetOnServer(Document asset, ByteArrayOutputStream stream) throws IOException { log.info("Copy asset on server - asset:{}, stream:{}", asset, stream); String result = null; @@ -321,26 +271,80 @@ private String copyAssetOnServer(Document asset, InputStream stream) { throw new InvalidConfigurationException("Asset stream is null!"); } - String path = asset.getDescription(); - String fileName = asset.getDisplayName(); - String documentStoreModuleName = fileName; - log.info("path:{}, fileName:{}, documentStoreModuleName:{}", path, fileName, documentStoreModuleName); + List serviceModules = asset.getJansModuleProperty(); + String assetFileName = asset.getDisplayName(); + String documentStoreModuleName = assetFileName; + log.info("Save asset for - serviceModules:{}, assetFileName:{}", serviceModules, assetFileName); + + if (StringUtils.isBlank(assetFileName)) { + throw new InvalidConfigurationException("Asset name is null!"); + } + + String assetDir = this.getAssetDir(assetFileName); + log.info("For saving assetFileName:{} assetDir:{}", assetFileName, assetDir); + + for (String serviceName : serviceModules) { + + String serviceDirectory = this.getServiceDirectory(assetDir, serviceName); + log.info("Save asset for - serviceName:{} in serviceDirectory:{}", serviceName, serviceDirectory); + + if (StringUtils.isBlank(serviceDirectory)) { + throw new InvalidConfigurationException("Service directory to save asset is null!"); + } + + String filePath = serviceDirectory + File.separator + assetFileName; + log.info("To save asset - documentStoreService:{}, filePath:{} ", documentStoreService, filePath); + + try (InputStream ins = getInputStream(stream)) { + result = documentStoreService.saveDocumentStream(filePath, null, ins, List.of(documentStoreModuleName)); + log.info("Result of asset saved on server :{}", result); + } + + } + return result; + + } - if (StringUtils.isBlank(path)) { - throw new InvalidConfigurationException("Path to copy the asset is null!"); + private boolean deleteAssetFromServer(Document asset) { + log.info("Delete asset - asset:{}", asset); + boolean deleteStatus = false; + if (asset == null) { + return deleteStatus; } - if (StringUtils.isBlank(fileName)) { + List serviceModules = asset.getJansModuleProperty(); + String assetFileName = asset.getDisplayName(); + + log.info("Asset to be deleted for serviceModules:{}, assetFileName:{}", serviceModules, assetFileName); + + if (StringUtils.isBlank(assetFileName)) { throw new InvalidConfigurationException("Asset name is null!"); } - String filePath = path + File.separator + fileName; - log.info("documentStoreService:{}, filePath:{}", documentStoreService, filePath); - result = documentStoreService.saveDocumentStream(filePath, null, stream, List.of(documentStoreModuleName)); - log.info("Asset saving result:{}", result); + String assetDir = this.getAssetDir(assetFileName); + log.info("For removing assetFileName:{} assetDir:{}", assetFileName, assetDir); - return result; + for (String serviceName : serviceModules) { + String serviceDirectory = this.getServiceDirectory(assetDir, serviceName); + log.info("Delete asset from - assetDir:{}, serviceDirectory:{}", assetDir, serviceDirectory); + + if (StringUtils.isBlank(serviceDirectory)) { + throw new InvalidConfigurationException("Service directory to save asset is null!"); + } + String filePath = serviceDirectory + File.separator + assetFileName; + try { + log.info("To delete asset - documentStoreService:{}, filePath:{} ", documentStoreService, filePath); + deleteStatus = documentStoreService.removeDocument(filePath); + log.info("Asset deletion status:{}", deleteStatus); + } catch (Exception ex) { + log.error("Error while deleting asset:{} with fileName:{} from server is:{}", asset.getInum(), + assetFileName, ex); + } + + } + + return deleteStatus; } private ByteArrayOutputStream getByteArrayOutputStream(InputStream input) throws IOException { @@ -351,4 +355,73 @@ private InputStream getInputStream(ByteArrayOutputStream bos) { return authUtil.getInputStream(bos); } + private boolean isAssetServerUploadEnabled() { + return this.appConfiguration.getAssetMgtConfiguration().isAssetServerUploadEnabled(); + } + + private String getAssetDir(String assetFileName) { + log.info("Get asset directory assetFileName:{}", assetFileName); + StringBuilder sb = new StringBuilder(); + + if (StringUtils.isBlank(assetFileName) || this.appConfiguration == null + || this.appConfiguration.getAssetMgtConfiguration() == null) { + return sb.toString(); + } + + AssetMgtConfiguration assetMgtConfiguration = this.appConfiguration.getAssetMgtConfiguration(); + sb.append(assetMgtConfiguration.getAssetBaseDirectory()); + String assetDir = getAssetDirectory(assetFileName); + + log.info("assetMgtConfiguration:{}, sb:{}, assetDir:{}", assetMgtConfiguration, sb, assetDir); + if (StringUtils.isNotBlank(assetDir)) { + sb.append(File.separator); + sb.append(assetDir); + } + + return sb.toString(); + } + + private String getServiceDirectory(String assetDir, String serviceName) { + + log.info("Get service directory assetDir:{}, serviceName:{}", assetDir, serviceName); + + String path = null; + if (StringUtils.isBlank(assetDir) || StringUtils.isBlank(serviceName)) { + return path; + } + path = String.format(assetDir, serviceName); + + return path; + + } + + private String getAssetDirectory(String assetFileName) { + log.info("Get asset Directory for assetFileName:{}", assetFileName); + + String directory = null; + if (StringUtils.isBlank(assetFileName) || this.appConfiguration == null + || this.appConfiguration.getAssetMgtConfiguration() == null) { + return directory; + } + + List dirMapping = this.appConfiguration.getAssetMgtConfiguration().getAssetDirMapping(); + log.info("Get asset Directory - dirMapping:{}", dirMapping); + if (dirMapping == null || dirMapping.isEmpty()) { + return directory; + } + String fileExtension = FilenameUtils.getExtension(assetFileName); + log.info("Get asset Directory - fileExtension:{}", fileExtension); + + Optional assetDirMapping = dirMapping.stream().filter(e -> e.getType().contains(fileExtension)) + .findFirst(); + log.info("Get asset Directory - assetDirMapping.isPresent():{}", assetDirMapping.isPresent()); + + if (assetDirMapping.isEmpty()) { + return directory; + } + + directory = assetDirMapping.get().getDirectory(); + return directory; + } + } diff --git a/jans-linux-setup/jans_setup/templates/jans-config-api/dynamic-conf.json b/jans-linux-setup/jans_setup/templates/jans-config-api/dynamic-conf.json index 2f8ff69da0d..42b2fb162df 100644 --- a/jans-linux-setup/jans_setup/templates/jans-config-api/dynamic-conf.json +++ b/jans-linux-setup/jans_setup/templates/jans-config-api/dynamic-conf.json @@ -3,7 +3,6 @@ "disableLoggerTimer": false, "disableAuditLogger": false, "customAttributeValidationEnabled": true, - "assetMgtEnabled": true, "apiApprovedIssuer": ["${apiApprovedIssuer}"], "apiProtectionType": "${apiProtectionType}", "apiClientId": "${jca_client_id}", @@ -71,6 +70,46 @@ "@jakarta.ws.rs.GET()" ] }, + "assetMgtConfiguration": { + "assetMgtEnabled": true, + "assetServerUploadEnabled": true, + "assetBaseDirectory": "/opt/jans/jetty/%s/custom", + "assetDirMapping": [ + { + "directory": "i18n", + "type": [ + "properties" + ], + "description": "Resource bundle file." + }, + { + "directory": "libs", + "type": [ + "jar" + ], + "description": "java archive library." + }, + { + "directory": "pages", + "type": [ + "xhtml" + ], + "description": "Web pages." + }, + { + "directory": "static", + "type": [ + "js", + "css", + "png", + "gif", + "jpg", + "jpeg" + ], + "description": "Static resources like Java-script, style-sheet and images." + } + ] + }, "plugins": [ { "name": "admin", diff --git a/jans-linux-setup/jans_setup/templates/jans-saml/jans-saml-config.json b/jans-linux-setup/jans_setup/templates/jans-saml/jans-saml-config.json index 8d0dc20c00f..d4b6002162c 100644 --- a/jans-linux-setup/jans_setup/templates/jans-saml/jans-saml-config.json +++ b/jans-linux-setup/jans_setup/templates/jans-saml/jans-saml-config.json @@ -15,6 +15,8 @@ "spMetadataUrl":"/realms/%s/broker/%s/endpoint/descriptor", "tokenUrl":"/realms/%s/protocol/openid-connect/token", "idpUrl":"/admin/realms/%s/identity-provider/instances", + "extIDPTokenUrl": "/realms/%s/broker/%s/token", + "extIDPRedirectUrl": "/kc/realms/%s/protocol/openid-connect/auth?client_id=%s&redirect_uri=%s&response_type=%s&kc_idp_hint=%s", "idpMetadataImportUrl":"/admin/realms/%s/identity-provider/import-config", "idpRootDir":"/opt/jans/idp/", "idpMetadataDir":"/opt/idp/configs/keycloak/idp/metadata",