使用范围用户模型设计可邀请的邀请令牌

时间:2017-01-17 08:01:18

标签: ruby-on-rails devise ruby-on-rails-5 devise-invitable

我有一个由site_id作用域的用户模型。当设计尝试按令牌查找受邀用户时,不包括site_id

class User < ApplicationRecord

belongs_to :site
default_scope { where(site_id: Site.current_id) }
devise :invitable, :confirmable, :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable

  validates_uniqueness_of :email, scope: :site
  validates_format_of :email, with: Devise::email_regexp

end

当我使用邀请链接并设计尝试通过邀请令牌查找用户时,site_id为NULL

 SELECT  `users`.* FROM `users` WHERE `users`.`site_id` IS NULL AND `users`.`invitation_token` = 'acomplicatedtoken' ORDER BY `users`.`id` ASC LIMIT 1

如何启用设计识别用户范围?

2 个答案:

答案 0 :(得分:0)

我的方法是覆盖invitations_controller.rb。我查看了devise_invitable(https://github.com/scambra/devise_invitable/blob/master/app/controllers/devise/invitations_controller.rb)内置的默认invitations_controller.rb,并调整了before_actions。

的routes.rb

devise_for :users, controllers: { invitations: 'users/invitations' }

/app/controllers/users/invitations_controller.rb

class Users::InvitationsController < Devise::InvitationsController

    skip_before_action :resource_from_invitation_token, only: [:edit]
    before_action :scoped_resource_from_invitation_token, only: [:edit]

    private
    def scoped_resource_from_invitation_token

        unless params[:invitation_token] && self.resource = User.find_by_invitation_token(params[:invitation_token], true)
            set_flash_message(:alert, :invitation_token_invalid) if is_flashing_format?
            redirect_to after_sign_out_path_for(resource_name)
        end

    end

end

# self.resource = resource_class.find_by_invitation_token

# is now

# self.resource = User.find_by_invitation_token

答案 1 :(得分:0)

更彻底:

class Users::InvitationsController < Devise::InvitationsController

  skip_before_action :has_invitations_left?, :only => [:create]
  skip_before_action :resource_from_invitation_token, :only => [:edit, :destroy]

  before_action :scoped_has_invitations_left?, :only => [:create]
  before_action :scoped_resource_from_invitation_token, :only => [:edit, :destroy]

  if respond_to? :helper_method
    helper_method :after_sign_in_path_for
  end

  # GET /resource/invitation/new
  def new
    self.resource = User.new
    render :new
  end

  # POST /resource/invitation
  def create
    self.resource = invite_resource
    resource_invited = resource.errors.empty?

    yield resource if block_given?

    if resource_invited
      if is_flashing_format? && self.resource.invitation_sent_at
        set_flash_message :notice, :send_instructions, :email => self.resource.email
      end
      if self.method(:after_invite_path_for).arity == 1
        respond_with resource, :location => after_invite_path_for(current_inviter)
      else
        respond_with resource, :location => after_invite_path_for(current_inviter, resource)
      end
    else
      respond_with_navigational(resource) { render :new }
    end
  end

  # GET /resource/invitation/accept?invitation_token=abcdef
  def edit
    set_minimum_password_length
    resource.invitation_token = params[:invitation_token]
    render :edit
  end

  # PUT /resource/invitation
  def update
    raw_invitation_token = update_resource_params[:invitation_token]
    self.resource = accept_resource
    invitation_accepted = resource.errors.empty?

    yield resource if block_given?

    if invitation_accepted
      if Devise.allow_insecure_sign_in_after_accept
        flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
        set_flash_message :notice, flash_message if is_flashing_format?
        sign_in(resource_name, resource)
        respond_with resource, :location => after_accept_path_for(resource)
      else
        set_flash_message :notice, :updated_not_active if is_flashing_format?
        respond_with resource, :location => new_session_path(resource_name)
      end
    else
      resource.invitation_token = raw_invitation_token
      respond_with_navigational(resource){ render :edit }
    end
  end

  # GET /resource/invitation/remove?invitation_token=abcdef
  def destroy
    resource.destroy
    set_flash_message :notice, :invitation_removed if is_flashing_format?
    redirect_to after_sign_out_path_for(resource_name)
  end

  protected

  def invite_resource(&block)
    User.invite!(invite_params, current_inviter, &block)
  end

  def accept_resource
    User.accept_invitation!(update_resource_params)
  end

  def current_inviter
    authenticate_inviter!
  end

  def scoped_has_invitations_left?
    unless current_inviter.nil? || current_inviter.has_invitations_left?
      self.resource = User.new
      set_flash_message :alert, :no_invitations_remaining if is_flashing_format?
      respond_with_navigational(resource) { render :new }
    end
  end

  def scoped_resource_from_invitation_token
    unless params[:invitation_token] && self.resource = User.find_by_invitation_token(params[:invitation_token], true)
      set_flash_message(:alert, :invitation_token_invalid) if is_flashing_format?
      redirect_to after_sign_out_path_for(resource_name)
    end
  end

  def invite_params
    devise_parameter_sanitizer.sanitize(:invite)
  end

  def update_resource_params
    devise_parameter_sanitizer.sanitize(:accept_invitation)
  end

  def translation_scope
    'devise.invitations'
  end
end