diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/UserCredentialWrapper.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/OldPasswordResetWrapper.java similarity index 62% rename from components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/UserCredentialWrapper.java rename to components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/OldPasswordResetWrapper.java index e5674b9de71..bef53c06b75 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/UserCredentialWrapper.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/OldPasswordResetWrapper.java @@ -21,34 +21,14 @@ package org.wso2.carbon.device.mgt.jaxrs.beans; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; -@ApiModel(value = "UserCredentialWrapper", description = "User credentials are included in this class.") -public class UserCredentialWrapper { +@ApiModel(value = "OldPasswordResetWrapper", description = "User credentials are included in this class.") +public class OldPasswordResetWrapper extends PasswordResetWrapper{ - @ApiModelProperty(name = "username", value = "Username of the user.", required = true ) - private String username; /* Base64 encoded password */ @ApiModelProperty(name = "oldPassword", value = "Old password of the user.", required = true ) private String oldPassword; - @ApiModelProperty(name = "newPassword", value = "New password of the user.", required = true ) - private String newPassword; - - public String getNewPassword() { - return newPassword; - } - - public void setNewPassword(String newPassword) { - this.newPassword = newPassword; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } public String getOldPassword() { return oldPassword; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/PasswordResetWrapper.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/PasswordResetWrapper.java new file mode 100644 index 00000000000..7bd67c20289 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/PasswordResetWrapper.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.jaxrs.beans; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "PasswordResetWrapper", description = "User credential is included in this class.") +public class PasswordResetWrapper { + + /* + Base64 encoded password + */ + @ApiModelProperty(name = "newPassword", value = "New password of the user.", required = true ) + private String newPassword; + + public String getNewPassword() { + return newPassword; + } + + public void setNewPassword(String newPassword) { + this.newPassword = newPassword; + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java index 1631eeaa280..a2c33625754 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/UserManagementService.java @@ -21,13 +21,12 @@ package org.wso2.carbon.device.mgt.jaxrs.service.api; import io.swagger.annotations.*; import org.wso2.carbon.apimgt.annotations.api.API; import org.wso2.carbon.apimgt.annotations.api.Permission; -import org.wso2.carbon.device.mgt.jaxrs.beans.UserCredentialWrapper; +import org.wso2.carbon.device.mgt.jaxrs.beans.OldPasswordResetWrapper; import org.wso2.carbon.device.mgt.jaxrs.beans.UserWrapper; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import java.util.Date; @API(name = "User Management API", version = "1.0.0", context = "/devicemgt_admin/users", tags = {"devicemgt_admin"}) @@ -438,6 +437,6 @@ public interface UserManagementService { @ApiParam( name = "credentials", value = "Credential.", - required = true) UserCredentialWrapper credentials); + required = true) OldPasswordResetWrapper credentials); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/UserManagementAdminService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/UserManagementAdminService.java index 7dd351734b3..baec3eff636 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/UserManagementAdminService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/UserManagementAdminService.java @@ -20,7 +20,7 @@ package org.wso2.carbon.device.mgt.jaxrs.service.api.admin; import io.swagger.annotations.*; import org.wso2.carbon.apimgt.annotations.api.Permission; -import org.wso2.carbon.device.mgt.jaxrs.beans.UserCredentialWrapper; +import org.wso2.carbon.device.mgt.jaxrs.beans.PasswordResetWrapper; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; @@ -71,6 +71,6 @@ public interface UserManagementAdminService { @ApiParam( name = "credentials", value = "Credential.", - required = true) UserCredentialWrapper credentials); + required = true) PasswordResetWrapper credentials); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java index 260b4df2911..1a2bb05f2d8 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/UserManagementServiceImpl.java @@ -26,7 +26,7 @@ import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.EmailMetaInfo; -import org.wso2.carbon.device.mgt.jaxrs.beans.UserCredentialWrapper; +import org.wso2.carbon.device.mgt.jaxrs.beans.OldPasswordResetWrapper; import org.wso2.carbon.device.mgt.jaxrs.beans.UserWrapper; import org.wso2.carbon.device.mgt.jaxrs.service.api.UserManagementService; import org.wso2.carbon.device.mgt.jaxrs.util.Constants; @@ -390,8 +390,8 @@ public class UserManagementServiceImpl implements UserManagementService { @PUT @Path("/{username}/credentials") @Override - public Response resetPassword(@PathParam("username") String username, UserCredentialWrapper credentials) { - return CredentialManagementResponseBuilder.buildChangePasswordResponse(credentials); + public Response resetPassword(@PathParam("username") String username, OldPasswordResetWrapper credentials) { + return CredentialManagementResponseBuilder.buildChangePasswordResponse(username, credentials); } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/UserManagementAdminServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/UserManagementAdminServiceImpl.java index fc30afea174..1613c49b874 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/UserManagementAdminServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/UserManagementAdminServiceImpl.java @@ -18,7 +18,7 @@ */ package org.wso2.carbon.device.mgt.jaxrs.service.impl.admin; -import org.wso2.carbon.device.mgt.jaxrs.beans.UserCredentialWrapper; +import org.wso2.carbon.device.mgt.jaxrs.beans.PasswordResetWrapper; import org.wso2.carbon.device.mgt.jaxrs.service.api.admin.UserManagementAdminService; import org.wso2.carbon.device.mgt.jaxrs.util.CredentialManagementResponseBuilder; @@ -34,8 +34,8 @@ public class UserManagementAdminServiceImpl implements UserManagementAdminServic @POST @Path("/{username}/credentials") @Override - public Response resetPassword(@PathParam("username") String user, UserCredentialWrapper credentials) { - return CredentialManagementResponseBuilder.buildResetPasswordResponse(credentials); + public Response resetPassword(@PathParam("username") String user, PasswordResetWrapper credentials) { + return CredentialManagementResponseBuilder.buildResetPasswordResponse(user, credentials); } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/CredentialManagementResponseBuilder.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/CredentialManagementResponseBuilder.java index dfdc187e163..d52bdec3d96 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/CredentialManagementResponseBuilder.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/CredentialManagementResponseBuilder.java @@ -18,15 +18,16 @@ package org.wso2.carbon.device.mgt.jaxrs.util; -import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.device.mgt.jaxrs.beans.UserCredentialWrapper; +import org.wso2.carbon.device.mgt.jaxrs.beans.PasswordResetWrapper; +import org.wso2.carbon.device.mgt.jaxrs.beans.OldPasswordResetWrapper; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreManager; import javax.ws.rs.core.Response; import java.io.UnsupportedEncodingException; +import java.util.regex.Pattern; /** * This class builds Credential modification related Responses @@ -34,26 +35,40 @@ import java.io.UnsupportedEncodingException; public class CredentialManagementResponseBuilder { private static Log log = LogFactory.getLog(CredentialManagementResponseBuilder.class); + private static String PASSWORD_VALIDATION_REGEX_TAG = "PasswordJavaRegEx"; + private static String PASSWORD_VALIDATION_ERROR_MSG_TAG = "PasswordJavaRegExViolationErrorMsg"; /** * Builds the response to change the password of a user + * @param username - Username of the user. * @param credentials - User credentials * @return Response Object */ - public static Response buildChangePasswordResponse(UserCredentialWrapper credentials) { + public static Response buildChangePasswordResponse(String username, OldPasswordResetWrapper credentials) { try { UserStoreManager userStoreManager = DeviceMgtAPIUtils.getUserStoreManager(); - byte[] decodedNewPassword = Base64.decodeBase64(credentials.getNewPassword()); - byte[] decodedOldPassword = Base64.decodeBase64(credentials.getOldPassword()); - userStoreManager.updateCredential(credentials.getUsername(), new String( - decodedNewPassword, "UTF-8"), new String(decodedOldPassword, "UTF-8")); + if (!userStoreManager.isExistingUser(username)) { + return Response.status(Response.Status.BAD_REQUEST).entity("No user found with the username " + + username).build(); + } + if (credentials == null || credentials.getNewPassword() == null || credentials.getOldPassword() == null) { + return Response.status(Response.Status.BAD_REQUEST).entity("Password cannot be empty.") + .build(); + } + if (!validateCredential(credentials.getNewPassword())) { + String errorMsg = DeviceMgtAPIUtils.getRealmService().getBootstrapRealmConfiguration() + .getUserStoreProperty(PASSWORD_VALIDATION_ERROR_MSG_TAG); + return Response.status(Response.Status.BAD_REQUEST).entity(errorMsg).build(); + } + userStoreManager.updateCredential(username, credentials.getNewPassword(), + credentials.getOldPassword()); return Response.status(Response.Status.OK).entity("UserImpl password by username: " + - credentials.getUsername() + " was successfully changed.").build(); + username + " was successfully changed.").build(); } catch (UserStoreException e) { log.error(e.getMessage(), e); return Response.status(Response.Status.BAD_REQUEST).entity("Old password does not match.").build(); } catch (UnsupportedEncodingException e) { - String errorMsg = "Could not change the password of the user: " + credentials.getUsername() + + String errorMsg = "Could not change the password of the user: " + username + ". The Character Encoding is not supported."; log.error(errorMsg, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorMsg).build(); @@ -62,27 +77,52 @@ public class CredentialManagementResponseBuilder { /** * Builds the response to reset the password of a user + * @param username - Username of the user. * @param credentials - User credentials * @return Response Object */ - public static Response buildResetPasswordResponse(UserCredentialWrapper credentials) { + public static Response buildResetPasswordResponse(String username, PasswordResetWrapper credentials) { try { UserStoreManager userStoreManager = DeviceMgtAPIUtils.getUserStoreManager(); - byte[] decodedNewPassword = Base64.decodeBase64(credentials.getNewPassword()); - userStoreManager.updateCredentialByAdmin(credentials.getUsername(), new String( - decodedNewPassword, "UTF-8")); - return Response.status(Response.Status.CREATED).entity("UserImpl password by username: " + - credentials.getUsername() + " was successfully changed.").build(); + if (!userStoreManager.isExistingUser(username)) { + return Response.status(Response.Status.BAD_REQUEST).entity("No user found with the username " + + username).build(); + } + if (credentials == null || credentials.getNewPassword() == null) { + return Response.status(Response.Status.BAD_REQUEST).entity("Password cannot be empty.") + .build(); + } + if (!validateCredential(credentials.getNewPassword())) { + String errorMsg = DeviceMgtAPIUtils.getRealmService().getBootstrapRealmConfiguration() + .getUserStoreProperty(PASSWORD_VALIDATION_ERROR_MSG_TAG); + return Response.status(Response.Status.BAD_REQUEST).entity(errorMsg).build(); + } + userStoreManager.updateCredentialByAdmin(username, credentials.getNewPassword()); + return Response.status(Response.Status.OK).entity("UserImpl password by username: " + + username + " was successfully changed.").build(); } catch (UserStoreException e) { - String msg = "ErrorResponse occurred while updating the credentials of user '" + credentials.getUsername() + "'"; + String msg = "ErrorResponse occurred while updating the credentials of user '" + username + "'"; log.error(msg, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } catch (UnsupportedEncodingException e) { - String msg = "Could not change the password of the user: " + credentials.getUsername() + + String msg = "Could not change the password of the user: " + username + ". The Character Encoding is not supported."; log.error(msg, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } } + private static boolean validateCredential(String password) + throws UserStoreException, UnsupportedEncodingException { + String passwordValidationRegex = DeviceMgtAPIUtils.getRealmService().getBootstrapRealmConfiguration() + .getUserStoreProperty(PASSWORD_VALIDATION_REGEX_TAG); + if (passwordValidationRegex != null) { + Pattern pattern = Pattern.compile(passwordValidationRegex); + if (pattern.matcher(password).matches()) { + return true; + } + } + return false; + } + } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java index dfb8bc19dfa..b38b9456831 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java @@ -131,6 +131,18 @@ public class DeviceMgtAPIUtils { return userStoreManager; } + public static RealmService getRealmService() throws UserStoreException { + RealmService realmService; + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + realmService = (RealmService) ctx.getOSGiService(RealmService.class, null); + if (realmService == null) { + String msg = "Realm service has not initialized."; + log.error(msg); + throw new IllegalStateException(msg); + } + return realmService; + } + /** * Getting the current tenant's user realm */