Description:
lists users in each contest. individual user contest management moved to each contest user list page
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r297:2abed488d02c - - 4 files changed: 92 inserted, 19 deleted

@@ -0,0 +1,65
1 + <h1>
2 + List users in <% if @contest %><%= @contest.title %>
3 + <% else %>Users not in any contests<% end %>
4 + </h1>
5 +
6 + <div class="submitbox">
7 + <%= link_to '[View all users]', :action => 'list' %>
8 + <% if Configuration.multicontests? %>
9 + <%= link_to '[Manage bulk users in contests]', :action => 'contest_management' %>
10 + <br/>
11 + View users in:
12 + <% @contests.each do |contest| %>
13 + <%= link_to "[#{contest.name}]", :action => 'contests', :id => contest.id %>
14 + <% end %>
15 + <%= link_to "[no contest]", :action => 'contests', :id => 'none' %>
16 + <% end %>
17 + </div>
18 +
19 + <table class="info">
20 + <tr class="info-head">
21 + <th>Login</th>
22 + <th>Full name</th>
23 + <th>Email</th>
24 + <th>Activated?</th>
25 + <th></th>
26 + <th></th>
27 + <th></th>
28 + <% if Configuration.multicontests? %>
29 + <th>Contests</th>
30 + <th>Other enabled contests</th>
31 + <% end %>
32 + </tr>
33 +
34 + <% for user in @users %>
35 + <tr class="info-<%= cycle("odd","even") %>">
36 + <td><%=h user.login %></td>
37 + <td><%=h user.full_name %></td>
38 + <td><%=h user.email %></td>
39 + <td><%=h user.activated %></td>
40 + <td><%= link_to 'Show', :action => 'show', :id => user %></td>
41 + <td><%= link_to 'Edit', :action => 'edit', :id => user %></td>
42 + <td><%= link_to 'Destroy', { :action => 'destroy', :id => user }, :confirm => 'Are you sure?', :method => :post %></td>
43 + <% if Configuration.multicontests? %>
44 + <td>
45 + <% user.contests.each do |contest| %>
46 + <%= contest.name %> [<%= link_to 'x', :action => 'remove_from_contest', :id => user.id, :contest_id => contest.id %>]
47 + <% end %>
48 + </td>
49 + <td>
50 + <% @contests.each do |contest| %>
51 + <% if not user.contests.all.find {|c| c.id==contest.id } %>
52 + <%= contest.name %> [<%= link_to '+', :action => 'add_to_contest', :id => user.id, :contest_id => contest.id %>]
53 + <% end %>
54 + <% end %>
55 + </td>
56 + <% end %>
57 + </tr>
58 + <% end %>
59 + </table>
60 +
61 +
62 + <br />
63 +
64 + <%= link_to 'New user', :action => 'new' %>
65 + <%= link_to 'New list of users', :action => 'new_list' %>
@@ -1,350 +1,364
1 class UserAdminController < ApplicationController
1 class UserAdminController < ApplicationController
2
2
3 include MailHelperMethods
3 include MailHelperMethods
4
4
5 before_filter :admin_authorization
5 before_filter :admin_authorization
6
6
7 def index
7 def index
8 list
8 list
9 render :action => 'list'
9 render :action => 'list'
10 end
10 end
11
11
12 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
12 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
13 verify :method => :post, :only => [ :destroy,
13 verify :method => :post, :only => [ :destroy,
14 :create, :create_from_list,
14 :create, :create_from_list,
15 :update ],
15 :update ],
16 :redirect_to => { :action => :list }
16 :redirect_to => { :action => :list }
17
17
18 def list
18 def list
19 @users = User.find(:all)
19 @users = User.find(:all)
20 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
20 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
21 - @contests = Contest.all(:conditions => {:enabled => true})
21 + @contests = Contest.enabled
22 end
22 end
23
23
24 def active
24 def active
25 sessions = ActiveRecord::SessionStore::Session.find(:all, :conditions => ["updated_at >= ?", 60.minutes.ago])
25 sessions = ActiveRecord::SessionStore::Session.find(:all, :conditions => ["updated_at >= ?", 60.minutes.ago])
26 @users = []
26 @users = []
27 sessions.each do |session|
27 sessions.each do |session|
28 if session.data[:user_id]
28 if session.data[:user_id]
29 @users << User.find(session.data[:user_id])
29 @users << User.find(session.data[:user_id])
30 end
30 end
31 end
31 end
32 end
32 end
33
33
34 def show
34 def show
35 @user = User.find(params[:id])
35 @user = User.find(params[:id])
36 end
36 end
37
37
38 def new
38 def new
39 @user = User.new
39 @user = User.new
40 end
40 end
41
41
42 def create
42 def create
43 @user = User.new(params[:user])
43 @user = User.new(params[:user])
44 @user.activated = true
44 @user.activated = true
45 if @user.save
45 if @user.save
46 flash[:notice] = 'User was successfully created.'
46 flash[:notice] = 'User was successfully created.'
47 redirect_to :action => 'list'
47 redirect_to :action => 'list'
48 else
48 else
49 render :action => 'new'
49 render :action => 'new'
50 end
50 end
51 end
51 end
52
52
53 def create_from_list
53 def create_from_list
54 lines = params[:user_list]
54 lines = params[:user_list]
55
55
56 note = []
56 note = []
57
57
58 lines.split("\n").each do |line|
58 lines.split("\n").each do |line|
59 items = line.chomp.split(',')
59 items = line.chomp.split(',')
60 if items.length>=2
60 if items.length>=2
61 login = items[0]
61 login = items[0]
62 full_name = items[1]
62 full_name = items[1]
63
63
64 added_random_password = false
64 added_random_password = false
65 if items.length>=3
65 if items.length>=3
66 password = items[2]
66 password = items[2]
67 user_alias = (items.length>=4) ? items[3] : login
67 user_alias = (items.length>=4) ? items[3] : login
68 else
68 else
69 password = random_password
69 password = random_password
70 user_alias = (items.length>=4) ? items[3] : login
70 user_alias = (items.length>=4) ? items[3] : login
71 added_random_password = true
71 added_random_password = true
72 end
72 end
73
73
74 user = User.new({:login => login,
74 user = User.new({:login => login,
75 :full_name => full_name,
75 :full_name => full_name,
76 :password => password,
76 :password => password,
77 :password_confirmation => password,
77 :password_confirmation => password,
78 :alias => user_alias})
78 :alias => user_alias})
79 user.activated = true
79 user.activated = true
80 user.save
80 user.save
81
81
82 if added_random_password
82 if added_random_password
83 note << "'#{login}' (+)"
83 note << "'#{login}' (+)"
84 else
84 else
85 note << login
85 note << login
86 end
86 end
87 end
87 end
88 end
88 end
89 flash[:notice] = 'User(s) ' + note.join(', ') +
89 flash[:notice] = 'User(s) ' + note.join(', ') +
90 ' were successfully created. ' +
90 ' were successfully created. ' +
91 '( (+) - created with random passwords.)'
91 '( (+) - created with random passwords.)'
92 redirect_to :action => 'list'
92 redirect_to :action => 'list'
93 end
93 end
94
94
95 def edit
95 def edit
96 @user = User.find(params[:id])
96 @user = User.find(params[:id])
97 end
97 end
98
98
99 def update
99 def update
100 @user = User.find(params[:id])
100 @user = User.find(params[:id])
101 if @user.update_attributes(params[:user])
101 if @user.update_attributes(params[:user])
102 flash[:notice] = 'User was successfully updated.'
102 flash[:notice] = 'User was successfully updated.'
103 redirect_to :action => 'show', :id => @user
103 redirect_to :action => 'show', :id => @user
104 else
104 else
105 render :action => 'edit'
105 render :action => 'edit'
106 end
106 end
107 end
107 end
108
108
109 def destroy
109 def destroy
110 User.find(params[:id]).destroy
110 User.find(params[:id]).destroy
111 redirect_to :action => 'list'
111 redirect_to :action => 'list'
112 end
112 end
113
113
114 def user_stat
114 def user_stat
115 @problems = Problem.find_available_problems
115 @problems = Problem.find_available_problems
116 @users = User.find(:all)
116 @users = User.find(:all)
117 @scorearray = Array.new
117 @scorearray = Array.new
118 @users.each do |u|
118 @users.each do |u|
119 ustat = Array.new
119 ustat = Array.new
120 ustat[0] = u
120 ustat[0] = u
121 @problems.each do |p|
121 @problems.each do |p|
122 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
122 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
123 if (sub!=nil) and (sub.points!=nil)
123 if (sub!=nil) and (sub.points!=nil)
124 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
124 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
125 else
125 else
126 ustat << [0,false]
126 ustat << [0,false]
127 end
127 end
128 end
128 end
129 @scorearray << ustat
129 @scorearray << ustat
130 end
130 end
131 end
131 end
132
132
133 def import
133 def import
134 if params[:file]==''
134 if params[:file]==''
135 flash[:notice] = 'Error importing no file'
135 flash[:notice] = 'Error importing no file'
136 redirect_to :action => 'list' and return
136 redirect_to :action => 'list' and return
137 end
137 end
138 import_from_file(params[:file])
138 import_from_file(params[:file])
139 end
139 end
140
140
141 def random_all_passwords
141 def random_all_passwords
142 users = User.find(:all)
142 users = User.find(:all)
143 @prefix = params[:prefix] || ''
143 @prefix = params[:prefix] || ''
144 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
144 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
145 @changed = false
145 @changed = false
146 if request.request_method == :post
146 if request.request_method == :post
147 @non_admin_users.each do |user|
147 @non_admin_users.each do |user|
148 password = random_password
148 password = random_password
149 user.password = password
149 user.password = password
150 user.password_confirmation = password
150 user.password_confirmation = password
151 user.save
151 user.save
152 end
152 end
153 @changed = true
153 @changed = true
154 end
154 end
155 end
155 end
156
156
157 # contest management
157 # contest management
158
158
159 + def contests
160 + if params[:id]!='none'
161 + @contest = Contest.find(params[:id])
162 + else
163 + @contest = nil
164 + end
165 + if @contest
166 + @users = @contest.users
167 + else
168 + @users = User.find_users_with_no_contest
169 + end
170 + @contests = Contest.enabled
171 + end
172 +
159 def add_to_contest
173 def add_to_contest
160 user = User.find(params[:id])
174 user = User.find(params[:id])
161 contest = Contest.find(params[:contest_id])
175 contest = Contest.find(params[:contest_id])
162 if user and contest
176 if user and contest
163 user.contests << contest
177 user.contests << contest
164 end
178 end
165 redirect_to :action => 'list'
179 redirect_to :action => 'list'
166 end
180 end
167
181
168 def remove_from_contest
182 def remove_from_contest
169 user = User.find(params[:id])
183 user = User.find(params[:id])
170 contest = Contest.find(params[:contest_id])
184 contest = Contest.find(params[:contest_id])
171 if user and contest
185 if user and contest
172 user.contests.delete(contest)
186 user.contests.delete(contest)
173 end
187 end
174 redirect_to :action => 'list'
188 redirect_to :action => 'list'
175 end
189 end
176
190
177 def contest_management
191 def contest_management
178 end
192 end
179
193
180 def manage_contest
194 def manage_contest
181 contest = Contest.find(params[:contest][:id])
195 contest = Contest.find(params[:contest][:id])
182 if !contest
196 if !contest
183 flash[:notice] = 'You did not choose the contest.'
197 flash[:notice] = 'You did not choose the contest.'
184 redirect_to :action => 'contest_management' and return
198 redirect_to :action => 'contest_management' and return
185 end
199 end
186
200
187 operation = params[:operation]
201 operation = params[:operation]
188
202
189 if not ['add','remove','assign'].include? operation
203 if not ['add','remove','assign'].include? operation
190 flash[:notice] = 'You did not choose the operation to perform.'
204 flash[:notice] = 'You did not choose the operation to perform.'
191 redirect_to :action => 'contest_management' and return
205 redirect_to :action => 'contest_management' and return
192 end
206 end
193
207
194 lines = params[:login_list]
208 lines = params[:login_list]
195 if !lines or lines.blank?
209 if !lines or lines.blank?
196 flash[:notice] = 'You entered an empty list.'
210 flash[:notice] = 'You entered an empty list.'
197 redirect_to :action => 'contest_management' and return
211 redirect_to :action => 'contest_management' and return
198 end
212 end
199
213
200 note = []
214 note = []
201 users = []
215 users = []
202 lines.split("\n").each do |line|
216 lines.split("\n").each do |line|
203 user = User.find_by_login(line.chomp)
217 user = User.find_by_login(line.chomp)
204 if user
218 if user
205 if operation=='add'
219 if operation=='add'
206 if ! user.contests.include? contest
220 if ! user.contests.include? contest
207 user.contests << contest
221 user.contests << contest
208 end
222 end
209 elsif operation=='remove'
223 elsif operation=='remove'
210 user.contests.delete(contest)
224 user.contests.delete(contest)
211 else
225 else
212 user.contests = [contest]
226 user.contests = [contest]
213 end
227 end
214
228
215 if params[:reset_timer]
229 if params[:reset_timer]
216 user.contest_stat.forced_logout = true
230 user.contest_stat.forced_logout = true
217 user.contest_stat.reset_timer_and_save
231 user.contest_stat.reset_timer_and_save
218 end
232 end
219
233
220 if params[:notification_emails]
234 if params[:notification_emails]
221 send_contest_update_notification_email(user, contest)
235 send_contest_update_notification_email(user, contest)
222 end
236 end
223
237
224 note << user.login
238 note << user.login
225 users << user
239 users << user
226 end
240 end
227 end
241 end
228
242
229 if params[:reset_timer]
243 if params[:reset_timer]
230 logout_users(users)
244 logout_users(users)
231 end
245 end
232
246
233 flash[:notice] = 'User(s) ' + note.join(', ') +
247 flash[:notice] = 'User(s) ' + note.join(', ') +
234 ' were successfully modified. '
248 ' were successfully modified. '
235 redirect_to :action => 'contest_management'
249 redirect_to :action => 'contest_management'
236 end
250 end
237
251
238 # admin management
252 # admin management
239
253
240 def admin
254 def admin
241 @admins = User.find(:all).find_all {|user| user.admin? }
255 @admins = User.find(:all).find_all {|user| user.admin? }
242 end
256 end
243
257
244 def grant_admin
258 def grant_admin
245 login = params[:login]
259 login = params[:login]
246 user = User.find_by_login(login)
260 user = User.find_by_login(login)
247 if user!=nil
261 if user!=nil
248 admin_role = Role.find_by_name('admin')
262 admin_role = Role.find_by_name('admin')
249 user.roles << admin_role
263 user.roles << admin_role
250 else
264 else
251 flash[:notice] = 'Unknown user'
265 flash[:notice] = 'Unknown user'
252 end
266 end
253 flash[:notice] = 'User added as admins'
267 flash[:notice] = 'User added as admins'
254 redirect_to :action => 'admin'
268 redirect_to :action => 'admin'
255 end
269 end
256
270
257 def revoke_admin
271 def revoke_admin
258 user = User.find(params[:id])
272 user = User.find(params[:id])
259 if user==nil
273 if user==nil
260 flash[:notice] = 'Unknown user'
274 flash[:notice] = 'Unknown user'
261 redirect_to :action => 'admin' and return
275 redirect_to :action => 'admin' and return
262 elsif user.login == 'root'
276 elsif user.login == 'root'
263 flash[:notice] = 'You cannot revoke admisnistrator permission from root.'
277 flash[:notice] = 'You cannot revoke admisnistrator permission from root.'
264 redirect_to :action => 'admin' and return
278 redirect_to :action => 'admin' and return
265 end
279 end
266
280
267 admin_role = Role.find_by_name('admin')
281 admin_role = Role.find_by_name('admin')
268 user.roles.delete(admin_role)
282 user.roles.delete(admin_role)
269 flash[:notice] = 'User permission revoked'
283 flash[:notice] = 'User permission revoked'
270 redirect_to :action => 'admin'
284 redirect_to :action => 'admin'
271 end
285 end
272
286
273 protected
287 protected
274
288
275 def random_password(length=5)
289 def random_password(length=5)
276 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
290 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
277 newpass = ""
291 newpass = ""
278 length.times { newpass << chars[rand(chars.size-1)] }
292 length.times { newpass << chars[rand(chars.size-1)] }
279 return newpass
293 return newpass
280 end
294 end
281
295
282 def import_from_file(f)
296 def import_from_file(f)
283 data_hash = YAML.load(f)
297 data_hash = YAML.load(f)
284 @import_log = ""
298 @import_log = ""
285
299
286 country_data = data_hash[:countries]
300 country_data = data_hash[:countries]
287 site_data = data_hash[:sites]
301 site_data = data_hash[:sites]
288 user_data = data_hash[:users]
302 user_data = data_hash[:users]
289
303
290 # import country
304 # import country
291 countries = {}
305 countries = {}
292 country_data.each_pair do |id,country|
306 country_data.each_pair do |id,country|
293 c = Country.find_by_name(country[:name])
307 c = Country.find_by_name(country[:name])
294 if c!=nil
308 if c!=nil
295 countries[id] = c
309 countries[id] = c
296 @import_log << "Found #{country[:name]}\n"
310 @import_log << "Found #{country[:name]}\n"
297 else
311 else
298 countries[id] = Country.new(:name => country[:name])
312 countries[id] = Country.new(:name => country[:name])
299 countries[id].save
313 countries[id].save
300 @import_log << "Created #{country[:name]}\n"
314 @import_log << "Created #{country[:name]}\n"
301 end
315 end
302 end
316 end
303
317
304 # import sites
318 # import sites
305 sites = {}
319 sites = {}
306 site_data.each_pair do |id,site|
320 site_data.each_pair do |id,site|
307 s = Site.find_by_name(site[:name])
321 s = Site.find_by_name(site[:name])
308 if s!=nil
322 if s!=nil
309 @import_log << "Found #{site[:name]}\n"
323 @import_log << "Found #{site[:name]}\n"
310 else
324 else
311 s = Site.new(:name => site[:name])
325 s = Site.new(:name => site[:name])
312 @import_log << "Created #{site[:name]}\n"
326 @import_log << "Created #{site[:name]}\n"
313 end
327 end
314 s.password = site[:password]
328 s.password = site[:password]
315 s.country = countries[site[:country_id]]
329 s.country = countries[site[:country_id]]
316 s.save
330 s.save
317 sites[id] = s
331 sites[id] = s
318 end
332 end
319
333
320 # import users
334 # import users
321 user_data.each_pair do |id,user|
335 user_data.each_pair do |id,user|
322 u = User.find_by_login(user[:login])
336 u = User.find_by_login(user[:login])
323 if u!=nil
337 if u!=nil
324 @import_log << "Found #{user[:login]}\n"
338 @import_log << "Found #{user[:login]}\n"
325 else
339 else
326 u = User.new(:login => user[:login])
340 u = User.new(:login => user[:login])
327 @import_log << "Created #{user[:login]}\n"
341 @import_log << "Created #{user[:login]}\n"
328 end
342 end
329 u.full_name = user[:name]
343 u.full_name = user[:name]
330 u.password = user[:password]
344 u.password = user[:password]
331 u.country = countries[user[:country_id]]
345 u.country = countries[user[:country_id]]
332 u.site = sites[user[:site_id]]
346 u.site = sites[user[:site_id]]
333 u.activated = true
347 u.activated = true
334 u.email = "empty-#{u.login}@none.com"
348 u.email = "empty-#{u.login}@none.com"
335 if not u.save
349 if not u.save
336 @import_log << "Errors\n"
350 @import_log << "Errors\n"
337 u.errors.each { |attr,msg| @import_log << "#{attr} - #{msg}\n" }
351 u.errors.each { |attr,msg| @import_log << "#{attr} - #{msg}\n" }
338 end
352 end
339 end
353 end
340
354
341 end
355 end
342
356
343 def logout_users(users)
357 def logout_users(users)
344 users.each do |user|
358 users.each do |user|
345 contest_stat = user.contest_stat(true)
359 contest_stat = user.contest_stat(true)
346 if contest_stat and !contest_stat.forced_logout
360 if contest_stat and !contest_stat.forced_logout
347 contest_stat.forced_logout = true
361 contest_stat.forced_logout = true
348 contest_stat.save
362 contest_stat.save
349 end
363 end
350 end
364 end
@@ -1,296 +1,302
1 require 'digest/sha1'
1 require 'digest/sha1'
2
2
3 class User < ActiveRecord::Base
3 class User < ActiveRecord::Base
4
4
5 has_and_belongs_to_many :roles
5 has_and_belongs_to_many :roles
6
6
7 has_many :test_requests, :order => "submitted_at DESC"
7 has_many :test_requests, :order => "submitted_at DESC"
8
8
9 has_many :messages,
9 has_many :messages,
10 :class_name => "Message",
10 :class_name => "Message",
11 :foreign_key => "sender_id",
11 :foreign_key => "sender_id",
12 :order => 'created_at DESC'
12 :order => 'created_at DESC'
13
13
14 has_many :replied_messages,
14 has_many :replied_messages,
15 :class_name => "Message",
15 :class_name => "Message",
16 :foreign_key => "receiver_id",
16 :foreign_key => "receiver_id",
17 :order => 'created_at DESC'
17 :order => 'created_at DESC'
18
18
19 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
19 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
20
20
21 belongs_to :site
21 belongs_to :site
22 belongs_to :country
22 belongs_to :country
23
23
24 has_and_belongs_to_many :contests, :uniq => true, :order => 'name'
24 has_and_belongs_to_many :contests, :uniq => true, :order => 'name'
25
25
26 named_scope :activated_users, :conditions => {:activated => true}
26 named_scope :activated_users, :conditions => {:activated => true}
27
27
28 validates_presence_of :login
28 validates_presence_of :login
29 validates_uniqueness_of :login
29 validates_uniqueness_of :login
30 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
30 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
31 validates_length_of :login, :within => 3..30
31 validates_length_of :login, :within => 3..30
32
32
33 validates_presence_of :full_name
33 validates_presence_of :full_name
34 validates_length_of :full_name, :minimum => 1
34 validates_length_of :full_name, :minimum => 1
35
35
36 validates_presence_of :password, :if => :password_required?
36 validates_presence_of :password, :if => :password_required?
37 validates_length_of :password, :within => 4..20, :if => :password_required?
37 validates_length_of :password, :within => 4..20, :if => :password_required?
38 validates_confirmation_of :password, :if => :password_required?
38 validates_confirmation_of :password, :if => :password_required?
39
39
40 validates_format_of :email,
40 validates_format_of :email,
41 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
41 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
42 :if => :email_validation?
42 :if => :email_validation?
43 validate :uniqueness_of_email_from_activated_users,
43 validate :uniqueness_of_email_from_activated_users,
44 :if => :email_validation?
44 :if => :email_validation?
45 validate :enough_time_interval_between_same_email_registrations,
45 validate :enough_time_interval_between_same_email_registrations,
46 :if => :email_validation?
46 :if => :email_validation?
47
47
48 # these are for ytopc
48 # these are for ytopc
49 # disable for now
49 # disable for now
50 #validates_presence_of :province
50 #validates_presence_of :province
51
51
52 attr_accessor :password
52 attr_accessor :password
53
53
54 before_save :encrypt_new_password
54 before_save :encrypt_new_password
55 before_save :assign_default_site
55 before_save :assign_default_site
56
56
57 def self.authenticate(login, password)
57 def self.authenticate(login, password)
58 user = find_by_login(login)
58 user = find_by_login(login)
59 return user if user && user.authenticated?(password)
59 return user if user && user.authenticated?(password)
60 end
60 end
61
61
62 def authenticated?(password)
62 def authenticated?(password)
63 if self.activated
63 if self.activated
64 hashed_password == User.encrypt(password,self.salt)
64 hashed_password == User.encrypt(password,self.salt)
65 else
65 else
66 false
66 false
67 end
67 end
68 end
68 end
69
69
70 def admin?
70 def admin?
71 self.roles.detect {|r| r.name == 'admin' }
71 self.roles.detect {|r| r.name == 'admin' }
72 end
72 end
73
73
74 def email_for_editing
74 def email_for_editing
75 if self.email==nil
75 if self.email==nil
76 "(unknown)"
76 "(unknown)"
77 elsif self.email==''
77 elsif self.email==''
78 "(blank)"
78 "(blank)"
79 else
79 else
80 self.email
80 self.email
81 end
81 end
82 end
82 end
83
83
84 def email_for_editing=(e)
84 def email_for_editing=(e)
85 self.email=e
85 self.email=e
86 end
86 end
87
87
88 def alias_for_editing
88 def alias_for_editing
89 if self.alias==nil
89 if self.alias==nil
90 "(unknown)"
90 "(unknown)"
91 elsif self.alias==''
91 elsif self.alias==''
92 "(blank)"
92 "(blank)"
93 else
93 else
94 self.alias
94 self.alias
95 end
95 end
96 end
96 end
97
97
98 def alias_for_editing=(e)
98 def alias_for_editing=(e)
99 self.alias=e
99 self.alias=e
100 end
100 end
101
101
102 def activation_key
102 def activation_key
103 if self.hashed_password==nil
103 if self.hashed_password==nil
104 encrypt_new_password
104 encrypt_new_password
105 end
105 end
106 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
106 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
107 end
107 end
108
108
109 def verify_activation_key(key)
109 def verify_activation_key(key)
110 key == activation_key
110 key == activation_key
111 end
111 end
112
112
113 def self.random_password(length=5)
113 def self.random_password(length=5)
114 chars = 'abcdefghjkmnopqrstuvwxyz'
114 chars = 'abcdefghjkmnopqrstuvwxyz'
115 password = ''
115 password = ''
116 length.times { password << chars[rand(chars.length - 1)] }
116 length.times { password << chars[rand(chars.length - 1)] }
117 password
117 password
118 end
118 end
119
119
120 def self.find_non_admin_with_prefix(prefix='')
120 def self.find_non_admin_with_prefix(prefix='')
121 users = User.find(:all)
121 users = User.find(:all)
122 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
122 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
123 end
123 end
124
124
125 # Contest information
125 # Contest information
126
126
127 + def self.find_users_with_no_contest()
128 + users = User.find(:all)
129 + return users.find_all { |u| u.contests.length == 0 }
130 + end
131 +
132 +
127 def contest_time_left
133 def contest_time_left
128 if Configuration.contest_mode?
134 if Configuration.contest_mode?
129 return nil if site==nil
135 return nil if site==nil
130 return site.time_left
136 return site.time_left
131 elsif Configuration.indv_contest_mode?
137 elsif Configuration.indv_contest_mode?
132 time_limit = Configuration.contest_time_limit
138 time_limit = Configuration.contest_time_limit
133 if time_limit == nil
139 if time_limit == nil
134 return nil
140 return nil
135 end
141 end
136 if contest_stat==nil or contest_stat.started_at==nil
142 if contest_stat==nil or contest_stat.started_at==nil
137 return (Time.now.gmtime + time_limit) - Time.now.gmtime
143 return (Time.now.gmtime + time_limit) - Time.now.gmtime
138 else
144 else
139 finish_time = contest_stat.started_at + time_limit
145 finish_time = contest_stat.started_at + time_limit
140 current_time = Time.now.gmtime
146 current_time = Time.now.gmtime
141 if current_time > finish_time
147 if current_time > finish_time
142 return 0
148 return 0
143 else
149 else
144 return finish_time - current_time
150 return finish_time - current_time
145 end
151 end
146 end
152 end
147 else
153 else
148 return nil
154 return nil
149 end
155 end
150 end
156 end
151
157
152 def contest_finished?
158 def contest_finished?
153 if Configuration.contest_mode?
159 if Configuration.contest_mode?
154 return false if site==nil
160 return false if site==nil
155 return site.finished?
161 return site.finished?
156 elsif Configuration.indv_contest_mode?
162 elsif Configuration.indv_contest_mode?
157 return false if self.contest_stat(true)==nil
163 return false if self.contest_stat(true)==nil
158 return contest_time_left == 0
164 return contest_time_left == 0
159 else
165 else
160 return false
166 return false
161 end
167 end
162 end
168 end
163
169
164 def contest_started?
170 def contest_started?
165 if Configuration.contest_mode?
171 if Configuration.contest_mode?
166 return true if site==nil
172 return true if site==nil
167 return site.started
173 return site.started
168 else
174 else
169 return true
175 return true
170 end
176 end
171 end
177 end
172
178
173 def update_start_time
179 def update_start_time
174 stat = self.contest_stat
180 stat = self.contest_stat
175 if stat == nil or stat.started_at == nil
181 if stat == nil or stat.started_at == nil
176 stat ||= UserContestStat.new(:user => self)
182 stat ||= UserContestStat.new(:user => self)
177 stat.started_at = Time.now.gmtime
183 stat.started_at = Time.now.gmtime
178 stat.save
184 stat.save
179 end
185 end
180 end
186 end
181
187
182 def problem_in_user_contests?(problem)
188 def problem_in_user_contests?(problem)
183 problem_contests = problem.contests.all
189 problem_contests = problem.contests.all
184
190
185 if problem_contests.length == 0 # this is public contest
191 if problem_contests.length == 0 # this is public contest
186 return true
192 return true
187 end
193 end
188
194
189 contests.each do |contest|
195 contests.each do |contest|
190 if problem_contests.find {|c| c.id == contest.id }
196 if problem_contests.find {|c| c.id == contest.id }
191 return true
197 return true
192 end
198 end
193 end
199 end
194 return false
200 return false
195 end
201 end
196
202
197 def available_problems_group_by_contests
203 def available_problems_group_by_contests
198 contest_problems = []
204 contest_problems = []
199 pin = {}
205 pin = {}
200 contests.enabled.each do |contest|
206 contests.enabled.each do |contest|
201 available_problems = contest.problems.available
207 available_problems = contest.problems.available
202 contest_problems << {
208 contest_problems << {
203 :contest => contest,
209 :contest => contest,
204 :problems => available_problems
210 :problems => available_problems
205 }
211 }
206 available_problems.each {|p| pin[p.id] = true}
212 available_problems.each {|p| pin[p.id] = true}
207 end
213 end
208 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
214 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
209 contest_problems << {
215 contest_problems << {
210 :contest => nil,
216 :contest => nil,
211 :problems => other_avaiable_problems
217 :problems => other_avaiable_problems
212 }
218 }
213 return contest_problems
219 return contest_problems
214 end
220 end
215
221
216 def available_problems
222 def available_problems
217 if not Configuration.multicontests?
223 if not Configuration.multicontests?
218 return Problem.find_available_problems
224 return Problem.find_available_problems
219 else
225 else
220 contest_problems = []
226 contest_problems = []
221 pin = {}
227 pin = {}
222 contests.enabled.each do |contest|
228 contests.enabled.each do |contest|
223 contest.problems.available.each do |problem|
229 contest.problems.available.each do |problem|
224 if not pin.has_key? problem.id
230 if not pin.has_key? problem.id
225 contest_problems << problem
231 contest_problems << problem
226 end
232 end
227 pin[problem.id] = true
233 pin[problem.id] = true
228 end
234 end
229 end
235 end
230 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
236 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
231 return contest_problems + other_avaiable_problems
237 return contest_problems + other_avaiable_problems
232 end
238 end
233 end
239 end
234
240
235 def can_view_problem?(problem)
241 def can_view_problem?(problem)
236 if not Configuration.multicontests?
242 if not Configuration.multicontests?
237 return problem.available
243 return problem.available
238 else
244 else
239 return problem_in_user_contests? problem
245 return problem_in_user_contests? problem
240 end
246 end
241 end
247 end
242
248
243 protected
249 protected
244 def encrypt_new_password
250 def encrypt_new_password
245 return if password.blank?
251 return if password.blank?
246 self.salt = (10+rand(90)).to_s
252 self.salt = (10+rand(90)).to_s
247 self.hashed_password = User.encrypt(self.password,self.salt)
253 self.hashed_password = User.encrypt(self.password,self.salt)
248 end
254 end
249
255
250 def assign_default_site
256 def assign_default_site
251 # have to catch error when migrating (because self.site is not available).
257 # have to catch error when migrating (because self.site is not available).
252 begin
258 begin
253 if self.site==nil
259 if self.site==nil
254 self.site = Site.find_by_name('default')
260 self.site = Site.find_by_name('default')
255 if self.site==nil
261 if self.site==nil
256 self.site = Site.find(1) # when 'default has be renamed'
262 self.site = Site.find(1) # when 'default has be renamed'
257 end
263 end
258 end
264 end
259 rescue
265 rescue
260 end
266 end
261 end
267 end
262
268
263 def password_required?
269 def password_required?
264 self.hashed_password.blank? || !self.password.blank?
270 self.hashed_password.blank? || !self.password.blank?
265 end
271 end
266
272
267 def self.encrypt(string,salt)
273 def self.encrypt(string,salt)
268 Digest::SHA1.hexdigest(salt + string)
274 Digest::SHA1.hexdigest(salt + string)
269 end
275 end
270
276
271 def uniqueness_of_email_from_activated_users
277 def uniqueness_of_email_from_activated_users
272 user = User.activated_users.find_by_email(self.email)
278 user = User.activated_users.find_by_email(self.email)
273 if user and (user.login != self.login)
279 if user and (user.login != self.login)
274 self.errors.add_to_base("Email has already been taken")
280 self.errors.add_to_base("Email has already been taken")
275 end
281 end
276 end
282 end
277
283
278 def enough_time_interval_between_same_email_registrations
284 def enough_time_interval_between_same_email_registrations
279 return if !self.new_record?
285 return if !self.new_record?
280 return if self.activated
286 return if self.activated
281 open_user = User.find_by_email(self.email,
287 open_user = User.find_by_email(self.email,
282 :order => 'created_at DESC')
288 :order => 'created_at DESC')
283 if open_user and open_user.created_at and
289 if open_user and open_user.created_at and
284 (open_user.created_at > Time.now.gmtime - 5.minutes)
290 (open_user.created_at > Time.now.gmtime - 5.minutes)
285 self.errors.add_to_base("There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
291 self.errors.add_to_base("There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
286 end
292 end
287 end
293 end
288
294
289 def email_validation?
295 def email_validation?
290 begin
296 begin
291 return VALIDATE_USER_EMAILS
297 return VALIDATE_USER_EMAILS
292 rescue
298 rescue
293 return false
299 return false
294 end
300 end
295 end
301 end
296 end
302 end
@@ -1,89 +1,77
1 <h1>Listing users</h1>
1 <h1>Listing users</h1>
2
2
3 <div class="submitbox">
3 <div class="submitbox">
4 <b>Quick add</b>
4 <b>Quick add</b>
5 <% form_tag :action => 'create' do %>
5 <% form_tag :action => 'create' do %>
6 <table border="0">
6 <table border="0">
7 <tr>
7 <tr>
8 <td><label for="user_login">Login</label></td>
8 <td><label for="user_login">Login</label></td>
9 <td><label for="user_full_name">Full name</label></td>
9 <td><label for="user_full_name">Full name</label></td>
10 <td><label for="user_password">Password</label></td>
10 <td><label for="user_password">Password</label></td>
11 <td><label for="user_password_confirmation">Confirm</label></td>
11 <td><label for="user_password_confirmation">Confirm</label></td>
12 <td><label for="user_email">Email</label></td>
12 <td><label for="user_email">Email</label></td>
13 </tr>
13 </tr>
14 <tr>
14 <tr>
15 <td><%= text_field 'user', 'login', :size => 10 %></td>
15 <td><%= text_field 'user', 'login', :size => 10 %></td>
16 <td><%= text_field 'user', 'full_name', :size => 30 %></td>
16 <td><%= text_field 'user', 'full_name', :size => 30 %></td>
17 <td><%= password_field 'user', 'password', :size => 10 %></td>
17 <td><%= password_field 'user', 'password', :size => 10 %></td>
18 <td><%= password_field 'user', 'password_confirmation', :size => 10 %></td>
18 <td><%= password_field 'user', 'password_confirmation', :size => 10 %></td>
19 <td><%= text_field 'user', 'email', :size => 15 %></td>
19 <td><%= text_field 'user', 'email', :size => 15 %></td>
20 <td><%= submit_tag "Create" %></td>
20 <td><%= submit_tag "Create" %></td>
21 </tr>
21 </tr>
22 </table>
22 </table>
23 <% end %>
23 <% end %>
24 <br/>
24 <br/>
25 <b>Import from site management</b>
25 <b>Import from site management</b>
26 <% form_tag({:action => 'import'}, :multipart => true) do %>
26 <% form_tag({:action => 'import'}, :multipart => true) do %>
27 File: <%= file_field_tag 'file' %> <%= submit_tag 'Import' %>
27 File: <%= file_field_tag 'file' %> <%= submit_tag 'Import' %>
28 <% end %>
28 <% end %>
29 <br/>
29 <br/>
30 <b>What else: </b>
30 <b>What else: </b>
31 <%= link_to '[New user]', :action => 'new' %>
31 <%= link_to '[New user]', :action => 'new' %>
32 <%= link_to '[New list of users]', :action => 'new_list' %>
32 <%= link_to '[New list of users]', :action => 'new_list' %>
33 <%= link_to '[View administrators]', :action => 'admin' %>
33 <%= link_to '[View administrators]', :action => 'admin' %>
34 <%= link_to '[Random passwords]', :action => 'random_all_passwords' %>
34 <%= link_to '[Random passwords]', :action => 'random_all_passwords' %>
35 <%= link_to '[View active users]', :action => 'active' %>
35 <%= link_to '[View active users]', :action => 'active' %>
36 <% if Configuration.multicontests? %>
36 <% if Configuration.multicontests? %>
37 + <br/><b>Multi-contest:</b>
37 <%= link_to '[Manage bulk users in contests]', :action => 'contest_management' %>
38 <%= link_to '[Manage bulk users in contests]', :action => 'contest_management' %>
39 + View users in:
40 + <% @contests.each do |contest| %>
41 + <%= link_to "[#{contest.name}]", :action => 'contests', :id => contest.id %>
42 + <% end %>
43 + <%= link_to "[no contest]", :action => 'contests', :id => 'none' %>
38 <% end %>
44 <% end %>
39 </div>
45 </div>
40
46
41 <table class="info">
47 <table class="info">
42 <tr class="info-head">
48 <tr class="info-head">
43 <% for column in User.content_columns %>
49 <% for column in User.content_columns %>
44 <% if !@hidden_columns.index(column.name) %>
50 <% if !@hidden_columns.index(column.name) %>
45 <th><%= column.human_name %></th>
51 <th><%= column.human_name %></th>
46 <% end %>
52 <% end %>
47 <% end %>
53 <% end %>
48 <th></th>
54 <th></th>
49 <th></th>
55 <th></th>
50 <th></th>
56 <th></th>
51 - <% if Configuration.multicontests? %>
52 - <th>Contests</th>
53 - <th>Other enabled contests</th>
54 - <% end %>
55 </tr>
57 </tr>
56
58
57 <% for user in @users %>
59 <% for user in @users %>
58 <tr class="info-<%= cycle("odd","even") %>">
60 <tr class="info-<%= cycle("odd","even") %>">
59 <% for column in User.content_columns %>
61 <% for column in User.content_columns %>
60 <% if !@hidden_columns.index(column.name) %>
62 <% if !@hidden_columns.index(column.name) %>
61 <td><%=h user.send(column.name) %></td>
63 <td><%=h user.send(column.name) %></td>
62 <% end %>
64 <% end %>
63 <% end %>
65 <% end %>
64 <td><%= link_to 'Show', :action => 'show', :id => user %></td>
66 <td><%= link_to 'Show', :action => 'show', :id => user %></td>
65 <td><%= link_to 'Edit', :action => 'edit', :id => user %></td>
67 <td><%= link_to 'Edit', :action => 'edit', :id => user %></td>
66 <td><%= link_to 'Destroy', { :action => 'destroy', :id => user }, :confirm => 'Are you sure?', :method => :post %></td>
68 <td><%= link_to 'Destroy', { :action => 'destroy', :id => user }, :confirm => 'Are you sure?', :method => :post %></td>
67 - <% if Configuration.multicontests? %>
68 - <td>
69 - <% user.contests.each do |contest| %>
70 - <%= contest.name %> [<%= link_to 'x', :action => 'remove_from_contest', :id => user.id, :contest_id => contest.id %>]
71 - <% end %>
72 - </td>
73 - <td>
74 - <% @contests.each do |contest| %>
75 - <% if not user.contests.all.find {|c| c.id==contest.id } %>
76 - <%= contest.name %> [<%= link_to '+', :action => 'add_to_contest', :id => user.id, :contest_id => contest.id %>]
77 - <% end %>
78 - <% end %>
79 - </td>
80 - <% end %>
81 </tr>
69 </tr>
82 <% end %>
70 <% end %>
83 </table>
71 </table>
84
72
85
73
86 <br />
74 <br />
87
75
88 <%= link_to 'New user', :action => 'new' %>
76 <%= link_to 'New user', :action => 'new' %>
89 <%= link_to 'New list of users', :action => 'new_list' %>
77 <%= link_to 'New list of users', :action => 'new_list' %>
You need to be logged in to leave comments. Login now