opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/rest2ldap/endpoints/api/users-and-groups-v1.json
@@ -74,7 +74,7 @@ "frapi:opendj:rest2ldap:user:1.0": { "superType": "frapi:opendj:rest2ldap:object:1.0", "objectClasses": [ "person", "organizationalPerson", "inetOrgPerson" ], "supportedActions": [ "passwordModify" ], "supportedActions": [ "modifyPassword", "resetPassword" ], "properties": { "_id": { "type": "simple", opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Action.java
@@ -21,15 +21,14 @@ * supported. */ public enum Action { // Notes: // // - actions are likely to become an extension point in future versions of Rest2Ldap, in which case this enum // will need to be converted into a regular class or interface, // // - the actions are named so that they can be parsed easily from JSON. // Note: actions are likely to become an extension point in future versions of Rest2Ldap, in which case this enum // will need to be converted into a regular class or interface, /** An action that allows users to change or reset their password. */ PASSWORDMODIFY("passwordModify"); /** An action that allows users to change their password. */ MODIFY_PASSWORD("modifyPassword"), /** An action that allows users to reset their password. */ RESET_PASSWORD("resetPassword"); private final String actionId; opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceImpl.java
@@ -159,8 +159,10 @@ final Action action = asEnum(request.getAction(), Action.class); if (resource.hasSupportedAction(action)) { switch (action) { case PASSWORDMODIFY: return passwordModify(context, resourceId, request); case RESET_PASSWORD: return resetPassword(context, resourceId, request); case MODIFY_PASSWORD: return modifyPassword(context, resourceId, request); } } } catch (final IllegalArgumentException ignored) { @@ -170,7 +172,41 @@ } private Promise<ActionResponse, ResourceException> passwordModify( private Promise<ActionResponse, ResourceException> resetPassword( final Context context, final String resourceId, final ActionRequest request) { if (!context.containsContext(ClientContext.class) || !context.asContext(ClientContext.class).isSecure()) { return newResourceException(FORBIDDEN, ERR_PASSWORD_RESET_SECURE_CONNECTION.get().toString()).asPromise(); } if (!context.containsContext(SecurityContext.class) || context.asContext(SecurityContext.class).getAuthenticationId() == null) { return newResourceException(FORBIDDEN, ERR_PASSWORD_RESET_USER_AUTHENTICATED.get().toString()).asPromise(); } final Connection connection = connectionFrom(context); return resolveResourceDnAndType(context, connection, resourceId, null) .thenAsync(new AsyncFunction<RoutingContext, PasswordModifyExtendedResult, ResourceException>() { @Override public Promise<PasswordModifyExtendedResult, ResourceException> apply(RoutingContext dnAndType) { final PasswordModifyExtendedRequest pwdModifyRequest = newPasswordModifyExtendedRequest().setUserIdentity("dn: " + dnAndType.getDn()); return connection.extendedRequestAsync(pwdModifyRequest) .thenCatchAsync(adaptLdapException(PasswordModifyExtendedResult.class)); } }).thenAsync(new AsyncFunction<PasswordModifyExtendedResult, ActionResponse, ResourceException>() { @Override public Promise<ActionResponse, ResourceException> apply(PasswordModifyExtendedResult r) { final JsonValue result = new JsonValue(new LinkedHashMap<>()); final byte[] generatedPwd = r.getGeneratedPassword(); if (generatedPwd != null) { result.put("generatedPassword", valueOfBytes(generatedPwd).toString()); } return newActionResponse(result).asPromise(); } }); } private Promise<ActionResponse, ResourceException> modifyPassword( final Context context, final String resourceId, final ActionRequest request) { if (!context.containsContext(ClientContext.class) || !context.asContext(ClientContext.class).isSecure()) { @@ -185,8 +221,8 @@ final String oldPassword; final String newPassword; try { oldPassword = jsonContent.get("oldPassword").asString(); newPassword = jsonContent.get("newPassword").asString(); oldPassword = jsonContent.get("oldPassword").required().asString(); newPassword = jsonContent.get("newPassword").required().asString(); } catch (JsonValueException e) { final LocalizableMessage msg = ERR_PASSWORD_MODIFY_REQUEST_IS_INVALID.get(); final ResourceException ex = newBadRequestException(msg, e); @@ -209,12 +245,8 @@ }).thenAsync(new AsyncFunction<PasswordModifyExtendedResult, ActionResponse, ResourceException>() { @Override public Promise<ActionResponse, ResourceException> apply(PasswordModifyExtendedResult r) { final JsonValue result = new JsonValue(new LinkedHashMap<>()); final byte[] generatedPwd = r.getGeneratedPassword(); if (generatedPwd != null) { result.put("generatedPassword", valueOfBytes(generatedPwd).toString()); } return newActionResponse(result).asPromise(); // Empty response. return newActionResponse(new JsonValue(new LinkedHashMap<>(0))).asPromise(); } }); } opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap.properties
@@ -100,13 +100,13 @@ ERR_CLIENT_PROVIDED_RESOURCE_ID_MISSING_54=Resources cannot be created without a client provided resource ID ERR_NOT_YET_IMPLEMENTED_55=Not yet implemented ERR_ACTION_NOT_SUPPORTED_56=The action '%s' is not supported ERR_PASSWORD_MODIFY_SECURE_CONNECTION_57=Password modify requires a secure connection ERR_PASSWORD_MODIFY_USER_AUTHENTICATED_58=Password modify requires user to be authenticated ERR_PASSWORD_MODIFY_SECURE_CONNECTION_57=Passwords can only be modified using a secure connection ERR_PASSWORD_MODIFY_USER_AUTHENTICATED_58=Passwords can only be modified by authenticated users ERR_DECODING_CONTROL_59=Unable to decode ldap control: '%s' ERR_ERROR_RESPONSE_60=An error occurred while processing the request '%s': '%s' (details: '%s') ERR_RUNTIME_EXCEPTION_61=A runtime exception occurred wile processing the request '%s': '%s' ERR_PASSWORD_MODIFY_REQUEST_IS_INVALID_62=The password modify request has been rejected because it is invalid. \ A password modify request may contain two string valued fields 'oldPassword' and 'newPassword' ERR_PASSWORD_MODIFY_REQUEST_IS_INVALID_62=The modify password request has been rejected because it is invalid. \ A modify password request must contain two string valued fields 'oldPassword' and 'newPassword' ERR_CONFIG_INVALID_TRUST_MANAGER_63=The trust-manager defined in '%s' is invalid: %s ERR_CONFIG_INVALID_KEY_MANAGER_64=The key-manager defined in '%s' is invalid: %s ERR_MISSING_TYPE_PROPERTY_IN_CREATE_65=The resource cannot be created because it does not contain the \ @@ -136,3 +136,5 @@ directory or cannot be read INFO_REST2LDAP_STARTING_80=Rest2Ldap starting with configuration directory '%s' INFO_REST2LDAP_CREATING_ENDPOINT_81=Rest2Ldap created endpoint '%s' version %s ERR_PASSWORD_RESET_SECURE_CONNECTION_82=Passwords can only be reset using a secure connection ERR_PASSWORD_RESET_USER_AUTHENTICATED_83=Passwords can only be reset by authenticated users opendj-server-legacy/resource/config/rest2ldap/endpoints/api/users-and-groups-v1.json
@@ -74,7 +74,7 @@ "frapi:opendj:rest2ldap:user:1.0": { "superType": "frapi:opendj:rest2ldap:object:1.0", "objectClasses": [ "person", "organizationalPerson", "inetOrgPerson" ], "supportedActions": [ "passwordModify" ], "supportedActions": [ "modifyPassword", "resetPassword" ], "properties": { "_id": { "type": "simple",