我有一个Rails 3.2应用程序,需要用户登录(current_user)才能访问子域名的事件页面。我正在使用设计进行身份验证。
如果我提供了直接链接,有没有办法允许用户一次性访问活动页面?然后我会希望他们在尝试访问不同的活动页面时被提示登录(或注册),或者如果他们离开并在将来的某个日期回到同一个活动页面。
我在railscasts上观看了来宾帐户剧集,但似乎用户可以继续以访客身份登录,而无需注册此方法。
这是我的事件控制器代码:
def show
@event = Event.find_by_name(request.subdomain)
if params[:id].present?
@event = Event.find(params[:id])
end
# if @event.present? and @event.videos.present?
@video = Video.find_by_id(params[:video]) || @event.videos.first
# else
# @video = @event.videos.first
# end
# @json = Event.all.to_gmaps4rails
if @user = current_user
else
flash[:alert] = "Please sign in first"
redirect_to sign_up_url(:subdomain => false)
end
end
感谢您提供任何帮助/建议......
编辑:只是提供更多背景信息:
我每周都会尝试将很多用户带到这一个活动页面,如果我只是发送一个链接,我不确定将单独的哈希硬编码到网址中是否可行/切实可行通过社交媒体和电子邮件等。
由于用户点击此链接并直接转到相关页面,因此没有触发操作来创建单独的访客模型,所以我认为答案必须是基于会话的,添加一些列到现有用户模型,但确保每个用户只使用一次。我想也许IP地址可以工作?
答案 0 :(得分:3)
最有先见之明的解决方案是为访客用户创建一个会话变量,其中包含一个布尔值,表示他们是否访问过该页面(如果他们没有访问过,则启用访问权限,反之亦然):
# in your controller
before_filter :check_guest, :only => :show
private
def check_guest
# if user isn't logged in
if current_user.nil?
# if user has already viewed, redirect
if session[:viewed] == true
flash[:alert] = "Please sign in first"
redirect_to sign_up_url(:subdomain => false)
# if user hasn't viewed, allow access, but flag as having viewed
else
session[:viewed] = true
end
end
end
虽然使用会话是解决此特定问题的事实上的方法,但其实施存在限制:
答案 1 :(得分:3)
一个解决方案,而不是设置会话变量,是用url对一次性哈希进行编码,如下所示:
http://site.com/event?access_id=AKJHDA23fdsank
然后,在访问该事件时,将删除访问代码。这将需要管理数据库中的访问代码,但具有万无一失的附加好处。
你可以简单地创建一个api url来生成这些链接,以简化共享过程。
其他一切都很容易被骗。
答案 2 :(得分:1)
您可以使用feature_flags gem设置布尔值:
答案 3 :(得分:0)
我不知道预先构建的解决方案,但它不应该太难实现。我做了类似的事情:
class GuestPass < ActiveRecord::Base
belongs_to :event
# the guest_passes table has a `code` column that contains a long arbitrary string token
end
class Event < ActiveRecord::Base
has_many :guest_passes
def authenticate_guest_pass!(token)
return false unless token
guest_passes.where(code: token).first
end
end
class EventsController < ActiveRecord::Base
before_action :load_event, only: [ :show ]
before_action :validate_guest_pass, unless: current_user
private
def load_event
@event = Event.find(params[:id])
end
def validate_guest_pass
pass = @event.authenticate_guest_pass!(params[:pass])
if pass
pass.delete
else
# redirect to sign in or whatever
end
end
end
然后,您只需生成GuestPass
条记录,并将其粘贴在您提供的链接中:它们看起来像/events/1?pass=xyzzy
(这里的代码可以使用一些清理;我并不是说它很漂亮。但它是第一次通过。)
答案 4 :(得分:0)
这是我对zeantsoi解决方案的略微修改版本,其附加好处是即使用户退出浏览器会话也会持续存在。
def check_guest
#if user is logged in
unless current_user
@event = Event.find_by_name(request.subdomain)
#if user has already viewed, redirect
if @event.guest_ip_address == request.remote_ip
flash[:alert] = "Please sign in first"
redirect_to sign_up_url(:subdomain => false)
#if user hasn't viewed, allow access, but flag as having viewed and store their ip address in the event model so it knows not to show the page again unless current_user
else
session[:viewed] = request.remote_ip
@event.guest_ip_address = session[:viewed]
@event.save!
end
end