self.current_user = user
above and then delegating current_user
to your ActionCable connection:env["warden"].user(:user)
or the variable will return nil
.current_user
to the ActionCable connection
and be home by lunch:id
out of the session store.current_user
to the ActionCable connection
.devise-jwt
gem to create a JWT token which is injected into the HEAD. You can use it as a reference for all of the instructions below.connection.rb
using ugly hacks where you pass a token as part of your ActionCable connection URL. While this seems to make sense - after all, this is close to how the other techniques above work - putting your token into the URL is a real security vulnerability and there's a better way: move the responsibility for authentication from the ActionCable connection down to the channels themselves. Let's consider a potential solution that uses the Warden::JWTAuth module:current_user
accessor as usual, but we won't be able to set it until someone successfully create a subscription to a channel. If they fail to pass a valid token, we can deny them a subscription. That means that all channels will need to be able to authenticate tokens during the subscription creation process. We will create a subscribed
method in ApplicationCable
, which all of your channels inherit from.reject
. This means that while they have successfully established an ActionCable connection, they do not have the credentials to subscribe to the individual channel. Notice how we manually set the current_user
on the connection if the authentication is successful.ApplicationCable::Channel
definition in your application. You can set additional channels to authenticate in this manner by making sure that they inherit from ApplicationCable::Channel
and that the subscribed
method calls super
before your stream_from
or stream_for
statement:warden-jwt_auth
gem is in your project (possibly through devise-jwt
) and that there is a valid current_user
accessor in scope.current_user
to the ActionCable connection
as you would in any other Reflex class:identified_by
values in a single connection class. Note that you still have to delegate both current_user
and session_id
to the connection so you can access these values in your Reflex action methods.acts_as_tenant
gem has skyrocketed since the excellent JumpStart Pro came out. It's easy to create Reflexes that automatically support tenant scopes.Account
- that other models get scoped to. If you have an Image
class that acts_as_tenant :account
then every query (read and write) to the Image
class will automatically include a WHERE
clause restricting results to the current Account
.Connection
module:tenant
branch of the stimulus_reflex_harness repo, if you'd like to dig into this approach further.before_reflex
callback is the best place to handle privilege checks, because you can call throw :abort
to prevent the Reflex if the user is making decisions above their pay grade.accessible_by
method ensures that you only access records permitted for the current user. Depending on your requirements, you might opt to use different strategies for Page Morphs than you do for other types of Reflexes. This is because the CCC authorize!
method is designed to operate on the current ActionController instance. StimulusReflex only creates Controller instances for Page Morphs, as they incur a performance penalty.current_ability
to it, it's hard to justify documenting that approach here since there is already a viable, one-size-fits-all solution available and there is a performance hit when you create a Controller.authorize!
method in your Reflex action, because a Reflex is not a Controller.Pundit
module, you can take advantage of the authorize
method.current_user
in scope and a policy matching the name of your Reflex action. In the following example we create a sing?
policy for our sing
Reflex action in song_policy.rb
authorize
call fails, a Pundit::NotAuthorizedError
will be raised, which you can handle in your Reflex action or leave unhandled so that it bubbles up and gets picked up by a 3rd-party error handling mechanism such as Sentry or HoneyBadger.current_user
in scope and an application_policy.rb
already in place. In this application, the User
model has a boolean attribute called admin
.params
hash in your ActionCable Channel class. While it's usually not necessary to send extra information to the StimulusReflex Channel, it is a mechanism available to you. You might have used it to implement the token-based JWT auth technique above.