From deca3939ae5482b660aa10bb1bcfefeafd46e043 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Thu, 23 Jun 2016 00:21:25 +0000
Subject: [PATCH] OPENDJ-2789 Split passwordModify into distinct requests: modifyPassword and resetPassword
---
opendj-server-legacy/resource/config/rest2ldap/endpoints/api/users-and-groups-v1.json | 2
opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Action.java | 15 +++----
opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap.properties | 10 +++--
opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceImpl.java | 54 +++++++++++++++++++++-----
opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/rest2ldap/endpoints/api/users-and-groups-v1.json | 2
5 files changed, 58 insertions(+), 25 deletions(-)
diff --git a/opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/rest2ldap/endpoints/api/users-and-groups-v1.json b/opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/rest2ldap/endpoints/api/users-and-groups-v1.json
index dbdfe7d..9e11c37 100644
--- a/opendj-rest2ldap-servlet/src/main/webapp/WEB-INF/classes/rest2ldap/endpoints/api/users-and-groups-v1.json
+++ b/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",
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Action.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Action.java
index 1cd7ee6..21d6bae 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Action.java
+++ b/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;
diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceImpl.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceImpl.java
index a1da30e..6cd3367 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SubResourceImpl.java
+++ b/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();
}
});
}
diff --git a/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap.properties b/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap.properties
index befdf97..3f56fc3 100644
--- a/opendj-rest2ldap/src/main/resources/org/forgerock/opendj/rest2ldap/rest2ldap.properties
+++ b/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
diff --git a/opendj-server-legacy/resource/config/rest2ldap/endpoints/api/users-and-groups-v1.json b/opendj-server-legacy/resource/config/rest2ldap/endpoints/api/users-and-groups-v1.json
index dbdfe7d..9e11c37 100644
--- a/opendj-server-legacy/resource/config/rest2ldap/endpoints/api/users-and-groups-v1.json
+++ b/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",
--
Gitblit v1.10.0