我一直在研究一个项目,现在使用Devise进行用户身份验证.无论何时创建用户,它都会为它们生成密码盐以及加密密码.
当我进入这个项目的尾端时,我正在测试用户注册,并注意到我的新角色没有为这些新用户在数据库中创建密码盐,而我的老用户都有盐.新用户可以签到好,但我担心为什么Devise不再创造盐.
我遇到的Devise唯一的奇怪之处就是当我升级模块并记住日志说有关删除加密的内容时,因为bcrypt现在是默认加密,或者是那种效果.我这样做了......不确定这是否与当前问题有关.
另外,想想也许是我的项目被打包了,我从零开始创建了一个全新的Rails应用程序并添加了Devise,甚至这个新项目也没有为用户创建盐.
在Devise中设置密码盐是否有新方法,或者是否有人知道为什么盐不再被创建?不幸的是,Devise wiki在这个问题上没有太多可说的内容,到目前为止谷歌一直没有成功.
或者......首先是否需要加盐?我想,看起来更安全.
我的用户/设计配置如下.
配置/初始化/ devise.rb
Devise.setup do |config|
config.mailer_sender = "mail@domain.com"
require 'devise/orm/active_record'
config.authentication_keys = [ :login ]
config.stretches = 10
config.encryptor = :bcrypt
# Setup a pepper to generate the encrypted password.
config.pepper = "79c2bf3b[...]"
end
Run Code Online (Sandbox Code Playgroud)
应用程序/模型/ user.rb
devise :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable
Run Code Online (Sandbox Code Playgroud)
UPDATE
我能够在Devise升级之后找到通知,其中包含......
[DEVISE] From version 1.2, there is no need to set your encryptor to bcrypt since encryptors are only enabled if you include :encryptable in your models. …Run Code Online (Sandbox Code Playgroud) 我目前正在尝试使用一堆虚假数据填充项目上的开发数据库,以模拟它与数百篇文章/用户的外观和操作方式.我查看了不同的宝石来完成这项任务 - 比如Factory Girl,但文档非常缺乏,我没有得到它 - 但最终使用了Populator和Faker宝石,并做了以下rake任务......
namespace :db do
desc "Testing populator"
task :populate => :environment do
require "populator"
require "faker"
User.populate 3 do |user|
name = Faker::Internet.user_name
user.name = name
user.cached_slug = name
user.email = Faker::Internet.email
user.created_at = 4.years.ago..Time.now
end
end
end
Run Code Online (Sandbox Code Playgroud)
适用于基于文本的数据.但是,所有用户都有一个可以通过Paperclip附件上传的头像,以及所有常规内容都以相同的方式添加缩略图附件.
我理解Populator gem只是对数据库进行直接填充而不必通过ActiveRecord验证来执行此操作.因此我认为Paperclip无法运行以生成所有不同的缩略图并且需要(并上传到正确的目录)对于头像,如果我在上面的rake任务中填充了一个文件路径的字段.
有没有办法通过Populator或其他方式填充假图像?或者也许是一种将rake任务指向我硬盘上的库存图像目录以自动生成每条记录的随机缩略图的方法?曾经在Google上寻找过一种方式,但是没有找到关于这个主题的更多信息.
UPDATE
最终的解决方案,基于pwnfactory的思路......
namespace :db do
desc "Testing populator"
task :populate => :environment do
require "populator"
require "faker"
User.populate 3 do |user|
name = Faker::Internet.user_name
user.name = name
user.cached_slug = name
user.email = Faker::Internet.email …Run Code Online (Sandbox Code Playgroud) 我一直在努力掌握编写测试的方法,但是由于测试似乎永远无法验证我想要的方式,因此我遇到了很多麻烦.特别是,我一直在尝试使用Factory Girl而不是固定装置 - 正如我最近在网上看到的Railscasts和其他建议所示 - 由于它所宣称的好处,而且还没有成功.
例如,这是一个用户模型的简单Rspec测试,测试以确保存在用户名...
describe User do
it "should not be valid without a username" do
user = FactoryGirl.create(:user, :username => "", :password => "secret")
user.should_not be_valid
end
end
Run Code Online (Sandbox Code Playgroud)
和我的factories.rb文件,如果它有帮助...
FactoryGirl.define do
factory :user do
sequence(:username) { |n| "registered-#{n}" }
password "foobar"
end
end
Run Code Online (Sandbox Code Playgroud)
当我运行'rake spec'时,它告诉我......
1) User should not be valid without a username
Failure/Error: user = FactoryGirl.create(:user, :username => "", :password => "secret")
ActiveRecord::RecordInvalid:
Validation failed: Username can't be blank
Run Code Online (Sandbox Code Playgroud)
嗯......这就是POINT.如果我指定用户不应该有效,那么这个测试真的不应该通过吗?
如果我更换了Factory Girl系列并在测试中设置了类似的用户'user = …
我有一个带Devise的Rails 3项目,启用了确认,因此用户必须在注册后通过电子邮件确认他们的帐户.目前,该项目将用户返回到登录页面并抛出"您已成功注册..."通知.我想要做的是将它们重定向到"谢谢"页面,并提供进一步说明(检查您的电子邮件,垃圾邮件文件夹,等等).
我的第一站是Devise wiki,在那里我找到了这个页面.看起来很容易,我做了以下改动,并严格按照指示......
/app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
"http://google.com"
end
end
Run Code Online (Sandbox Code Playgroud)
/config/routes.rb
devise_for :users, :controllers => { :registrations => "registrations" }
Run Code Online (Sandbox Code Playgroud)
我必须在方向上进行的一项修改是将"registrations"文件夹移出/ app/views/devise视图文件夹并移至top/app/views文件夹,因为返回的错误现在缺少视图.无论如何,尽管控制器覆盖似乎工作(我不认为视图原本会打破其他方式),这些方向不起作用...页面忽略after_sign_up并在注册后返回登录页面.
在互联网上搜索包括其他Stack Overflow线程,但我发现的任何内容都没有对我有用...或者回答混淆重定向注册用于登录IN,或者他们实际做的是在登录后更改重定向(正如Devise通常注册后自动登录,不启用确认).
我试过的其他事情......
将after_sign_up_path_for(资源)移动到应用程序控制器中.不行.奇怪的是,对after_sign_in_path_for(资源)执行相同操作并以用户身份登录重定向.
将registrations_controller.rb从/ app/controllers /移动到/ app/controllers/users文件夹并相应地更新所有路由/引用/等.不行.
将Devise的registrations_controller.rb复制到我自己的registrations_controller.rb中.没有工作,只是抛出一个错误,我把它全部卷回来.
我尝试了def after_inactive_sign_up_path_for(资源),因为我认为这个帐户不活跃的事实可能是罪魁祸首.这也被忽略了.
值得一提的是,我已经尝试在这些重大更改后重新启动我的项目,但没有任何需要.
有没有人在启用确认功能的情况下取得成功?
这是一个两部分问题.我需要将我在开发服务器上的rails网站限制为只有几个IP地址,因此公众无法访问它.(基本HTTP身份验证不会"完全"工作,因为auth会破坏项目中的Flash上传器.)
基于我的Google搜索,这是我在路线文件中提出的...
class WhitelistConstraint
def initialize
@ips = '127.0.0.1'
end
def matches?(request)
@ips.include?(request.remote_ip)
end
end
MyProject::Application.routes.draw do
constraints WhitelistConstraint.new do
# all my routing stuff here
end
end
Run Code Online (Sandbox Code Playgroud)
工作得很好.但是,我需要修改它以便使用多个IP地址.我尝试在@ips上使用数组,以及循环遍历每个循环,但都没有工作.
最重要的是,我的问题的第二部分......我可能只需要检查IP的一部分,例如'127.0.0'.我该怎么办?
对于所有弹珠来说,如果我能解决这个问题,那么我就完成了一个项目.
无论如何,我使用Ruby on Rails 3和Devise进行用户身份验证.您可能知道,默认情况下,在用户admin/edit中,如果用户提供新密码,则必须在current_password字段中输入当前密码.有关如何禁用current_password的TON信息,以便用户可以自由更改和保存.
但是,我发现相反的情况很少:要求更多字段的当前密码...在我的情况下,电子邮件字段.并且只在更改电子邮件地址时才需要当前密码,而不是在它保持不变的情况下.目前,用户可以在不提供当前密码的情况下自由更改电子邮件,出于安全考虑,我不希望这样.
在查看了Devise wiki之后,我确实找到了这个页面,我想我可以反转这段代码来完成这个解决方案.我设法在我的user.rb模型中完成了这一点(我从这篇文章中删除了不必要的逻辑)....
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable, :lockable and :timeoutable
devise :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :name, :email, :password, :password_confirmation, :avatar, :remember_me, :agree
attr_accessor :accessible, :agree, :signed_in
attr_readonly :name
# Validation
validates :name, :presence => TRUE, :uniqueness => TRUE, :length => { :within => 4..20 }
validates :agree, :term_agreement => …Run Code Online (Sandbox Code Playgroud) 在我的项目中,我修改了Devise中的注册表单,通过访问者添加:agree选项(用户必须接受注册的服务条款等).如果他们不同意,则不会进行验证.
这导致了一个问题,当用户试图编辑他们的帐户信息,因为它找到了:同意验证,但我能够添加'除非'子句并添加另一个名为:signed_in的访问器,在控制器中定义(我无法'弄清楚如何让模型确定用户是否已登录,设计的助手对我来说不起作用).我的User模型和users_controller的相关部分看起来像......
user.rb
validates :agree, :term_agreement => TRUE, :unless => :signed_in
Run Code Online (Sandbox Code Playgroud)
users_controller.rb
def update
@user = User.find(params[:id])
if user_signed_in?
@user.signed_in = params[:user]
end
[...]
end
Run Code Online (Sandbox Code Playgroud)
所以,一切正常......当用户已经登录时,"同意"验证会覆盖.但是,我必须找出覆盖其他方案的最佳方法...当用户重置密码并需要更改时它.
我正在测试用户帐户,并尝试在一个帐户上重置我的密码,但是我遇到了:同意验证...现在我必须找到一种方法来覆盖它.我注意到更改密码表单的隐藏字段值为:reset_password_token,但我尝试过:除非=>:reset_password_token但它不起作用.
那么实现这个目标的最佳方法是什么?除此之外,我怎么能有一个/或条件(除非:signed_in或:reset_password等):except子句?
我有一个Review模型,允许对产品进行"1-10"评级系统.在我的表单视图中,这是我如何在该字段中吐出1-10的下拉列表...
<%= f.select :rating, options_for_select((0..10).to_a, @review.rating) %>
Run Code Online (Sandbox Code Playgroud)
工作得很好,但团队现在想要评级系统的.5十进制数,所以可以评定7.5,8.0,8.5等.
然而,这让我感到困惑......我怎样才能改变上面的代码并迭代一组数字并在Ruby中每次递增0.5.(注意:是的,我已将我的评级列从整数转换为浮点数.)
这是一个棘手的问题.
我有一个包含多种内容类型的项目,例如文章,评论等.每种内容类型都有注释,注释是多态的,因为它们可以属于任何内容类型.
我想在我的所有内容页面上放置一个总评论计数器来显示有多少评论,并且我实现了一个计数器缓存来执行此操作.(像@ article.comments.count这样的东西是更多的查询,因为我使用Ancestry gem进行线程注释,子注释不计入该数字,只计算根数.)
计数器缓存效果很好,并显示准确的评论数量,但一如既往只有一点点.评论并不总是立即发布,只有注册用户可以立即发布,并且这些评论的状态为"2".未注册的用户进入审核队列; 这些评论有一个:状态为'1'.
问题是,计数器缓存对它们进行了相同的计算,因此如果您有适度的四条评论和一条已批准的评论,则总计数为5.
有没有办法在计数器缓存中添加一个异常,告诉它如果comment.status不是'2'则不增加?同样,当在评论资源的后端并设置要发布的注释(给它状态为2)时,是否有一种方法(模型,控制器或其他方式)为其关联的多态/内容类型增量制作计数器缓存?
comments.rb
# Comments
has_many :comments, :as => :commentable, :dependent => :destroy
accepts_nested_attributes_for :comments
Run Code Online (Sandbox Code Playgroud)
article.rb
belongs_to :commentable, :polymorphic => TRUE, :touch => TRUE, :counter_cache => TRUE
Run Code Online (Sandbox Code Playgroud) 我最近提出了一个应用文章等的应用程序,其上有一个评论/审核系统.当用户发表评论时,会发生以下三种情况之一.
首先,如果他们是注册用户并通过Devise登录,他们的评论将被标记为状态"2"并立即发布.如果他们是具有先前批准的具有匹配电子邮件地址的评论的匿名用户,则评论获得状态"1"并被放入审核队列以供批准.如果用户完全是全新的并且他们的电子邮件不在系统中,则该评论的状态为"0",并且会向其收件箱发送电子邮件以单击链接以批准其电子邮件.完成任何此操作后,将显示相应的通知/闪烁消息.
我已经完成了所有这些工作,但在控制器中几乎完成了所有逻辑和变量定义,使得创建动作非常胖.为了学习最佳实践和'胖模型,瘦子控制器'的惯例,我试图将我可以使用的逻辑移到评论模型中,特别是那些确定他们是否登录或者是什么的部分.假设,模型中有这样的东西......
attr_accessor :message
before_create :poster_type
def poster_type
if current_user
self.status = 2
self.message = 'Your comment has been posted.'
elsif Comment.find_by_mail(self.mail, :conditions => { :status => [1,2]}).present?
self.status = 1
self.message = 'Your comment has been sent for moderation.'
else
self.status = 0
self.message = 'This is a new email, please confirm...'
end
end
Run Code Online (Sandbox Code Playgroud)
问题是,显然你不能在模型中使用Devise的current_user方法(或其他像user_signed_in?等).我对此研究的每个答案都表示无益,访问current_user值等不是模型的业务.
但是,我并不需要给模型提供用户的信息(因为我已经看到所有其他线程试图这样做),所有我需要模型中的方法来确定它们是否已登录.
另外,如果你不能在模型中使用current_user(或其他用户检测方法),那么除了定义控制器中的所有逻辑之外你别无选择,这也不是那么糟糕的做法吗?所以如果可能的话,我怎么能在模型中做这个逻辑呢?或者我应该只是让控制器变胖?
我有一个使用Devise的用户模型,我已经设置了角色,因此可以为用户分配一个或多个角色.如果我想在视图中查看用户的角色,则以下代码可以正常运行...
<% if current_user.roles.include? Role.find_by_name('Administrator') %>
You are an administrator!
<% end %>
Run Code Online (Sandbox Code Playgroud)
但现在,假设我想检查用户是否具有多个角色之一,以查看他们是管理员还是编辑.我确信以下内容会起作用....
<% if current_user.roles.include? Role.find_by_name('Administrator' || 'Editor') %>
Run Code Online (Sandbox Code Playgroud)
...但它没有,只有当你是管理员并忽略在该列表中的第一个之后检查所有其他角色时它才有效.我尝试过其他组合,比如Role.find_by_name(['管理员','编辑'])等等,但没有成功.究竟如何格式化以完成多个角色的检查?我已经在谷歌各地寻找,但所有的例子都使用了一个角色.
ruby-on-rails ×11
devise ×6
ruby ×5
constraints ×1
encryption ×1
factory-bot ×1
ip ×1
model ×1
numbers ×1
paperclip ×1
redirect ×1
roles ×1
routing ×1
rspec ×1
salt ×1
validation ×1