diff --git a/jans-config-api/common/src/main/java/io/jans/configapi/util/ApiConstants.java b/jans-config-api/common/src/main/java/io/jans/configapi/util/ApiConstants.java index 308a558a2fc..c257bf413e5 100644 --- a/jans-config-api/common/src/main/java/io/jans/configapi/util/ApiConstants.java +++ b/jans-config-api/common/src/main/java/io/jans/configapi/util/ApiConstants.java @@ -110,6 +110,7 @@ private ApiConstants() {} public static final String ALL = "all"; public static final String ACTIVE = "active"; public static final String INACTIVE = "inactive"; + public static final String ADD_SCRIPT_TEMPLATE = "addScriptTemplate"; // API Protection public static final String PROTECTION_TYPE_OAUTH2 = "oauth2"; diff --git a/jans-config-api/docs/jans-config-api-swagger.yaml b/jans-config-api/docs/jans-config-api-swagger.yaml index af85a6f098f..e77d7e184c6 100644 --- a/jans-config-api/docs/jans-config-api-swagger.yaml +++ b/jans-config-api/docs/jans-config-api-swagger.yaml @@ -3853,6 +3853,15 @@ paths: summary: Adds a new custom script description: Adds a new custom script operationId: post-config-scripts + parameters: + - name: addScriptTemplate + in: query + description: Boolean flag to indicate if script template is to be added. If + CustomScript request object has script populated then script template will + not be added. + schema: + type: boolean + default: false requestBody: description: CustomScript object content: @@ -7524,19 +7533,19 @@ components: $ref: '#/components/schemas/AttributeValidation' tooltip: type: string - whitePagesCanView: - type: boolean - userCanEdit: - type: boolean - userCanAccess: + userCanView: type: boolean adminCanAccess: type: boolean - userCanView: + adminCanView: + type: boolean + userCanEdit: type: boolean adminCanEdit: type: boolean - adminCanView: + userCanAccess: + type: boolean + whitePagesCanView: type: boolean baseDn: type: string @@ -8257,8 +8266,6 @@ components: type: object additionalProperties: type: string - fapi: - type: boolean allResponseTypesSupported: uniqueItems: true type: array @@ -8268,6 +8275,8 @@ components: - code - token - id_token + fapi: + type: boolean AuthenticationFilter: required: - baseDn @@ -9127,6 +9136,7 @@ components: type: string enum: - ldap + - db - file baseDn: type: string @@ -9234,6 +9244,12 @@ components: type: string "y": type: string + key_ops: + type: string + enum: + - "KeyOps{value='connect'} CONNECT" + - "KeyOps{value='ssa'} SSA" + - "KeyOps{value='all'} ALL" WebKeysConfiguration: type: object properties: diff --git a/jans-config-api/plugins/docs/fido2-plugin-swagger.yaml b/jans-config-api/plugins/docs/fido2-plugin-swagger.yaml index e2f1847d3f0..3f1df9fe063 100644 --- a/jans-config-api/plugins/docs/fido2-plugin-swagger.yaml +++ b/jans-config-api/plugins/docs/fido2-plugin-swagger.yaml @@ -130,6 +130,10 @@ components: type: array items: type: string + superGluuEnabled: + type: boolean + oldU2fMigrationEnabled: + type: boolean fido2Configuration: $ref: '#/components/schemas/Fido2Configuration' Fido2Configuration: @@ -172,6 +176,30 @@ components: type: array items: type: string + Fido2DeviceData: + type: object + properties: + uuid: + type: string + token: + type: string + writeOnly: true + type: + type: string + platform: + type: string + name: + type: string + os_name: + type: string + os_version: + type: string + custom_data: + type: object + additionalProperties: + type: string + push_token: + type: string Fido2RegistrationData: type: object properties: @@ -209,6 +237,7 @@ components: - pending - registered - compromised + - canceled counter: type: integer format: int32 @@ -228,15 +257,32 @@ components: type: string challange: type: string + challengeHash: + type: string creationDate: type: string format: date-time userInum: type: string - publicKeyId: + rpId: + type: string + sessionStateId: + type: string + expirationDate: type: string + format: date-time + deletable: + type: boolean + ttl: + type: integer + format: int32 displayName: type: string + publicKeyId: + type: string + publicKeyIdHash: + type: integer + format: int32 registrationData: $ref: '#/components/schemas/Fido2RegistrationData' counter: @@ -248,10 +294,15 @@ components: - pending - registered - compromised + - canceled deviceNotificationConf: type: string - challangeHash: - type: string + deviceData: + $ref: '#/components/schemas/Fido2DeviceData' + expiration: + type: integer + format: int32 + writeOnly: true baseDn: type: string securitySchemes: diff --git a/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/service/RegistrationPersistenceService.java b/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/service/RegistrationPersistenceService.java deleted file mode 100644 index 43686138e50..00000000000 --- a/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/service/RegistrationPersistenceService.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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.plugin.fido2.service; - -import io.jans.as.common.service.common.UserService; -import jakarta.enterprise.inject.Specializes; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import jakarta.enterprise.context.ApplicationScoped; -/** - * Override RegistrationPersistenceService bean - * @author Yuriy Movchan - * @version Jun 01, 2023 - */ -@ApplicationScoped -public class RegistrationPersistenceService extends io.jans.as.common.service.common.fido2.RegistrationPersistenceService { - - public String getUserInum(String userName) - { - return userService.getUserInum(userName); - } - - @Inject - @Named("userFido2Srv") - protected UserService userService; - -} 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 78dc7dd88aa..6ba10d39923 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 @@ -196,7 +196,7 @@ public Response updateUser(@Valid CustomUser customUser) logger.debug("Updated user:{}", user); } catch (Exception ex) { logger.error("Error while updating user", ex); - thorwInternalServerException(ex); + throwInternalServerException(ex); } // excludedAttributes diff --git a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/service/UserMgmtService.java b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/service/UserMgmtService.java index 96b448e1931..39248893166 100644 --- a/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/service/UserMgmtService.java +++ b/jans-config-api/plugins/user-mgt-plugin/src/main/java/io/jans/configapi/plugin/mgt/service/UserMgmtService.java @@ -3,6 +3,7 @@ import com.github.fge.jsonpatch.JsonPatchException; import io.jans.as.common.model.common.User; import io.jans.as.common.util.AttributeConstants; +import io.jans.configapi.core.service.ConfigUserService; import io.jans.as.model.config.StaticConfiguration; import io.jans.as.model.configuration.AppConfiguration; import io.jans.configapi.core.util.Jackson; @@ -34,7 +35,7 @@ @ApplicationScoped @Named("userMgmtSrv") -public class UserMgmtService extends io.jans.as.common.service.common.UserService { +public class UserMgmtService { @Inject private Logger logger; @@ -48,26 +49,29 @@ public class UserMgmtService extends io.jans.as.common.service.common.UserServic @Inject ConfigurationService configurationService; + @Inject + PersistenceEntryManager persistenceEntryManager; + @Inject AuthUtil authUtil; @Inject MgtUtil mgtUtil; - private static final String BIRTH_DATE = "birthdate"; + @Inject + ConfigUserService userService; - @Override - public List getPersonCustomObjectClassList() { - return appConfiguration.getPersonCustomObjectClassList(); - } + private static final String BIRTH_DATE = "birthdate"; - @Override public String getPeopleBaseDn() { - return staticConfiguration.getBaseDn().getPeople(); + return userService.getPeopleBaseDn(); } public PagedResult searchUsers(SearchRequest searchRequest) { - logger.debug("Search Users with searchRequest:{}", escapeLog(searchRequest)); + if (logger.isDebugEnabled()) { + logger.debug("Search Users with searchRequest:{}, getPeopleBaseDn():{}", escapeLog(searchRequest), + getPeopleBaseDn()); + } Filter searchFilter = null; List filters = new ArrayList<>(); if (searchRequest.getFilterAssertionValue() != null && !searchRequest.getFilterAssertionValue().isEmpty()) { @@ -85,7 +89,7 @@ public PagedResult searchUsers(SearchRequest searchRequest) { searchFilter = Filter.createORFilter(filters); } logger.debug("Users searchFilter:{}", searchFilter); - return persistenceEntryManager.findPagedEntries(getPeopleBaseDn(), User.class, searchFilter, null, + return persistenceEntryManager.findPagedEntries(userService.getPeopleBaseDn(), User.class, searchFilter, null, searchRequest.getSortBy(), SortOrder.getByValue(searchRequest.getSortOrder()), searchRequest.getStartIndex(), searchRequest.getCount(), searchRequest.getMaxCount()); @@ -104,7 +108,7 @@ public User patchUser(String inum, UserPatchRequest userPatchRequest) throws Jso return null; } - User user = getUserByInum(inum); + User user = userService.getUserByInum(inum); if (user == null) { return null; } @@ -126,7 +130,7 @@ public User patchUser(String inum, UserPatchRequest userPatchRequest) throws Jso // persist user ignoreCustomObjectClassesForNonLDAP(user); - user = updateUser(user); + user = userService.updateUser(user); logger.debug("User after patch user:{}", user); return user; @@ -135,7 +139,7 @@ public User patchUser(String inum, UserPatchRequest userPatchRequest) throws Jso public User getUserBasedOnInum(String inum) { User result = null; try { - result = getUserByInum(inum); + result = userService.getUserByInum(inum); } catch (Exception ex) { logger.error("Failed to load user entry", ex); } @@ -150,12 +154,12 @@ private User updateCustomAttributes(User user, List custo } for (CustomObjectAttribute attribute : customAttributes) { - CustomObjectAttribute existingAttribute = getCustomAttribute(user, attribute.getName()); + CustomObjectAttribute existingAttribute = userService.getCustomAttribute(user, attribute.getName()); logger.debug("Existing CustomAttributes with existingAttribute:{} ", existingAttribute); // add if (existingAttribute == null) { - boolean result = addUserAttribute(user, attribute.getName(), attribute.getValues(), + boolean result = userService.addUserAttribute(user, attribute.getName(), attribute.getValues(), attribute.isMultiValued()); logger.debug("Result of adding CustomAttributes attribute:{} , result:{} ", attribute, result); } @@ -324,4 +328,12 @@ public User ignoreCustomObjectClassesForNonLDAP(User user) { } return user; } + + public User addUser(User user, boolean active) { + return userService.addUser(user, active); + } + + public User updateUser(User user) { + return userService.updateUser(user); + } } diff --git a/jans-config-api/profiles/local/test.properties b/jans-config-api/profiles/local/test.properties index 92aaa2de881..bd94ee40460 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 https://jans.io/oauth/config/read-all https://jans.io/oauth/config/write-all https://jans.io/oauth/config/delete-all https://jans.io/oauth/config/openid-read https://jans.io/oauth/config/openid-write https://jans.io/oauth/config/openid-delete https://jans.io/oauth/config/uma-read https://jans.io/oauth/config/uma-write https://jans.io/oauth/config/uma-delete https://jans.io/oauth/jans-auth-server/config/adminui/user/role.readonly https://jans.io/oauth/jans-auth-server/config/adminui/user/role.write https://jans.io/oauth/jans-auth-server/config/adminui/read-all https://jans.io/oauth/jans-auth-server/config/adminui/write-all https://jans.io/oauth/jans-auth-server/config/adminui/user/role.delete https://jans.io/oauth/jans-auth-server/config/adminui/delete-all https://jans.io/oauth/jans-auth-server/config/adminui/user/permission.readonly https://jans.io/oauth/jans-auth-server/config/adminui/user/permission.write https://jans.io/oauth/jans-auth-server/config/adminui/user/permission.write https://jans.io/oauth/jans-auth-server/config/adminui/user/permission.delete https://jans.io/oauth/jans-auth-server/config/adminui/user/rolePermissionMapping.readonly https://jans.io/oauth/jans-auth-server/config/adminui/user/rolePermissionMapping.write https://jans.io/oauth/jans-auth-server/config/adminui/user/rolePermissionMapping.delete https://jans.io/oauth/jans-auth-server/config/adminui/license.readonly https://jans.io/oauth/jans-auth-server/config/adminui/license.write https://jans.io/oauth/config/plugin.readonly # jans.server -token.endpoint=https://jans.server2/jans-auth/restv1/token +token.endpoint=https://jans.server1/jans-auth/restv1/token token.grant.type=client_credentials -test.client.id=1800.c9c0b756-a1fc-4013-9feb-64d531ac2dc1 -test.client.secret=ONfjpemnGAFU -test.issuer=https://jans.server2/ \ No newline at end of file +test.client.id=1800.53043ff9-102c-4b52-8456-c7c5cde2dfd3 +test.client.secret=tYRVpvtI4S3U +test.issuer=https://jans.server1/ \ No newline at end of file diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AcrsResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AcrsResource.java index cfcfc6b52b3..cfa7b5f9ab4 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AcrsResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AcrsResource.java @@ -81,7 +81,7 @@ public Response updateDefaultAuthenticationMethod(@NotNull AuthenticationMethod log.debug("ACRS details to update - authenticationMethod:{}", authenticationMethod); if (authenticationMethod == null || StringUtils.isBlank(authenticationMethod.getDefaultAcr())) { - thorwBadRequestException("Default authentication method should not be null or empty !"); + throwBadRequestException("Default authentication method should not be null or empty !"); } if (authenticationMethod != null) { 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 3226e414a01..84bd3cacd1d 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 @@ -138,7 +138,7 @@ public Response createFlow(@Valid Flow flow) Flow existingFlow = findFlow(flow.getQname(), false); logger.debug(" existingFlow:{}", existingFlow); if (existingFlow != null) { - thorwBadRequestException("Flow identified by name '" + flow.getQname() + "' already exists!"); + throwBadRequestException("Flow identified by name '" + flow.getQname() + "' already exists!"); } // validate flow data @@ -203,7 +203,7 @@ public Response createFlowFromSource(@Parameter(description = "Agama Flow name") Flow existingFlow = findFlow(decodedFlowName, false); logger.debug(" existing-flow:{}", existingFlow); if (existingFlow != null) { - thorwBadRequestException("Flow identified by name '" + decodedFlowName + "' already exists!"); + throwBadRequestException("Flow identified by name '" + decodedFlowName + "' already exists!"); } Flow flow = new Flow(); @@ -347,7 +347,7 @@ private void validateAgamaFlowData(Flow flow, boolean checkNonMandatoryFields) String validateMsg = agamaFlowService.validateFlowFields(flow, checkNonMandatoryFields); logger.debug("Agama Flow to be validation msg:{} ", validateMsg); if (StringUtils.isNotBlank(validateMsg)) { - thorwBadRequestException(validateMsg); + throwBadRequestException(validateMsg); } // validate syntax @@ -365,7 +365,7 @@ private void validateSyntax(Flow flow) { } catch (SyntaxException | TranspilerException e) { logger.error("Transpiler exception", e); e.setStackTrace(new StackTraceElement[0]); - thorwBadRequestException(e); + throwBadRequestException(e); } } diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AuthConfigResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AuthConfigResource.java index 7f9e69f4c6b..0ee8a7187f2 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AuthConfigResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/AuthConfigResource.java @@ -128,7 +128,7 @@ private void validateAgamaConfiguration(EngineConfig engineConfig) { } if (engineConfig.getMaxItemsLoggedInCollections() < 1) { - thorwBadRequestException("maxItemsLoggedInCollections should be greater than zero -> " + throwBadRequestException("maxItemsLoggedInCollections should be greater than zero -> " + engineConfig.getMaxItemsLoggedInCollections()); } } 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 b92c03fe928..602928460f4 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 @@ -375,7 +375,7 @@ private Client checkScopeFormat(Client client) { logger.debug("Scope validation result - validScopes:{}, invalidScopes:{} ", validScopes, invalidScopes); if (!invalidScopes.isEmpty()) { - thorwBadRequestException("Invalid scope in request -> " + invalidScopes.toString()); + throwBadRequestException("Invalid scope in request -> " + invalidScopes.toString()); } // reset scopes @@ -425,7 +425,7 @@ private Client validateClaim(Client client) { logger.debug("Claim validation result - validClaims:{}, invalidClaims:{} ", validClaims, invalidClaims); if (!invalidClaims.isEmpty()) { - thorwBadRequestException("Invalid claim in request -> " + invalidClaims.toString()); + throwBadRequestException("Invalid claim in request -> " + invalidClaims.toString()); } // reset Claims 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 c4934cdc888..079e7981c6d 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 @@ -16,6 +16,7 @@ import io.jans.service.custom.CustomScriptService; import io.jans.configapi.util.ApiAccessConstants; import io.jans.configapi.util.ApiConstants; +import io.jans.model.ScriptLocationType; import io.jans.model.custom.script.CustomScriptType; import io.jans.model.custom.script.model.CustomScript; import io.jans.orm.model.PagedResult; @@ -43,6 +44,8 @@ import java.util.Objects; import java.util.UUID; +import org.apache.commons.lang.StringUtils; + @Path(ApiConstants.CONFIG + ApiConstants.SCRIPTS) @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @@ -93,7 +96,8 @@ 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(@Parameter(description = "Script name") @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)); @@ -118,7 +122,8 @@ public Response getCustomScriptByName(@Parameter(description = "Script name") @P @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(@Parameter(description = "Script type") @PathParam(ApiConstants.TYPE) @NotNull String type, + 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, @@ -148,7 +153,8 @@ public Response getCustomScriptsByTypePattern(@Parameter(description = "Script t @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(@Parameter(description = "Script identifier") @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)); } @@ -176,13 +182,21 @@ public Response getCustomScriptByInum(@Parameter(description = "Script identifie @POST @ProtectedApi(scopes = { ApiAccessConstants.SCRIPTS_WRITE_ACCESS }, groupScopes = {}, superScopes = { ApiAccessConstants.SUPER_ADMIN_WRITE_ACCESS }) - public Response createScript(@Valid CustomScript customScript) { - logger.debug("Custom Script to create - customScript:{}", customScript); + public Response createScript(@Valid CustomScript customScript, + @Parameter(description = "Boolean flag to indicate if script template is to be added. If CustomScript request object has script populated then script template will not be added.") @DefaultValue("false") @QueryParam(value = ApiConstants.ADD_SCRIPT_TEMPLATE) boolean addScriptTemplate) { + logger.info("Custom Script to create - customScript:{}, addScriptTemplate:{}", customScript, addScriptTemplate); Objects.requireNonNull(customScript, "Attempt to create null custom script"); String inum = customScript.getInum(); if (StringHelper.isEmpty(inum)) { inum = UUID.randomUUID().toString(); } + if (StringUtils.isBlank(customScript.getScript()) && !addScriptTemplate) { + customScript.setScript(""); // this will ensure that default Script Template is not added + } + + // validate Script LocationType value + validateScriptLocationType(customScript); + customScript.setDn(customScriptService.buildDn(inum)); customScript.setInum(inum); customScriptService.add(customScript); @@ -208,6 +222,10 @@ public Response updateScript(@Valid @NotNull CustomScript customScript) { checkResourceNotNull(existingScript, CUSTOM_SCRIPT); customScript.setInum(existingScript.getInum()); logger.debug("Custom Script updated {}", customScript); + + // validate Script LocationType value + validateScriptLocationType(customScript); + customScriptService.update(customScript); return Response.ok(customScript).build(); } @@ -223,7 +241,8 @@ 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(@Parameter(description = "Script identifier") @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)); @@ -251,8 +270,9 @@ public Response deleteScript(@Parameter(description = "Script identifier") @Path @ProtectedApi(scopes = { ApiAccessConstants.SCRIPTS_WRITE_ACCESS }, groupScopes = {}, superScopes = { ApiAccessConstants.SUPER_ADMIN_WRITE_ACCESS }) @Path(ApiConstants.INUM_PATH) - public Response patchAtribute(@Parameter(description = "Script identifier") @PathParam(ApiConstants.INUM) @NotNull String inum, @NotNull String pathString) - throws JsonPatchException, IOException { + public Response patchScript( + @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), escapeLog(pathString)); @@ -289,4 +309,22 @@ private PagedResult doSearch(String pattern, String sortBy, String return pagedResult; } + /** + * ScriptLocationType.LDAP has been deprecated and hence for any new script + * creation or modification we need to ensure that valid values are used. + * + * @param customScript + */ + private void validateScriptLocationType(CustomScript customScript) { + logger.info("validate ScriptLocationType - customScript:{}", customScript); + if (customScript == null || customScript.getLocationType() == null) { + return; + } + + if (ScriptLocationType.LDAP.getValue().equalsIgnoreCase(customScript.getLocationType().getValue())) { + + throwBadRequestException("Invalid value for '"+customScript.LOCATION_TYPE_MODEL_PROPERTY+"' in request is 'ldap' which is deprecated. Use '"+ScriptLocationType.DB.getValue()+"' instead."); + } + } + } diff --git a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/OrganizationResource.java b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/OrganizationResource.java index c878d482d11..9f22bbd2551 100644 --- a/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/OrganizationResource.java +++ b/jans-config-api/server/src/main/java/io/jans/configapi/rest/resource/auth/OrganizationResource.java @@ -76,7 +76,7 @@ public Response patchOrganization(@NotNull String pathString) throws JsonPatchEx } catch (Exception ex) { logger.error("Error while patching Organization details", ex); - thorwInternalServerException(ex); + throwInternalServerException(ex); } return Response.ok(organizationService.getOrganization()).build(); } diff --git a/jans-config-api/server/src/test/resources/feature/config/scripts/custom/generic/custom.feature b/jans-config-api/server/src/test/resources/feature/config/scripts/custom/generic/custom.feature index f343040007e..2bee94d9729 100644 --- a/jans-config-api/server/src/test/resources/feature/config/scripts/custom/generic/custom.feature +++ b/jans-config-api/server/src/test/resources/feature/config/scripts/custom/generic/custom.feature @@ -84,4 +84,20 @@ Feature: Verify Custom Script configuration endpoint When method PATCH Then status 200 And print response - And assert response.length !=0 \ No newline at end of file + And assert response.length !=0 + + + Scenario: Post person custom script by inum + Given url mainUrl + And header Authorization = 'Bearer ' + accessToken + And request read('post-script.json') + When method POST + Then status 201 + And print response + And print response.inum + And print 'Delete newly created script' + Given url mainUrl + '/' +response.inum + And header Authorization = 'Bearer ' + accessToken + When method DELETE + Then status 204 + And print response \ No newline at end of file diff --git a/jans-config-api/server/src/test/resources/feature/config/scripts/custom/generic/post-script.json b/jans-config-api/server/src/test/resources/feature/config/scripts/custom/generic/post-script.json new file mode 100644 index 00000000000..a4c0beea841 --- /dev/null +++ b/jans-config-api/server/src/test/resources/feature/config/scripts/custom/generic/post-script.json @@ -0,0 +1,17 @@ +{ +"internal": false, +"level": 1, +"programmingLanguage": "PYTHON", +"description": "Introspection Custom Parameters Sample Script", +"enabled": false, +"revision": 1, +"moduleProperties": [ + { + "value2": "db", + "value1": "location_type" + } +], +"scriptType": "INTROSPECTION", +"name": "introspection_custom_params", +"modified": false +} \ No newline at end of file diff --git a/jans-config-api/server/src/test/resources/feature/config/scripts/custom/persons/person-script.json b/jans-config-api/server/src/test/resources/feature/config/scripts/custom/persons/person-script.json index b424052b2b8..72b3497b0e1 100644 --- a/jans-config-api/server/src/test/resources/feature/config/scripts/custom/persons/person-script.json +++ b/jans-config-api/server/src/test/resources/feature/config/scripts/custom/persons/person-script.json @@ -4,13 +4,13 @@ "enabled": false, "internal": false, "level": 30, - "locationType": "ldap", + "locationType": "db", "modified": false, "moduleProperties": [ { "description": "", "value1": "location_type", - "value2": "ldap" + "value2": "db" }, { "description": "", diff --git a/jans-config-api/server/src/test/resources/feature/config/scripts/custom/persons/person-scripts.feature b/jans-config-api/server/src/test/resources/feature/config/scripts/custom/persons/person-scripts.feature index 404ca019ee3..47163507930 100644 --- a/jans-config-api/server/src/test/resources/feature/config/scripts/custom/persons/person-scripts.feature +++ b/jans-config-api/server/src/test/resources/feature/config/scripts/custom/persons/person-scripts.feature @@ -46,7 +46,7 @@ Then status 200 And assert response.entries.length <= 3 And assert response.entries[0].scriptType == 'person_authentication' - +@ignore @CreateUpdateDelete Scenario: Create new Person Script Given url mainUrl + '/type' @@ -119,4 +119,4 @@ And print request When method GET And print response Then status 200 -And assert response.scriptType == 'person_authentication' \ No newline at end of file +And assert response.scriptType == 'person_authentication' 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 75f3971baf8..4cb76109757 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 @@ -119,19 +119,19 @@ public static void checkNotEmpty(String attribute, String attributeName) { } } - public static void thorwBadRequestException(String msg) { + public static void throwBadRequestException(String msg) { throw new BadRequestException(getBadRequestException(msg)); } - public static void thorwBadRequestException(Object obj) { + public static void throwBadRequestException(Object obj) { throw new BadRequestException(getBadRequestException(obj)); } - public static void thorwInternalServerException(String msg) { + public static void throwInternalServerException(String msg) { throw new InternalServerErrorException(getInternalServerException(msg)); } - public static void thorwInternalServerException(Throwable throwable) { + public static void throwInternalServerException(Throwable throwable) { throwable = findRootError(throwable); if (throwable != null) { throw new InternalServerErrorException(getInternalServerException(throwable.getMessage())); @@ -194,7 +194,7 @@ protected SearchRequest createSearchRequest(String schemas, String filter, Strin int maxCount = maximumRecCount; log.debug(" count:{}, maxCount:{}", count, maxCount); if (count > maxCount) { - thorwBadRequestException("Maximum number of results per page is " + maxCount); + throwBadRequestException("Maximum number of results per page is " + maxCount); } count = count == null ? maxCount : count; diff --git a/jans-config-api/shared/src/main/java/io/jans/configapi/core/service/ConfigUserService.java b/jans-config-api/shared/src/main/java/io/jans/configapi/core/service/ConfigUserService.java new file mode 100644 index 00000000000..8806e7a0db3 --- /dev/null +++ b/jans-config-api/shared/src/main/java/io/jans/configapi/core/service/ConfigUserService.java @@ -0,0 +1,39 @@ +/* + * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. + * + * Copyright (c) 2020, Janssen Project + */ + +package io.jans.configapi.core.service; + +import java.util.List; + +import io.jans.as.common.util.AttributeConstants; +import io.jans.as.model.config.StaticConfiguration; +import io.jans.as.model.configuration.AppConfiguration; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + + +@ApplicationScoped +public class ConfigUserService extends io.jans.as.common.service.common.UserService { + + public static final String[] USER_OBJECT_CLASSES = new String[]{AttributeConstants.JANS_PERSON}; + + @Inject + private StaticConfiguration staticConfiguration; + + @Inject + private AppConfiguration appConfiguration; + + @Override + public List getPersonCustomObjectClassList() { + return appConfiguration.getPersonCustomObjectClassList(); + } + + @Override + public String getPeopleBaseDn() { + return staticConfiguration.getBaseDn().getPeople(); + } + +} diff --git a/jans-core/util/src/main/java/io/jans/model/ScriptLocationType.java b/jans-core/util/src/main/java/io/jans/model/ScriptLocationType.java index 6b203cfde3d..faca4fb00aa 100644 --- a/jans-core/util/src/main/java/io/jans/model/ScriptLocationType.java +++ b/jans-core/util/src/main/java/io/jans/model/ScriptLocationType.java @@ -18,7 +18,13 @@ */ public enum ScriptLocationType implements AttributeEnum { - LDAP("ldap", "Database"), FILE("file", "File"); + /** + * @deprecated Use DB instead. + */ + @Deprecated + LDAP("ldap", "Ldap"), //Todo: migrate existing scripts with LDAP to DB + DB("db", "Database"), + FILE("file", "File"); private String value; private String displayName; diff --git a/jans-linux-setup/jans_setup/schema/jans_schema.json b/jans-linux-setup/jans_setup/schema/jans_schema.json index 5d3003d176f..284a00bbe46 100644 --- a/jans-linux-setup/jans_setup/schema/jans_schema.json +++ b/jans-linux-setup/jans_setup/schema/jans_schema.json @@ -787,6 +787,7 @@ "names": [ "jansPersistentJWT" ], + "multivalued": true, "oid": "jansAttr", "substr": "caseIgnoreSubstringsMatch", "syntax": "1.3.6.1.4.1.1466.115.121.1.15",