Description:
add more error message to user list upgrade. Fix #9
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r785:2cf37c58fc60 - - 2 files changed: 13 inserted, 7 deleted

@@ -1,518 +1,522
1 1 require 'csv'
2 2
3 3 class UserAdminController < ApplicationController
4 4
5 5 include MailHelperMethods
6 6
7 7 before_action :admin_authorization
8 8
9 9 def index
10 10 @user_count = User.count
11 11 if params[:page] == 'all'
12 12 @users = User.all
13 13 @paginated = false
14 14 else
15 15 @users = User.paginate :page => params[:page]
16 16 @paginated = true
17 17 end
18 18 @users = User.all
19 19 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
20 20 @contests = Contest.enabled
21 21 end
22 22
23 23 def active
24 24 sessions = ActiveRecord::SessionStore::Session.where("updated_at >= ?", 60.minutes.ago)
25 25 @users = []
26 26 sessions.each do |session|
27 27 if session.data[:user_id]
28 28 @users << User.find(session.data[:user_id])
29 29 end
30 30 end
31 31 end
32 32
33 33 def show
34 34 @user = User.find(params[:id])
35 35 end
36 36
37 37 def new
38 38 @user = User.new
39 39 end
40 40
41 41 def create
42 42 @user = User.new(user_params)
43 43 @user.activated = true
44 44 if @user.save
45 45 flash[:notice] = 'User was successfully created.'
46 46 redirect_to :action => 'index'
47 47 else
48 48 render :action => 'new'
49 49 end
50 50 end
51 51
52 52 def clear_last_ip
53 53 @user = User.find(params[:id])
54 54 @user.last_ip = nil
55 55 @user.save
56 56 redirect_to action: 'index', page: params[:page]
57 57 end
58 58
59 59 def create_from_list
60 60 lines = params[:user_list]
61 61
62 62 note = []
63 63 error_note = []
64 + error_msg = nil
64 65 ok_user = []
65 66
66 67 lines.split("\n").each do |line|
67 68 items = line.chomp.split(',')
68 69 if items.length>=2
69 70 login = items[0]
70 71 full_name = items[1]
71 72 remark =''
72 73 user_alias = ''
73 74
74 75 added_random_password = false
75 76 if items.length >= 3 and items[2].chomp(" ").length > 0;
76 77 password = items[2].chomp(" ")
77 78 else
78 79 password = random_password
79 - add_random_password=true;
80 + added_random_password=true;
80 81 end
81 82
82 83 if items.length>= 4 and items[3].chomp(" ").length > 0;
83 84 user_alias = items[3].chomp(" ")
84 85 else
85 86 user_alias = login
86 87 end
87 88
88 89 if items.length>=5
89 90 remark = items[4].strip;
90 91 end
91 92
92 93 user = User.find_by_login(login)
93 94 if (user)
94 95 user.full_name = full_name
95 96 user.password = password
96 97 user.remark = remark
97 98 else
98 99 user = User.new({:login => login,
99 100 :full_name => full_name,
100 101 :password => password,
101 102 :password_confirmation => password,
102 103 :alias => user_alias,
103 104 :remark => remark})
104 105 end
105 106 user.activated = true
106 107
107 108 if user.save
108 109 if added_random_password
109 110 note << "'#{login}' (+)"
110 111 else
111 112 note << login
112 113 end
113 114 ok_user << user
114 115 else
115 - error_note << "#{login}"
116 + error_note << "'#{login}'"
117 + error_msg = user.errors.full_messages.to_sentence unless error_msg
116 118 end
117 119
118 120 end
119 121 end
120 122
121 123 #add to group
122 124 if params[:add_to_group]
123 125 group = Group.where(id: params[:group_id]).first
124 126 if group
125 127 group.users << ok_user
126 128 end
127 129 end
128 130
129 131 # show flash
132 + if note.size > 0
130 133 flash[:success] = 'User(s) ' + note.join(', ') +
131 134 ' were successfully created. ' +
132 135 '( (+) - created with random passwords.)'
136 + end
133 137 if error_note.size > 0
134 - flash[:error] = "Following user(s) failed to be created: " + error_note.join(', ')
138 + flash[:error] = "Following user(s) failed to be created: " + error_note.join(', ') + ". The error of the first failed one are: " + error_msg;
135 139 end
136 140 redirect_to :action => 'index'
137 141 end
138 142
139 143 def edit
140 144 @user = User.find(params[:id])
141 145 end
142 146
143 147 def update
144 148 @user = User.find(params[:id])
145 149 if @user.update_attributes(user_params)
146 150 flash[:notice] = 'User was successfully updated.'
147 151 redirect_to :action => 'show', :id => @user
148 152 else
149 153 render :action => 'edit'
150 154 end
151 155 end
152 156
153 157 def destroy
154 158 User.find(params[:id]).destroy
155 159 redirect_to :action => 'index'
156 160 end
157 161
158 162 def user_stat
159 163 if params[:commit] == 'download csv'
160 164 @problems = Problem.all
161 165 else
162 166 @problems = Problem.available_problems
163 167 end
164 168 @users = User.includes(:contests, :contest_stat).where(enabled: true)
165 169 @scorearray = Array.new
166 170 @users.each do |u|
167 171 ustat = Array.new
168 172 ustat[0] = u
169 173 @problems.each do |p|
170 174 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
171 175 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
172 176 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
173 177 else
174 178 ustat << [0,false]
175 179 end
176 180 end
177 181 @scorearray << ustat
178 182 end
179 183 if params[:commit] == 'download csv' then
180 184 csv = gen_csv_from_scorearray(@scorearray,@problems)
181 185 send_data csv, filename: 'last_score.csv'
182 186 else
183 187 render template: 'user_admin/user_stat'
184 188 end
185 189 end
186 190
187 191 def user_stat_max
188 192 if params[:commit] == 'download csv'
189 193 @problems = Problem.all
190 194 else
191 195 @problems = Problem.available_problems
192 196 end
193 197 @users = User.includes(:contests).includes(:contest_stat).all
194 198 @scorearray = Array.new
195 199 #set up range from param
196 200 since_id = params.fetch(:since_id, 0).to_i
197 201 until_id = params.fetch(:until_id, 0).to_i
198 202 @users.each do |u|
199 203 ustat = Array.new
200 204 ustat[0] = u
201 205 @problems.each do |p|
202 206 max_points = 0
203 207 Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub|
204 208 max_points = sub.points if sub and sub.points and (sub.points > max_points)
205 209 end
206 210 ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)]
207 211 end
208 212 @scorearray << ustat
209 213 end
210 214
211 215 if params[:commit] == 'download csv' then
212 216 csv = gen_csv_from_scorearray(@scorearray,@problems)
213 217 send_data csv, filename: 'max_score.csv'
214 218 else
215 219 render template: 'user_admin/user_stat'
216 220 end
217 221 end
218 222
219 223 def import
220 224 if params[:file]==''
221 225 flash[:notice] = 'Error importing no file'
222 226 redirect_to :action => 'index' and return
223 227 end
224 228 import_from_file(params[:file])
225 229 end
226 230
227 231 def random_all_passwords
228 232 users = User.all
229 233 @prefix = params[:prefix] || ''
230 234 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
231 235 @changed = false
232 236 if params[:commit] == 'Go ahead'
233 237 @non_admin_users.each do |user|
234 238 password = random_password
235 239 user.password = password
236 240 user.password_confirmation = password
237 241 user.save
238 242 end
239 243 @changed = true
240 244 end
241 245 end
242 246
243 247 # contest management
244 248
245 249 def contests
246 250 @contest, @users = find_contest_and_user_from_contest_id(params[:id])
247 251 @contests = Contest.enabled
248 252 end
249 253
250 254 def assign_from_list
251 255 contest_id = params[:users_contest_id]
252 256 org_contest, users = find_contest_and_user_from_contest_id(contest_id)
253 257 contest = Contest.find(params[:new_contest][:id])
254 258 if !contest
255 259 flash[:notice] = 'Error: no contest'
256 260 redirect_to :action => 'contests', :id =>contest_id
257 261 end
258 262
259 263 note = []
260 264 users.each do |u|
261 265 u.contests = [contest]
262 266 note << u.login
263 267 end
264 268 flash[:notice] = 'User(s) ' + note.join(', ') +
265 269 " were successfully reassigned to #{contest.title}."
266 270 redirect_to :action => 'contests', :id =>contest.id
267 271 end
268 272
269 273 def add_to_contest
270 274 user = User.find(params[:id])
271 275 contest = Contest.find(params[:contest_id])
272 276 if user and contest
273 277 user.contests << contest
274 278 end
275 279 redirect_to :action => 'index'
276 280 end
277 281
278 282 def remove_from_contest
279 283 user = User.find(params[:id])
280 284 contest = Contest.find(params[:contest_id])
281 285 if user and contest
282 286 user.contests.delete(contest)
283 287 end
284 288 redirect_to :action => 'index'
285 289 end
286 290
287 291 def contest_management
288 292 end
289 293
290 294 def manage_contest
291 295 contest = Contest.find(params[:contest][:id])
292 296 if !contest
293 297 flash[:notice] = 'You did not choose the contest.'
294 298 redirect_to :action => 'contest_management' and return
295 299 end
296 300
297 301 operation = params[:operation]
298 302
299 303 if not ['add','remove','assign'].include? operation
300 304 flash[:notice] = 'You did not choose the operation to perform.'
301 305 redirect_to :action => 'contest_management' and return
302 306 end
303 307
304 308 lines = params[:login_list]
305 309 if !lines or lines.blank?
306 310 flash[:notice] = 'You entered an empty list.'
307 311 redirect_to :action => 'contest_management' and return
308 312 end
309 313
310 314 note = []
311 315 users = []
312 316 lines.split("\n").each do |line|
313 317 user = User.find_by_login(line.chomp)
314 318 if user
315 319 if operation=='add'
316 320 if ! user.contests.include? contest
317 321 user.contests << contest
318 322 end
319 323 elsif operation=='remove'
320 324 user.contests.delete(contest)
321 325 else
322 326 user.contests = [contest]
323 327 end
324 328
325 329 if params[:reset_timer]
326 330 user.contest_stat.forced_logout = true
327 331 user.contest_stat.reset_timer_and_save
328 332 end
329 333
330 334 if params[:notification_emails]
331 335 send_contest_update_notification_email(user, contest)
332 336 end
333 337
334 338 note << user.login
335 339 users << user
336 340 end
337 341 end
338 342
339 343 if params[:reset_timer]
340 344 logout_users(users)
341 345 end
342 346
343 347 flash[:notice] = 'User(s) ' + note.join(', ') +
344 348 ' were successfully modified. '
345 349 redirect_to :action => 'contest_management'
346 350 end
347 351
348 352 # admin management
349 353
350 354 def admin
351 355 @admins = User.all.find_all {|user| user.admin? }
352 356 end
353 357
354 358 def grant_admin
355 359 login = params[:login]
356 360 user = User.find_by_login(login)
357 361 if user!=nil
358 362 admin_role = Role.find_by_name('admin')
359 363 user.roles << admin_role
360 364 else
361 365 flash[:notice] = 'Unknown user'
362 366 end
363 367 flash[:notice] = 'User added as admins'
364 368 redirect_to :action => 'admin'
365 369 end
366 370
367 371 def revoke_admin
368 372 user = User.find(params[:id])
369 373 if user==nil
370 374 flash[:notice] = 'Unknown user'
371 375 redirect_to :action => 'admin' and return
372 376 elsif user.login == 'root'
373 377 flash[:notice] = 'You cannot revoke admisnistrator permission from root.'
374 378 redirect_to :action => 'admin' and return
375 379 end
376 380
377 381 admin_role = Role.find_by_name('admin')
378 382 user.roles.delete(admin_role)
379 383 flash[:notice] = 'User permission revoked'
380 384 redirect_to :action => 'admin'
381 385 end
382 386
383 387 # mass mailing
384 388
385 389 def mass_mailing
386 390 end
387 391
388 392 def bulk_mail
389 393 lines = params[:login_list]
390 394 if !lines or lines.blank?
391 395 flash[:notice] = 'You entered an empty list.'
392 396 redirect_to :action => 'mass_mailing' and return
393 397 end
394 398
395 399 mail_subject = params[:subject]
396 400 if !mail_subject or mail_subject.blank?
397 401 flash[:notice] = 'You entered an empty mail subject.'
398 402 redirect_to :action => 'mass_mailing' and return
399 403 end
400 404
401 405 mail_body = params[:email_body]
402 406 if !mail_body or mail_body.blank?
403 407 flash[:notice] = 'You entered an empty mail body.'
404 408 redirect_to :action => 'mass_mailing' and return
405 409 end
406 410
407 411 note = []
408 412 users = []
409 413 lines.split("\n").each do |line|
410 414 user = User.find_by_login(line.chomp)
411 415 if user
412 416 send_mail(user.email, mail_subject, mail_body)
413 417 note << user.login
414 418 end
415 419 end
416 420
417 421 flash[:notice] = 'User(s) ' + note.join(', ') +
418 422 ' were successfully modified. '
419 423 redirect_to :action => 'mass_mailing'
420 424 end
421 425
422 426 #bulk manage
423 427 def bulk_manage
424 428
425 429 begin
426 430 @users = User.where('(login REGEXP ?) OR (remark REGEXP ?)',params[:regex],params[:regex]) if params[:regex]
427 431 @users.count if @users #i don't know why I have to call count, but if I won't exception is not raised
428 432 rescue Exception
429 433 flash[:error] = 'Regular Expression is malformed'
430 434 @users = nil
431 435 end
432 436
433 437 if params[:commit]
434 438 @action = {}
435 439 @action[:set_enable] = params[:enabled]
436 440 @action[:enabled] = params[:enable] == "1"
437 441 @action[:gen_password] = params[:gen_password]
438 442 @action[:add_group] = params[:add_group]
439 443 @action[:group_name] = params[:group_name]
440 444 end
441 445
442 446 if params[:commit] == "Perform"
443 447 if @action[:set_enable]
444 448 @users.update_all(enabled: @action[:enabled])
445 449 end
446 450 if @action[:gen_password]
447 451 @users.each do |u|
448 452 password = random_password
449 453 u.password = password
450 454 u.password_confirmation = password
451 455 u.save
452 456 end
453 457 end
454 458 if @action[:add_group] and @action[:group_name]
455 459 @group = Group.find(@action[:group_name])
456 460 ok = []
457 461 failed = []
458 462 @users.each do |user|
459 463 begin
460 464 @group.users << user
461 465 ok << user.login
462 466 rescue => e
463 467 failed << user.login
464 468 end
465 469 end
466 470 flash[:success] = "The following users are added to the 'group #{@group.name}': " + ok.join(', ') if ok.count > 0
467 471 flash[:alert] = "The following users are already in the 'group #{@group.name}': " + failed.join(', ') if failed.count > 0
468 472 end
469 473 end
470 474 end
471 475
472 476 protected
473 477
474 478 def random_password(length=5)
475 479 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
476 480 newpass = ""
477 481 length.times { newpass << chars[rand(chars.size-1)] }
478 482 return newpass
479 483 end
480 484
481 485 def import_from_file(f)
482 486 data_hash = YAML.load(f)
483 487 @import_log = ""
484 488
485 489 country_data = data_hash[:countries]
486 490 site_data = data_hash[:sites]
487 491 user_data = data_hash[:users]
488 492
489 493 # import country
490 494 countries = {}
491 495 country_data.each_pair do |id,country|
492 496 c = Country.find_by_name(country[:name])
493 497 if c!=nil
494 498 countries[id] = c
495 499 @import_log << "Found #{country[:name]}\n"
496 500 else
497 501 countries[id] = Country.new(:name => country[:name])
498 502 countries[id].save
499 503 @import_log << "Created #{country[:name]}\n"
500 504 end
501 505 end
502 506
503 507 # import sites
504 508 sites = {}
505 509 site_data.each_pair do |id,site|
506 510 s = Site.find_by_name(site[:name])
507 511 if s!=nil
508 512 @import_log << "Found #{site[:name]}\n"
509 513 else
510 514 s = Site.new(:name => site[:name])
511 515 @import_log << "Created #{site[:name]}\n"
512 516 end
513 517 s.password = site[:password]
514 518 s.country = countries[site[:country_id]]
515 519 s.save
516 520 sites[id] = s
517 521 end
518 522
@@ -1,80 +1,82
1 1 .container-fluid
2 2 .row
3 3 .col-md-6
4 4 %h1 Group #{@group.name}
5 5 .row
6 6 .col-md-6
7 7 %b Description:
8 8 = @group.description
9 9 %br
10 10 = link_to 'Edit', edit_group_path(@group), class: 'btn btn-primary'
11 11 .row
12 12 .col-md-12
13 13 %h1 Group details
14 14 .row
15 15 .col-md-6
16 16 .panel.panel-default
17 17 .panel-heading
18 18 .panel-title Users in this group
19 19 .panel-body
20 20 %ul
21 21 %li
22 22 If you want to add several users to a group, it may be easier to just re-import those users in
23 23 = link_to 'New list of users', new_list_user_admin_index_path
24 - page
24 + page. You can also use
25 + = link_to 'Bulk Manage User', bulk_manage_user_admin_index_path
26 + page.
25 27 =form_tag add_user_group_path(@group), class: 'form-inline' do
26 28 .form-group
27 29 =label_tag :user_id, "User"
28 - =select_tag :user_id, options_from_collection_for_select(User.all,'id','full_name'), class: 'select2'
30 + =select_tag :user_id, options_from_collection_for_select(User.all,'id','full_name'), class: 'select2', style: 'width: 10em';
29 31 =submit_tag "Add",class: 'btn btn-primary'
30 32
31 33
32 34 %table.table.table-hover
33 35 %thead
34 36 %tr
35 37 %th Login
36 38 %th Full name
37 39 %th Remark
38 40 %th= link_to 'Remove All', remove_all_user_group_path(@group), method: :delete, :data => { :confirm => "Remove ALL USERS from group?" }, class: 'btn btn-danger btn-sm'
39 41
40 42 %tbody
41 43 - @group.users.each do |user|
42 44 %tr
43 45 %td= user.login
44 46 %td= user.full_name
45 47 %td= user.remark
46 48 %td= link_to 'Remove', remove_user_group_path(@group,user), :method => :delete, :data => { :confirm => "Remove #{user.full_name}?" }, class: 'btn btn-danger btn-sm'
47 49 .col-md-6
48 50 .panel.panel-default
49 51 .panel-heading
50 52 .panel-title Problems
51 53 .panel-body
52 54 %ul
53 55 %li
54 56 If you want to add several problem to a group, it may be easier to bulk manage them in the
55 - = link_to 'Bulk Manage', manage_problems_path
57 + = link_to 'Bulk Manage Problems', manage_problems_path
56 58 page
57 59 =form_tag add_problem_group_path(@group), class: 'form-inline' do
58 60 .form-group
59 61 =label_tag :problem_id, "Problem"
60 - =select_tag :problem_id, options_from_collection_for_select(Problem.all,'id','full_name'), class: 'select2'
62 + =select_tag :problem_id, options_from_collection_for_select(Problem.all,'id','full_name'), class: 'select2', style: 'width: 10em';
61 63 =submit_tag "Add",class: 'btn btn-primary'
62 64
63 65
64 66 %table.table.table-hover
65 67 %thead
66 68 %tr
67 69 %th name
68 70 %th Full name
69 71 %th Full score
70 72 %th= link_to 'Remove All', remove_all_problem_group_path(@group), method: :delete, :data => { :confirm => "Remove ALL PROBLEMS from group?" }, class: 'btn btn-danger btn-sm'
71 73
72 74 %tbody
73 75 - @group.problems.each do |problem|
74 76 %tr
75 77 %td= problem.name
76 78 %td= problem.full_name
77 79 %td= problem.full_score
78 80 %td= link_to 'Remove', remove_problem_group_path(@group,problem), :method => :delete, :data => { :confirm => "Remove #{problem.full_name}?" }, class: 'btn btn-danger btn-sm'
79 81
80 82
You need to be logged in to leave comments. Login now