Skip to content
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

Feature Request: Constraint helpers for config/routes.rb #139

Closed
henrikbjorn opened this issue May 25, 2023 · 6 comments
Closed

Feature Request: Constraint helpers for config/routes.rb #139

henrikbjorn opened this issue May 25, 2023 · 6 comments

Comments

@henrikbjorn
Copy link
Contributor

When using devise they have helpers that can be used in config/routes.rb like:

authenticated :admin do
  root to: 'admin/dashboard#show', as: :admin_root
end

Which i personally like very much and better than doing require_user! in my controllers.

Would be a awesome addition to passwordless.

Not sure how it would work with Passwordless as most the user finding and authorizing etc. is in the ControllerHelper where Devise calls Warden e.g: https://github.com/heartcombo/devise/blob/main/lib/devise/rails/routes.rb#L477

@mikker
Copy link
Owner

mikker commented May 25, 2023

Good question! PRs welcome ❤️

@yshmarov
Copy link
Contributor

on a custom app that I built, something like this works for me:

# app/constraints/user_constraint.rb
class UserConstraint
  def initialize(&block)
    @block = block
  end

  def matches?(request)
    user = current_user(request)
    user.present? && @block.call(user)
  end

  def current_user(request)
    User.find_by(id: request.session[:user_id])
  end
end
# config/routes.rb
  # authenticate :user, ->(user) { user.admin? } do # <- devise syntax
  constraints UserConstraint.new { |user| user.admin? } do
    mount GoodJob::Engine, at: "good_job"
    mount Avo::Engine, at: Avo.configuration.root_path
  end

  # authenticated :user do # <- devise syntax
  constraints UserConstraint.new { |user| user.present? } do
    get 'dashboard', to: 'static#dashboard'
  end

@tdegrunt
Copy link
Contributor

Similarly to the above, but the following works for me with Passwordless:

# app/constraints/user_constraint.rb
class PasswordlessConstraint
  include Passwordless::ControllerHelpers

  attr_reader :authenticatable_type, :session, :lambda

  def initialize(authenticatable_type, lambda)
    @authenticatable_type = authenticatable_type
    @lambda = lambda
  end

  def matches?(request)
    @session = request.session
    authenticatable = authenticate_by_session(authenticatable_type)
    authenticatable.present? && lambda.call(authenticatable)
  end
end
# config/routes.rb
constraints PasswordlessConstraint.new(User, ->(user) { user.has_role?("admin") }) do
  root to: 'admin/dashboard#show', as: :admin_root
end

The rest is syntactic sugar, but a bit too much magic.

@mikker
Copy link
Owner

mikker commented Apr 30, 2024

@tdegrunt That's amazing! Would love to include it if you're up for creating a PR with a test and some docs?

@henrikbjorn
Copy link
Contributor Author

Will this re-query the database for the user?

We might want to think about using env as warden does.

@tdegrunt
Copy link
Contributor

Took me a while, been on holiday, but added a PR for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants