mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Matthew Swift
23.56.2016 deca3939ae5482b660aa10bb1bcfefeafd46e043
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",