Skip to content

Commit

Permalink
server: move reset password WS, #TASK-7200 #TASK-7130
Browse files Browse the repository at this point in the history
  • Loading branch information
pfurio committed Nov 13, 2024
1 parent 6ee003d commit 7aa6df5
Show file tree
Hide file tree
Showing 17 changed files with 116 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public abstract class OpenCgaCompleter implements Completer {
.map(Candidate::new)
.collect(toList());

private List<Candidate> organizationsList = asList( "create","notes-create","notes-search","notes-delete","notes-update","update-status-user","user-update","configuration-update","info","update")
private List<Candidate> organizationsList = asList( "create","notes-create","notes-search","notes-delete","notes-update","password-reset","update-status-user","user-update","configuration-update","info","update")
.stream()
.map(Candidate::new)
.collect(toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ public OpencgaCliOptionsParser() {
organizationsSubCommands.addCommand("notes-search", organizationsCommandOptions.searchNotesCommandOptions);
organizationsSubCommands.addCommand("notes-delete", organizationsCommandOptions.deleteNotesCommandOptions);
organizationsSubCommands.addCommand("notes-update", organizationsCommandOptions.updateNotesCommandOptions);
organizationsSubCommands.addCommand("password-reset", organizationsCommandOptions.resetPasswordCommandOptions);
organizationsSubCommands.addCommand("update-status-user", organizationsCommandOptions.userUpdateStatusCommandOptions);
organizationsSubCommands.addCommand("user-update", organizationsCommandOptions.updateUserCommandOptions);
organizationsSubCommands.addCommand("configuration-update", organizationsCommandOptions.updateConfigurationCommandOptions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ public void execute() throws Exception {
case "notes-update":
queryResponse = updateNotes();
break;
case "password-reset":
queryResponse = resetPassword();
break;
case "update-status-user":
queryResponse = userUpdateStatus();
break;
Expand Down Expand Up @@ -240,6 +243,17 @@ private RestResponse<Note> updateNotes() throws Exception {
return openCGAClient.getOrganizationClient().updateNotes(commandOptions.id, noteUpdateParams, queryParams);
}

private RestResponse<ObjectMap> resetPassword() throws Exception {
logger.debug("Executing resetPassword in Organizations command line");

OrganizationsCommandOptions.ResetPasswordCommandOptions commandOptions = organizationsCommandOptions.resetPasswordCommandOptions;

ObjectMap queryParams = new ObjectMap();
queryParams.putIfNotEmpty("userId", commandOptions.userId);

return openCGAClient.getOrganizationClient().resetPassword(queryParams);
}

private RestResponse<User> userUpdateStatus() throws Exception {
logger.debug("Executing userUpdateStatus in Organizations command line");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class OrganizationsCommandOptions {
public SearchNotesCommandOptions searchNotesCommandOptions;
public DeleteNotesCommandOptions deleteNotesCommandOptions;
public UpdateNotesCommandOptions updateNotesCommandOptions;
public ResetPasswordCommandOptions resetPasswordCommandOptions;
public UserUpdateStatusCommandOptions userUpdateStatusCommandOptions;
public UpdateUserCommandOptions updateUserCommandOptions;
public UpdateConfigurationCommandOptions updateConfigurationCommandOptions;
Expand All @@ -54,6 +55,7 @@ public OrganizationsCommandOptions(CommonCommandOptions commonCommandOptions, JC
this.searchNotesCommandOptions = new SearchNotesCommandOptions();
this.deleteNotesCommandOptions = new DeleteNotesCommandOptions();
this.updateNotesCommandOptions = new UpdateNotesCommandOptions();
this.resetPasswordCommandOptions = new ResetPasswordCommandOptions();
this.userUpdateStatusCommandOptions = new UserUpdateStatusCommandOptions();
this.updateUserCommandOptions = new UpdateUserCommandOptions();
this.updateConfigurationCommandOptions = new UpdateConfigurationCommandOptions();
Expand Down Expand Up @@ -228,6 +230,23 @@ public class UpdateNotesCommandOptions {

}

@Parameters(commandNames = {"password-reset"}, commandDescription ="Reset user's password")
public class ResetPasswordCommandOptions {

@ParametersDelegate
public CommonCommandOptions commonOptions = commonCommandOptions;

@Parameter(names = {"--json-file"}, description = "File with the body data in JSON format. Note, that using this parameter will ignore all the other parameters.", required = false, arity = 1)
public String jsonFile;

@Parameter(names = {"--json-data-model"}, description = "Show example of file structure for body data.", help = true, arity = 0)
public Boolean jsonDataModel = false;

@Parameter(names = {"--user-id"}, description = "User whose password needs to be reset", required = false, arity = 1)
public String userId;

}

@Parameters(commandNames = {"update-status-user"}, commandDescription ="Update the user status")
public class UserUpdateStatusCommandOptions {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ public class FiltersCommandOptions {

}

@Parameters(commandNames = {"password-reset"}, commandDescription ="Reset password")
@Parameters(commandNames = {"password-reset"}, commandDescription ="[DEPRECATED]")
public class ResetPasswordCommandOptions {

@ParametersDelegate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,26 @@ public OpenCGAResult<Organization> update(String organizationId, OrganizationUpd
return result;
}

public OpenCGAResult<?> resetUserPassword(String userId, String token) throws CatalogException {
ParamUtils.checkParameter(userId, "userId");
ParamUtils.checkParameter(token, "token");
JwtPayload jwtPayload = catalogManager.getUserManager().validateToken(token);
String organizationId = jwtPayload.getOrganization();
try {
authorizationManager.checkIsAtLeastOrganizationOwnerOrAdmin(organizationId, jwtPayload.getUserId());
String authOrigin = catalogManager.getUserManager().getAuthenticationOriginId(organizationId, userId);
OpenCGAResult<?> writeResult = authenticationFactory.resetPassword(organizationId, authOrigin, userId);

auditManager.auditUser(organizationId, jwtPayload.getUserId(organizationId), Enums.Action.RESET_USER_PASSWORD, userId,
new AuditRecord.Status(AuditRecord.Status.Result.SUCCESS));
return writeResult;
} catch (CatalogException e) {
auditManager.auditUser(organizationId, jwtPayload.getUserId(organizationId), Enums.Action.RESET_USER_PASSWORD, userId,
new AuditRecord.Status(AuditRecord.Status.Result.ERROR, e.getError()));
throw e;
}
}

public OpenCGAResult<User> updateUser(@Nullable String organizationId, String userId, OrganizationUserUpdateParams updateParams,
QueryOptions options, String token) throws CatalogException {
JwtPayload tokenPayload = catalogManager.getUserManager().validateToken(token);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -773,26 +773,6 @@ public OpenCGAResult<User> restore(String ids, QueryOptions options, String sess
throw new UnsupportedOperationException();
}

public OpenCGAResult resetPassword(String userId, String token) throws CatalogException {
ParamUtils.checkParameter(userId, "userId");
ParamUtils.checkParameter(token, "token");
JwtPayload jwtPayload = validateToken(token);
String organizationId = jwtPayload.getOrganization();
try {
authorizationManager.checkIsAtLeastOrganizationOwnerOrAdmin(organizationId, jwtPayload.getUserId());
String authOrigin = getAuthenticationOriginId(organizationId, userId);
OpenCGAResult writeResult = authenticationFactory.resetPassword(organizationId, authOrigin, userId);

auditManager.auditUser(organizationId, jwtPayload.getUserId(organizationId), Enums.Action.RESET_USER_PASSWORD, userId,
new AuditRecord.Status(AuditRecord.Status.Result.SUCCESS));
return writeResult;
} catch (CatalogException e) {
auditManager.auditUser(organizationId, jwtPayload.getUserId(organizationId), Enums.Action.RESET_USER_PASSWORD, userId,
new AuditRecord.Status(AuditRecord.Status.Result.ERROR, e.getError()));
throw e;
}
}

public AuthenticationResponse loginAsAdmin(String password) throws CatalogException {
return login(ParamConstants.ADMIN_ORGANIZATION, OPENCGA, password);
}
Expand Down Expand Up @@ -1533,7 +1513,7 @@ private void checkUserExists(String organizationId, String userId) throws Catalo
}
}

private String getAuthenticationOriginId(String organizationId, String userId) throws CatalogException {
String getAuthenticationOriginId(String organizationId, String userId) throws CatalogException {
OpenCGAResult<User> user = getUserDBAdaptor(organizationId).get(userId, new QueryOptions());
if (user == null || user.getNumResults() == 0) {
throw new CatalogException(userId + " user not found");
Expand Down
7 changes: 7 additions & 0 deletions opencga-client/src/main/R/R/Organization-methods.R
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#' | searchNotes | /{apiVersion}/organizations/notes/search | include, exclude, creationDate, modificationDate, id, scope, visibility, uuid, userId, tags, version |
#' | deleteNotes | /{apiVersion}/organizations/notes/{id}/delete | id[*], includeResult |
#' | updateNotes | /{apiVersion}/organizations/notes/{id}/update | include, exclude, id[*], tagsAction, includeResult, body[*] |
#' | resetPassword | /{apiVersion}/organizations/password/reset | userId |
#' | userUpdateStatus | /{apiVersion}/organizations/user/{user}/status/update | include, exclude, user[*], organization, includeResult, body[*] |
#' | updateUser | /{apiVersion}/organizations/user/{user}/update | include, exclude, user[*], organization, includeResult, body[*] |
#' | updateConfiguration | /{apiVersion}/organizations/{organization}/configuration/update | include, exclude, organization[*], includeResult, authenticationOriginsAction, body[*] |
Expand Down Expand Up @@ -91,6 +92,12 @@ setMethod("organizationClient", "OpencgaR", function(OpencgaR, id, organization,
updateNotes=fetchOpenCGA(object=OpencgaR, category="organizations", categoryId=NULL, subcategory="notes",
subcategoryId=id, action="update", params=params, httpMethod="POST", as.queryParam=NULL, ...),

#' @section Endpoint /{apiVersion}/organizations/password/reset:
#' Reset user's password.
#' @param userId User whose password needs to be reset.
resetPassword=fetchOpenCGA(object=OpencgaR, category="organizations", categoryId=NULL, subcategory="password",
subcategoryId=NULL, action="reset", params=params, httpMethod="POST", as.queryParam=NULL, ...),

#' @section Endpoint /{apiVersion}/organizations/user/{user}/status/update:
#' Update the user status.
#' @param include Fields included in the response, whole JSON path must be provided.
Expand Down
2 changes: 1 addition & 1 deletion opencga-client/src/main/R/R/User-methods.R
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ setMethod("userClient", "OpencgaR", function(OpencgaR, filterId, user, users, en
subcategoryId=filterId, action="update", params=params, httpMethod="POST", as.queryParam=NULL, ...),

#' @section Endpoint /{apiVersion}/users/{user}/password/reset:
#' Reset password.
#' [DEPRECATED].
#' @param user User ID.
resetPassword=fetchOpenCGA(object=OpencgaR, category="users", categoryId=user, subcategory="password",
subcategoryId=NULL, action="reset", params=params, httpMethod="GET", as.queryParam=NULL, ...),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,18 @@ public RestResponse<Note> updateNotes(String id, NoteUpdateParams data, ObjectMa
return execute("organizations", null, "notes", id, "update", params, POST, Note.class);
}

/**
* Reset user's password.
* @param params Map containing any of the following optional parameters.
* userId: User whose password needs to be reset.
* @return a RestResponse object.
* @throws ClientException ClientException if there is any server error.
*/
public RestResponse<ObjectMap> resetPassword(ObjectMap params) throws ClientException {
params = params != null ? params : new ObjectMap();
return execute("organizations", null, "password", null, "reset", params, POST, ObjectMap.class);
}

/**
* Update the user status.
* @param user User ID.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ public RestResponse<UserFilter> updateFilter(String user, String filterId, Filte
}

/**
* Reset password.
* [DEPRECATED].
* @param user User ID.
* @return a RestResponse object.
* @throws ClientException ClientException if there is any server error.
Expand Down
9 changes: 9 additions & 0 deletions opencga-client/src/main/javascript/Organization.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@ export default class Organization extends OpenCGAParentClass {
return this._post("organizations", null, "notes", id, "update", data, params);
}

/** Reset user's password
* @param {Object} [params] - The Object containing the following optional parameters:
* @param {String} [params.userId] - User whose password needs to be reset.
* @returns {Promise} Promise object in the form of RestResponse instance.
*/
resetPassword(params) {
return this._post("organizations", null, "password", null, "reset", null, params);
}

/** Update the user status
* @param {String} user - User ID.
* @param {Object} data - JSON containing the User fields to be updated.
Expand Down
2 changes: 1 addition & 1 deletion opencga-client/src/main/javascript/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export default class User extends OpenCGAParentClass {
return this._post("users", user, "filters", filterId, "update", data);
}

/** Reset password
/** [DEPRECATED]
* @param {String} user - User ID.
* @returns {Promise} Promise object in the form of RestResponse instance.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,16 @@ def update_notes(self, id, data=None, **options):

return self._post(category='organizations', resource='update', subcategory='notes', second_query_id=id, data=data, **options)

def reset_password(self, **options):
"""
Reset user's password.
PATH: /{apiVersion}/organizations/password/reset
:param str user_id: User whose password needs to be reset.
"""

return self._post(category='organizations', resource='reset', subcategory='password', **options)

def user_update_status(self, user, data=None, **options):
"""
Update the user status.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def update_filter(self, user, filter_id, data=None, **options):

def reset_password(self, user, **options):
"""
Reset password.
[DEPRECATED].
PATH: /{apiVersion}/users/{user}/password/reset
:param str user: User ID. (REQUIRED)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,20 @@ public Response create(
}
}

@POST
@Path("/password/reset")
@ApiOperation(value = "Reset user's password",
notes = "Reset the user's password and send a new random one to the e-mail stored in catalog.")
public Response resetPassword(
@ApiParam(value = "User whose password needs to be reset") @QueryParam("userId") String userId) {
try {
OpenCGAResult<?> result = catalogManager.getOrganizationManager().resetUserPassword(userId, token);
return createOkResponse(result, "The new password has been sent to the user's email.");
} catch (Exception e) {
return createErrorResponse(e);
}
}

@GET
@Path("/notes/search")
@ApiOperation(value = "Search for notes of scope ORGANIZATION", response = Note.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,14 @@ public Response changePassword(
}
}

@Deprecated
@GET
@Path("/{user}/password/reset")
@ApiOperation(value = "Reset password", hidden = false,
notes = "Reset the user's password and send a new random one to the e-mail stored in catalog.", response = User.class)
@ApiOperation(value = "[DEPRECATED]", notes = "[DEPRECATED] This WS has been moved to /organizations/password/reset.", response = User.class)
public Response resetPassword(
@ApiParam(value = ParamConstants.USER_DESCRIPTION, required = true) @PathParam("user") String userId) {
try {
OpenCGAResult<User> result = catalogManager.getUserManager().resetPassword(userId, token);
OpenCGAResult<?> result = catalogManager.getOrganizationManager().resetUserPassword(userId, token);
return createOkResponse(result, "The new password has been sent to the user's email.");
} catch (Exception e) {
return createErrorResponse(e);
Expand Down

0 comments on commit 7aa6df5

Please sign in to comment.