From a87b75bb257b00f71ba643bc81ed110e0c914b79 Mon Sep 17 00:00:00 2001 From: pujavs <43700552+pujavs@users.noreply.github.com> Date: Tue, 10 Jan 2023 22:53:29 +0530 Subject: [PATCH] feat(config-api): data conversion, audit log and swagger enhancement (#3588) * feat(config-api): interceptor code * feat(config-api): interceptor for request * feat(config-api): interceptor code wip * feat(config-api): interceptor code wip * feat(config-api): syns with main * feat(config-api): client creation claim enhancement * feat(config-api): client creation claim enhancement * fix: jans-linux-setup opPolicyUri and opTosUri (#3411) * feat(config-api): autit log enhancement * feat(config-api): interceptor code * feat(config-api): datatype conversion wip * feat(config-api): data conversion wip * feat(config-api): datatype conversion * feat(config-api): datatype conversion * feat(config-api): data conversion code * feat(config-api): data conversion code * feat(config-api): date conversion code * feat(config-api): date conversion code * feat(config-api): audit log enhancement * feat(config-api): request interceptor * feat(config-api): date data conversion * feat(config-api): swagger spec * feat(config-api): swagger update for param desc * feat(config-api): data conversion * feat(config-api): data conversion, audit log and swagger enhancement Co-authored-by: Devrim --- .../configuration/ApiAppConfiguration.java | 10 + .../model/configuration/AuditLogConf.java | 18 +- .../configuration/ConversionAttributes.java | 42 +++ .../DataFormatConversionConf.java | 41 +++ .../docs/jans-config-api-swagger-auto.yaml | 102 ++++++- .../rest/user/UserManagementResource.java | 13 +- .../plugins/docs/fido2-plugin-swagger.yaml | 1 + .../docs/jans-admin-ui-plugin-swagger.yaml | 6 + .../plugins/docs/user-mgt-plugin-swagger.yaml | 9 + .../fido2/rest/Fido2RegistrationResource.java | 3 +- .../plugin/mgt/rest/UserResource.java | 17 +- .../test/resources/feature/mgt/user/user.json | 9 - .../profiles/local/test.properties | 8 +- .../interceptor/AuditLogInterceptor.java | 50 ++- .../interceptor/RequestReaderInterceptor.java | 287 ++++++++++++++++++ .../rest/resource/auth/AgamaResource.java | 28 +- .../resource/auth/AttributesResource.java | 19 +- .../rest/resource/auth/ClientsResource.java | 17 +- .../resource/auth/CustomScriptResource.java | 31 +- .../rest/resource/auth/JwksResource.java | 7 +- .../auth/LdapConfigurationResource.java | 5 +- .../rest/resource/auth/ScopesResource.java | 25 +- .../rest/resource/auth/SessionResource.java | 3 +- .../rest/resource/auth/StatResource.java | 9 +- .../resource/auth/UmaResourcesResource.java | 19 +- .../java/io/jans/configapi/util/AuthUtil.java | 21 ++ .../src/main/resources/META-INF/beans.xml | 3 +- .../configapi/core/rest/BaseResource.java | 9 +- .../jans-config-api/dynamic-conf.json | 15 +- .../io/jans/orm/PersistenceEntryManager.java | 2 + .../io/jans/orm/impl/BaseEntryManager.java | 2 +- 31 files changed, 703 insertions(+), 128 deletions(-) create mode 100644 jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/ConversionAttributes.java create mode 100644 jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/DataFormatConversionConf.java create mode 100644 jans-config-api/server/src/main/java/io/jans/configapi/interceptor/RequestReaderInterceptor.java 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 2814b8a703b..f14478a49b7 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 @@ -37,6 +37,7 @@ public class ApiAppConfiguration implements Configuration { private List userMandatoryAttributes; private AgamaConfiguration agamaConfiguration; private AuditLogConf auditLogConf; + private DataFormatConversionConf dataFormatConversionConf; public boolean isConfigOauthEnabled() { return configOauthEnabled; @@ -239,6 +240,14 @@ public AuditLogConf getAuditLogConf() { public void setAuditLogConf(AuditLogConf auditLogConf) { this.auditLogConf = auditLogConf; } + + public DataFormatConversionConf getDataFormatConversionConf() { + return dataFormatConversionConf; + } + + public void setDataFormatConversionConf(DataFormatConversionConf dataFormatConversionConf) { + this.dataFormatConversionConf = dataFormatConversionConf; + } @Override public String toString() { @@ -256,6 +265,7 @@ public String toString() { + " , userMandatoryAttributes="+ userMandatoryAttributes + " , agamaConfiguration="+ agamaConfiguration + " , auditLogConf="+ auditLogConf + + " , dataFormatConversionConf="+ dataFormatConversionConf + "]"; } diff --git a/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/AuditLogConf.java b/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/AuditLogConf.java index c5e6f3d061e..d54a74728b3 100644 --- a/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/AuditLogConf.java +++ b/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/AuditLogConf.java @@ -1,6 +1,8 @@ package io.jans.configapi.model.configuration; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import java.util.Collection; import java.util.List; @JsonIgnoreProperties(ignoreUnknown = true) @@ -11,6 +13,11 @@ public class AuditLogConf { */ private boolean enabled; + /** + * HTTP methods for which audit is disabled + */ + private Collection ignoreHttpMethod; + /** * List of header attributes */ @@ -24,6 +31,14 @@ public void setEnabled(boolean enabled) { this.enabled = enabled; } + public Collection getIgnoreHttpMethod() { + return ignoreHttpMethod; + } + + public void setIgnoreHttpMethod(Collection ignoreHttpMethod) { + this.ignoreHttpMethod = ignoreHttpMethod; + } + public List getHeaderAttributes() { return headerAttributes; } @@ -34,7 +49,8 @@ public void setHeaderAttributes(List headerAttributes) { @Override public String toString() { - return "AuditLogConf [enabled=" + enabled + ", headerAttributes=" + headerAttributes + "]"; + return "AuditLogConf [enabled=" + enabled + ", ignoreHttpMethod=" + ignoreHttpMethod + ", headerAttributes=" + + headerAttributes + "]"; } } diff --git a/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/ConversionAttributes.java b/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/ConversionAttributes.java new file mode 100644 index 00000000000..c6e3f2453c2 --- /dev/null +++ b/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/ConversionAttributes.java @@ -0,0 +1,42 @@ +package io.jans.configapi.model.configuration; + +import java.util.Collection; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ConversionAttributes { + + /** + * Date attributes for conversion + */ + private Collection dateAttributes; + + /** + * boolean attributes for conversion + */ + private Collection booleanAttributes; + + public Collection getDateAttributes() { + return dateAttributes; + } + + public void setDateAttributes(Collection dateAttributes) { + this.dateAttributes = dateAttributes; + } + + public Collection getBooleanAttributes() { + return booleanAttributes; + } + + public void setBooleanAttributes(Collection booleanAttributes) { + this.booleanAttributes = booleanAttributes; + } + + @Override + public String toString() { + return "ConversionAttributes [dateAttributes=" + dateAttributes + ", booleanAttributes=" + booleanAttributes + + "]"; + } + +} diff --git a/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/DataFormatConversionConf.java b/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/DataFormatConversionConf.java new file mode 100644 index 00000000000..b986d6a9d76 --- /dev/null +++ b/jans-config-api/common/src/main/java/io/jans/configapi/model/configuration/DataFormatConversionConf.java @@ -0,0 +1,41 @@ +package io.jans.configapi.model.configuration; + +import java.util.Collection; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class DataFormatConversionConf { + + /** + * Flag to enable and disable data conversion + */ + private boolean enabled; + + /** + * HTTP methods for which data conversion is to be disabled + */ + private Collection ignoreHttpMethod; + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public Collection getIgnoreHttpMethod() { + return ignoreHttpMethod; + } + + public void setIgnoreHttpMethod(Collection ignoreHttpMethod) { + this.ignoreHttpMethod = ignoreHttpMethod; + } + + @Override + public String toString() { + return "DataFormatConversionConf [enabled=" + enabled + ", ignoreHttpMethod=" + ignoreHttpMethod + "]"; + } + +} diff --git a/jans-config-api/docs/jans-config-api-swagger-auto.yaml b/jans-config-api/docs/jans-config-api-swagger-auto.yaml index 59b1f008f08..38064fd0104 100644 --- a/jans-config-api/docs/jans-config-api-swagger-auto.yaml +++ b/jans-config-api/docs/jans-config-api-swagger-auto.yaml @@ -326,33 +326,40 @@ paths: parameters: - name: pattern in: query + description: Search pattern schema: type: string default: "" - name: limit in: query + description: Search size - max size of the results to return schema: type: integer format: int32 default: 50 - name: startIndex in: query + description: The 1-based index of the first query result schema: type: integer format: int32 default: 0 - name: sortBy in: query + description: Attribute whose value will be used to order the returned response schema: type: string default: agFlowQname - name: sortOrder in: query + description: Order in which the sortBy param is applied. Allowed values are + "ascending" and "descending" schema: type: string default: ascending - name: includeSource in: query + description: Boolean flag to indicate agama source is to be included schema: type: boolean default: false @@ -448,11 +455,13 @@ paths: parameters: - name: qname in: path + description: Agama Flow name required: true schema: type: string - name: includeSource in: query + description: Boolean flag to indicate agama source is to be included schema: type: boolean default: false @@ -495,6 +504,7 @@ paths: parameters: - name: qname in: path + description: Agama Flow name required: true schema: type: string @@ -544,6 +554,7 @@ paths: parameters: - name: qname in: path + description: Agama Flow name required: true schema: type: string @@ -568,6 +579,7 @@ paths: parameters: - name: qname in: path + description: Agama Flow name required: true schema: type: string @@ -619,6 +631,7 @@ paths: parameters: - name: qname in: path + description: Agama Flow name required: true schema: type: string @@ -653,6 +666,7 @@ paths: parameters: - name: qname in: path + description: Agama Flow name required: true schema: type: string @@ -703,33 +717,40 @@ paths: parameters: - name: limit in: query + description: Search size - max size of the results to return schema: type: integer format: int32 default: 50 - name: pattern in: query + description: Search pattern schema: type: string default: "" - name: status in: query + description: Status of the attribute schema: type: string default: all - name: startIndex in: query + description: The 1-based index of the first query result schema: type: integer format: int32 default: 0 - name: sortBy in: query + description: Attribute whose value will be used to order the returned response schema: type: string default: inum - name: sortOrder in: query + description: Order in which the sortBy param is applied. Allowed values are + "ascending" and "descending" schema: type: string default: ascending @@ -1010,6 +1031,7 @@ paths: parameters: - name: inum in: path + description: Attribute Id required: true schema: type: string @@ -1073,6 +1095,7 @@ paths: parameters: - name: inum in: path + description: Attribute Id required: true schema: type: string @@ -1097,6 +1120,7 @@ paths: parameters: - name: inum in: path + description: Attribute Id required: true schema: type: string @@ -1789,27 +1813,33 @@ paths: parameters: - name: limit in: query + description: Search size - max size of the results to return schema: type: integer format: int32 default: 50 - name: pattern in: query + description: Search pattern schema: type: string default: "" - name: startIndex in: query + description: The 1-based index of the first query result schema: type: integer format: int32 default: 0 - name: sortBy in: query + description: Attribute whose value will be used to order the returned response schema: type: string - name: sortOrder in: query + description: Order in which the sortBy param is applied. Allowed values are + "ascending" and "descending" schema: type: string responses: @@ -2985,6 +3015,7 @@ paths: parameters: - name: inum in: path + description: Client identifier required: true schema: type: string @@ -3131,6 +3162,7 @@ paths: parameters: - name: inum in: path + description: Client identifier required: true schema: type: string @@ -3155,6 +3187,7 @@ paths: parameters: - name: inum in: path + description: Client identifier required: true schema: type: string @@ -3582,28 +3615,34 @@ paths: parameters: - name: limit in: query + description: Search size - max size of the results to return schema: type: integer format: int32 default: 50 - name: pattern in: query + description: Search pattern schema: type: string default: "" - name: startIndex in: query + description: The 1-based index of the first query result schema: type: integer format: int32 default: 0 - name: sortBy in: query + description: Attribute whose value will be used to order the returned response schema: type: string default: inum - name: sortOrder in: query + description: Order in which the sortBy param is applied. Allowed values are + "ascending" and "descending" schema: type: string default: ascending @@ -3838,6 +3877,7 @@ paths: parameters: - name: inum in: path + description: Script identifier required: true schema: type: string @@ -3862,6 +3902,7 @@ paths: parameters: - name: inum in: path + description: Script identifier required: true schema: type: string @@ -3905,6 +3946,7 @@ paths: parameters: - name: inum in: path + description: Script identifier required: true schema: type: string @@ -3960,6 +4002,7 @@ paths: parameters: - name: name in: path + description: Script name required: true schema: type: string @@ -4015,33 +4058,40 @@ paths: parameters: - name: type in: path + description: Script type required: true schema: type: string - name: limit in: query + description: Search size - max size of the results to return schema: type: integer format: int32 default: 50 - name: pattern in: query + description: Search pattern schema: type: string default: "" - name: startIndex in: query + description: The 1-based index of the first query result schema: type: integer format: int32 default: 0 - name: sortBy in: query + description: Attribute whose value will be used to order the returned response schema: type: string default: inum - name: sortOrder in: query + description: Order in which the sortBy param is applied. Allowed values are + "ascending" and "descending" schema: type: string default: ascending @@ -4128,6 +4178,7 @@ paths: parameters: - name: kid in: path + description: The unique identifier for the key required: true schema: type: string @@ -4170,6 +4221,7 @@ paths: parameters: - name: kid in: path + description: The unique identifier for the key required: true schema: type: string @@ -4194,6 +4246,7 @@ paths: parameters: - name: kid in: path + description: The unique identifier for the key required: true schema: type: string @@ -4685,6 +4738,7 @@ paths: parameters: - name: name in: path + description: Name of LDAP configuration required: true schema: type: string @@ -4762,6 +4816,7 @@ paths: parameters: - name: name in: path + description: Name of LDAP configuration required: true schema: type: string @@ -5030,36 +5085,45 @@ paths: parameters: - name: type in: query + description: Scope type schema: type: string default: "" - name: limit in: query + description: Search size - max size of the results to return schema: type: integer format: int32 default: 50 - name: pattern in: query + description: Search pattern schema: type: string default: "" - name: startIndex in: query + description: The 1-based index of the first query result schema: type: integer format: int32 default: 0 - name: sortBy in: query + description: Attribute whose value will be used to order the returned response schema: type: string - name: sortOrder in: query + description: Order in which the sortBy param is applied. Allowed values are + "ascending" and "descending" schema: type: string - name: withAssociatedClients in: query + description: Boolean fag to indicate if clients associated with the scope + are to be returned schema: type: boolean default: false @@ -5303,6 +5367,7 @@ paths: parameters: - name: inum in: path + description: Scope identifier required: true schema: type: string @@ -5681,6 +5746,7 @@ paths: parameters: - name: inum in: path + description: Scope identifier required: true schema: type: string @@ -5705,6 +5771,7 @@ paths: parameters: - name: inum in: path + description: Scope identifier required: true schema: type: string @@ -5774,6 +5841,8 @@ paths: parameters: - name: creatorId in: path + description: Id of the scope creator. If creator is client then client_id + if user then user_id required: true schema: type: string @@ -6148,6 +6217,7 @@ paths: parameters: - name: type in: path + description: Type of the scope required: true schema: type: string @@ -6548,6 +6618,7 @@ paths: parameters: - name: userDn in: path + description: User domain name required: true schema: type: string @@ -6574,22 +6645,29 @@ paths: parameters: - name: Authorization in: header + description: Authorization code schema: type: string - name: month in: query + description: Month for which the stat report is to be fetched. The parameter + is mandatory if start_month and end_month parameters are not present. schema: type: string + example: 202012 - name: start_month in: query + description: Start-Month for which the stat report is to be fetched schema: type: string - name: end_month in: query + description: End-Month for which the stat report is to be fetched schema: type: string - name: format in: query + description: Report format schema: type: string responses: @@ -6619,27 +6697,33 @@ paths: parameters: - name: limit in: query + description: Search size - max size of the results to return schema: type: integer format: int32 default: 50 - name: pattern in: query + description: Search pattern schema: type: string default: "" - name: startIndex in: query + description: The 1-based index of the first query result schema: type: integer format: int32 default: 0 - name: sortBy in: query + description: Attribute whose value will be used to order the returned response schema: type: string - name: sortOrder in: query + description: Order in which the sortBy param is applied. Allowed values are + "ascending" and "descending" schema: type: string responses: @@ -6845,6 +6929,7 @@ paths: parameters: - name: id in: path + description: Resource description ID required: true schema: type: string @@ -6891,6 +6976,7 @@ paths: parameters: - name: id in: path + description: Resource description ID required: true schema: type: string @@ -6915,6 +7001,7 @@ paths: parameters: - name: id in: path + description: Resource description ID required: true schema: type: string @@ -6974,6 +7061,7 @@ paths: parameters: - name: clientId in: path + description: Client ID required: true schema: type: string @@ -7299,11 +7387,11 @@ components: type: string whitePagesCanView: type: boolean - userCanAccess: + adminCanAccess: type: boolean adminCanView: type: boolean - adminCanAccess: + userCanAccess: type: boolean userCanEdit: type: boolean @@ -8161,6 +8249,8 @@ components: type: boolean includeSidInResponse: type: boolean + disablePromptLogin: + type: boolean sessionIdLifetime: type: integer format: int32 @@ -8266,6 +8356,10 @@ components: type: string jmsPassword: type: string + externalUriWhiteList: + type: array + items: + type: string clientWhiteList: type: array items: @@ -9204,10 +9298,6 @@ components: type: string permissionGranted: type: boolean - isJwt: - type: boolean - jwt: - type: string permissionGrantedMap: $ref: '#/components/schemas/SessionIdAccessMap' sessionAttributes: diff --git a/jans-config-api/plugins/admin-ui-plugin/src/main/java/io/jans/ca/plugin/adminui/rest/user/UserManagementResource.java b/jans-config-api/plugins/admin-ui-plugin/src/main/java/io/jans/ca/plugin/adminui/rest/user/UserManagementResource.java index 5769f1b94e7..d07d4ad87d7 100644 --- a/jans-config-api/plugins/admin-ui-plugin/src/main/java/io/jans/ca/plugin/adminui/rest/user/UserManagementResource.java +++ b/jans-config-api/plugins/admin-ui-plugin/src/main/java/io/jans/ca/plugin/adminui/rest/user/UserManagementResource.java @@ -9,6 +9,7 @@ import io.jans.ca.plugin.adminui.utils.ErrorResponse; import io.jans.configapi.core.rest.ProtectedApi; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -147,7 +148,7 @@ public Response editRole(@Valid @NotNull AdminRole roleArg) { @Path(ROLES + ROLE_PATH_VARIABLE) @Produces(MediaType.APPLICATION_JSON) @ProtectedApi(scopes = {SCOPE_ROLE_READ}, groupScopes = {SCOPE_ROLE_WRITE}, superScopes = {AppConstants.SCOPE_ADMINUI_READ}) - public Response getRole(@PathParam(ROLE_CONST) @NotNull String adminUIRole) { + public Response getRole(@Parameter(description = "Admin UI role") @PathParam(ROLE_CONST) @NotNull String adminUIRole) { try { log.info("Get all Admin-UI roles."); AdminRole roleObj = userManagementService.getRoleObjByName(adminUIRole); @@ -174,7 +175,7 @@ public Response getRole(@PathParam(ROLE_CONST) @NotNull String adminUIRole) { @Path(ROLES + ROLE_PATH_VARIABLE) @Produces(MediaType.APPLICATION_JSON) @ProtectedApi(scopes = {SCOPE_ROLE_DELETE}, superScopes = {AppConstants.SCOPE_ADMINUI_DELETE}) - public Response deleteRole(@PathParam(ROLE_CONST) @NotNull String adminUIRole) { + public Response deleteRole(@Parameter(description = "Admin UI role") @PathParam(ROLE_CONST) @NotNull String adminUIRole) { try { log.info("Deleting Admin-UI role."); List roles = userManagementService.deleteRole(adminUIRole); @@ -284,7 +285,7 @@ public Response editPermission(@Valid @NotNull AdminPermission permissionArg) { @Path(PERMISSIONS + PERMISSION_PATH_VARIABLE) @Produces(MediaType.APPLICATION_JSON) @ProtectedApi(scopes = {SCOPE_PERMISSION_READ}, groupScopes = {SCOPE_PERMISSION_WRITE}, superScopes = {AppConstants.SCOPE_ADMINUI_READ}) - public Response getPermission(@PathParam(PERMISSION_CONST) @NotNull String adminUIPermission) { + public Response getPermission(@Parameter(description = "Admin UI Permission") @PathParam(PERMISSION_CONST) @NotNull String adminUIPermission) { try { log.info("Get Admin-UI permission."); AdminPermission permissionObj = userManagementService.getPermissionObjByName(adminUIPermission); @@ -311,7 +312,7 @@ public Response getPermission(@PathParam(PERMISSION_CONST) @NotNull String admin @Path(PERMISSIONS + PERMISSION_PATH_VARIABLE) @Produces(MediaType.APPLICATION_JSON) @ProtectedApi(scopes = {SCOPE_PERMISSION_DELETE}, superScopes = {AppConstants.SCOPE_ADMINUI_DELETE}) - public Response deletePermission(@PathParam(PERMISSION_CONST) @NotNull String adminUIPermission) { + public Response deletePermission(@Parameter(description = "Admin UI Permission") @PathParam(PERMISSION_CONST) @NotNull String adminUIPermission) { try { log.info("Deleting Admin-UI permission."); List permissions = userManagementService.deletePermission(adminUIPermission); @@ -421,7 +422,7 @@ public Response mapPermissionsToRole(@Valid @NotNull RolePermissionMapping roleP @Path(ROLE_PERMISSIONS_MAPPING + ROLE_PATH_VARIABLE) @Produces(MediaType.APPLICATION_JSON) @ProtectedApi(scopes = {SCOPE_ROLE_PERMISSION_MAPPING_READ}, groupScopes = {SCOPE_ROLE_PERMISSION_MAPPING_WRITE}, superScopes = {AppConstants.SCOPE_ADMINUI_READ}) - public Response getAdminUIRolePermissionsMapping(@PathParam(ROLE_CONST) @NotNull String adminUIRole) { + public Response getAdminUIRolePermissionsMapping(@Parameter(description = "Admin UI Role") @PathParam(ROLE_CONST) @NotNull String adminUIRole) { try { log.info("Get Admin-UI role-permissions mapping by role-name."); RolePermissionMapping roleScopeMapping = userManagementService.getAdminUIRolePermissionsMapping(adminUIRole); @@ -448,7 +449,7 @@ public Response getAdminUIRolePermissionsMapping(@PathParam(ROLE_CONST) @NotNull @Path(ROLE_PERMISSIONS_MAPPING + ROLE_PATH_VARIABLE) @Produces(MediaType.APPLICATION_JSON) @ProtectedApi(scopes = {SCOPE_ROLE_PERMISSION_MAPPING_DELETE}, superScopes = {AppConstants.SCOPE_ADMINUI_DELETE}) - public Response removePermissionsFromRole(@PathParam(ROLE_CONST) @NotNull String role) { + public Response removePermissionsFromRole(@Parameter(description = "role") @PathParam(ROLE_CONST) @NotNull String role) { try { log.info("Removing permissions to Admin-UI role."); List roleScopeMapping = userManagementService.removePermissionsFromRole(role); diff --git a/jans-config-api/plugins/docs/fido2-plugin-swagger.yaml b/jans-config-api/plugins/docs/fido2-plugin-swagger.yaml index 4061cb382ff..8c1780ad95b 100644 --- a/jans-config-api/plugins/docs/fido2-plugin-swagger.yaml +++ b/jans-config-api/plugins/docs/fido2-plugin-swagger.yaml @@ -73,6 +73,7 @@ paths: parameters: - name: username in: path + description: User name required: true schema: type: string diff --git a/jans-config-api/plugins/docs/jans-admin-ui-plugin-swagger.yaml b/jans-config-api/plugins/docs/jans-admin-ui-plugin-swagger.yaml index a03ee668a5d..9f5c0152788 100644 --- a/jans-config-api/plugins/docs/jans-admin-ui-plugin-swagger.yaml +++ b/jans-config-api/plugins/docs/jans-admin-ui-plugin-swagger.yaml @@ -412,6 +412,7 @@ paths: parameters: - name: adminUIPermission in: path + description: Admin UI Permission required: true schema: type: string @@ -442,6 +443,7 @@ paths: parameters: - name: adminUIPermission in: path + description: Admin UI Permission required: true schema: type: string @@ -473,6 +475,7 @@ paths: parameters: - name: adminUIRole in: path + description: Admin UI role required: true schema: type: string @@ -503,6 +506,7 @@ paths: parameters: - name: adminUIRole in: path + description: Admin UI role required: true schema: type: string @@ -534,6 +538,7 @@ paths: parameters: - name: adminUIRole in: path + description: Admin UI Role required: true schema: type: string @@ -564,6 +569,7 @@ paths: parameters: - name: adminUIRole in: path + description: role required: true schema: type: string diff --git a/jans-config-api/plugins/docs/user-mgt-plugin-swagger.yaml b/jans-config-api/plugins/docs/user-mgt-plugin-swagger.yaml index 329dc7b4369..a74747c2026 100644 --- a/jans-config-api/plugins/docs/user-mgt-plugin-swagger.yaml +++ b/jans-config-api/plugins/docs/user-mgt-plugin-swagger.yaml @@ -26,27 +26,33 @@ paths: parameters: - name: limit in: query + description: Search size - max size of the results to return schema: type: integer format: int32 default: 50 - name: pattern in: query + description: Search pattern schema: type: string default: "" - name: startIndex in: query + description: The 1-based index of the first query result schema: type: integer format: int32 default: 0 - name: sortBy in: query + description: Attribute whose value will be used to order the returned response schema: type: string - name: sortOrder in: query + description: Order in which the sortBy param is applied. Allowed values are + "ascending" and "descending" schema: type: string responses: @@ -506,6 +512,7 @@ paths: parameters: - name: inum in: path + description: User identifier required: true schema: type: string @@ -618,6 +625,7 @@ paths: parameters: - name: inum in: path + description: User identifier required: true schema: type: string @@ -642,6 +650,7 @@ paths: parameters: - name: inum in: path + description: User identifier required: true schema: type: string diff --git a/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/rest/Fido2RegistrationResource.java b/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/rest/Fido2RegistrationResource.java index c56f8d5ae1b..b1441f619bd 100644 --- a/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/rest/Fido2RegistrationResource.java +++ b/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/rest/Fido2RegistrationResource.java @@ -9,6 +9,7 @@ import io.jans.orm.model.fido2.Fido2RegistrationEntry; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -47,7 +48,7 @@ public class Fido2RegistrationResource extends BaseResource { @GET @Path(Constants.ENTRIES + ApiConstants.USERNAME_PATH) @ProtectedApi(scopes = {ApiAccessConstants.FIDO2_CONFIG_READ_ACCESS}) - public Response findAllRegisteredByUsername(@PathParam("username") @NotNull String username) { + public Response findAllRegisteredByUsername(@Parameter(description = "User name") @PathParam("username") @NotNull String username) { logger.debug("FIDO2 registration entries by username."); List entries = fido2RegistrationService.findAllRegisteredByUsername(username); return Response.ok(entries).build(); diff --git a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/rest/UserResource.java b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/rest/UserResource.java index 004e4247ae6..78dc7dd88aa 100644 --- a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/rest/UserResource.java +++ b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/rest/UserResource.java @@ -24,6 +24,7 @@ import org.slf4j.Logger; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; @@ -74,11 +75,11 @@ private class UserPagedResult extends PagedResult{}; @GET @ProtectedApi(scopes = { ApiAccessConstants.USER_READ_ACCESS }) public Response getUsers( - @DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, - @DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, - @DefaultValue(ApiConstants.DEFAULT_LIST_START_INDEX) @QueryParam(value = ApiConstants.START_INDEX) int startIndex, - @QueryParam(value = ApiConstants.SORT_BY) String sortBy, - @QueryParam(value = ApiConstants.SORT_ORDER) String sortOrder) + @Parameter(description = "Search size - max size of the results to return") @DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, + @Parameter(description = "Search pattern") @DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, + @Parameter(description = "The 1-based index of the first query result") @DefaultValue(ApiConstants.DEFAULT_LIST_START_INDEX) @QueryParam(value = ApiConstants.START_INDEX) int startIndex, + @Parameter(description = "Attribute whose value will be used to order the returned response") @QueryParam(value = ApiConstants.SORT_BY) String sortBy, + @Parameter(description = "Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\"") @QueryParam(value = ApiConstants.SORT_ORDER) String sortOrder) throws IllegalAccessException, InvocationTargetException { if (logger.isDebugEnabled()) { logger.debug("User search param - limit:{}, pattern:{}, startIndex:{}, sortBy:{}, sortOrder:{}", @@ -102,7 +103,7 @@ public Response getUsers( @GET @ProtectedApi(scopes = { ApiAccessConstants.USER_READ_ACCESS }) @Path(ApiConstants.INUM_PATH) - public Response getUserByInum(@PathParam(ApiConstants.INUM) @NotNull String inum) + public Response getUserByInum(@Parameter(description = "User identifier") @PathParam(ApiConstants.INUM) @NotNull String inum) throws IllegalAccessException, InvocationTargetException { if (logger.isDebugEnabled()) { logger.debug("User search by inum:{}", escapeLog(inum)); @@ -221,7 +222,7 @@ public Response updateUser(@Valid CustomUser customUser) @PATCH @ProtectedApi(scopes = { ApiAccessConstants.USER_WRITE_ACCESS }) @Path(ApiConstants.INUM_PATH) - public Response patchUser(@PathParam(ApiConstants.INUM) @NotNull String inum, + public Response patchUser(@Parameter(description = "User identifier") @PathParam(ApiConstants.INUM) @NotNull String inum, @NotNull UserPatchRequest userPatchRequest) throws IllegalAccessException, InvocationTargetException, JsonPatchException, IOException { if (logger.isDebugEnabled()) { @@ -259,7 +260,7 @@ public Response patchUser(@PathParam(ApiConstants.INUM) @NotNull String inum, @DELETE @Path(ApiConstants.INUM_PATH) @ProtectedApi(scopes = { ApiAccessConstants.USER_DELETE_ACCESS }) - public Response deleteUser(@PathParam(ApiConstants.INUM) @NotNull String inum) { + public Response deleteUser(@Parameter(description = "User identifier") @PathParam(ApiConstants.INUM) @NotNull String inum) { if (logger.isDebugEnabled()) { logger.debug("User to be deleted - inum:{} ", escapeLog(inum)); } diff --git a/jans-config-api/plugins/user-mgt-plugin/src/test/resources/feature/mgt/user/user.json b/jans-config-api/plugins/user-mgt-plugin/src/test/resources/feature/mgt/user/user.json index b3fb18928d1..04ea6d4fc02 100644 --- a/jans-config-api/plugins/user-mgt-plugin/src/test/resources/feature/mgt/user/user.json +++ b/jans-config-api/plugins/user-mgt-plugin/src/test/resources/feature/mgt/user/user.json @@ -1,15 +1,6 @@ { "userId": "testUser4", "customAttributes": [ - { - "name": "birthdate", - "multiValued": false, - "values": [ - "20001231041508.553Z" - ], - "value": "20001231041508.553Z", - "displayValue": "20001231041508.553Z" - }, { "name": "emailVerified", "multiValued": false, diff --git a/jans-config-api/profiles/local/test.properties b/jans-config-api/profiles/local/test.properties index 467212d9653..149b615cf92 100644 --- a/jans-config-api/profiles/local/test.properties +++ b/jans-config-api/profiles/local/test.properties @@ -2,8 +2,8 @@ test.scopes=https://jans.io/oauth/config/acrs.readonly https://jans.io/oauth/config/acrs.write https://jans.io/oauth/config/attributes.readonly https://jans.io/oauth/config/attributes.write https://jans.io/oauth/config/attributes.delete https://jans.io/oauth/config/cache.readonly https://jans.io/oauth/config/cache.write https://jans.io/oauth/config/openid/clients.readonly https://jans.io/oauth/config/openid/clients.write https://jans.io/oauth/config/openid/clients.delete https://jans.io/oauth/jans-auth-server/config/properties.readonly https://jans.io/oauth/jans-auth-server/config/properties.write https://jans.io/oauth/config/smtp.readonly https://jans.io/oauth/config/smtp.write https://jans.io/oauth/config/smtp.delete https://jans.io/oauth/config/scripts.readonly https://jans.io/oauth/config/scripts.write https://jans.io/oauth/config/scripts.delete https://jans.io/oauth/config/fido2.readonly https://jans.io/oauth/config/fido2.write https://jans.io/oauth/config/jwks.readonly https://jans.io/oauth/config/jwks.write https://jans.io/oauth/config/jwks.delete https://jans.io/oauth/config/database/ldap.readonly https://jans.io/oauth/config/database/ldap.write https://jans.io/oauth/config/database/ldap.delete https://jans.io/oauth/config/logging.readonly https://jans.io/oauth/config/logging.write https://jans.io/oauth/config/scopes.readonly https://jans.io/oauth/config/scopes.write https://jans.io/oauth/config/scopes.delete https://jans.io/oauth/config/uma/resources.readonly https://jans.io/oauth/config/uma/resources.write https://jans.io/oauth/config/uma/resources.delete https://jans.io/oauth/config/database/sql.readonly https://jans.io/oauth/config/database/sql.write https://jans.io/oauth/config/database/sql.delete https://jans.io/oauth/config/stats.readonly jans_stat https://jans.io/scim/users.read https://jans.io/scim/users.write https://jans.io/oauth/config/scim/users.read https://jans.io/oauth/config/scim/users.write https://jans.io/scim/config.readonly https://jans.io/scim/config.write https://jans.io/oauth/config/organization.readonly https://jans.io/oauth/config/organization.write https://jans.io/oauth/config/user.readonly https://jans.io/oauth/config/user.write https://jans.io/oauth/config/user.delete https://jans.io/oauth/config/agama.readonly https://jans.io/oauth/config/agama.write https://jans.io/oauth/config/agama.delete https://jans.io/oauth/jans-auth-server/session.readonly https://jans.io/oauth/jans-auth-server/session.delete revoke_session # jans.server -token.endpoint=https://jans.server1/jans-auth/restv1/token +token.endpoint=https://jans.server2/jans-auth/restv1/token token.grant.type=client_credentials -test.client.id=1800.da71aef0-977c-40f0-bbc4-fca1b8cc5aa6 -test.client.secret=uqgP0W5YIiT7 -test.issuer=https://jans.server1/ \ No newline at end of file +test.client.id=1800.aebd53eb-4451-46ff-ab23-5deacaee0197 +test.client.secret=AwL3oOsiz2dW +test.issuer=https://jans.server2/ \ No newline at end of file diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/interceptor/AuditLogInterceptor.java b/jans-config-api/server/src/main/java/io/jans/configapi/interceptor/AuditLogInterceptor.java index 77b73ea8fc2..b4af376bc42 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/interceptor/AuditLogInterceptor.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/interceptor/AuditLogInterceptor.java @@ -12,12 +12,12 @@ import jakarta.annotation.Priority; import jakarta.inject.Inject; import jakarta.servlet.http.HttpServletRequest; -import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.UriInfo; import java.lang.reflect.Method; +import java.lang.reflect.Parameter; import java.util.Collections; import java.util.Map; import java.util.HashMap; @@ -57,15 +57,14 @@ public Object aroundReadFrom(InvocationContext context) throws Exception { try { LOG.info("Audit Log Interceptor - context:{}, info:{}, request:{}, httpHeaders:{}, AUDIT_LOG:{}", context, info, request, httpHeaders, AUDIT_LOG); - AUDIT_LOG.info("\n ********************** Request ********************** "); // Get Audit config AuditLogConf auditLogConf = getAuditLogConf(); - LOG.info("auditLogConf:{}", auditLogConf); + LOG.info("auditLogConf:{}, ignoreMethod(context):{}", auditLogConf, ignoreMethod(context, auditLogConf)); // Log if enabled - if (auditLogConf != null && auditLogConf.isEnabled()) { - + if (!ignoreMethod(context, auditLogConf)) { + AUDIT_LOG.info("\n ********************** Audit Request Detail Start ********************** "); // Request audit String beanClassName = context.getClass().getName(); String method = context.getMethod().getName(); @@ -79,10 +78,11 @@ public Object aroundReadFrom(InvocationContext context) throws Exception { // Request object audit processRequest(context, auditLogConf); + AUDIT_LOG.info("\n ********************** Audit Request Detail End ********************** "); } } catch (Exception ex) { - throw new WebApplicationException(ex); + LOG.error("Not able to log audit details due to error:{}", ex); } return context.proceed(); } @@ -92,16 +92,22 @@ private void processRequest(InvocationContext context, AuditLogConf auditLogConf Object[] ctxParameters = context.getParameters(); Method method = context.getMethod(); + int paramCount = method.getParameterCount(); + Parameter[] parameters = method.getParameters(); Class[] clazzArray = method.getParameterTypes(); - LOG.debug("Audit Log Interceptor process - ctxParameters:{}, method:{}, clazzArray:{}", ctxParameters, method, - clazzArray); + AUDIT_LOG.info("RequestReaderInterceptor - Processing Data - paramCount:{} , parameters:{}, clazzArray:{} ", + paramCount, parameters, clazzArray); if (clazzArray != null && clazzArray.length > 0) { for (int i = 0; i < clazzArray.length; i++) { + Class clazz = clazzArray[i]; + String propertyName = parameters[i].getName(); + AUDIT_LOG.info("propertyName:{}, clazz:{} , clazz.isPrimitive():{} ", propertyName, clazz, + clazz.isPrimitive()); + Object obj = ctxParameters[i]; - LOG.info("Request obj:{}", obj); - AUDIT_LOG.info("objectType:{}, obj:{} ", clazzArray[i], obj); + AUDIT_LOG.info("RequestReaderInterceptor final - obj - obj:{} ", obj); } } @@ -111,6 +117,28 @@ private AuditLogConf getAuditLogConf() { return this.authUtil.getAuditLogConf(); } + private boolean ignoreMethod(InvocationContext context, AuditLogConf auditLogConf) { + LOG.debug("Checking if method to be ignored - context:{}, auditLogConf:{}", context, auditLogConf); + + if (auditLogConf == null || context.getMethod().getAnnotations() == null + || context.getMethod().getAnnotations().length <= 0) { + return false; + } + + for (int i = 0; i < context.getMethod().getAnnotations().length; i++) { + LOG.debug("Check if method is to be ignored - context.getMethod().getAnnotations()[i]:{} ", + context.getMethod().getAnnotations()[i]); + + if (context.getMethod().getAnnotations()[i] != null && auditLogConf.getIgnoreHttpMethod() != null + && auditLogConf.getIgnoreHttpMethod() + .contains(context.getMethod().getAnnotations()[i].toString())) { + return true; + } + + } + return false; + } + private Map getAuditHeaderAttributes(AuditLogConf auditLogConf) { LOG.info("AuditLogInterceptor::getAuditHeaderAttributes() - auditLogConf:{}", auditLogConf); if (auditLogConf == null) { @@ -118,7 +146,7 @@ private Map getAuditHeaderAttributes(AuditLogConf auditLogConf) } List attributes = auditLogConf.getHeaderAttributes(); LOG.info("AuditLogInterceptor::getAuditHeaderAttributes() - attributes:{}", attributes); - + Map attributeMap = null; if (attributes != null && !attributes.isEmpty()) { attributeMap = new HashMap<>(); diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/interceptor/RequestReaderInterceptor.java b/jans-config-api/server/src/main/java/io/jans/configapi/interceptor/RequestReaderInterceptor.java new file mode 100644 index 00000000000..ce92c0a977d --- /dev/null +++ b/jans-config-api/server/src/main/java/io/jans/configapi/interceptor/RequestReaderInterceptor.java @@ -0,0 +1,287 @@ +/* + * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * + * Copyright (c) 2020, Janssen Project + */ + +package io.jans.configapi.interceptor; + +import io.jans.model.GluuAttribute; +import io.jans.model.attribute.AttributeDataType; +import io.jans.configapi.core.util.DataUtil; +import io.jans.configapi.model.configuration.DataFormatConversionConf; +import io.jans.configapi.core.interceptor.RequestInterceptor; +import io.jans.configapi.service.auth.AttributeService; +import io.jans.configapi.util.AuthUtil; +import io.jans.orm.PersistenceEntryManager; +import io.jans.orm.annotation.AttributesList; +import jakarta.annotation.Priority; +import jakarta.inject.Inject; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.ws.rs.container.ResourceInfo; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.HttpHeaders; + +import jakarta.ws.rs.core.UriInfo; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.Date; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import jakarta.interceptor.AroundInvoke; +import jakarta.interceptor.Interceptor; +import jakarta.interceptor.InvocationContext; + +import io.jans.orm.model.AttributeData; +import io.jans.orm.reflect.property.Getter; +import io.jans.orm.reflect.property.PropertyAnnotation; +import io.jans.orm.reflect.property.Setter; +import io.jans.orm.reflect.util.ReflectHelper; + +import java.lang.reflect.InvocationTargetException; + +@Interceptor +@RequestInterceptor +@Priority(Interceptor.Priority.APPLICATION) +public class RequestReaderInterceptor { + + private static final Logger logger = LoggerFactory.getLogger(RequestReaderInterceptor.class); + + @Context + UriInfo info; + + @Context + HttpServletRequest request; + + @Context + private HttpHeaders httpHeaders; + + @Context + private ResourceInfo resourceInfo; + + @Inject + AuthUtil authUtil; + + @Inject + AttributeService attributeService; + + @Inject + PersistenceEntryManager persistenceEntryManager; + + @SuppressWarnings({ "all" }) + @AroundInvoke + public Object aroundReadFrom(InvocationContext context) throws Exception { + logger.debug( + " Request Interceptor info:{}, request:{}, httpHeaders:{}, resourceInfo:{}, persistenceEntryManager:{}, getDataFormatConversionConf():{}, isDataFormatConversionEnaled():{}, isIgnoreMethod(context):{}", + info, request, httpHeaders, resourceInfo, persistenceEntryManager, getDataFormatConversionConf(), + isDataFormatConversionEnaled(), isIgnoreMethod(context)); + + try { + // perform data conversion if enabled and method is not ignored + if (isDataFormatConversionEnaled() && !isIgnoreMethod(context)) { + logger.debug("======================= DataType Conversion Start ============================"); + processRequest(context); + logger.debug("======================= DataType Conversion End ============================"); + } + + } catch (Exception ex) { + ex.printStackTrace(); + logger.error("Exception while data conversion:{}", ex.getMessage()); + } + return context.proceed(); + } + + private void processRequest(InvocationContext context) { + logger.debug( + " Process Request Data - context:{} , context.getClass():{}, context.getContextData():{}, context.getMethod():{} , context.getParameters():{} , context.getTarget():{} ", + context, context.getClass(), context.getContextData(), context.getMethod(), context.getParameters(), + context.getTarget()); + + Object[] ctxParameters = context.getParameters(); + logger.debug(" Request Parameters - ctxParameters:{} ", ctxParameters); + + Method method = context.getMethod(); + + int paramCount = method.getParameterCount(); + Parameter[] parameters = method.getParameters(); + Class[] clazzArray = method.getParameterTypes(); + + logger.debug("Parameter Data - paramCount:{} , parameters:{}, clazzArray:{} ", paramCount, parameters, + clazzArray); + + if (clazzArray != null && clazzArray.length > 0) { + for (int i = 0; i < clazzArray.length; i++) { + Class clazz = clazzArray[i]; + String propertyName = parameters[i].getName(); + logger.debug("propertyName:{}, clazz:{} , clazz.isPrimitive():{} ", propertyName, clazz, + clazz.isPrimitive()); + + Object obj = ctxParameters[i]; + if (!clazz.isPrimitive() && obj != null) { + processCustomAttributes(obj); + logger.debug("Request object post processing - propertyName:{}, obj:{} ", propertyName, obj); + } + } + } + } + + private void processCustomAttributes(T obj) { + logger.debug("Object for custom attribute obj:{}", obj); + + Class entryClass = obj.getClass(); + List propertiesAnnotations = persistenceEntryManager + .getEntryPropertyAnnotations(entryClass); + logger.debug("propertiesAnnotations:{}", propertiesAnnotations); + + for (PropertyAnnotation propertiesAnnotation : propertiesAnnotations) { + try { + String propertyName = propertiesAnnotation.getPropertyName(); + + // Process properties with @AttributesList annotation + Annotation ldapAttribute = ReflectHelper.getAnnotationByType(propertiesAnnotation.getAnnotations(), + AttributesList.class); + logger.debug("Custom attributes - ldapAttribute:{}", ldapAttribute); + if (ldapAttribute == null) { + continue; + } + + List listAttributes = persistenceEntryManager + .getAttributeDataListFromCustomAttributesList(obj, (AttributesList) ldapAttribute, + propertyName); + logger.debug("Custom AttributesList before conversion listAttributes:{}", listAttributes); + processAttributeData(obj, propertyName, ldapAttribute, listAttributes); + logger.debug("Custom AttributesList after conversion listAttributes:{}", listAttributes); + + } catch (Exception ex) { + logger.error("Error while processing Custom Attributes", ex); + } + } + } + + private List processAttributeData(Object obj, String propertyName, Annotation ldapAttribute, + List listAttributes) + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + logger.debug("Attribute Data for processing obj:{}, propertyName:{}, ldapAttribute:{}, listAttributes:{}", obj, + propertyName, ldapAttribute, listAttributes); + + if (listAttributes != null && !listAttributes.isEmpty()) { + for (AttributeData attData : listAttributes) { + logger.debug("AttributeData - attData:{}", attData); + GluuAttribute gluuAttribute = attributeService.getByLdapName(attData.getName()); + + logger.debug("AttributeData details - attData.getName():{}, attData.getValue():{},gluuAttribute:{}", + attData.getName(), attData.getValue(), gluuAttribute); + + if (attData.getValue() != null && gluuAttribute != null) { + AttributeDataType attributeDataType = gluuAttribute.getDataType(); + logger.debug( + "AttributeDataType - attData.getName():{}, attributeDataType:{}, AttributeDataType.DATE.getValue():{}", + attData.getName(), attributeDataType, AttributeDataType.DATE.getValue()); + if (AttributeDataType.DATE.getValue().equalsIgnoreCase(attributeDataType.getValue())) { + logger.debug(" Calling decodeTime() - attData.getValue():{}", attData.getValue()); + AttributeData attributeData = decodeTime(attData); + listAttributes.remove(attData); + listAttributes.add(attributeData); + } + } + } + + logger.debug("Getting updated custom attribute list for propertyName:{} , listAttributes:{} ", propertyName, + listAttributes); + List data = persistenceEntryManager.getCustomAttributesListFromAttributeDataList(obj, + (AttributesList) ldapAttribute, propertyName, listAttributes); + logger.debug("updated custom attribute data:{}", data); + + logger.debug("Setting the custom attribute in request object propertyName:{}, data:{} ", propertyName, + data); + // set data + setObjectData(obj, propertyName, data); + logger.debug("After setting the custom attribute in request object propertyName:{}, data:{} ", propertyName, + data); + + } + return listAttributes; + } + + private AttributeData decodeTime(AttributeData attributeData) { + logger.debug("Date data to decode attributeData:{}", attributeData); + AttributeData atrData = attributeData; + if (atrData == null || atrData.getValue() == null) { + return atrData; + } + + Object attValue = atrData.getValue(); + if (attValue != null) { + Date date = authUtil.parseStringToDateObj(attValue.toString()); + logger.debug(" Date data to decode date:{}", date); + if (date != null) { + date = persistenceEntryManager.decodeTime(null, date.toString()); + logger.debug(" Set decoded date atrData.getName():{}, date:{}", atrData.getName(), date); + atrData = new AttributeData(atrData.getName(), date); + atrData.setMultiValued(attributeData.getMultiValued()); + } + + } + + return atrData; + } + + private void setObjectData(Object obj, String propertyName, Object propertyValue) + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + logger.debug("Data to set new value - obj:{}, propertyName:{}, propertyValue:{}", obj, propertyName, + propertyValue); + Setter setterMethod = DataUtil.getSetterMethod(obj.getClass(), propertyName); + propertyValue = setterMethod.getMethod().invoke(obj, propertyValue); + logger.debug("After setterMethod invoked key:{}, propertyValue:{} ", propertyName, propertyValue); + + Getter getterMethod = DataUtil.getGetterMethod(obj.getClass(), propertyName); + propertyValue = getterMethod.get(obj); + logger.debug("Verify new value key:{}, propertyValue:{} ", propertyName, propertyValue); + + } + + private DataFormatConversionConf getDataFormatConversionConf() { + logger.debug("authUtil.getDataFormatConversionConf():{}", authUtil.getDataFormatConversionConf()); + return this.authUtil.getDataFormatConversionConf(); + } + + private boolean isDataFormatConversionEnaled() { + DataFormatConversionConf dataFormatConversionConf = getDataFormatConversionConf(); + if (dataFormatConversionConf == null) { + return false; + } + logger.debug("dataFormatConversionConf:{}, dataFormatConversionConf.isEnabled():{}", dataFormatConversionConf, + dataFormatConversionConf.isEnabled()); + return dataFormatConversionConf.isEnabled(); + } + + private boolean isIgnoreMethod(InvocationContext context) { + logger.debug("Checking if method to be ignored"); + if (context.getMethod().getAnnotations() == null || context.getMethod().getAnnotations().length <= 0) { + return false; + } + + for (int i = 0; i < context.getMethod().getAnnotations().length; i++) { + DataFormatConversionConf dataFormatConversionConf = getDataFormatConversionConf(); + if (dataFormatConversionConf == null) { + return false; + } + logger.debug("====== Verifying - dataFormatConversionConf:{}, context.getMethod().getAnnotations()[i]:{} ", + dataFormatConversionConf, context.getMethod().getAnnotations()[i]); + + if (context.getMethod().getAnnotations()[i] != null + && dataFormatConversionConf.getIgnoreHttpMethod() != null && dataFormatConversionConf + .getIgnoreHttpMethod().contains(context.getMethod().getAnnotations()[i].toString())) { + return true; + } + + } + return false; + } + +} diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AgamaResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AgamaResource.java index 6aaa87faf95..3226e414a01 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AgamaResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AgamaResource.java @@ -24,7 +24,9 @@ import io.jans.configapi.core.model.SearchRequest; import io.jans.orm.exception.EntryPersistenceException; import io.jans.orm.model.PagedResult; + import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; @@ -70,12 +72,12 @@ public class AgamaResource extends ConfigBaseResource { @GET @ProtectedApi(scopes = { ApiAccessConstants.AGAMA_READ_ACCESS }, groupScopes = { ApiAccessConstants.AGAMA_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) - public Response getFlows(@DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, - @DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, - @DefaultValue(ApiConstants.DEFAULT_LIST_START_INDEX) @QueryParam(value = ApiConstants.START_INDEX) int startIndex, - @DefaultValue("agFlowQname") @QueryParam(value = ApiConstants.SORT_BY) String sortBy, - @DefaultValue(ApiConstants.ASCENDING) @QueryParam(value = ApiConstants.SORT_ORDER) String sortOrder, - @DefaultValue("false") @QueryParam(value = ApiConstants.INCLUDE_SOURCE) boolean includeSource) { + public Response getFlows(@Parameter(description = "Search pattern") @DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, + @Parameter(description = "Search size - max size of the results to return") @DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, + @Parameter(description = "The 1-based index of the first query result") @DefaultValue(ApiConstants.DEFAULT_LIST_START_INDEX) @QueryParam(value = ApiConstants.START_INDEX) int startIndex, + @Parameter(description = "Attribute whose value will be used to order the returned response") @DefaultValue("agFlowQname") @QueryParam(value = ApiConstants.SORT_BY) String sortBy, + @Parameter(description = "Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\"") @DefaultValue(ApiConstants.ASCENDING) @QueryParam(value = ApiConstants.SORT_ORDER) String sortOrder, + @Parameter(description = "Boolean flag to indicate agama source is to be included") @DefaultValue("false") @QueryParam(value = ApiConstants.INCLUDE_SOURCE) boolean includeSource) { if (logger.isDebugEnabled()) { logger.debug( @@ -102,8 +104,8 @@ public Response getFlows(@DefaultValue("") @QueryParam(value = ApiConstants.PATT @ProtectedApi(scopes = { ApiAccessConstants.AGAMA_READ_ACCESS }, groupScopes = { ApiAccessConstants.AGAMA_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) @Path(ApiConstants.QNAME_PATH) - public Response getFlowByName(@PathParam(ApiConstants.QNAME) @NotNull String flowName, - @DefaultValue("false") @QueryParam(value = ApiConstants.INCLUDE_SOURCE) boolean includeSource) { + public Response getFlowByName(@Parameter(description = "Agama Flow name") @PathParam(ApiConstants.QNAME) @NotNull String flowName, + @Parameter(description = "Boolean flag to indicate agama source is to be included") @DefaultValue("false") @QueryParam(value = ApiConstants.INCLUDE_SOURCE) boolean includeSource) { if (logger.isDebugEnabled()) { logger.debug("Search Agama with flowName:{}, includeSource:{}", escapeLog(flowName), escapeLog(includeSource)); @@ -161,7 +163,7 @@ public Response createFlow(@Valid Flow flow) @ProtectedApi(scopes = { ApiAccessConstants.AGAMA_READ_ACCESS }, groupScopes = { ApiAccessConstants.AGAMA_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) @Path("/syntax-check/" + ApiConstants.QNAME_PATH) - public Response doSyntaxCheck(@PathParam(ApiConstants.QNAME) String qname, String source) { + public Response doSyntaxCheck(@Parameter(description = "Agama Flow name") @PathParam(ApiConstants.QNAME) String qname, String source) { Exception e = null; try { @@ -190,7 +192,7 @@ public Response doSyntaxCheck(@PathParam(ApiConstants.QNAME) String qname, Strin @Path(ApiConstants.QNAME_PATH) @ProtectedApi(scopes = { ApiAccessConstants.AGAMA_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_WRITE_ACCESS }) - public Response createFlowFromSource(@PathParam(ApiConstants.QNAME) @NotNull String flowName, @Valid String source) + public Response createFlowFromSource(@Parameter(description = "Agama Flow name") @PathParam(ApiConstants.QNAME) @NotNull String flowName, @Valid String source) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { logger.debug(" Flow to be created flowName:{}, source:{}", flowName, source); @@ -232,7 +234,7 @@ public Response createFlowFromSource(@PathParam(ApiConstants.QNAME) @NotNull Str @Path(ApiConstants.SOURCE + ApiConstants.QNAME_PATH) @ProtectedApi(scopes = { ApiAccessConstants.AGAMA_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_WRITE_ACCESS }) - public Response updateFlowSource(@PathParam(ApiConstants.QNAME) @NotNull String flowName, @Valid String source) + public Response updateFlowSource(@Parameter(description = "Agama Flow name") @PathParam(ApiConstants.QNAME) @NotNull String flowName, @Valid String source) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { logger.debug(" Flow to be updated flowName:{}, source:{}", flowName, source); @@ -269,7 +271,7 @@ public Response updateFlowSource(@PathParam(ApiConstants.QNAME) @NotNull String @Path(ApiConstants.QNAME_PATH) @ProtectedApi(scopes = { ApiAccessConstants.AGAMA_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_WRITE_ACCESS }) - public Response patchFlow(@PathParam(ApiConstants.QNAME) @NotNull String flowName, @NotNull JsonPatch jsonPatch) + public Response patchFlow(@Parameter(description = "Agama Flow name") @PathParam(ApiConstants.QNAME) @NotNull String flowName, @NotNull JsonPatch jsonPatch) throws JsonPatchException, IOException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { if (logger.isDebugEnabled()) { @@ -305,7 +307,7 @@ public Response patchFlow(@PathParam(ApiConstants.QNAME) @NotNull String flowNam @Path(ApiConstants.QNAME_PATH) @ProtectedApi(scopes = { ApiAccessConstants.AGAMA_DELETE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_DELETE_ACCESS }) - public Response delete(@PathParam(ApiConstants.QNAME) @NotNull String flowName) { + public Response delete(@Parameter(description = "Agama Flow name") @PathParam(ApiConstants.QNAME) @NotNull String flowName) { logger.debug(" Flow to delete - flowName:{}", flowName); String decodedFlowName = getURLDecodedValue(flowName); logger.trace(" Agama Decoded flow name is:{}", decodedFlowName); diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AttributesResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AttributesResource.java index 5fbeab63569..2741c4b5921 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AttributesResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AttributesResource.java @@ -20,6 +20,7 @@ import io.jans.orm.model.PagedResult; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; @@ -71,12 +72,12 @@ public class AttributesResource extends ConfigBaseResource { @ProtectedApi(scopes = { ApiAccessConstants.ATTRIBUTES_READ_ACCESS }, groupScopes = { ApiAccessConstants.ATTRIBUTES_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) public Response getAttributes( - @DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, - @DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, - @DefaultValue(ApiConstants.ALL) @QueryParam(value = ApiConstants.STATUS) String status, - @DefaultValue(ApiConstants.DEFAULT_LIST_START_INDEX) @QueryParam(value = ApiConstants.START_INDEX) int startIndex, - @DefaultValue(ApiConstants.INUM) @QueryParam(value = ApiConstants.SORT_BY) String sortBy, - @DefaultValue(ApiConstants.ASCENDING) @QueryParam(value = ApiConstants.SORT_ORDER) String sortOrder) { + @Parameter(description = "Search size - max size of the results to return") @DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, + @Parameter(description = "Search pattern") @DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, + @Parameter(description = "Status of the attribute") @DefaultValue(ApiConstants.ALL) @QueryParam(value = ApiConstants.STATUS) String status, + @Parameter(description = "The 1-based index of the first query result") @DefaultValue(ApiConstants.DEFAULT_LIST_START_INDEX) @QueryParam(value = ApiConstants.START_INDEX) int startIndex, + @Parameter(description = "Attribute whose value will be used to order the returned response") @DefaultValue(ApiConstants.INUM) @QueryParam(value = ApiConstants.SORT_BY) String sortBy, + @Parameter(description = "Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\"") @DefaultValue(ApiConstants.ASCENDING) @QueryParam(value = ApiConstants.SORT_ORDER) String sortOrder) { if (logger.isDebugEnabled()) { logger.debug( @@ -102,7 +103,7 @@ public Response getAttributes( @ProtectedApi(scopes = { ApiAccessConstants.ATTRIBUTES_READ_ACCESS }, groupScopes = { ApiAccessConstants.ATTRIBUTES_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) @Path(ApiConstants.INUM_PATH) - public Response getAttributeByInum(@PathParam(ApiConstants.INUM) @NotNull String inum) { + public Response getAttributeByInum(@Parameter(description = "Attribute Id") @PathParam(ApiConstants.INUM) @NotNull String inum) { GluuAttribute attribute = attributeService.getAttributeByInum(inum); checkResourceNotNull(attribute, GLUU_ATTRIBUTE); return Response.ok(attribute).build(); @@ -173,7 +174,7 @@ public Response updateAttribute(@Valid GluuAttribute attribute) { @ProtectedApi(scopes = { ApiAccessConstants.ATTRIBUTES_WRITE_ACCESS }, groupScopes = {}, superScopes = { ApiAccessConstants.SUPER_ADMIN_WRITE_ACCESS }) @Path(ApiConstants.INUM_PATH) - public Response patchAtribute(@PathParam(ApiConstants.INUM) @NotNull String inum, @NotNull String pathString) + public Response patchAtribute(@Parameter(description = "Attribute Id") @PathParam(ApiConstants.INUM) @NotNull String inum, @NotNull String pathString) throws JsonPatchException, IOException { log.debug(" GluuAttribute details to patch - inum:{}, pathString:{}", inum, pathString); GluuAttribute existingAttribute = attributeService.getAttributeByInum(inum); @@ -195,7 +196,7 @@ public Response patchAtribute(@PathParam(ApiConstants.INUM) @NotNull String inum @Path(ApiConstants.INUM_PATH) @ProtectedApi(scopes = { ApiAccessConstants.ATTRIBUTES_DELETE_ACCESS }, groupScopes = {}, superScopes = { ApiAccessConstants.SUPER_ADMIN_DELETE_ACCESS }) - public Response deleteAttribute(@PathParam(ApiConstants.INUM) @NotNull String inum) { + public Response deleteAttribute(@Parameter(description = "Attribute Id") @PathParam(ApiConstants.INUM) @NotNull String inum) { log.debug(" GluuAttribute details to delete - inum:{}", inum); GluuAttribute attribute = attributeService.getAttributeByInum(inum); checkResourceNotNull(attribute, GLUU_ATTRIBUTE); diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java index 4dcaed8b610..b92c03fe928 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ClientsResource.java @@ -32,6 +32,7 @@ import io.jans.util.security.StringEncrypter.EncryptionException; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; @@ -99,11 +100,11 @@ public class ClientsResource extends ConfigBaseResource { @ProtectedApi(scopes = { ApiAccessConstants.OPENID_CLIENTS_READ_ACCESS }, groupScopes = { ApiAccessConstants.OPENID_READ_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) public Response getOpenIdConnectClients( - @DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, - @DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, - @DefaultValue(ApiConstants.DEFAULT_LIST_START_INDEX) @QueryParam(value = ApiConstants.START_INDEX) int startIndex, - @QueryParam(value = ApiConstants.SORT_BY) String sortBy, - @QueryParam(value = ApiConstants.SORT_ORDER) String sortOrder) throws EncryptionException { + @Parameter(description = "Search size - max size of the results to return") @DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, + @Parameter(description = "Search pattern") @DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, + @Parameter(description = "The 1-based index of the first query result") @DefaultValue(ApiConstants.DEFAULT_LIST_START_INDEX) @QueryParam(value = ApiConstants.START_INDEX) int startIndex, + @Parameter(description = "Attribute whose value will be used to order the returned response") @QueryParam(value = ApiConstants.SORT_BY) String sortBy, + @Parameter(description = "Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\"") @QueryParam(value = ApiConstants.SORT_ORDER) String sortOrder) throws EncryptionException { if (logger.isDebugEnabled()) { logger.debug("Client serach param - limit:{}, pattern:{}, startIndex:{}, sortBy:{}, sortOrder:{}", escapeLog(limit), escapeLog(pattern), escapeLog(startIndex), escapeLog(sortBy), @@ -126,7 +127,7 @@ public Response getOpenIdConnectClients( @ProtectedApi(scopes = { ApiAccessConstants.OPENID_CLIENTS_READ_ACCESS }, groupScopes = { ApiAccessConstants.OPENID_READ_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) @Path(ApiConstants.INUM_PATH) - public Response getOpenIdClientByInum(@PathParam(ApiConstants.INUM) @NotNull String inum) { + public Response getOpenIdClientByInum(@Parameter(description = "Client identifier") @PathParam(ApiConstants.INUM) @NotNull String inum) { if (logger.isDebugEnabled()) { logger.debug("Client serach by inum:{}", escapeLog(inum)); } @@ -254,7 +255,7 @@ public Response updateClient(@Valid Client client) throws EncryptionException { @ProtectedApi(scopes = { ApiAccessConstants.OPENID_CLIENTS_WRITE_ACCESS }, groupScopes = { ApiAccessConstants.OPENID_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_WRITE_ACCESS }) @Path(ApiConstants.INUM_PATH) - public Response patchClient(@PathParam(ApiConstants.INUM) @NotNull String inum, @NotNull String jsonPatchString) + public Response patchClient(@Parameter(description = "Client identifier") @PathParam(ApiConstants.INUM) @NotNull String inum, @NotNull String jsonPatchString) throws JsonPatchException, IOException { if (logger.isDebugEnabled()) { logger.debug("Client details to be patched - inum:{}, jsonPatchString:{}", escapeLog(inum), @@ -279,7 +280,7 @@ public Response patchClient(@PathParam(ApiConstants.INUM) @NotNull String inum, @Path(ApiConstants.INUM_PATH) @ProtectedApi(scopes = { ApiAccessConstants.OPENID_CLIENTS_DELETE_ACCESS }, groupScopes = { ApiAccessConstants.OPENID_DELETE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_DELETE_ACCESS }) - public Response deleteClient(@PathParam(ApiConstants.INUM) @NotNull String inum) { + public Response deleteClient(@Parameter(description = "Client identifier") @PathParam(ApiConstants.INUM) @NotNull String inum) { if (logger.isDebugEnabled()) { logger.debug("Client to be deleted - inum:{} ", escapeLog(inum)); } diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/CustomScriptResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/CustomScriptResource.java index 8a7dffc0d66..c4934cdc888 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/CustomScriptResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/CustomScriptResource.java @@ -22,6 +22,7 @@ import io.jans.util.StringHelper; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; @@ -64,11 +65,11 @@ public class CustomScriptResource extends ConfigBaseResource { @ProtectedApi(scopes = { ApiAccessConstants.SCRIPTS_READ_ACCESS }, groupScopes = { ApiAccessConstants.SCRIPTS_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) public Response getAllCustomScripts( - @DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, - @DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, - @DefaultValue(ApiConstants.DEFAULT_LIST_START_INDEX) @QueryParam(value = ApiConstants.START_INDEX) int startIndex, - @DefaultValue(ApiConstants.INUM) @QueryParam(value = ApiConstants.SORT_BY) String sortBy, - @DefaultValue(ApiConstants.ASCENDING) @QueryParam(value = ApiConstants.SORT_ORDER) String sortOrder) { + @Parameter(description = "Search size - max size of the results to return") @DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, + @Parameter(description = "Search pattern") @DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, + @Parameter(description = "The 1-based index of the first query result") @DefaultValue(ApiConstants.DEFAULT_LIST_START_INDEX) @QueryParam(value = ApiConstants.START_INDEX) int startIndex, + @Parameter(description = "Attribute whose value will be used to order the returned response") @DefaultValue(ApiConstants.INUM) @QueryParam(value = ApiConstants.SORT_BY) String sortBy, + @Parameter(description = "Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\"") @DefaultValue(ApiConstants.ASCENDING) @QueryParam(value = ApiConstants.SORT_ORDER) String sortOrder) { if (logger.isDebugEnabled()) { logger.debug( @@ -92,7 +93,7 @@ public Response getAllCustomScripts( @Path(PATH_SEPARATOR + ApiConstants.NAME + ApiConstants.NAME_PARAM_PATH) @ProtectedApi(scopes = { ApiAccessConstants.SCRIPTS_READ_ACCESS }, groupScopes = { ApiAccessConstants.SCRIPTS_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) - public Response getCustomScriptByName(@PathParam(ApiConstants.NAME) @NotNull String name) { + public Response getCustomScriptByName(@Parameter(description = "Script name") @PathParam(ApiConstants.NAME) @NotNull String name) { if (logger.isDebugEnabled()) { logger.debug("Custom Script to be fetched based on type - name:{} ", escapeLog(name)); @@ -117,12 +118,12 @@ public Response getCustomScriptByName(@PathParam(ApiConstants.NAME) @NotNull Str @Path(PATH_SEPARATOR + ApiConstants.TYPE + ApiConstants.TYPE_PATH) @ProtectedApi(scopes = { ApiAccessConstants.SCRIPTS_READ_ACCESS }, groupScopes = { ApiAccessConstants.SCRIPTS_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) - public Response getCustomScriptsByTypePattern(@PathParam(ApiConstants.TYPE) @NotNull String type, - @DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, - @DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, - @DefaultValue(ApiConstants.DEFAULT_LIST_START_INDEX) @QueryParam(value = ApiConstants.START_INDEX) int startIndex, - @DefaultValue(ApiConstants.INUM) @QueryParam(value = ApiConstants.SORT_BY) String sortBy, - @DefaultValue(ApiConstants.ASCENDING) @QueryParam(value = ApiConstants.SORT_ORDER) String sortOrder) { + public Response getCustomScriptsByTypePattern(@Parameter(description = "Script type") @PathParam(ApiConstants.TYPE) @NotNull String type, + @Parameter(description = "Search size - max size of the results to return") @DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, + @Parameter(description = "Search pattern") @DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, + @Parameter(description = "The 1-based index of the first query result") @DefaultValue(ApiConstants.DEFAULT_LIST_START_INDEX) @QueryParam(value = ApiConstants.START_INDEX) int startIndex, + @Parameter(description = "Attribute whose value will be used to order the returned response") @DefaultValue(ApiConstants.INUM) @QueryParam(value = ApiConstants.SORT_BY) String sortBy, + @Parameter(description = "Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\"") @DefaultValue(ApiConstants.ASCENDING) @QueryParam(value = ApiConstants.SORT_ORDER) String sortOrder) { if (logger.isDebugEnabled()) { logger.debug( @@ -147,7 +148,7 @@ public Response getCustomScriptsByTypePattern(@PathParam(ApiConstants.TYPE) @Not @Path(PATH_SEPARATOR + ApiConstants.INUM + PATH_SEPARATOR + ApiConstants.INUM_PATH) @ProtectedApi(scopes = { ApiAccessConstants.SCRIPTS_READ_ACCESS }, groupScopes = { ApiAccessConstants.SCRIPTS_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) - public Response getCustomScriptByInum(@PathParam(ApiConstants.INUM) @NotNull String inum) { + public Response getCustomScriptByInum(@Parameter(description = "Script identifier") @PathParam(ApiConstants.INUM) @NotNull String inum) { if (logger.isDebugEnabled()) { logger.debug("Custom Script to be fetched - inum:{} ", escapeLog(inum)); } @@ -222,7 +223,7 @@ public Response updateScript(@Valid @NotNull CustomScript customScript) { @Path(ApiConstants.INUM_PATH) @ProtectedApi(scopes = { ApiAccessConstants.SCRIPTS_DELETE_ACCESS }, groupScopes = {}, superScopes = { ApiAccessConstants.SUPER_ADMIN_DELETE_ACCESS }) - public Response deleteScript(@PathParam(ApiConstants.INUM) @NotNull String inum) { + public Response deleteScript(@Parameter(description = "Script identifier") @PathParam(ApiConstants.INUM) @NotNull String inum) { try { if (logger.isDebugEnabled()) { logger.debug("Custom Script Resource to delete - inum:{}", escapeLog(inum)); @@ -250,7 +251,7 @@ public Response deleteScript(@PathParam(ApiConstants.INUM) @NotNull String inum) @ProtectedApi(scopes = { ApiAccessConstants.SCRIPTS_WRITE_ACCESS }, groupScopes = {}, superScopes = { ApiAccessConstants.SUPER_ADMIN_WRITE_ACCESS }) @Path(ApiConstants.INUM_PATH) - public Response patchAtribute(@PathParam(ApiConstants.INUM) @NotNull String inum, @NotNull String pathString) + public Response patchAtribute(@Parameter(description = "Script identifier") @PathParam(ApiConstants.INUM) @NotNull String inum, @NotNull String pathString) throws JsonPatchException, IOException { if (logger.isDebugEnabled()) { logger.debug("Custom Script Resource to patch - inum:{} , pathString:{}", escapeLog(inum), diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/JwksResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/JwksResource.java index 2277f784771..b8e588419bf 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/JwksResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/JwksResource.java @@ -18,6 +18,7 @@ import io.jans.configapi.core.util.Jackson; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; @@ -149,7 +150,7 @@ public Response getKeyById(@NotNull JSONWebKey jwk) { @ProtectedApi(scopes = { ApiAccessConstants.JWKS_READ_ACCESS } , groupScopes = { ApiAccessConstants.JWKS_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) @Path(ApiConstants.KID_PATH) - public Response getKeyById(@PathParam(ApiConstants.KID) @NotNull String kid) { + public Response getKeyById(@Parameter(description = "The unique identifier for the key") @PathParam(ApiConstants.KID) @NotNull String kid) { log.debug("Fetch JWK details by kid:{}", kid); WebKeysConfiguration webkeys = configurationService.findConf().getWebKeys(); log.debug("WebKeysConfiguration before addding new key:{}", webkeys); @@ -170,7 +171,7 @@ public Response getKeyById(@PathParam(ApiConstants.KID) @NotNull String kid) { @Consumes(MediaType.APPLICATION_JSON_PATCH_JSON) @ProtectedApi(scopes = { ApiAccessConstants.JWKS_WRITE_ACCESS }, groupScopes = {}, superScopes = { ApiAccessConstants.SUPER_ADMIN_WRITE_ACCESS }) @Path(ApiConstants.KID_PATH) - public Response patch(@PathParam(ApiConstants.KID) @NotNull String kid, @NotNull String requestString) + public Response patch(@Parameter(description = "The unique identifier for the key") @PathParam(ApiConstants.KID) @NotNull String kid, @NotNull String requestString) throws JsonPatchException, IOException { log.debug("JWKS details to be patched for kid:{}, requestString:{}", kid ,requestString); Conf conf = configurationService.findConf(); @@ -205,7 +206,7 @@ public Response patch(@PathParam(ApiConstants.KID) @NotNull String kid, @NotNull @DELETE @ProtectedApi(scopes = { ApiAccessConstants.JWKS_DELETE_ACCESS } , groupScopes = {}, superScopes = { ApiAccessConstants.SUPER_ADMIN_DELETE_ACCESS }) @Path(ApiConstants.KID_PATH) - public Response deleteKey(@PathParam(ApiConstants.KID) @NotNull String kid) { + public Response deleteKey(@Parameter(description = "The unique identifier for the key") @PathParam(ApiConstants.KID) @NotNull String kid) { log.debug("Key to be to be deleted - kid:{}", kid); final Conf conf = configurationService.findConf(); WebKeysConfiguration webkeys = configurationService.findConf().getWebKeys(); diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/LdapConfigurationResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/LdapConfigurationResource.java index c09729faf71..c6769e035db 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/LdapConfigurationResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/LdapConfigurationResource.java @@ -17,6 +17,7 @@ import io.jans.model.ldap.GluuLdapConfiguration; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; @@ -73,7 +74,7 @@ public Response getLdapConfiguration() { @Path(ApiConstants.NAME_PARAM_PATH) @ProtectedApi(scopes = { ApiAccessConstants.DATABASE_LDAP_READ_ACCESS } , groupScopes = { ApiAccessConstants.DATABASE_LDAP_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) - public Response getLdapConfigurationByName(@PathParam(ApiConstants.NAME) String name) { + public Response getLdapConfigurationByName(@Parameter(description = "Name of LDAP configuration") @PathParam(ApiConstants.NAME) String name) { GluuLdapConfiguration ldapConfiguration = findLdapConfigurationByName(name); return Response.ok(ldapConfiguration).build(); } @@ -156,7 +157,7 @@ public Response deleteLdapConfigurationByName(@PathParam(ApiConstants.NAME) Stri @Path(ApiConstants.NAME_PARAM_PATH) @Consumes(MediaType.APPLICATION_JSON_PATCH_JSON) @ProtectedApi(scopes = { ApiAccessConstants.DATABASE_LDAP_WRITE_ACCESS }, groupScopes = {}, superScopes = { ApiAccessConstants.SUPER_ADMIN_WRITE_ACCESS }) - public Response patchLdapConfigurationByName(@PathParam(ApiConstants.NAME) String name, + public Response patchLdapConfigurationByName(@Parameter(description = "Name of LDAP configuration") @PathParam(ApiConstants.NAME) String name, @NotNull String requestString) throws JsonPatchException, IOException { logger.debug("LDAP configuration to be patched - name:{}, requestString:{} ", name, requestString); GluuLdapConfiguration ldapConfiguration = findLdapConfigurationByName(name); diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ScopesResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ScopesResource.java index f4845572e30..fe02970097a 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ScopesResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/ScopesResource.java @@ -22,6 +22,7 @@ import io.jans.configapi.core.util.Jackson; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; @@ -82,13 +83,13 @@ public class ScopesResource extends ConfigBaseResource { @GET @ProtectedApi(scopes = { ApiAccessConstants.SCOPES_READ_ACCESS } , groupScopes = { ApiAccessConstants.SCOPES_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) - public Response getScopes(@DefaultValue("") @QueryParam(ApiConstants.TYPE) String type, - @DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, - @DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, - @DefaultValue(ApiConstants.DEFAULT_LIST_START_INDEX) @QueryParam(value = ApiConstants.START_INDEX) int startIndex, - @QueryParam(value = ApiConstants.SORT_BY) String sortBy, - @QueryParam(value = ApiConstants.SORT_ORDER) String sortOrder, - @DefaultValue("false") @QueryParam(value = ApiConstants.WITH_ASSOCIATED_CLIENTS) boolean withAssociatedClients) { + public Response getScopes(@Parameter(description = "Scope type") @DefaultValue("") @QueryParam(ApiConstants.TYPE) String type, + @Parameter(description = "Search size - max size of the results to return") @DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, + @Parameter(description = "Search pattern") @DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, + @Parameter(description = "The 1-based index of the first query result") @DefaultValue(ApiConstants.DEFAULT_LIST_START_INDEX) @QueryParam(value = ApiConstants.START_INDEX) int startIndex, + @Parameter(description = "Attribute whose value will be used to order the returned response") @QueryParam(value = ApiConstants.SORT_BY) String sortBy, + @Parameter(description = "Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\"") @QueryParam(value = ApiConstants.SORT_ORDER) String sortOrder, + @Parameter(description = "Boolean fag to indicate if clients associated with the scope are to be returned") @DefaultValue("false") @QueryParam(value = ApiConstants.WITH_ASSOCIATED_CLIENTS) boolean withAssociatedClients) { log.debug( "SCOPES to be fetched based on type:{}, limit:{}, pattern:{}, startIndex:{}, sortBy:{}, sortOrder:{}, withAssociatedClients:{}", type, limit, pattern, startIndex, sortBy, sortOrder, withAssociatedClients); @@ -110,7 +111,7 @@ public Response getScopes(@DefaultValue("") @QueryParam(ApiConstants.TYPE) Strin @ProtectedApi(scopes = { ApiAccessConstants.SCOPES_READ_ACCESS } , groupScopes = { ApiAccessConstants.SCOPES_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) @Path(ApiConstants.INUM_PATH) - public Response getScopeById(@NotNull @PathParam(ApiConstants.INUM) String inum, + public Response getScopeById(@Parameter(description = "Scope identifier") @NotNull @PathParam(ApiConstants.INUM) String inum, @DefaultValue("false") @QueryParam(value = ApiConstants.WITH_ASSOCIATED_CLIENTS) boolean withAssociatedClients) { log.debug("SCOPES to be fetched by inum:{}", inum); CustomScope scope = scopeService.getScopeByInum(inum, withAssociatedClients); @@ -129,7 +130,7 @@ public Response getScopeById(@NotNull @PathParam(ApiConstants.INUM) String inum, @ProtectedApi(scopes = { ApiAccessConstants.SCOPES_READ_ACCESS }, groupScopes = { ApiAccessConstants.SCOPES_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) @Path(ApiConstants.CREATOR + ApiConstants.CREATORID_PATH) - public Response getScopeByClientId(@NotNull @PathParam(ApiConstants.CREATORID) String creatorId) { + public Response getScopeByClientId(@Parameter(description = "Id of the scope creator. If creator is client then client_id if user then user_id") @NotNull @PathParam(ApiConstants.CREATORID) String creatorId) { log.debug("SCOPES to be fetched by creatorId:{}", creatorId); SearchRequest searchReq = new SearchRequest(); searchReq.setFilterAttributeName(Arrays.asList("creatorId")); @@ -150,7 +151,7 @@ public Response getScopeByClientId(@NotNull @PathParam(ApiConstants.CREATORID) S @ProtectedApi(scopes = { ApiAccessConstants.SCOPES_READ_ACCESS } , groupScopes = { ApiAccessConstants.SCOPES_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) @Path(ApiConstants.TYPE + ApiConstants.TYPE_PATH) - public Response getScopeByType(@NotNull @PathParam(ApiConstants.TYPE) String type) { + public Response getScopeByType(@Parameter(description = "Type of the scope") @NotNull @PathParam(ApiConstants.TYPE) String type) { log.debug("SCOPES to be fetched by type:{}", type); SearchRequest searchReq = new SearchRequest(); searchReq.setFilterAttributeName(Arrays.asList("jansScopeTyp")); @@ -232,7 +233,7 @@ public Response updateScope(@Valid Scope scope) { @Consumes(MediaType.APPLICATION_JSON_PATCH_JSON) @ProtectedApi(scopes = { ApiAccessConstants.SCOPES_WRITE_ACCESS }, groupScopes = {}, superScopes = { ApiAccessConstants.SUPER_ADMIN_WRITE_ACCESS }) @Path(ApiConstants.INUM_PATH) - public Response patchScope(@PathParam(ApiConstants.INUM) @NotNull String inum, @NotNull String pathString) + public Response patchScope(@Parameter(description = "Scope identifier") @PathParam(ApiConstants.INUM) @NotNull String inum, @NotNull String pathString) throws JsonPatchException, IOException { log.debug("SCOPES patch details - inum:{}, pathString:{}", inum, pathString); Scope existingScope = scopeService.getScopeByInum(inum); @@ -256,7 +257,7 @@ public Response patchScope(@PathParam(ApiConstants.INUM) @NotNull String inum, @ @DELETE @Path(ApiConstants.INUM_PATH) @ProtectedApi(scopes = { ApiAccessConstants.SCOPES_DELETE_ACCESS }, groupScopes = {}, superScopes = { ApiAccessConstants.SUPER_ADMIN_DELETE_ACCESS }) - public Response deleteScope(@PathParam(ApiConstants.INUM) @NotNull String inum) { + public Response deleteScope(@Parameter(description = "Scope identifier") @PathParam(ApiConstants.INUM) @NotNull String inum) { log.debug("SCOPES to be deleted - inum:{}", inum); Scope scope = scopeService.getScopeByInum(inum); checkResourceNotNull(scope, SCOPE); diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/SessionResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/SessionResource.java index 1da2c0840aa..a1ac93082ba 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/SessionResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/SessionResource.java @@ -13,6 +13,7 @@ import io.jans.configapi.util.ApiAccessConstants; import io.jans.configapi.util.ApiConstants; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -68,7 +69,7 @@ public Response getAllSessions() { @ProtectedApi(scopes = { ApiAccessConstants.JANS_AUTH_SESSION_DELETE_ACCESS, ApiAccessConstants.JANS_AUTH_REVOKE_SESSION } , groupScopes = {}, superScopes = { ApiAccessConstants.SUPER_ADMIN_DELETE_ACCESS }) @Path(ApiConstants.USERDN_PATH) - public Response getAppConfiguration(@PathParam(ApiConstants.USERDN) @NotNull String userDn) { + public Response getAppConfiguration(@Parameter(description = "User domain name") @PathParam(ApiConstants.USERDN) @NotNull String userDn) { logger.debug("userDn:{}", userDn); sessionService.revokeSession(userDn); return Response.ok().build(); diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/StatResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/StatResource.java index 496c31f60ab..4f0064a3e0e 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/StatResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/StatResource.java @@ -9,6 +9,7 @@ import io.jans.configapi.util.ApiConstants; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -48,9 +49,11 @@ public class StatResource extends ConfigBaseResource { @GET @ProtectedApi(scopes = { ApiAccessConstants.STATS_USER_READ_ACCESS, ApiAccessConstants.JANS_STAT } , groupScopes = {}, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) @Produces(MediaType.APPLICATION_JSON) - public Response getStatistics(@HeaderParam("Authorization") String authorization, - @QueryParam(value = "month") String month, @QueryParam(value = "start_month") String startMonth, - @QueryParam(value = "end_month") String endMonth, @QueryParam(value = "format") String format) { + public Response getStatistics(@Parameter(description = "Authorization code") @HeaderParam("Authorization") String authorization, + @Parameter(description = "Month for which the stat report is to be fetched. The parameter is mandatory if start_month and end_month parameters are not present.", example="202012 (2020 Dec) 202101 (2021 Jan)") @QueryParam(value = "month") String month, + @Parameter(description = "Start-Month for which the stat report is to be fetched") @QueryParam(value = "start_month") String startMonth, + @Parameter(description = "End-Month for which the stat report is to be fetched") @QueryParam(value = "end_month") String endMonth, + @Parameter(description = "Report format") @QueryParam(value = "format") String format) { if (StringUtils.isBlank(format)) { format = ""; } diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/UmaResourcesResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/UmaResourcesResource.java index d01993838e2..12d0aee75fb 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/UmaResourcesResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/UmaResourcesResource.java @@ -20,6 +20,7 @@ import io.jans.orm.exception.EntryPersistenceException; import io.jans.orm.model.PagedResult; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; @@ -70,11 +71,11 @@ public class UmaResourcesResource extends ConfigBaseResource { @ProtectedApi(scopes = { ApiAccessConstants.UMA_RESOURCES_READ_ACCESS } , groupScopes = { ApiAccessConstants.UMA_RESOURCES_WRITE_ACCESS, ApiAccessConstants.UMA_READ_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) public Response fetchUmaResources( - @DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, - @DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, - @DefaultValue(ApiConstants.DEFAULT_LIST_START_INDEX) @QueryParam(value = ApiConstants.START_INDEX) int startIndex, - @QueryParam(value = ApiConstants.SORT_BY) String sortBy, - @QueryParam(value = ApiConstants.SORT_ORDER) String sortOrder) { + @Parameter(description = "Search size - max size of the results to return") @DefaultValue(ApiConstants.DEFAULT_LIST_SIZE) @QueryParam(value = ApiConstants.LIMIT) int limit, + @Parameter(description = "Search pattern") @DefaultValue("") @QueryParam(value = ApiConstants.PATTERN) String pattern, + @Parameter(description = "The 1-based index of the first query result") @DefaultValue(ApiConstants.DEFAULT_LIST_START_INDEX) @QueryParam(value = ApiConstants.START_INDEX) int startIndex, + @Parameter(description = "Attribute whose value will be used to order the returned response") @QueryParam(value = ApiConstants.SORT_BY) String sortBy, + @Parameter(description = "Order in which the sortBy param is applied. Allowed values are \"ascending\" and \"descending\"") @QueryParam(value = ApiConstants.SORT_ORDER) String sortOrder) { logger.debug("UMA_RESOURCE to be fetched - limit:{}, pattern:{}, startIndex:{}, sortBy:{}, sortOrder:{}", limit, pattern, startIndex, sortBy, sortOrder); SearchRequest searchReq = createSearchRequest(umaResourceService.getBaseDnForResource(), pattern, sortBy, @@ -95,7 +96,7 @@ public Response fetchUmaResources( @Path(ApiConstants.ID_PATH) @ProtectedApi(scopes = { ApiAccessConstants.UMA_RESOURCES_READ_ACCESS }, groupScopes = { ApiAccessConstants.UMA_RESOURCES_WRITE_ACCESS, ApiAccessConstants.UMA_READ_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) - public Response getUmaResourceByInum(@PathParam(value = ApiConstants.ID) @NotNull String id) { + public Response getUmaResourceByInum(@Parameter(description = "Resource description ID") @PathParam(value = ApiConstants.ID) @NotNull String id) { logger.debug("UMA_RESOURCE to fetch by id:{}", id); return Response.ok(findOrThrow(id)).build(); } @@ -112,7 +113,7 @@ public Response getUmaResourceByInum(@PathParam(value = ApiConstants.ID) @NotNul @ProtectedApi(scopes = { ApiAccessConstants.UMA_RESOURCES_READ_ACCESS }, groupScopes = { ApiAccessConstants.UMA_RESOURCES_WRITE_ACCESS, ApiAccessConstants.UMA_READ_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_READ_ACCESS }) public Response getUmaResourceByAssociatedClient( - @PathParam(value = ApiConstants.CLIENTID) @NotNull String associatedClientId) { + @Parameter(description = "Client ID") @PathParam(value = ApiConstants.CLIENTID) @NotNull String associatedClientId) { logger.debug("UMA_RESOURCE to fetch by associatedClientId:{} ", associatedClientId); return Response.ok(getUmaResourceByClient(associatedClientId)).build(); @@ -187,7 +188,7 @@ public Response updateUmaResource(@Valid UmaResource resource) { @Consumes(MediaType.APPLICATION_JSON_PATCH_JSON) @ProtectedApi(scopes = { ApiAccessConstants.UMA_RESOURCES_WRITE_ACCESS }, groupScopes = { ApiAccessConstants.UMA_WRITE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_WRITE_ACCESS }) @Path(ApiConstants.ID_PATH) - public Response patchResource(@PathParam(ApiConstants.ID) @NotNull String id, @NotNull String pathString) + public Response patchResource(@Parameter(description = "Resource description ID") @PathParam(ApiConstants.ID) @NotNull String id, @NotNull String pathString) throws JsonPatchException, IOException { logger.debug("Patch for id:{} , pathString:{}", id, pathString); UmaResource existingResource = findOrThrow(id); @@ -207,7 +208,7 @@ public Response patchResource(@PathParam(ApiConstants.ID) @NotNull String id, @N @DELETE @Path(ApiConstants.ID_PATH) @ProtectedApi(scopes = { ApiAccessConstants.UMA_RESOURCES_DELETE_ACCESS }, groupScopes = { ApiAccessConstants.UMA_DELETE_ACCESS }, superScopes = { ApiAccessConstants.SUPER_ADMIN_DELETE_ACCESS }) - public Response deleteUmaResource(@PathParam(value = ApiConstants.ID) @NotNull String id) { + public Response deleteUmaResource(@Parameter(description = "Resource description ID") @PathParam(value = ApiConstants.ID) @NotNull String id) { logger.debug("UMA_RESOURCE to delete - id:{}", id); UmaResource umaResource = findOrThrow(id); umaResourceService.remove(umaResource); diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/util/AuthUtil.java b/jans-config-api/server/src/main/java/io/jans/configapi/util/AuthUtil.java index 916283e93fc..070862e7b6c 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/util/AuthUtil.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/util/AuthUtil.java @@ -11,6 +11,7 @@ import io.jans.as.persistence.model.Scope; import io.jans.configapi.model.configuration.AgamaConfiguration; import io.jans.configapi.model.configuration.AuditLogConf; +import io.jans.configapi.model.configuration.DataFormatConversionConf; import io.jans.configapi.security.api.ApiProtectionCache; import io.jans.configapi.security.client.AuthClientFactory; import io.jans.configapi.configuration.ConfigurationFactory; @@ -22,10 +23,13 @@ import io.jans.util.security.StringEncrypter.EncryptionException; import java.lang.reflect.Method; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -72,6 +76,10 @@ public String getAuthOpenidConfigurationUrl() { public AuditLogConf getAuditLogConf() { return this.configurationFactory.getApiAppConfiguration().getAuditLogConf(); } + + public DataFormatConversionConf getDataFormatConversionConf() { + return this.configurationFactory.getApiAppConfiguration().getDataFormatConversionConf(); + } public String getIssuer() { return this.configurationService.find().getIssuer(); @@ -416,5 +424,18 @@ public List getAllScopeList(Map> scope return scopeList; } + + public Date parseStringToDateObj(String dateString) { + String DATE_PATTERN_YYYY_MM_DD = "yyyy-MM-dd"; + SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_PATTERN_YYYY_MM_DD); + log.debug("parseStringToDateObj:{} ", dateString); + Date date = null; + try { + date = dateFormat.parse(dateString); + } catch (ParseException e) { + log.error("Error in parsing string to date. Allowed Date Format : {}, Date-String : {} ", DATE_PATTERN_YYYY_MM_DD, dateString); + } + return date; + } } diff --git a/jans-config-api/server/src/main/resources/META-INF/beans.xml b/jans-config-api/server/src/main/resources/META-INF/beans.xml index a22aceb3cf6..b812014eb46 100644 --- a/jans-config-api/server/src/main/resources/META-INF/beans.xml +++ b/jans-config-api/server/src/main/resources/META-INF/beans.xml @@ -4,6 +4,7 @@ xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_3_0.xsd" bean-discovery-mode="all" version="3.0"> - io.jans.configapi.interceptor.AuditLogInterceptor + io.jans.configapi.interceptor.AuditLogInterceptor + io.jans.configapi.interceptor.RequestReaderInterceptor diff --git a/jans-config-api/shared/src/main/java/io/jans/configapi/core/rest/BaseResource.java b/jans-config-api/shared/src/main/java/io/jans/configapi/core/rest/BaseResource.java index 57aed1fd011..c57b9bc3a80 100644 --- a/jans-config-api/shared/src/main/java/io/jans/configapi/core/rest/BaseResource.java +++ b/jans-config-api/shared/src/main/java/io/jans/configapi/core/rest/BaseResource.java @@ -7,16 +7,22 @@ package io.jans.configapi.core.rest; import static io.jans.as.model.util.Util.escapeLog; + +import io.jans.configapi.core.interceptor.RequestInterceptor; import io.jans.configapi.core.model.ApiError; import io.jans.configapi.core.model.SearchRequest; import io.jans.configapi.core.util.Util; import io.jans.orm.model.SortOrder; import jakarta.inject.Inject; +import jakarta.servlet.http.HttpServletRequest; import jakarta.ws.rs.BadRequestException; import jakarta.ws.rs.InternalServerErrorException; import jakarta.ws.rs.NotFoundException; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.UriInfo; import java.util.List; import java.util.Map; @@ -27,8 +33,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +@RequestInterceptor public class BaseResource { - + @Inject Util util; 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 4a9cbb38546..15d372e09cc 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 @@ -55,10 +55,17 @@ ] }, "auditLogConf": { - "enabled": true, - "headerAttributes": [ - "User-inum" - ] + "enabled": true, + "ignoreHttpMethod": [], + "headerAttributes": [ + "User-inum" + ] + }, + "dataFormatConversionConf": { + "enabled": true, + "ignoreHttpMethod": [ + "@jakarta.ws.rs.GET()" + ] } } diff --git a/jans-orm/core/src/main/java/io/jans/orm/PersistenceEntryManager.java b/jans-orm/core/src/main/java/io/jans/orm/PersistenceEntryManager.java index 4542e1e3187..6c8ddc5834b 100644 --- a/jans-orm/core/src/main/java/io/jans/orm/PersistenceEntryManager.java +++ b/jans-orm/core/src/main/java/io/jans/orm/PersistenceEntryManager.java @@ -35,6 +35,7 @@ import io.jans.orm.model.SearchScope; import io.jans.orm.model.SortOrder; import io.jans.orm.operation.PersistenceOperationService; +import io.jans.orm.reflect.property.PropertyAnnotation; import io.jans.orm.search.filter.Filter; /** @@ -148,6 +149,7 @@ List getAttributeDataListFromCustomAttributesList(Object entry, A String propertyName); List getCustomAttributesListFromAttributeDataList(Object entry, AttributesList attributesList, String propertyName, Collection attributes); + List getEntryPropertyAnnotations(Class entryClass); boolean destroy(); diff --git a/jans-orm/core/src/main/java/io/jans/orm/impl/BaseEntryManager.java b/jans-orm/core/src/main/java/io/jans/orm/impl/BaseEntryManager.java index c7c7752356a..2cb62cd292d 100644 --- a/jans-orm/core/src/main/java/io/jans/orm/impl/BaseEntryManager.java +++ b/jans-orm/core/src/main/java/io/jans/orm/impl/BaseEntryManager.java @@ -1744,7 +1744,7 @@ public List getCustomAttributesListFromAttributeDataList(Object entry, A return getCustomAttributesListFromAttributeData(entryClass, attributesList, propertyName, attributes, null); } - protected List getEntryPropertyAnnotations(Class entryClass) { + public List getEntryPropertyAnnotations(Class entryClass) { final List annotations = getEntryClassAnnotations(entryClass, "property_", LDAP_ENTRY_PROPERTY_ANNOTATIONS); // KeyShortcuter.initIfNeeded(entryClass, annotations); return annotations;