-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature/Identity] Reset Password API #6309
Changes from all commits
017666e
fe4f5e0
c7c3212
0f42b1a
64682f9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
*/ | ||
|
||
package org.opensearch.identity.rest.user.resetpassword; | ||
|
||
import org.opensearch.action.ActionType; | ||
|
||
/** | ||
* Action type for creating or updating a user | ||
*/ | ||
public class ResetPasswordAction extends ActionType<ResetPasswordResponse> { | ||
|
||
public static final ResetPasswordAction INSTANCE = new ResetPasswordAction(); | ||
|
||
// TODO : revisit this action type | ||
public static final String NAME = "cluster:admin/user/resetpassword"; | ||
|
||
private ResetPasswordAction() { | ||
super(NAME, ResetPasswordResponse::new); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
*/ | ||
|
||
package org.opensearch.identity.rest.user.resetpassword; | ||
|
||
import org.opensearch.action.ActionRequest; | ||
import org.opensearch.action.ActionRequestValidationException; | ||
import org.opensearch.common.io.stream.StreamInput; | ||
import org.opensearch.common.io.stream.StreamOutput; | ||
import org.opensearch.common.xcontent.ToXContentObject; | ||
import org.opensearch.common.xcontent.XContentBuilder; | ||
|
||
import java.io.IOException; | ||
|
||
import static org.opensearch.action.ValidateActions.addValidationError; | ||
|
||
/** | ||
* Request to reset an internal user password | ||
*/ | ||
public class ResetPasswordRequest extends ActionRequest implements ToXContentObject { | ||
|
||
private String username; | ||
private String oldPassword; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We shouldn't require the old password, if a user forgot there password how would they get a new password issued? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's leave this as a prototype design for now. (I just wanna transfer our conversation on github :)) I'm not gonna resolve this comment, so that I can use this as a reminder for myself, in case if we wanna change it in the future. |
||
private String newPassword; | ||
|
||
public ResetPasswordRequest(StreamInput in) throws IOException { | ||
super(in); | ||
username = in.readString(); | ||
oldPassword = in.readString(); | ||
newPassword = in.readString(); | ||
} | ||
|
||
public ResetPasswordRequest(String username, String oldPassword, String newPassword) { | ||
this.username = username; | ||
this.oldPassword = oldPassword; | ||
this.newPassword = newPassword; | ||
} | ||
|
||
public String getUsername() { | ||
return username; | ||
} | ||
|
||
public void setUsername(String username) { | ||
this.username = username; | ||
} | ||
|
||
public String getOldPassword() { | ||
return oldPassword; | ||
} | ||
|
||
public String getNewPassword() { | ||
return newPassword; | ||
} | ||
|
||
@Override | ||
public ActionRequestValidationException validate() { | ||
ActionRequestValidationException validationException = null; | ||
if (username == null) { // TODO: check the condition once | ||
validationException = addValidationError("No username specified", validationException); | ||
} else if (oldPassword == null) { | ||
validationException = addValidationError("No current password specified", validationException); | ||
} else if (newPassword == null) { | ||
validationException = addValidationError("No new password specified", validationException); | ||
} | ||
return validationException; | ||
} | ||
|
||
@Override | ||
public void writeTo(StreamOutput out) throws IOException { | ||
super.writeTo(out); | ||
out.writeString(username); | ||
out.writeString(oldPassword); | ||
out.writeString(newPassword); | ||
} | ||
|
||
@Override | ||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { | ||
builder.startObject(); | ||
builder.value(username); | ||
builder.value(oldPassword); | ||
builder.value(newPassword); | ||
builder.endObject(); | ||
return builder; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
*/ | ||
|
||
package org.opensearch.identity.rest.user.resetpassword; | ||
|
||
import org.opensearch.action.ActionResponse; | ||
import org.opensearch.common.ParseField; | ||
import org.opensearch.common.io.stream.StreamInput; | ||
import org.opensearch.common.io.stream.StreamOutput; | ||
import org.opensearch.common.xcontent.ConstructingObjectParser; | ||
import org.opensearch.common.xcontent.StatusToXContentObject; | ||
import org.opensearch.common.xcontent.XContentBuilder; | ||
import org.opensearch.rest.RestStatus; | ||
|
||
import java.io.IOException; | ||
|
||
import static org.opensearch.common.xcontent.ConstructingObjectParser.constructorArg; | ||
import static org.opensearch.rest.RestStatus.NOT_FOUND; | ||
import static org.opensearch.rest.RestStatus.OK; | ||
|
||
/** | ||
* Response class for create user request | ||
* Contains list of responses of each user creation request | ||
*/ | ||
public class ResetPasswordResponse extends ActionResponse implements StatusToXContentObject { | ||
|
||
// TODO: revisit this class | ||
private final ResetPasswordResponseInfo resetPasswordResponseInfo; | ||
|
||
public ResetPasswordResponse(ResetPasswordResponseInfo resetPasswordResponseInfo) { | ||
this.resetPasswordResponseInfo = resetPasswordResponseInfo; | ||
} | ||
|
||
public ResetPasswordResponse(StreamInput in) throws IOException { | ||
super(in); | ||
resetPasswordResponseInfo = new ResetPasswordResponseInfo(in); | ||
} | ||
|
||
public ResetPasswordResponseInfo getResetPasswordResponseInfo() { | ||
return resetPasswordResponseInfo; | ||
} | ||
|
||
/** | ||
* @return Whether the attempt to Create a user was successful | ||
*/ | ||
@Override | ||
public RestStatus status() { | ||
if (resetPasswordResponseInfo == null) return NOT_FOUND; | ||
return OK; | ||
} | ||
|
||
@Override | ||
public void writeTo(StreamOutput out) throws IOException { | ||
if (resetPasswordResponseInfo != null) { | ||
resetPasswordResponseInfo.writeTo(out); | ||
} | ||
} | ||
|
||
@Override | ||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { | ||
if (resetPasswordResponseInfo != null) { | ||
resetPasswordResponseInfo.toXContent(builder, params); | ||
} | ||
return builder; | ||
} | ||
|
||
private static final ConstructingObjectParser<ResetPasswordResponse, Void> PARSER = new ConstructingObjectParser<>( | ||
"reset_password_response", | ||
true, | ||
(Object[] parsedObjects) -> { | ||
@SuppressWarnings("unchecked") | ||
ResetPasswordResponseInfo resetPasswordResponseInfo1 = (ResetPasswordResponseInfo) parsedObjects[0]; | ||
return new ResetPasswordResponse(resetPasswordResponseInfo1); | ||
} | ||
); | ||
static { | ||
PARSER.declareObject(constructorArg(), ResetPasswordResponseInfo.PARSER, new ParseField("user")); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this API is used by all users, it may need a different namespace than
cluster:admin/user/*
which are a group of actions intended for the cluster admin. When it comes to authorizing this request, all users of the cluster should be able to call and use this API without being granted permission for it.