Skip to content
Mike Nelson edited this page Jan 29, 2020 · 1 revision

The Subroutine::Auth module provides basic bindings for application authorization. It assumes that, optionally, a User will be provided as the first argument to an Op. It forces authorization to be declared on each class it's included in. The user is accessible via the current_user accessor.

class SayHiOp < ::Subroutine::Op
  include ::Subroutine::Auth

  require_user!

  string :say_what, default: "hi"

  protected

  def perform
    puts "#{current_user.name} says: #{say_what}"
  end
end
user = User.find("john")
SayHiOp.submit!(user)
# => John says: hi

SayHiOp.submit!(user, say_what: "hello")
# => John says: hello


SayHiOp.submit!
# => raises Subroutine::Auth::NotAuthorizedError

There are a handful of authorization configurations:

  1. require_user! - ensures that a user is provided
  2. require_no_user! - ensures that a user is not present
  3. no_user_requirements! - explicitly doesn't matter

In addition to these top-level authorization declarations you can provide custom authorizations like so:

class AccountSetSecretOp < ::Subroutine::Op
  include ::Subroutine::Auth

  require_user!
  authorize :authorize_first_name_is_john
  
  # If you use a policy-based authorization framework like pundit:
  # `policy` is a shortcut for the following:
  # authorize -> { unauthorized! unless policy.can_set_secret? }
  
  policy :can_set_secret?

  string :secret
  belongs_to :account

  protected

  def perform
    account.secret = secret
    current_user.save!
  end

  def authorize_first_name_is_john
    unless current_user.first_name == "john"
      unauthorized!
    end
  end

  def policy
    ::UserPolicy.new(current_user, current_user)
  end

end
Clone this wiki locally