Description:
force log out when password change
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r884:490fbe2ccf0b - - 2 files changed: 6 inserted, 0 deleted

@@ -1,265 +1,270
1 1 require 'ipaddr'
2 2 require "securerandom"
3 3
4 4 class ApplicationController < ActionController::Base
5 5 protect_from_forgery
6 6
7 7 before_action :current_user
8 8 before_action :nav_announcement
9 9 before_action :unique_visitor_id
10 10
11 11 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
12 12 MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login'
13 13 WHITELIST_IGNORE_CONF_KEY = 'right.whitelist_ignore'
14 14 WHITELIST_IP_CONF_KEY = 'right.whitelist_ip'
15 15
16 16 #report and redirect for unauthorized activities
17 17 def unauthorized_redirect(notice = 'You are not authorized to view the page you requested')
18 18 flash[:notice] = notice
19 19 redirect_to login_main_path
20 20 end
21 21
22 22 # Returns the current logged-in user (if any).
23 23 def current_user
24 24 return nil unless session[:user_id]
25 25 @current_user ||= User.find(session[:user_id])
26 26 end
27 27
28 28 def nav_announcement
29 29 @nav_announcement = Announcement.where(on_nav_bar: true)
30 30 end
31 31
32 32 def admin_authorization
33 33 return false unless check_valid_login
34 34 user = User.includes(:roles).find(session[:user_id])
35 35 unless user.admin?
36 36 unauthorized_redirect
37 37 return false
38 38 end
39 39 return true
40 40 end
41 41
42 42 #admin always count as every roles
43 43 def role_authorization(roles)
44 44 return false unless check_valid_login
45 45 user = User.find(session[:user_id])
46 46 return true if user.admin?
47 47 roles.each do |r|
48 48 return true if user.has_role?(r)
49 49 end
50 50 unauthorized_redirect
51 51 end
52 52
53 53 def authorization_by_roles(allowed_roles)
54 54 return false unless check_valid_login
55 55 unless @current_user.roles.detect { |role| allowed_roles.member?(role.name) }
56 56 unauthorized_redirect
57 57 return false
58 58 end
59 59 end
60 60
61 61 def testcase_authorization
62 62 #admin always has privileged
63 63 if @current_user.admin?
64 64 return true
65 65 end
66 66
67 67 unauthorized_redirect unless GraderConfiguration["right.view_testcase"]
68 68 end
69 69
70 70 def unique_visitor_id
71 71 unless cookies.encrypted[:uuid]
72 72 value = SecureRandom.uuid
73 73 cookies.encrypted[:uuid] = { value: value, expires: 20.year }
74 74 return value
75 75 else
76 76 return cookies.encrypted[:uuid]
77 77 end
78 78 end
79 79
80 80 protected
81 81
82 82 #redirect to root (and also force logout)
83 83 #if the user is not logged_in or the system is in "ADMIN ONLY" mode
84 84 def check_valid_login
85 85 #check if logged in
86 86 unless session[:user_id]
87 87 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
88 88 unauthorized_redirect('You need to login but you cannot log in at this time')
89 89 else
90 90 unauthorized_redirect('You need to login')
91 91 end
92 92 return false
93 93 end
94 94
95 95 # check if run in single user mode
96 96 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
97 97 if @current_user==nil || (!@current_user.admin?)
98 98 unauthorized_redirect('You cannot log in at this time')
99 99 return false
100 100 end
101 101 end
102 102
103 103 # check if the user is enabled
104 104 unless @current_user.enabled? || @current_user.admin?
105 105 unauthorized_redirect 'Your account is disabled'
106 106 return false
107 107 end
108 108
109 109 # check if user ip is allowed
110 110 unless @current_user.admin? || GraderConfiguration[WHITELIST_IGNORE_CONF_KEY]
111 111 unless is_request_ip_allowed?
112 112 unauthorized_redirect 'Your IP is not allowed to login at this time.'
113 113 return false
114 114 end
115 115 end
116 116
117 + # check if password is changed
118 + if session[:last_password_hash] != @current_user.hashed_password
119 + unauthorized_redirect 'You are forced to log out.'
120 + end
121 +
117 122 if GraderConfiguration.multicontests?
118 123 return true if @current_user.admin?
119 124 begin
120 125 if @current_user.contest_stat(true).forced_logout
121 126 flash[:notice] = 'You have been automatically logged out.'
122 127 redirect_to :controller => 'main', :action => 'index'
123 128 end
124 129 rescue
125 130 end
126 131 end
127 132 return true
128 133 end
129 134
130 135 #redirect to root (and also force logout)
131 136 #if the user use different ip from the previous connection
132 137 # only applicable when MULTIPLE_IP_LOGIN options is false only
133 138 def authenticate_by_ip_address
134 139 #this assume that we have already authenticate normally
135 140 unless GraderConfiguration[MULTIPLE_IP_LOGIN_CONF_KEY]
136 141 user = User.find(session[:user_id])
137 142 if (!user.admin? && user.last_ip && user.last_ip != unique_visitor_id)
138 143 flash[:notice] = "You cannot use the system from two different places"
139 144 redirect_to :controller => 'main', :action => 'login'
140 145 return false
141 146 end
142 147 unless user.last_ip
143 148 user.last_ip = unique_visitor_id
144 149 user.save
145 150 end
146 151 end
147 152 return true
148 153 end
149 154
150 155 def authorization
151 156 return false unless check_valid_login
152 157 user = User.find(session[:user_id])
153 158 unless user.roles.detect { |role|
154 159 role.rights.detect{ |right|
155 160 right.controller == self.class.controller_name and
156 161 (right.action == 'all' || right.action == action_name)
157 162 }
158 163 }
159 164 flash[:notice] = 'You are not authorized to view the page you requested'
160 165 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
161 166 redirect_to :controller => 'main', :action => 'login'
162 167 return false
163 168 end
164 169 end
165 170
166 171 def verify_time_limit
167 172 return true if session[:user_id]==nil
168 173 user = User.find(session[:user_id], :include => :site)
169 174 return true if user==nil || user.site == nil
170 175 if user.contest_finished?
171 176 flash[:notice] = 'Error: the contest you are participating is over.'
172 177 redirect_to :back
173 178 return false
174 179 end
175 180 return true
176 181 end
177 182
178 183 def is_request_ip_allowed?
179 184 unless GraderConfiguration[WHITELIST_IGNORE_CONF_KEY]
180 185 user_ip = IPAddr.new(request.remote_ip)
181 186 allowed = GraderConfiguration[WHITELIST_IP_CONF_KEY] || ''
182 187
183 188 allowed.delete(' ').split(',').each do |ips|
184 189 allow_ips = IPAddr.new(ips)
185 190 if allow_ips.include?(user_ip)
186 191 return true
187 192 end
188 193 end
189 194 return false
190 195 end
191 196 return true
192 197 end
193 198
194 199 #function for datatable ajax query
195 200 #return record,total_count,filter_count
196 201 def process_query_record(record,
197 202 total_count: nil,
198 203 select: '',
199 204 global_search: [],
200 205 no_search: false,
201 206 force_order: '',
202 207 date_filter: '', date_param_since: 'date_since',date_param_until: 'date_until',
203 208 hard_limit: nil)
204 209 arel_table = record.model.arel_table
205 210
206 211 if !no_search && params['search']
207 212 global_value = record.model.sanitize_sql(params['search']['value'].strip.downcase)
208 213 if !global_value.blank?
209 214 global_value.split.each do |value|
210 215 global_where = global_search.map{|f| "LOWER(#{f}) like '%#{value}%'"}.join(' OR ')
211 216 record = record.where(global_where)
212 217 end
213 218 end
214 219
215 220 params['columns'].each do |i, col|
216 221 if !col['search']['value'].blank?
217 222 record = record.where(arel_table[col['name']].lower.matches("%#{col['search']['value'].strip.downcase}%"))
218 223 end
219 224 end
220 225 end
221 226
222 227 if !date_filter.blank?
223 228 param_since = params[date_param_since]
224 229 param_until = params[date_param_until]
225 230 date_since = Time.zone.parse( param_since ) || Time.new(1,1,1) rescue Time.new(1,1,1)
226 231 date_until = Time.zone.parse( param_until ) || Time.zone.now() rescue Time.zone.now()
227 232 date_range = date_since..(date_until.end_of_day)
228 233 record = record.where(date_filter.to_sym => date_range)
229 234 end
230 235
231 236 if force_order.blank?
232 237 if params['order']
233 238 params['order'].each do |i, o|
234 239 colName = params['columns'][o['column']]['name']
235 240 colName = "#{record.model.table_name}.#{colName}" if colName.upcase == 'ID'
236 241 record = record.order("#{colName} #{o['dir'].casecmp('desc') != 0 ? 'ASC' : 'DESC'}") unless colName.blank?
237 242 end
238 243 end
239 244 else
240 245 record = record.order(force_order)
241 246 end
242 247
243 248 filterCount = record.count(record.model.primary_key)
244 249 # if .group() is used, filterCount might be like {id_1: count_1, id_2: count_2, ...}
245 250 # so we should count the result again..
246 251 if filterCount.is_a? Hash
247 252 filterCount = filterCount.count
248 253 end
249 254
250 255
251 256 record = record.offset(params['start'] || 0)
252 257 record = record.limit(hard_limit)
253 258 if (params['length'])
254 259 limit = params['length'].to_i
255 260 limit == hard_limit if (hard_limit && hard_limit < limit)
256 261 record = record.limit(limit)
257 262 end
258 263 if (!select.blank?)
259 264 record = record.select(select)
260 265 end
261 266
262 267 return record, total_count || record.model.count, filterCount
263 268 end
264 269
265 270 end
@@ -1,99 +1,100
1 1 class LoginController < ApplicationController
2 2
3 3 @@authenticators = []
4 4
5 5 def index
6 6 # show login screen
7 7 reset_session
8 8 redirect_to :controller => 'main', :action => 'login'
9 9 end
10 10
11 11 def login
12 12 user = get_authenticated_user(params[:login], params[:password])
13 13 unless user
14 14 flash[:notice] = 'Wrong password'
15 15 redirect_to :controller => 'main', :action => 'login'
16 16 return
17 17 end
18 18
19 19 if (!GraderConfiguration['right.bypass_agreement']) and (!params[:accept_agree]) and !user.admin?
20 20 flash[:notice] = 'You must accept the agreement before logging in'
21 21 redirect_to :controller => 'main', :action => 'login'
22 22 return
23 23 end
24 24
25 25 #store uuid when login
26 26 if user.last_ip.nil?
27 27 user.last_ip = cookies.encrypted[:uuid]
28 28 else
29 29 if user.last_ip != cookies.encrypted[:uuid]
30 30 user.last_ip =cookies.encrypted[:uuid]
31 31 #log different login
32 32 end
33 33 end
34 34
35 35 #process logging in
36 36 session[:user_id] = user.id
37 + session[:last_password_hash] = user.hashed_password
37 38 session[:admin] = user.admin?
38 39
39 40 # clear forced logout flag for multicontests contest change
40 41 if GraderConfiguration.multicontests?
41 42 contest_stat = user.contest_stat
42 43 if contest_stat.respond_to? :forced_logout
43 44 if contest_stat.forced_logout
44 45 contest_stat.forced_logout = false
45 46 contest_stat.save
46 47 end
47 48 end
48 49 end
49 50
50 51 #save login information
51 52 Login.create(user_id: user.id, ip_address: cookies.encrypted[:uuid])
52 53
53 54 redirect_to :controller => 'main', :action => 'list'
54 55 end
55 56
56 57 def site_login
57 58 begin
58 59 site = Site.find(params[:login][:site_id])
59 60 rescue ActiveRecord::RecordNotFound
60 61 site = nil
61 62 end
62 63 if site==nil
63 64 flash[:notice] = 'Wrong site'
64 65 redirect_to :controller => 'main', :action => 'login' and return
65 66 end
66 67 if (site.password) and (site.password == params[:login][:password])
67 68 session[:site_id] = site.id
68 69 redirect_to :controller => 'site', :action => 'index'
69 70 else
70 71 flash[:notice] = 'Wrong site password'
71 72 redirect_to :controller => 'site', :action => 'login'
72 73 end
73 74 end
74 75
75 76 def logout
76 77 redirect_to root_path
77 78 end
78 79
79 80 def self.add_authenticator(authenticator)
80 81 @@authenticators << authenticator
81 82 end
82 83
83 84 protected
84 85
85 86 def get_authenticated_user(login, password)
86 87 if @@authenticators.empty?
87 88 return User.authenticate(login, password)
88 89 else
89 90 user = User.authenticate(login, password)
90 91 @@authenticators.each do |authenticator|
91 92 if not user
92 93 user = authenticator.authenticate(login, password)
93 94 end
94 95 end
95 96 return user
96 97 end
97 98 end
98 99
99 100 end
You need to be logged in to leave comments. Login now