2017-01-17 9 views
0

site_id로 범위가 지정된 User 모델이 있습니다. 유증 토큰에 의해 초대 된 사용자를 조회하려고하면 내가 초대 링크를 사용하고, 초대 토큰이 사용자를 조회하는 시도를 고안 할 때, 사이트 ID가 Devise 범위가 지정된 사용자 모델이 포함 된 Invitable 초대 토큰

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 

포함되어 있지 않습니다는 사이트 ID는 NULL입니다

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

devise가 User Scope을 인식하도록하려면 어떻게해야합니까?

+0

사용자 모델 내에서'Site.id'를 사용합니다. '사이트'객체에 대해 더 많이 알 수 있습니까? – fossil

답변

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 
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