-
Notifications
You must be signed in to change notification settings - Fork 993
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
Fixes #37936 - Invalidate jwt for any user or users(API) #10397
Conversation
end | ||
end | ||
|
||
api :DELETE, '/users/:id/registration_tokens', N_("Invalidate all JSON Web Tokens (JWTs) for a specific 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.
api :DELETE, '/users/:id/registration_tokens', N_("Invalidate all JSON Web Tokens (JWTs) for a specific user.") | |
api :DELETE, '/users/:id/registration_tokens', N_("Invalidate all registration tokens for a specific user.") |
28cdc1b
to
85928e7
Compare
|
||
class Api::V2::RegistrationTokensControllerTest < ActionController::TestCase | ||
test 'user shall invalidate tokens for self' do | ||
user = User.create :login => "foo", :mail => "foo@bar.com", :auth_source => auth_sources(:one) |
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.
You can use FactoryBot.create(:user)
here.
class Api::V2::RegistrationTokensControllerTest < ActionController::TestCase | ||
test 'user shall invalidate tokens for self' do | ||
user = User.create :login => "foo", :mail => "foo@bar.com", :auth_source => auth_sources(:one) | ||
FactoryBot.build(:jwt_secret, token: 'test_jwt_secret', user: 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.
You probably want to create the token as part of the user creation, and use the create
method - to make sure the token is saved before the action.
end | ||
|
||
def find_resource(permission = :view_users) | ||
editing_self? ? User.find(User.current.id) : User.authorized(permission).except_hidden.find(params[:id]) |
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.
@ekohl what do you think, should we block changes to hidden accounts here?
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.
I was also wondering about that.
@girijaasoni In the UI PR, we used the term |
@nofaralfasi , we can handle that in the documentation. Registration tokens make more sense from user POV(specially from API POV), as we are creating a new controller. For UI, we are trying to use the existing controller where jwt is used as phrasing. |
end | ||
|
||
api :DELETE, "/registration_tokens", N_("Invalidate all JSON Web Tokens (JWTs) for multiple users.") | ||
param :search, String, :required => true |
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.
@girijaasoni could you please share an example for this query? What does the search
param should contain?
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.
curl --user test-user1:changeme -X DELETE http://localhost:3000/api/registration_tokens/remove_multiple?search=id%20%5E%20%281%2C2%2C3%29 -H 'Content-Type: application/json'
this is the command I'm using for a scoped search query id ^ (1, 2, 3)
you will need to URL encode in the search params as curl does not accept brackets and operators.
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.
Where does the remove_multiple
come from? And why not to pass an array instead?
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.
my bad, I meant curl --user test-user1:changeme -X DELETE http://localhost:3000/api/registration_tokens?search=id%20%5E%20%281%2C2%2C3%29 -H 'Content-Type: application/json
we are using scoped search for this here so we can search with id or name or whatever. If you don't understand this we can sync up
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.
I understand how search_for
works, but it still seems a bit unintuitive to me that the user needs to write queries in this format. I would have expected a simpler approach. At least, that's my perspective.
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.
I must agree with @nofaralfasi here, for bulk actions that already exist (mostly in Katello), we provide ids
param of the entities that are about to be changed/deleted.
search
param is used mostly in index
actions. Ideal approach is to use index action with search and then use the result in the second "destructive" call.
Although, I personally don't like REST or our? REST because of that (multiple calls instead of one), but at least we're consistent.
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.
@shweta83 and @ShimShtein, since you both approved, WDYT about ^ (#10397 (comment))? Did I miss something?
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.
IDs are mostly hidden value, and definitely not a user-friendly one. I would go with the search approach, from what I know, people are using naming schemes for their users, so performing an action on a group would become much easier if search is implemented. I don't see a reason to "punish" the user that wants to perform such an action with a second call (index with search condition -> invalidation with ids).
We can add an ids
parameter as a "syntactic sugar" here, but I don't think it's really needed in this iteration.
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.
Okay, I won't block on that then.
It just seems weird we didn't do the same before for other endpoints.
8858b6c
to
6d841de
Compare
raise ::Foreman::Exception.new(N_("No record found for %s"), params[:id]) | ||
end | ||
@user.jwt_secret&.destroy | ||
process_success _('Successfully invalidated JWTs for %s.' % @user.login) |
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.
@girijaasoni Can we add a newline here as well?
@girijaasoni invalidate token for other users doesn't work for invalidating self token. Can we fix that too? |
The users you specify will no longer be able to register hosts by using their JWTs. | ||
DOC | ||
|
||
def invalidate_tokens |
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.
I find the naming a bit inconsistent between the invalidate_jwt
method and this one, invalidate_tokens
. Would it make sense to align their names for clarity?
The users you specify will no longer be able to register hosts by using their JWTs. | ||
DOC | ||
|
||
def invalidate_tokens |
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.
def invalidate_tokens | |
def invalidate_jwt_tokens |
To be a bit more consistent with the naming.
end | ||
end | ||
|
||
api :DELETE, '/users/:id/registration_tokens', N_("Invalidate all registration Tokens for a specific 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.
api :DELETE, '/users/:id/registration_tokens', N_("Invalidate all registration Tokens for a specific user.") | |
api :DELETE, '/users/:id/registration_tokens', N_("Invalidate all registration tokens for a specific user.") |
process_success _('Successfully invalidated JWTs for %s.' % @user.login) | ||
end | ||
|
||
api :DELETE, "/registration_tokens", N_("Invalidate all JSON Web Tokens (JWTs) for multiple users.") |
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.
api :DELETE, "/registration_tokens", N_("Invalidate all JSON Web Tokens (JWTs) for multiple users.") | |
api :DELETE, "/registration_tokens", N_("Invalidate all registration tokens for multiple users.") |
DOC | ||
|
||
def invalidate_tokens | ||
raise ::Foreman::Exception.new(N_("Please provide search parameters")) if params[:search].blank? |
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.
raise ::Foreman::Exception.new(N_("Please provide search parameters")) if params[:search].blank? | |
raise ::Foreman::Exception.new(N_("Please provide search parameter")) if params[:search].blank? |
raise ::Foreman::Exception.new(N_("No record found %s"), params[:search]) | ||
end | ||
JwtSecret.where(user_id: @users).destroy_all | ||
process_success _("Successfully invalidated JWTs for %s.\n" % @users.pluck(:login).to_sentence) |
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.
process_success _("Successfully invalidated JWTs for %s.\n" % @users.pluck(:login).to_sentence) | |
process_success _("Successfully invalidated registration tokens for %s.\n" % @users.pluck(:login).to_sentence) |
process_success _("Successfully invalidated registration tokens for %s.\n" % @user.login) | ||
end | ||
|
||
api :DELETE, "/registration_tokens", N_("Invalidate all registration tokens for multiple users.") |
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.
Why didn't we use /users
here?
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.
According to REST principles, you should state what resource you are acting upon. If you wan to use nested resources (as in users/:id/registration_token
) that would work only for a specific user. There is no good way to specify a sub-object of multiple parent objects. So since registration token is an object by itself, we are addressing multiple registration token objects by a search condition.
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.
LGTM
end | ||
|
||
api :DELETE, "/registration_tokens", N_("Invalidate all registration tokens for multiple users.") | ||
param :search, String, :required => true |
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.
@Lennonka , could you please provide me with a description for the search parameters that I could use.
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.
URL-encoded search query that selects users for which registration tokens will be invalidated. Search query example: id ^ (2, 4, 6)
Too bad we didn't use the same terminology in the UI in #10357. Is it too late to change it? |
It is not required in UI, we are using the correct terminology there, this is specific to API |
Thanks everyone! |
Link to UI PR: #10357