1 module LoginSystem
2 def self.included(base)
3 base.extend ClassMethods
4 base.class_eval do
5 prepend_before_filter :authenticate, :authorize
6 helper_method :current_user
7 end
8 end
9
10 protected
11
12 def current_user
13 @current_user ||= (login_from_session || login_from_cookie || login_from_http)
14 end
15
16 def current_user=(value=nil)
17 if value && value.is_a?(User)
18 @current_user = value
19 session['user_id'] = value.id
20 else
21 @current_user = nil
22 session['user_id'] = nil
23 end
24 @current_user
25 end
26
27 def authenticate
28 action = params['action'].to_s.intern
29 if current_user
30 session['user_id'] = current_user.id
31 true
32 else
33 session[:return_to] = request.request_uri
34 respond_to do |format|
35 format.html { redirect_to login_url }
36 format.any(:xml,:json) { request_http_basic_authentication }
37 end
38 false
39 end
40 end
41
42 def authorize
43 action = action_name.to_s.intern
44 if user_has_access_to_action?(action)
45 true
46 else
47 permissions = self.class.controller_permissions[action]
48 flash[:error] = permissions[:denied_message] || 'Access denied.'
49 respond_to do |format|
50 format.html { redirect_to(permissions[:denied_url] || { :action => :index }) }
51 format.any(:xml, :json) { head :forbidden }
52 end
53 false
54 end
55 end
56
57 def user_has_access_to_action?(action)
58 self.class.user_has_access_to_action?(current_user, action, self)
59 end
60
61 def login_from_session
62 User.find(session['user_id']) rescue nil
63 end
64
65 def login_from_cookie
66 if !cookies[:session_token].blank? && user = User.find_by_session_token(cookies[:session_token]) # don't find by empty value
67 user.remember_me
68 set_session_cookie(user)
69 user
70 end
71 end
72
73 def login_from_http
74 if [Mime::XML, Mime::JSON].include?(request.format)
75 authenticate_with_http_basic do |user_name, password|
76 User.authenticate(user_name, password)
77 end
78 end
79 end
80
81 def set_session_cookie(user = current_user)
82 cookies[:session_token] = { :value => user.session_token , :expires => Radiant::Config['session_timeout'].to_i.from_now.utc }
83 end
84
85 module ClassMethods
86 def no_login_required
87 skip_before_filter :authenticate
88 skip_before_filter :authorize
89 end
90
91 def login_required?
92 filter_chain.any? {|f| f.method == :authenticate || f.method == :authorize }
93 end
94
95 def login_required
96 unless login_required?
97 prepend_before_filter :authenticate, :authorize
98 end
99 end
100
101 def only_allow_access_to(*args)
102 options = {}
103 options = args.pop.dup if args.last.kind_of?(Hash)
104 options.symbolize_keys!
105 actions = args.map { |a| a.to_s.intern }
106 actions.each do |action|
107 controller_permissions[action] = options
108 end
109 end
110
111 def controller_permissions
112 @controller_permissions ||= Hash.new { |h,k| h[k.to_s.intern] = Hash.new }
113 end
114
115 def user_has_access_to_action?(user, action, instance=new)
116 permissions = controller_permissions[action.to_s.intern]
117 case
118 when allowed_roles = permissions[:when]
119 allowed_roles = [allowed_roles].flatten
120 allowed_roles.any? { |role| user.has_role?(role) }
121 when condition_method = permissions[:if]
122 instance.send(condition_method)
123 else
124 true
125 end
126 end
127 end
128 end