Reputation: 2036
So there I was, right. Just looking through some code, studying bits and pieces when all of a sudden, my ocular receptors were assaulted by the unfamiliar. I was like:
What!!! What's that all about!
Anyway, what I saw was (source):
def authenticate_user!
if doorkeeper_token
Thread.current[:current_user] = User.find(doorkeeper_token.resource_owner_id)
end
# ...
end
So after looking at it for a while, thinking:
Wtf is this
Thread.current[]
insanity? Is this even necessary? What's it even trying to do?
It seemed to me it was kind of like wearing a baseball cap backwards: You may look pretty f'ing cool but that sun glare is winning. I then decided to Google around, read some articles and some SO.
None seemed to concisely answer my question: Given the context of the code, would it not be the same as:
def authenticate_user!
if doorkeeper_token
@current_user = User.find(doorkeeper_token.resource_owner_id)
end
# ...
end
If not, what situation/scenario is it useful/protecting against?
I hope you enjoyed my story and want to contribute an awesome ending.
Upvotes: 2
Views: 1786
Reputation: 2036
From the author:
I use Thread to store current user to be able transparently authenticate user and extend this later. Currently this code gives priority to token-based authentication via Doorkeepr, and you can extend it to any other algorithm. I am not a big fan of Devise and did not want to use the token-based authentication strategy it provides.
Once you write user info inside Thread.currrent[:current_user], any other service can read it independently and use for whatever purposes it is needed. For example, as i mentioned above, checking authorization, logging who did the events happening in the system, etc
as for writing it to
@current_user
, i am not sure it will be accessible in all contexts. But i have not really checked this
Reference: https://github.com/rilian/devise-doorkeeper-cancan-api-example/issues/1#issuecomment-143479288
Upvotes: 0
Reputation: 48599
There are different bulletin boards on which you can pin information. The bulletin board where local variables
are posted is hidden behind hedges and cannot be seen by the views who live in the next yard:
current_user = User.find(doorkeeper_token.resource_owner_id)
The bulletin board where @variables
are posted is nailed to the top of a ladder, so the views have an unobstructed view of the @variables over the tops of the hedges:
@current_user = User.find(doorkeeper_token.resource_owner_id)
But other methods, which live in classes across the street, cannot see the @variables posted on the bulletin board on top of the ladder because a row of trees is in the way.
Thread variables
, such as:
Thread.current[:current_user] = User.find(doorkeeper_token.resource_owner_id)
launch a kite, which flies higher than the trees, and the variables posted on the kite can be seen by the methods that live across the street.
Why not create a ruby global variable
, e.g. $current_user, instead? Because then requests initiated simultaneously by different users will write to the same global variable, potentially screwing things up.
Given the context of the code
There's not enough context to tell why a (thread) global variable is needed.
Upvotes: 5