-
Notifications
You must be signed in to change notification settings - Fork 896
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
Add User.revoke_sessions #20601
Add User.revoke_sessions #20601
Conversation
7446bc3
to
580cfcb
Compare
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.
this looks good nick
def revoke_sessions | ||
current_sessions = Session.where(:user_id => id) | ||
ManageIQ::Session.revoke(current_sessions.map(&:session_id)) | ||
current_sessions.destroy_all |
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.
Wondering if this should be in a transaction?
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.
Probably not a bad idea.
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.
Actually, I am going to hold off on this.
While a transaction would be nice, unfortunately, there is a possibility it will be not function as expected, since ManageIQ::Session
could have a .store
of memcached
, so the transaction wouldn't be "fully reverted" if we were to wrap both .revoke
and .destroy_all
in a single transaction.
I think the .destroy_all
would be in it's own transaction, but I could be wrong so I don't know if there is any value of wrapping just that line.
if data[:userid] | ||
user_tokens_cache_key = "tokens_for_#{data[:userid]}" | ||
user_tokens_cache = read(user_tokens_cache_key) || [] | ||
user_tokens_cache << token |
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.
This is really tricky in a multi-threaded environment particularly with memcached. As two competing threads come in, they can't step on each other.
This was sort of what I was hinting at in the original proposal (#20378 (comment) - see the cross out section on memory_store), where I mentioned for memached we might need to use CAS.
These particular "create an extra index in the memory store" was what we were trying to avoid by storing all of the records in the sessions table regardless of the store type. I'm not against encoding an index in each one instead, but I think each one has nuances.
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.
if we are using multiple memcached instances, then each server will have a unique list of session ids
and has a low likelihood of stepping on another server's toes. Also, every server can not clear the sessions on other memcached servers. Maybe the use cases for problems are simpler in terms of the session store and more complicated in terms of broadcasting to delete all of a user's sessions.
Yes. A single server could have multiple sessions coming live at the same time. Maybe via the api and rails at the same time? I am having trouble coming up with a use case that doesn't seem far fetched.
Before we go super complex on distributed memcached servers, can we entertain using a single session store? Just like we use a single data store (postgres).
b4bf634
to
7b86b37
Compare
@Fryguy @kbrock @lpichler I think I have addressed all of your feedback, so please let me know if there is anything else. @lpichler do these changes now work for you? I assume you had this pulled down locally previously. @Fryguy So, I think the only outstanding item in this PR is the threading issues, which I think I would like to address in a followup, assuming you are okay with the approach we have now currently. This isn't to say it isn't important, but since I am not sure how we want to tackle it, and if what we did is even helping, I think deferring the implementation of this would allow the rest of the effort to move forward while we mull over the details to address that particular issue. That said, if you think how any of this is implemented currently might be at odds with a future "thread/process -safe" solution in the future, I am happy to address that now. The deferring of implementing the locking/mutex/CAS bits is what I am suggesting at the moment. |
yes it works - otherwise I have two comments and it looks that those issues need to be solved: thanks |
7b86b37
to
fb2cb6b
Compare
@lpichler thanks for taking a look! I should have addressed your issues now. Sorry for the derps... |
@NickLaMuro, it is working great, thanks! it looks that CI failure is related to this PR. |
fb2cb6b
to
137d230
Compare
It was, though the way the spec was written, it probably was a scenario that wouldn't happen. Regardless, I added a guard clause ( |
I am good with deferring the theadsafety issues to another PR, but I think it has to be in relatively quickly. Puma by its nature is multi-threaded, so we will start seeing issues almost immediately, I'd expect. @jrafanie wdyt? |
Implements methods for tracking user tokens for a given userid so they can be deleted all at once.
Makes the instance variable `@token_store` of `TokenStore` a `cattr_reader`, and then uses that to loop through each of the token stores to delete all of the sessions associated with the currently instanced userid.
137d230
to
7b4679d
Compare
Checked commits NickLaMuro/manageiq@0bd0c87~...7b4679d with ruby 2.6.3, rubocop 0.69.0, haml-lint 0.28.0, and yamllint |
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.
this is looking much nicer. thanks nick
@@ -1,20 +1,47 @@ | |||
class TokenStore | |||
@token_caches = {} # Hash of Memory/Dalli Store Caches, Keyed by namespace | |||
module KeyValueHelpers |
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.
thanks - this is much nicer than the individual monkey patches
if data[:userid] | ||
user_tokens_cache_key = "tokens_for_#{data[:userid]}" | ||
user_tokens_cache = read(user_tokens_cache_key) || [] | ||
user_tokens_cache << token |
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.
if we are using multiple memcached instances, then each server will have a unique list of session ids
and has a low likelihood of stepping on another server's toes. Also, every server can not clear the sessions on other memcached servers. Maybe the use cases for problems are simpler in terms of the session store and more complicated in terms of broadcasting to delete all of a user's sessions.
Yes. A single server could have multiple sessions coming live at the same time. Maybe via the api and rails at the same time? I am having trouble coming up with a use case that doesn't seem far fetched.
Before we go super complex on distributed memcached servers, can we entertain using a single session store? Just like we use a single data store (postgres).
@kbrock I will not be "entertaining" anything like that until after this PR has been merged, and probably not even consider it myself until the next release. I already asked for this to be reviewed a few days ago now after it has been open for close to a couple of weeks, only for it to be made unmergable to "entertain a refactoring" that really solved nothing: This is holding up other dependent work on being finished, so anything in he name of refactoring is a hard pass until the MVP of this feature is addressed. |
@Fryguy Can this be merged? I think Nick addressed all of the comments |
Built on top of #20477
Requires ManageIQ/manageiq-schema#503
Adds functionality to revoke all sessions (API, UI, etc.) from a given user.
Links
Steps for Testing/QA
I tested this locally by:
User
instance (.revoke_sessions
)