Description:
manages users in contests
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r280:f8e3b2e72e4a - - 7 files changed: 111 inserted, 7 deleted

@@ -0,0 +1,16
1 + %h1 Bulk edit users in contests
2 +
3 + - form_tag :action => 'manage_contest' do
4 + List users' login below; one per line.
5 + %br/
6 + = text_area_tag 'login_list', nil, :rows => 25, :cols => 80
7 + %br/
8 + You want to
9 + = select(nil,"operation",[['add users to','add'],['remove users from','remove']])
10 + contest
11 + = select("contest","id",Contest.all.collect {|c| [c.title, c.id]})
12 +     
13 + = submit_tag "Perform action", :confirm => 'Are you sure?'
14 +
15 + %hr/
16 + = link_to '[go back to index]', :action => 'index'
@@ -1,259 +1,322
1 class UserAdminController < ApplicationController
1 class UserAdminController < ApplicationController
2
2
3 before_filter :admin_authorization
3 before_filter :admin_authorization
4
4
5 def index
5 def index
6 list
6 list
7 render :action => 'list'
7 render :action => 'list'
8 end
8 end
9
9
10 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
10 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
11 verify :method => :post, :only => [ :destroy,
11 verify :method => :post, :only => [ :destroy,
12 :create, :create_from_list,
12 :create, :create_from_list,
13 :update ],
13 :update ],
14 :redirect_to => { :action => :list }
14 :redirect_to => { :action => :list }
15
15
16 def list
16 def list
17 @users = User.find(:all)
17 @users = User.find(:all)
18 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
18 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
19 + @contests = Contest.all(:conditions => {:enabled => true})
19 end
20 end
20
21
21 def active
22 def active
22 sessions = ActiveRecord::SessionStore::Session.find(:all, :conditions => ["updated_at >= ?", 60.minutes.ago])
23 sessions = ActiveRecord::SessionStore::Session.find(:all, :conditions => ["updated_at >= ?", 60.minutes.ago])
23 @users = []
24 @users = []
24 sessions.each do |session|
25 sessions.each do |session|
25 if session.data[:user_id]
26 if session.data[:user_id]
26 @users << User.find(session.data[:user_id])
27 @users << User.find(session.data[:user_id])
27 end
28 end
28 end
29 end
29 end
30 end
30
31
31 def show
32 def show
32 @user = User.find(params[:id])
33 @user = User.find(params[:id])
33 end
34 end
34
35
35 def new
36 def new
36 @user = User.new
37 @user = User.new
37 end
38 end
38
39
39 def create
40 def create
40 @user = User.new(params[:user])
41 @user = User.new(params[:user])
41 @user.activated = true
42 @user.activated = true
42 if @user.save
43 if @user.save
43 flash[:notice] = 'User was successfully created.'
44 flash[:notice] = 'User was successfully created.'
44 redirect_to :action => 'list'
45 redirect_to :action => 'list'
45 else
46 else
46 render :action => 'new'
47 render :action => 'new'
47 end
48 end
48 end
49 end
49
50
50 def create_from_list
51 def create_from_list
51 lines = params[:user_list]
52 lines = params[:user_list]
52
53
53 note = []
54 note = []
54
55
55 lines.split("\n").each do |line|
56 lines.split("\n").each do |line|
56 items = line.chomp.split(',')
57 items = line.chomp.split(',')
57 if items.length>=2
58 if items.length>=2
58 login = items[0]
59 login = items[0]
59 full_name = items[1]
60 full_name = items[1]
60
61
61 added_random_password = false
62 added_random_password = false
62 if items.length>=3
63 if items.length>=3
63 password = items[2]
64 password = items[2]
64 user_alias = (items.length>=4) ? items[3] : login
65 user_alias = (items.length>=4) ? items[3] : login
65 else
66 else
66 password = random_password
67 password = random_password
67 user_alias = (items.length>=4) ? items[3] : login
68 user_alias = (items.length>=4) ? items[3] : login
68 added_random_password = true
69 added_random_password = true
69 end
70 end
70
71
71 user = User.new({:login => login,
72 user = User.new({:login => login,
72 :full_name => full_name,
73 :full_name => full_name,
73 :password => password,
74 :password => password,
74 :password_confirmation => password,
75 :password_confirmation => password,
75 :alias => user_alias})
76 :alias => user_alias})
76 user.activated = true
77 user.activated = true
77 user.save
78 user.save
78
79
79 if added_random_password
80 if added_random_password
80 note << "'#{login}' (+)"
81 note << "'#{login}' (+)"
81 else
82 else
82 note << login
83 note << login
83 end
84 end
84 end
85 end
85 end
86 end
86 flash[:notice] = 'User(s) ' + note.join(', ') +
87 flash[:notice] = 'User(s) ' + note.join(', ') +
87 ' were successfully created. ' +
88 ' were successfully created. ' +
88 '( (+) - created with random passwords.)'
89 '( (+) - created with random passwords.)'
89 redirect_to :action => 'list'
90 redirect_to :action => 'list'
90 end
91 end
91
92
92 def edit
93 def edit
93 @user = User.find(params[:id])
94 @user = User.find(params[:id])
94 end
95 end
95
96
96 def update
97 def update
97 @user = User.find(params[:id])
98 @user = User.find(params[:id])
98 if @user.update_attributes(params[:user])
99 if @user.update_attributes(params[:user])
99 flash[:notice] = 'User was successfully updated.'
100 flash[:notice] = 'User was successfully updated.'
100 redirect_to :action => 'show', :id => @user
101 redirect_to :action => 'show', :id => @user
101 else
102 else
102 render :action => 'edit'
103 render :action => 'edit'
103 end
104 end
104 end
105 end
105
106
106 def destroy
107 def destroy
107 User.find(params[:id]).destroy
108 User.find(params[:id]).destroy
108 redirect_to :action => 'list'
109 redirect_to :action => 'list'
109 end
110 end
110
111
111 def user_stat
112 def user_stat
112 @problems = Problem.find_available_problems
113 @problems = Problem.find_available_problems
113 @users = User.find(:all)
114 @users = User.find(:all)
114 @scorearray = Array.new
115 @scorearray = Array.new
115 @users.each do |u|
116 @users.each do |u|
116 ustat = Array.new
117 ustat = Array.new
117 ustat[0] = u
118 ustat[0] = u
118 @problems.each do |p|
119 @problems.each do |p|
119 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
120 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
120 if (sub!=nil) and (sub.points!=nil)
121 if (sub!=nil) and (sub.points!=nil)
121 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
122 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
122 else
123 else
123 ustat << [0,false]
124 ustat << [0,false]
124 end
125 end
125 end
126 end
126 @scorearray << ustat
127 @scorearray << ustat
127 end
128 end
128 end
129 end
129
130
130 def import
131 def import
131 if params[:file]==''
132 if params[:file]==''
132 flash[:notice] = 'Error importing no file'
133 flash[:notice] = 'Error importing no file'
133 redirect_to :action => 'list' and return
134 redirect_to :action => 'list' and return
134 end
135 end
135 import_from_file(params[:file])
136 import_from_file(params[:file])
136 end
137 end
137
138
138 def random_all_passwords
139 def random_all_passwords
139 users = User.find(:all)
140 users = User.find(:all)
140 @prefix = params[:prefix] || ''
141 @prefix = params[:prefix] || ''
141 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
142 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
142 @changed = false
143 @changed = false
143 if request.request_method == :post
144 if request.request_method == :post
144 @non_admin_users.each do |user|
145 @non_admin_users.each do |user|
145 password = random_password
146 password = random_password
146 user.password = password
147 user.password = password
147 user.password_confirmation = password
148 user.password_confirmation = password
148 user.save
149 user.save
149 end
150 end
150 @changed = true
151 @changed = true
151 end
152 end
152 end
153 end
153
154
155 + # contest management
156 +
157 + def add_to_contest
158 + user = User.find(params[:id])
159 + contest = Contest.find(params[:contest_id])
160 + if user and contest
161 + user.contests << contest
162 + end
163 + redirect_to :action => 'list'
164 + end
165 +
166 + def remove_from_contest
167 + user = User.find(params[:id])
168 + contest = Contest.find(params[:contest_id])
169 + if user and contest
170 + user.contests.delete(contest)
171 + end
172 + redirect_to :action => 'list'
173 + end
174 +
175 + def contest_management
176 + end
177 +
178 + def manage_contest
179 + contest = Contest.find(params[:contest][:id])
180 + if !contest
181 + flash[:notice] = 'You did not choose the contest.'
182 + redirect_to :action => 'contest_management' and return
183 + end
184 +
185 + operation = params[:operation]
186 +
187 + if operation!='add' and operation!='remove'
188 + flash[:notice] = 'You did not choose the operation to perform.'
189 + redirect_to :action => 'contest_management' and return
190 + end
191 +
192 + lines = params[:login_list]
193 + if !lines or lines.blank?
194 + flash[:notice] = 'You entered an empty list.'
195 + redirect_to :action => 'contest_management' and return
196 + end
197 +
198 + note = []
199 + lines.split("\n").each do |line|
200 + puts line
201 + user = User.find_by_login(line.chomp)
202 + puts user
203 + if user
204 + if operation=='add'
205 + user.contests << contest
206 + else
207 + user.contests.delete(contest)
208 + end
209 + note << user.login
210 + end
211 + end
212 + flash[:notice] = 'User(s) ' + note.join(', ') +
213 + ' were successfully modified. '
214 + redirect_to :action => 'contest_management'
215 + end
216 +
154 # admin management
217 # admin management
155
218
156 def admin
219 def admin
157 @admins = User.find(:all).find_all {|user| user.admin? }
220 @admins = User.find(:all).find_all {|user| user.admin? }
158 end
221 end
159
222
160 def grant_admin
223 def grant_admin
161 login = params[:login]
224 login = params[:login]
162 user = User.find_by_login(login)
225 user = User.find_by_login(login)
163 if user!=nil
226 if user!=nil
164 admin_role = Role.find_by_name('admin')
227 admin_role = Role.find_by_name('admin')
165 user.roles << admin_role
228 user.roles << admin_role
166 else
229 else
167 flash[:notice] = 'Unknown user'
230 flash[:notice] = 'Unknown user'
168 end
231 end
169 flash[:notice] = 'User added as admins'
232 flash[:notice] = 'User added as admins'
170 redirect_to :action => 'admin'
233 redirect_to :action => 'admin'
171 end
234 end
172
235
173 def revoke_admin
236 def revoke_admin
174 user = User.find(params[:id])
237 user = User.find(params[:id])
175 if user==nil
238 if user==nil
176 flash[:notice] = 'Unknown user'
239 flash[:notice] = 'Unknown user'
177 redirect_to :action => 'admin' and return
240 redirect_to :action => 'admin' and return
178 elsif user.login == 'root'
241 elsif user.login == 'root'
179 flash[:notice] = 'You cannot revoke admisnistrator permission from root.'
242 flash[:notice] = 'You cannot revoke admisnistrator permission from root.'
180 redirect_to :action => 'admin' and return
243 redirect_to :action => 'admin' and return
181 end
244 end
182
245
183 admin_role = Role.find_by_name('admin')
246 admin_role = Role.find_by_name('admin')
184 user.roles.delete(admin_role)
247 user.roles.delete(admin_role)
185 flash[:notice] = 'User permission revoked'
248 flash[:notice] = 'User permission revoked'
186 redirect_to :action => 'admin'
249 redirect_to :action => 'admin'
187 end
250 end
188
251
189 protected
252 protected
190
253
191 def random_password(length=5)
254 def random_password(length=5)
192 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
255 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
193 newpass = ""
256 newpass = ""
194 length.times { newpass << chars[rand(chars.size-1)] }
257 length.times { newpass << chars[rand(chars.size-1)] }
195 return newpass
258 return newpass
196 end
259 end
197
260
198 def import_from_file(f)
261 def import_from_file(f)
199 data_hash = YAML.load(f)
262 data_hash = YAML.load(f)
200 @import_log = ""
263 @import_log = ""
201
264
202 country_data = data_hash[:countries]
265 country_data = data_hash[:countries]
203 site_data = data_hash[:sites]
266 site_data = data_hash[:sites]
204 user_data = data_hash[:users]
267 user_data = data_hash[:users]
205
268
206 # import country
269 # import country
207 countries = {}
270 countries = {}
208 country_data.each_pair do |id,country|
271 country_data.each_pair do |id,country|
209 c = Country.find_by_name(country[:name])
272 c = Country.find_by_name(country[:name])
210 if c!=nil
273 if c!=nil
211 countries[id] = c
274 countries[id] = c
212 @import_log << "Found #{country[:name]}\n"
275 @import_log << "Found #{country[:name]}\n"
213 else
276 else
214 countries[id] = Country.new(:name => country[:name])
277 countries[id] = Country.new(:name => country[:name])
215 countries[id].save
278 countries[id].save
216 @import_log << "Created #{country[:name]}\n"
279 @import_log << "Created #{country[:name]}\n"
217 end
280 end
218 end
281 end
219
282
220 # import sites
283 # import sites
221 sites = {}
284 sites = {}
222 site_data.each_pair do |id,site|
285 site_data.each_pair do |id,site|
223 s = Site.find_by_name(site[:name])
286 s = Site.find_by_name(site[:name])
224 if s!=nil
287 if s!=nil
225 @import_log << "Found #{site[:name]}\n"
288 @import_log << "Found #{site[:name]}\n"
226 else
289 else
227 s = Site.new(:name => site[:name])
290 s = Site.new(:name => site[:name])
228 @import_log << "Created #{site[:name]}\n"
291 @import_log << "Created #{site[:name]}\n"
229 end
292 end
230 s.password = site[:password]
293 s.password = site[:password]
231 s.country = countries[site[:country_id]]
294 s.country = countries[site[:country_id]]
232 s.save
295 s.save
233 sites[id] = s
296 sites[id] = s
234 end
297 end
235
298
236 # import users
299 # import users
237 user_data.each_pair do |id,user|
300 user_data.each_pair do |id,user|
238 u = User.find_by_login(user[:login])
301 u = User.find_by_login(user[:login])
239 if u!=nil
302 if u!=nil
240 @import_log << "Found #{user[:login]}\n"
303 @import_log << "Found #{user[:login]}\n"
241 else
304 else
242 u = User.new(:login => user[:login])
305 u = User.new(:login => user[:login])
243 @import_log << "Created #{user[:login]}\n"
306 @import_log << "Created #{user[:login]}\n"
244 end
307 end
245 u.full_name = user[:name]
308 u.full_name = user[:name]
246 u.password = user[:password]
309 u.password = user[:password]
247 u.country = countries[user[:country_id]]
310 u.country = countries[user[:country_id]]
248 u.site = sites[user[:site_id]]
311 u.site = sites[user[:site_id]]
249 u.activated = true
312 u.activated = true
250 u.email = "empty-#{u.login}@none.com"
313 u.email = "empty-#{u.login}@none.com"
251 if not u.save
314 if not u.save
252 @import_log << "Errors\n"
315 @import_log << "Errors\n"
253 u.errors.each { |attr,msg| @import_log << "#{attr} - #{msg}\n" }
316 u.errors.each { |attr,msg| @import_log << "#{attr} - #{msg}\n" }
254 end
317 end
255 end
318 end
256
319
257 end
320 end
258
321
259 end
322 end
@@ -1,108 +1,108
1 class Problem < ActiveRecord::Base
1 class Problem < ActiveRecord::Base
2
2
3 belongs_to :description
3 belongs_to :description
4 - has_and_belongs_to_many :contests
4 + has_and_belongs_to_many :contests, :uniq => true
5 has_many :test_pairs, :dependent => :delete_all
5 has_many :test_pairs, :dependent => :delete_all
6
6
7 validates_presence_of :name
7 validates_presence_of :name
8 validates_format_of :name, :with => /^\w+$/
8 validates_format_of :name, :with => /^\w+$/
9 validates_presence_of :full_name
9 validates_presence_of :full_name
10
10
11 named_scope :available, :conditions => {:available => true}
11 named_scope :available, :conditions => {:available => true}
12
12
13 DEFAULT_TIME_LIMIT = 1
13 DEFAULT_TIME_LIMIT = 1
14 DEFAULT_MEMORY_LIMIT = 32
14 DEFAULT_MEMORY_LIMIT = 32
15
15
16 def self.find_available_problems
16 def self.find_available_problems
17 Problem.available.all(:order => "date_added DESC")
17 Problem.available.all(:order => "date_added DESC")
18 end
18 end
19
19
20 def self.create_from_import_form_params(params, old_problem=nil)
20 def self.create_from_import_form_params(params, old_problem=nil)
21 problem = old_problem || Problem.new
21 problem = old_problem || Problem.new
22 import_params = Problem.extract_params_and_check(params, problem)
22 import_params = Problem.extract_params_and_check(params, problem)
23
23
24 if not problem.valid?
24 if not problem.valid?
25 return problem, 'Error importing'
25 return problem, 'Error importing'
26 end
26 end
27
27
28 problem.full_score = 100
28 problem.full_score = 100
29 problem.date_added = Time.new
29 problem.date_added = Time.new
30 problem.test_allowed = true
30 problem.test_allowed = true
31 problem.output_only = false
31 problem.output_only = false
32 problem.available = false
32 problem.available = false
33
33
34 if not problem.save
34 if not problem.save
35 return problem, 'Error importing'
35 return problem, 'Error importing'
36 end
36 end
37
37
38 import_to_db = params.has_key? :import_to_db
38 import_to_db = params.has_key? :import_to_db
39
39
40 importer = TestdataImporter.new(problem)
40 importer = TestdataImporter.new(problem)
41
41
42 if not importer.import_from_file(import_params[:file],
42 if not importer.import_from_file(import_params[:file],
43 import_params[:time_limit],
43 import_params[:time_limit],
44 import_params[:memory_limit],
44 import_params[:memory_limit],
45 import_to_db)
45 import_to_db)
46 problem.errors.add_to_base('Import error.')
46 problem.errors.add_to_base('Import error.')
47 end
47 end
48
48
49 return problem, importer.log_msg
49 return problem, importer.log_msg
50 end
50 end
51
51
52 def self.download_file_basedir
52 def self.download_file_basedir
53 return "#{RAILS_ROOT}/data/tasks"
53 return "#{RAILS_ROOT}/data/tasks"
54 end
54 end
55
55
56 protected
56 protected
57
57
58 def self.to_i_or_default(st, default)
58 def self.to_i_or_default(st, default)
59 if st!=''
59 if st!=''
60 st.to_i
60 st.to_i
61 else
61 else
62 default
62 default
63 end
63 end
64 end
64 end
65
65
66 def self.extract_params_and_check(params, problem)
66 def self.extract_params_and_check(params, problem)
67 time_limit = Problem.to_i_or_default(params[:time_limit],
67 time_limit = Problem.to_i_or_default(params[:time_limit],
68 DEFAULT_TIME_LIMIT)
68 DEFAULT_TIME_LIMIT)
69 memory_limit = Problem.to_i_or_default(params[:memory_limit],
69 memory_limit = Problem.to_i_or_default(params[:memory_limit],
70 DEFAULT_MEMORY_LIMIT)
70 DEFAULT_MEMORY_LIMIT)
71
71
72 if time_limit==0 and time_limit_s!='0'
72 if time_limit==0 and time_limit_s!='0'
73 problem.errors.add_to_base('Time limit format errors.')
73 problem.errors.add_to_base('Time limit format errors.')
74 elsif time_limit<=0 or time_limit >60
74 elsif time_limit<=0 or time_limit >60
75 problem.errors.add_to_base('Time limit out of range.')
75 problem.errors.add_to_base('Time limit out of range.')
76 end
76 end
77
77
78 if memory_limit==0 and memory_limit_s!='0'
78 if memory_limit==0 and memory_limit_s!='0'
79 problem.errors.add_to_base('Memory limit format errors.')
79 problem.errors.add_to_base('Memory limit format errors.')
80 elsif memory_limit<=0 or memory_limit >512
80 elsif memory_limit<=0 or memory_limit >512
81 problem.errors.add_to_base('Memory limit out of range.')
81 problem.errors.add_to_base('Memory limit out of range.')
82 end
82 end
83
83
84 if params[:file]==nil or params[:file]==''
84 if params[:file]==nil or params[:file]==''
85 problem.errors.add_to_base('No testdata file.')
85 problem.errors.add_to_base('No testdata file.')
86 end
86 end
87
87
88 file = params[:file]
88 file = params[:file]
89
89
90 if problem.errors.length!=0
90 if problem.errors.length!=0
91 return problem
91 return problem
92 end
92 end
93
93
94 problem.name = params[:name]
94 problem.name = params[:name]
95 if params[:full_name]!=''
95 if params[:full_name]!=''
96 problem.full_name = params[:full_name]
96 problem.full_name = params[:full_name]
97 else
97 else
98 problem.full_name = params[:name]
98 problem.full_name = params[:name]
99 end
99 end
100
100
101 return {
101 return {
102 :time_limit => time_limit,
102 :time_limit => time_limit,
103 :memory_limit => memory_limit,
103 :memory_limit => memory_limit,
104 :file => file
104 :file => file
105 }
105 }
106 end
106 end
107
107
108 end
108 end
@@ -1,216 +1,216
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
24 + has_and_belongs_to_many :contests, :uniq => true
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 contest_time_left
127 def contest_time_left
128 if Configuration.contest_mode?
128 if Configuration.contest_mode?
129 return nil if site==nil
129 return nil if site==nil
130 return site.time_left
130 return site.time_left
131 elsif Configuration.indv_contest_mode?
131 elsif Configuration.indv_contest_mode?
132 time_limit = Configuration.contest_time_limit
132 time_limit = Configuration.contest_time_limit
133 if time_limit == nil
133 if time_limit == nil
134 return nil
134 return nil
135 end
135 end
136 if contest_stat==nil
136 if contest_stat==nil
137 return (Time.now.gmtime + time_limit) - Time.now.gmtime
137 return (Time.now.gmtime + time_limit) - Time.now.gmtime
138 else
138 else
139 finish_time = contest_stat.started_at + time_limit
139 finish_time = contest_stat.started_at + time_limit
140 current_time = Time.now.gmtime
140 current_time = Time.now.gmtime
141 if current_time > finish_time
141 if current_time > finish_time
142 return 0
142 return 0
143 else
143 else
144 return finish_time - current_time
144 return finish_time - current_time
145 end
145 end
146 end
146 end
147 else
147 else
148 return nil
148 return nil
149 end
149 end
150 end
150 end
151
151
152 def contest_finished?
152 def contest_finished?
153 if Configuration.contest_mode?
153 if Configuration.contest_mode?
154 return false if site==nil
154 return false if site==nil
155 return site.finished?
155 return site.finished?
156 elsif Configuration.indv_contest_mode?
156 elsif Configuration.indv_contest_mode?
157 time_limit = Configuration.contest_time_limit
157 time_limit = Configuration.contest_time_limit
158
158
159 return false if contest_stat==nil
159 return false if contest_stat==nil
160
160
161 return contest_time_left == 0
161 return contest_time_left == 0
162 else
162 else
163 return false
163 return false
164 end
164 end
165 end
165 end
166
166
167 def contest_started?
167 def contest_started?
168 if Configuration.contest_mode?
168 if Configuration.contest_mode?
169 return true if site==nil
169 return true if site==nil
170 return site.started
170 return site.started
171 else
171 else
172 return true
172 return true
173 end
173 end
174 end
174 end
175
175
176 def update_start_time
176 def update_start_time
177 stat = self.contest_stat
177 stat = self.contest_stat
178 if stat == nil
178 if stat == nil
179 stat = UserContestStat.new(:user => self,
179 stat = UserContestStat.new(:user => self,
180 :started_at => Time.now.gmtime)
180 :started_at => Time.now.gmtime)
181 stat.save
181 stat.save
182 end
182 end
183 end
183 end
184
184
185 protected
185 protected
186 def encrypt_new_password
186 def encrypt_new_password
187 return if password.blank?
187 return if password.blank?
188 self.salt = (10+rand(90)).to_s
188 self.salt = (10+rand(90)).to_s
189 self.hashed_password = User.encrypt(self.password,self.salt)
189 self.hashed_password = User.encrypt(self.password,self.salt)
190 end
190 end
191
191
192 def assign_default_site
192 def assign_default_site
193 # have to catch error when migrating (because self.site is not available).
193 # have to catch error when migrating (because self.site is not available).
194 begin
194 begin
195 if self.site==nil
195 if self.site==nil
196 self.site = Site.find_by_name('default')
196 self.site = Site.find_by_name('default')
197 if self.site==nil
197 if self.site==nil
198 self.site = Site.find(1) # when 'default has be renamed'
198 self.site = Site.find(1) # when 'default has be renamed'
199 end
199 end
200 end
200 end
201 rescue
201 rescue
202 end
202 end
203 end
203 end
204
204
205 def password_required?
205 def password_required?
206 self.hashed_password.blank? || !self.password.blank?
206 self.hashed_password.blank? || !self.password.blank?
207 end
207 end
208
208
209 def self.encrypt(string,salt)
209 def self.encrypt(string,salt)
210 Digest::SHA1.hexdigest(salt + string)
210 Digest::SHA1.hexdigest(salt + string)
211 end
211 end
212
212
213 def uniqueness_of_email_from_activated_users
213 def uniqueness_of_email_from_activated_users
214 user = User.activated_users.find_by_email(self.email)
214 user = User.activated_users.find_by_email(self.email)
215 if user and (user.login != self.login)
215 if user and (user.login != self.login)
216 self.errors.add_to_base("Email has already been taken")
216 self.errors.add_to_base("Email has already been taken")
@@ -1,51 +1,52
1 - content_for :head do
1 - content_for :head do
2 = javascript_include_tag :defaults
2 = javascript_include_tag :defaults
3 = javascript_include_tag 'announcement_refresh.js'
3 = javascript_include_tag 'announcement_refresh.js'
4
4
5 = user_title_bar(@user)
5 = user_title_bar(@user)
6
6
7 .announcementbox{:style => (@announcements.length==0 ? "display:none" : "")}
7 .announcementbox{:style => (@announcements.length==0 ? "display:none" : "")}
8 %span{:class => 'title'}
8 %span{:class => 'title'}
9 Announcements
9 Announcements
10 #announcementbox-body
10 #announcementbox-body
11 = render :partial => 'announcement', :collection => @announcements
11 = render :partial => 'announcement', :collection => @announcements
12
12
13 - if Configuration.show_submitbox_to?(@user)
13 - if Configuration.show_submitbox_to?(@user)
14 .submitbox
14 .submitbox
15 = error_messages_for 'submission'
15 = error_messages_for 'submission'
16 = render :partial => 'submission_box'
16 = render :partial => 'submission_box'
17
17
18
18
19 %hr/
19 %hr/
20
20
21 - if (Configuration.contest_mode?) and (@user.site!=nil) and (@user.site.started!=true)
21 - if (Configuration.contest_mode?) and (@user.site!=nil) and (@user.site.started!=true)
22 %p=t 'main.start_soon'
22 %p=t 'main.start_soon'
23
23
24 - if Configuration.show_tasks_to?(@user)
24 - if Configuration.show_tasks_to?(@user)
25 - if not Configuration.multicontests?
25 - if not Configuration.multicontests?
26 %table.info
26 %table.info
27 %tr.info-head
27 %tr.info-head
28 %th
28 %th
29 %th Tasks
29 %th Tasks
30 %th # of sub(s)
30 %th # of sub(s)
31 %th Results
31 %th Results
32 = render :partial => 'problem', :collection => @problems
32 = render :partial => 'problem', :collection => @problems
33 - else
33 - else
34 - @contest_problems.each do |cp|
34 - @contest_problems.each do |cp|
35 + - if cp[:problems].length > 0
35 %h2{:class =>'contest-title'}
36 %h2{:class =>'contest-title'}
36 = "#{cp[:contest] ? cp[:contest].title : 'Public problems'}"
37 = "#{cp[:contest] ? cp[:contest].title : 'Public problems'}"
37 %table.info
38 %table.info
38 %tr.info-head
39 %tr.info-head
39 %th
40 %th
40 %th Tasks
41 %th Tasks
41 %th # of sub(s)
42 %th # of sub(s)
42 %th Results
43 %th Results
43 = render :partial => 'problem', :collection => cp[:problems]
44 = render :partial => 'problem', :collection => cp[:problems]
44
45
45
46
46 %hr/
47 %hr/
47
48
48 %script{:type => 'text/javascript'}
49 %script{:type => 'text/javascript'}
49 = "Announcement.refreshUrl = '#{url_for :controller => 'main', :action => 'announcements'}';"
50 = "Announcement.refreshUrl = '#{url_for :controller => 'main', :action => 'announcements'}';"
50 Announcement.registerRefreshEventTimer();
51 Announcement.registerRefreshEventTimer();
51
52
@@ -1,25 +1,25
1 %h1 Administrators
1 %h1 Administrators
2
2
3 - %table
3 + %table{:class => 'info'}
4 - %tr
4 + %tr{:class => 'info-head'}
5 %th #
5 %th #
6 %th Login
6 %th Login
7 %th Full name
7 %th Full name
8 %th
8 %th
9 - @admins.each_with_index do |user, i|
9 - @admins.each_with_index do |user, i|
10 %tr
10 %tr
11 %td= i+1
11 %td= i+1
12 %td= user.login
12 %td= user.login
13 %td= user.full_name
13 %td= user.full_name
14 %td
14 %td
15 - if user.login!='root'
15 - if user.login!='root'
16 = link_to '[revoke]', :action => 'revoke_admin', :id => user.id
16 = link_to '[revoke]', :action => 'revoke_admin', :id => user.id
17 %hr
17 %hr
18
18
19 - form_tag :action => 'grant_admin' do
19 - form_tag :action => 'grant_admin' do
20 Grant admin permission to:
20 Grant admin permission to:
21 = text_field_tag 'login'
21 = text_field_tag 'login'
22 = submit_tag 'Grant'
22 = submit_tag 'Grant'
23
23
24 %hr/
24 %hr/
25 = link_to '[go back to index]', :action => 'index'
25 = link_to '[go back to index]', :action => 'index'
@@ -1,65 +1,89
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? %>
37 + <%= link_to '[Manage bulk users in contests]', :action => 'contest_management' %>
38 + <% end %>
36 </div>
39 </div>
37
40
38 - <table>
41 + <table class="info">
39 - <tr>
42 + <tr class="info-head">
40 <% for column in User.content_columns %>
43 <% for column in User.content_columns %>
41 <% if !@hidden_columns.index(column.name) %>
44 <% if !@hidden_columns.index(column.name) %>
42 <th><%= column.human_name %></th>
45 <th><%= column.human_name %></th>
43 <% end %>
46 <% end %>
44 <% end %>
47 <% end %>
48 + <th></th>
49 + <th></th>
50 + <th></th>
51 + <% if Configuration.multicontests? %>
52 + <th>Contests</th>
53 + <th>Other enabled contests</th>
54 + <% end %>
45 </tr>
55 </tr>
46
56
47 <% for user in @users %>
57 <% for user in @users %>
48 - <tr>
58 + <tr class="info-<%= cycle("odd","even") %>">
49 <% for column in User.content_columns %>
59 <% for column in User.content_columns %>
50 <% if !@hidden_columns.index(column.name) %>
60 <% if !@hidden_columns.index(column.name) %>
51 <td><%=h user.send(column.name) %></td>
61 <td><%=h user.send(column.name) %></td>
52 <% end %>
62 <% end %>
53 <% end %>
63 <% end %>
54 <td><%= link_to 'Show', :action => 'show', :id => user %></td>
64 <td><%= link_to 'Show', :action => 'show', :id => user %></td>
55 <td><%= link_to 'Edit', :action => 'edit', :id => user %></td>
65 <td><%= link_to 'Edit', :action => 'edit', :id => user %></td>
56 <td><%= link_to 'Destroy', { :action => 'destroy', :id => user }, :confirm => 'Are you sure?', :method => :post %></td>
66 <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 %>
57 </tr>
81 </tr>
58 <% end %>
82 <% end %>
59 </table>
83 </table>
60
84
61
85
62 <br />
86 <br />
63
87
64 <%= link_to 'New user', :action => 'new' %>
88 <%= link_to 'New user', :action => 'new' %>
65 <%= link_to 'New list of users', :action => 'new_list' %>
89 <%= link_to 'New list of users', :action => 'new_list' %>
You need to be logged in to leave comments. Login now