使用管理员邀请设置可确认

时间:2016-06-06 23:20:30

标签: ruby-on-rails devise

致力于更新一些旧版设计代码(不会使用devise_invitable)并遭受不可避免的头痛。

所需的功能是避免交付Devise的确认电子邮件,直到管理员实际邀请给定用户为止。

devise/registrations#new上有一个表单,用户输入他们的电子邮件,管理员后端,最终是users#index,其中有一个"邀请按钮"

近年来,由于设计管理信息中心中的遗留业务逻辑会查找没有~> 4.1.1的用户,因此设计似乎已经发生了变化(应用目前处于confirmation_token)。并询问管理员是否要向这些用户发送邀请。

<%=(user.confirmation_token.nil? ? 
  (link_to "Send Invitation", invite_user_path(user.id), {:class => 'button radius tiny'}) : 
  (link_to "Resend", invite_user_path(user.id), {:class => 'button radius tiny'})) unless user.confirmed_at.present?
%>

这是User模型,其中包含许多方法,旨在覆盖默认的逻辑设计用于验证和创建用户。

class User < ActiveRecord::Base
  ...
  devise :database_authenticatable, :registerable, 
         :confirmable, :recoverable, :rememberable, 
         :trackable, :validatable

  has_and_belongs_to_many :roles, :join_table => :roles_users

  after_create :add_role

  def password_required?
   if !persisted?
     !(password != "")
   else
     !password.nil? || !password_confirmation.nil?
   end
  end

  # override Devise method
  def confirmation_required?
   false
  end

  # override Devise method
  def active_for_authentication?
   confirmed? || confirmation_period_valid?
  end

  def send_reset_password_instructions
    if self.confirmed?
      super
    else
     errors.add :base, "You must receive an invitation before you set your password."
    end
  end

  # new function to set the password
  def attempt_set_password(params)
    p = {}
    p[:password] = params[:password]
    p[:password_confirmation] = params[:password_confirmation]
    update_attributes(p)
  end

  # new function to determine whether a password has been set
  def has_no_password?
    self.encrypted_password.blank?
  end

  # new function to provide access to protected method pending_any_confirmation
  def only_if_unconfirmed
    pending_any_confirmation {yield}
  end

  private

  def add_role
    return if roles.pluck(:name).include? "partner"

    free = Role.find_by_name "free"
    roles << free
    save!
  end
end

在prod上修改后,似乎立即创建了确认令牌,就像创建User记录时一样。

2016-06-06T21:49:19.283289+00:00 app[web.1]:   
  SQL (27.9ms)  
    UPDATE `users` 
    SET `created_at` = '2016-06-06 21:49:19.172495', 
        `updated_at` = '2016-06-06 21:49:19.172495', 
        `id` = 37, 
        `unconfirmed_email` = 'adminemail@gmail.com', 
        `confirmation_token` = 'bdyrKwZG31mPtfAskEsU', 
        `confirmation_sent_at` = '2016-06-06 21:49:19.252215' 
    WHERE `users`.`id` = 37

有趣的是,它并非100%明确表示电子邮件实际正在发送,但我只是想了解为什么确认令牌(和confirmation_sent_at)仍然存在立即更新。那是一个错误吗?这是新的吗?或者我错了吗?

包括ConfirmationsController意大利面条代码也是为了您的观赏乐趣:

class ConfirmationsController < Devise::PasswordsController

  # Remove the first skip_before_filter (:require_no_authentication) if you
  # don't want to enable logged users to access the confirmation page.
  # skip_before_filter :require_no_authentication

  skip_before_filter :authenticate_user!

  # POST /resource/confirmation
  def create
    self.resource = resource_class.send_confirmation_instructions(resource_params)
    if successfully_sent?(resource)
      respond_with({}, :location => after_resending_confirmation_instructions_path_for(resource_name))
    else
      respond_with(resource)
    end
  end

  # PUT /resource/confirmation
  def update
    with_unconfirmed_confirmable do
      if @confirmable.has_no_password?
        @confirmable.attempt_set_password(resource_params)
        if @confirmable.valid?
          @confirmable.update_attributes!(resource_params)
          do_confirm
        else
          do_show
          @confirmable.errors.clear #so that we won't render :new
        end
      else
        self.class.add_error_on(self, :email, :password_allready_set)
      end
    end

    if !@confirmable.errors.empty?
      render 'devise/confirmations/new'
    end
  end

  # GET /resource/confirmation?confirmation_token=abcdef
  def show
    with_unconfirmed_confirmable do
      if @confirmable.has_no_password?
        do_show
      else
        do_confirm
      end
    end
    if !@confirmable.errors.empty?
      render 'devise/confirmations/new'
    end
  end

  protected

  def with_unconfirmed_confirmable
    @confirmable = User.find_or_initialize_with_error_by(:confirmation_token, params[:confirmation_token])
    self.resource = @confirmable
    if !@confirmable.new_record?
      @confirmable.only_if_unconfirmed {yield}
    end
  end

  def do_show
    @confirmation_token = params[:confirmation_token]
    @requires_password = true
    render 'devise/confirmations/show'
  end

  def do_confirm
    @confirmable.confirm!
    set_flash_message :notice, :confirmed
    sign_in_and_redirect(resource_name, @confirmable)
  end

  # The path used after resending confirmation instructions.
  def after_resending_confirmation_instructions_path_for(resource_name)
    new_session_path(resource_name)
  end

  # The path used after confirmation.
  def after_confirmation_path_for(resource_name, resource)
    after_sign_in_path_for(resource)
  end

  private

  def resource_params
    params.require(:user).permit(:first_name, :last_name, :email, :encrypted_password, :reset_password_token, :reset_password_sent_at, :remember_created_at, :sign_in_count, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip, :last_sign_in_ip, :created_at, :updated_at, :confirmation_token, :confirmed_at, :confirmation_sent_at)
  end
end

也添加RegistrationsController

class Users::RegistrationsController < Devise::RegistrationsController
  def new
    super
  end

  def create
    session[:email] = params[:user][:email] if params[:user][:email]

    if User.exists?(email: params[:user][:email])
      redirect_to :public_feed, flash: { notice: "Welcome back." }
    else
      super
    end
  end
end

0 个答案:

没有答案