My Rails 5应用程序仅允许管理员或支持用户创建用户,在创建用户时生成密码并通过电子邮件发送给用户,在第一次用户登录时,应用程序强制他们更改密码。
我的架构中有一个password_updated字段,我想在密码更新时填写为true,但是我在这里碰壁,不确定它的编码器眼睛和我只是看不出哪里出错了。
我的应用程序控制器:
# Force User To Change Password On First Login
def after_sign_in_path_for(resource)
if current_user.password_updated == "false"
edit_passwords_path
else
authenticated_root_path
end
end
我已将其设置为如果用户尝试跳过或跳过密码更改,则会将其重定向到密码更改。
我的密码控制器:
class PasswordsController < ApplicationController
def edit
@user = current_user
end
def update
if current_user.update_with_password(user_params)
current_user.password_updated = "true"
flash[:notice] = 'Your Password Has Been Sucessfully Updated.'
redirect_to authenticated_root_path
else
flash[:error] = 'Oh No! Something Went Wrong, Please Try Again.'
render :edit
end
end
private
def user_params
params.require(:user).permit(:password_updated, :current_password, :password, :password_confirmation)
end
end
最初我让应用程序控制器查看登录计数,但是如果用户关闭并等待足够长时间,他们可以重新登录而不必更改密码。我觉得这更有风险。
非常感谢这里的任何帮助。
答案 0 :(得分:1)
我建议允许管理员创建没有密码的用户。您必须从设计中覆盖password_required方法。
def password_required?
new_record? ? false : true
end
对于新记录,当admin创建它时,不需要密码,但是当用户注册时,它将提示添加密码。 或者您甚至可以保持条件,例如当用户是管理员时,返回false,否则返回true。
答案 1 :(得分:1)
我认为问题在于,在将current_user
设置为true后,您不会保存password_updated
所以代码应该像
def update
update_params = user_params.merge(password_updated: true)
if current_user.update_with_password(update_params)
flash[:notice] = 'Your Password Has Been Successfully Updated.'
redirect_to authenticated_root_path
else
flash[:error] = 'Oh No! Something Went Wrong, Please Try Again.'
render :edit
end
end
这样您只需保存一次current_user
。
我认为password_updated
是DB中的布尔字段
然后在application_controller.rb
current_user.password_updated?
中,您可以查看BrandName Expense
Apple $1.8B
Google $3.2B
GE -
facebook $281M
McDonald $719M
。
答案 2 :(得分:1)
我会选择使用邀请的不同方法。
使用令牌(密码学随机字符串)创建受邀用户,该令牌用于标识用户。这消除了以明文形式传达临时密码的需要,例如,您可以为邀请令牌添加到期时间以确保安全。
所以app流程如下:
/invitiations/new
/invitations
/invitations/edit?invitation_token=ABCD12
/invitations
发送PATCH。最小的例子是:
class AddInvitationTokenToUser < ActiveRecord::Migration[5.0]
def change
add_column :users, :invitation_token, :string
# this may not work on DBs that do not allow NULL on unique columns
add_index :users, :invitation_token, unique: true
end
end
然后我们需要设置User模型来创建随机邀请令牌。
require 'securerandom'
class User < ApplicationRecord
# @todo skip password validation if user has invitation_token
def set_invitation_token!
self.invitation_token = generate_invitation_token
end
private
def generate_invitation_token
# this ensures that the token is unique
begin
token = SecureRandom.urlsafe_base64
end while User.where(invitation_token: token).any?
token
end
end
为邀请设置控制器:
class InvitationsController < ApplicationController
before_action :authenticate!, only: [:new, :create]
before_action :authorize!, only: [:new, :create]
prepend_before_action :authenticate_user_from_token!, only: [:edit, :update]
skip_before_action :authenticate!, :authorize!, only: [:edit, :update]
def new
@user = User.new
end
def create
@user = User.new(create_params) do |u|
u.set_invitation_token!
end
if @user.save
# @todo email user invitation email
redirect_to '/somewhere'
else
render :new
end
end
def edit
end
def update
if @user.update(update_params)
@user.update_attibute(:invitation_token, nil)
redirect_to new_session_path, notice: 'Please sign in.'
else
render :edit
end
end
private
def authenticate_user_from_token!
unless params[:invitation_token].present?
raise ActiveRecord::RecordNotFound and return
end
@user = User.find_by!(invitation_token: params[:invitation_token])
end
def create_params
require(:user).permit(:email)
end
def update_params
require(:user).permit(:password, :password_confirmation)
end
end
为简洁起见,此处省略了几个步骤,例如跳过密码验证。
我建议您查看DeviseInvitable以获取此模式的更完整示例。