Description:
merge
Commit status:
[Not Reviewed]
References:
merge algo
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r836:36fbb20457ec - - 8 files changed: 94 inserted, 60 deleted

@@ -1,112 +1,111
1 1 class SubmissionsController < ApplicationController
2 2 before_action :check_valid_login
3 3 before_action :submission_authorization, only: [:show, :download, :edit]
4 4 before_action :admin_authorization, only: [:rejudge]
5 5
6 6 # GET /submissions
7 7 # GET /submissions.json
8 8 # Show problem selection and user's submission of that problem
9 9 def index
10 10 @user = @current_user
11 11 @problems = @user.available_problems
12 12
13 13 if params[:problem_id]==nil
14 14 @problem = nil
15 15 @submissions = nil
16 16 else
17 17 @problem = Problem.find_by_id(params[:problem_id])
18 18 if (@problem == nil) or (not @problem.available)
19 19 redirect_to list_main_path
20 20 flash[:error] = 'Authorization error: You have no right to view submissions for this problem'
21 21 return
22 22 end
23 23 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id).order(id: :desc)
24 24 end
25 25 end
26 26
27 27 # GET /submissions/1
28 28 # GET /submissions/1.json
29 29 def show
30 30 @submission = Submission.find(params[:id])
31 31
32 32 #log the viewing
33 33 user = User.find(session[:user_id])
34 34 SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin?
35 35
36 36 @task = @submission.task
37 37 end
38 38
39 39 def download
40 40 @submission = Submission.find(params[:id])
41 41 send_data(@submission.source, {:filename => @submission.download_filename, :type => 'text/plain'})
42 42 end
43 43
44 44 def compiler_msg
45 45 @submission = Submission.find(params[:id])
46 46 respond_to do |format|
47 47 format.js
48 48 end
49 49 end
50 50
51 51 #on-site new submission on specific problem
52 52 def direct_edit_problem
53 53 @problem = Problem.find(params[:problem_id])
54 54 unless @current_user.can_view_problem?(@problem)
55 55 unauthorized_redirect
56 56 return
57 57 end
58 58 @source = ''
59 59 if (params[:view_latest])
60 60 sub = Submission.find_last_by_user_and_problem(@current_user.id,@problem.id)
61 61 @source = @submission.source.to_s if @submission and @submission.source
62 62 end
63 63 render 'edit'
64 64 end
65 65
66 66 # GET /submissions/1/edit
67 67 def edit
68 68 @submission = Submission.find(params[:id])
69 69 @source = @submission.source.to_s
70 70 @problem = @submission.problem
71 71 @lang_id = @submission.language.id
72 72 end
73 73
74 74
75 75 def get_latest_submission_status
76 76 @problem = Problem.find(params[:pid])
77 77 @submission = Submission.find_last_by_user_and_problem(params[:uid],params[:pid])
78 78 respond_to do |format|
79 79 format.js
80 80 end
81 81 end
82 82
83 83 # GET /submissions/:id/rejudge
84 84 def rejudge
85 85 @submission = Submission.find(params[:id])
86 86 @task = @submission.task
87 87 @task.status_inqueue! if @task
88 88 respond_to do |format|
89 89 format.js
90 90 end
91 91 end
92 92
93 93 protected
94 94
95 95 def submission_authorization
96 96 #admin always has privileged
97 - if @current_user.admin?
98 - return true
99 - end
97 + return true if @current_user.admin?
98 + return true if @current_user.has_role?('TA') && (['show','download'].include? action_name)
100 99
101 100 sub = Submission.find(params[:id])
102 101 if @current_user.available_problems.include? sub.problem
103 102 return true if GraderConfiguration["right.user_view_submission"] or sub.user == @current_user
104 103 end
105 104
106 105 #default to NO
107 106 unauthorized_redirect
108 107 return false
109 108 end
110 109
111 110
112 111 end
@@ -166,414 +166,411
166 166 if params[:commit] == 'download csv'
167 167 @problems = Problem.all
168 168 else
169 169 @problems = Problem.available_problems
170 170 end
171 171 @users = User.includes(:contests, :contest_stat).where(enabled: true)
172 172 @scorearray = Array.new
173 173 @users.each do |u|
174 174 ustat = Array.new
175 175 ustat[0] = u
176 176 @problems.each do |p|
177 177 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
178 178 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
179 179 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
180 180 else
181 181 ustat << [0,false]
182 182 end
183 183 end
184 184 @scorearray << ustat
185 185 end
186 186 if params[:commit] == 'download csv' then
187 187 csv = gen_csv_from_scorearray(@scorearray,@problems)
188 188 send_data csv, filename: 'last_score.csv'
189 189 else
190 190 render template: 'user_admin/user_stat'
191 191 end
192 192 end
193 193
194 194 def user_stat_max
195 195 if params[:commit] == 'download csv'
196 196 @problems = Problem.all
197 197 else
198 198 @problems = Problem.available_problems
199 199 end
200 200 @users = User.includes(:contests).includes(:contest_stat).all
201 201 @scorearray = Array.new
202 202 #set up range from param
203 203 since_id = params.fetch(:since_id, 0).to_i
204 204 until_id = params.fetch(:until_id, 0).to_i
205 205 @users.each do |u|
206 206 ustat = Array.new
207 207 ustat[0] = u
208 208 @problems.each do |p|
209 209 max_points = 0
210 210 Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub|
211 211 max_points = sub.points if sub and sub.points and (sub.points > max_points)
212 212 end
213 213 ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)]
214 214 end
215 215 @scorearray << ustat
216 216 end
217 217
218 218 if params[:commit] == 'download csv' then
219 219 csv = gen_csv_from_scorearray(@scorearray,@problems)
220 220 send_data csv, filename: 'max_score.csv'
221 221 else
222 222 render template: 'user_admin/user_stat'
223 223 end
224 224 end
225 225
226 226 def import
227 227 if params[:file]==''
228 228 flash[:notice] = 'Error importing no file'
229 229 redirect_to :action => 'index' and return
230 230 end
231 231 import_from_file(params[:file])
232 232 end
233 233
234 234 def random_all_passwords
235 235 users = User.all
236 236 @prefix = params[:prefix] || ''
237 237 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
238 238 @changed = false
239 239 if params[:commit] == 'Go ahead'
240 240 @non_admin_users.each do |user|
241 241 password = random_password
242 242 user.password = password
243 243 user.password_confirmation = password
244 244 user.save
245 245 end
246 246 @changed = true
247 247 end
248 248 end
249 249
250 250 # contest management
251 251
252 252 def contests
253 253 @contest, @users = find_contest_and_user_from_contest_id(params[:id])
254 254 @contests = Contest.enabled
255 255 end
256 256
257 257 def assign_from_list
258 258 contest_id = params[:users_contest_id]
259 259 org_contest, users = find_contest_and_user_from_contest_id(contest_id)
260 260 contest = Contest.find(params[:new_contest][:id])
261 261 if !contest
262 262 flash[:notice] = 'Error: no contest'
263 263 redirect_to :action => 'contests', :id =>contest_id
264 264 end
265 265
266 266 note = []
267 267 users.each do |u|
268 268 u.contests = [contest]
269 269 note << u.login
270 270 end
271 271 flash[:notice] = 'User(s) ' + note.join(', ') +
272 272 " were successfully reassigned to #{contest.title}."
273 273 redirect_to :action => 'contests', :id =>contest.id
274 274 end
275 275
276 276 def add_to_contest
277 277 user = User.find(params[:id])
278 278 contest = Contest.find(params[:contest_id])
279 279 if user and contest
280 280 user.contests << contest
281 281 end
282 282 redirect_to :action => 'index'
283 283 end
284 284
285 285 def remove_from_contest
286 286 user = User.find(params[:id])
287 287 contest = Contest.find(params[:contest_id])
288 288 if user and contest
289 289 user.contests.delete(contest)
290 290 end
291 291 redirect_to :action => 'index'
292 292 end
293 293
294 294 def contest_management
295 295 end
296 296
297 297 def manage_contest
298 298 contest = Contest.find(params[:contest][:id])
299 299 if !contest
300 300 flash[:notice] = 'You did not choose the contest.'
301 301 redirect_to :action => 'contest_management' and return
302 302 end
303 303
304 304 operation = params[:operation]
305 305
306 306 if not ['add','remove','assign'].include? operation
307 307 flash[:notice] = 'You did not choose the operation to perform.'
308 308 redirect_to :action => 'contest_management' and return
309 309 end
310 310
311 311 lines = params[:login_list]
312 312 if !lines or lines.blank?
313 313 flash[:notice] = 'You entered an empty list.'
314 314 redirect_to :action => 'contest_management' and return
315 315 end
316 316
317 317 note = []
318 318 users = []
319 319 lines.split("\n").each do |line|
320 320 user = User.find_by_login(line.chomp)
321 321 if user
322 322 if operation=='add'
323 323 if ! user.contests.include? contest
324 324 user.contests << contest
325 325 end
326 326 elsif operation=='remove'
327 327 user.contests.delete(contest)
328 328 else
329 329 user.contests = [contest]
330 330 end
331 331
332 332 if params[:reset_timer]
333 333 user.contest_stat.forced_logout = true
334 334 user.contest_stat.reset_timer_and_save
335 335 end
336 336
337 337 if params[:notification_emails]
338 338 send_contest_update_notification_email(user, contest)
339 339 end
340 340
341 341 note << user.login
342 342 users << user
343 343 end
344 344 end
345 345
346 346 if params[:reset_timer]
347 347 logout_users(users)
348 348 end
349 349
350 350 flash[:notice] = 'User(s) ' + note.join(', ') +
351 351 ' were successfully modified. '
352 352 redirect_to :action => 'contest_management'
353 353 end
354 354
355 355 # admin management
356 356
357 357 def admin
358 - @admins = User.all.find_all {|user| user.admin? }
358 + @admins = Role.where(name: 'admin').take.users
359 + @tas = Role.where(name: 'ta').take.users
359 360 end
360 361
361 - def grant_admin
362 - login = params[:login]
363 - user = User.find_by_login(login)
364 - if user!=nil
365 - admin_role = Role.find_by_name('admin')
366 - user.roles << admin_role
367 - else
368 - flash[:notice] = 'Unknown user'
369 - end
370 - flash[:notice] = 'User added as admins'
371 - redirect_to :action => 'admin'
362 + def modify_role
363 + user = User.find_by_login(params[:login])
364 + role = Role.find_by_name(params[:role])
365 + unless user && role
366 + flash[:error] = 'Unknown user or role'
367 + redirect_to admin_user_admin_index_path
368 + return
372 369 end
373 -
374 - def revoke_admin
375 - user = User.find(params[:id])
376 - if user==nil
377 - flash[:notice] = 'Unknown user'
378 - redirect_to :action => 'admin' and return
379 - elsif user.login == 'root'
380 - flash[:notice] = 'You cannot revoke admisnistrator permission from root.'
381 - redirect_to :action => 'admin' and return
370 + if params[:commit] == 'Grant'
371 + #grant role
372 + user.roles << role
373 + flash[:notice] = "User '#{user.login}' has been granted the role '#{role.name}'"
374 + else
375 + #revoke role
376 + if user.login == 'root' && role.name == 'admin'
377 + flash[:error] = 'You cannot revoke admisnistrator permission from root.'
378 + redirect_to admin_user_admin_index_path
379 + return
382 380 end
383 -
384 - admin_role = Role.find_by_name('admin')
385 - user.roles.delete(admin_role)
386 - flash[:notice] = 'User permission revoked'
387 - redirect_to :action => 'admin'
381 + user.roles.delete(role)
382 + flash[:notice] = "The role '#{role.name}' has been revoked from User '#{user.login}'"
383 + end
384 + redirect_to admin_user_admin_index_path
388 385 end
389 386
390 387 # mass mailing
391 388
392 389 def mass_mailing
393 390 end
394 391
395 392 def bulk_mail
396 393 lines = params[:login_list]
397 394 if !lines or lines.blank?
398 395 flash[:notice] = 'You entered an empty list.'
399 396 redirect_to :action => 'mass_mailing' and return
400 397 end
401 398
402 399 mail_subject = params[:subject]
403 400 if !mail_subject or mail_subject.blank?
404 401 flash[:notice] = 'You entered an empty mail subject.'
405 402 redirect_to :action => 'mass_mailing' and return
406 403 end
407 404
408 405 mail_body = params[:email_body]
409 406 if !mail_body or mail_body.blank?
410 407 flash[:notice] = 'You entered an empty mail body.'
411 408 redirect_to :action => 'mass_mailing' and return
412 409 end
413 410
414 411 note = []
415 412 users = []
416 413 lines.split("\n").each do |line|
417 414 user = User.find_by_login(line.chomp)
418 415 if user
419 416 send_mail(user.email, mail_subject, mail_body)
420 417 note << user.login
421 418 end
422 419 end
423 420
424 421 flash[:notice] = 'User(s) ' + note.join(', ') +
425 422 ' were successfully modified. '
426 423 redirect_to :action => 'mass_mailing'
427 424 end
428 425
429 426 #bulk manage
430 427 def bulk_manage
431 428
432 429 begin
433 430 @users = User.where('(login REGEXP ?) OR (remark REGEXP ?)',params[:regex],params[:regex]) if params[:regex]
434 431 @users.count if @users #i don't know why I have to call count, but if I won't exception is not raised
435 432 rescue Exception
436 433 flash[:error] = 'Regular Expression is malformed'
437 434 @users = nil
438 435 end
439 436
440 437 if params[:commit]
441 438 @action = {}
442 439 @action[:set_enable] = params[:enabled]
443 440 @action[:enabled] = params[:enable] == "1"
444 441 @action[:gen_password] = params[:gen_password]
445 442 @action[:add_group] = params[:add_group]
446 443 @action[:group_name] = params[:group_name]
447 444 end
448 445
449 446 if params[:commit] == "Perform"
450 447 if @action[:set_enable]
451 448 @users.update_all(enabled: @action[:enabled])
452 449 end
453 450 if @action[:gen_password]
454 451 @users.each do |u|
455 452 password = random_password
456 453 u.password = password
457 454 u.password_confirmation = password
458 455 u.save
459 456 end
460 457 end
461 458 if @action[:add_group] and @action[:group_name]
462 459 @group = Group.find(@action[:group_name])
463 460 ok = []
464 461 failed = []
465 462 @users.each do |user|
466 463 begin
467 464 @group.users << user
468 465 ok << user.login
469 466 rescue => e
470 467 failed << user.login
471 468 end
472 469 end
473 470 flash[:success] = "The following users are added to the 'group #{@group.name}': " + ok.join(', ') if ok.count > 0
474 471 flash[:alert] = "The following users are already in the 'group #{@group.name}': " + failed.join(', ') if failed.count > 0
475 472 end
476 473 end
477 474 end
478 475
479 476 protected
480 477
481 478 def random_password(length=5)
482 479 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
483 480 newpass = ""
484 481 length.times { newpass << chars[rand(chars.size-1)] }
485 482 return newpass
486 483 end
487 484
488 485 def import_from_file(f)
489 486 data_hash = YAML.load(f)
490 487 @import_log = ""
491 488
492 489 country_data = data_hash[:countries]
493 490 site_data = data_hash[:sites]
494 491 user_data = data_hash[:users]
495 492
496 493 # import country
497 494 countries = {}
498 495 country_data.each_pair do |id,country|
499 496 c = Country.find_by_name(country[:name])
500 497 if c!=nil
501 498 countries[id] = c
502 499 @import_log << "Found #{country[:name]}\n"
503 500 else
504 501 countries[id] = Country.new(:name => country[:name])
505 502 countries[id].save
506 503 @import_log << "Created #{country[:name]}\n"
507 504 end
508 505 end
509 506
510 507 # import sites
511 508 sites = {}
512 509 site_data.each_pair do |id,site|
513 510 s = Site.find_by_name(site[:name])
514 511 if s!=nil
515 512 @import_log << "Found #{site[:name]}\n"
516 513 else
517 514 s = Site.new(:name => site[:name])
518 515 @import_log << "Created #{site[:name]}\n"
519 516 end
520 517 s.password = site[:password]
521 518 s.country = countries[site[:country_id]]
522 519 s.save
523 520 sites[id] = s
524 521 end
525 522
526 523 # import users
527 524 user_data.each_pair do |id,user|
528 525 u = User.find_by_login(user[:login])
529 526 if u!=nil
530 527 @import_log << "Found #{user[:login]}\n"
531 528 else
532 529 u = User.new(:login => user[:login])
533 530 @import_log << "Created #{user[:login]}\n"
534 531 end
535 532 u.full_name = user[:name]
536 533 u.password = user[:password]
537 534 u.country = countries[user[:country_id]]
538 535 u.site = sites[user[:site_id]]
539 536 u.activated = true
540 537 u.email = "empty-#{u.login}@none.com"
541 538 if not u.save
542 539 @import_log << "Errors\n"
543 540 u.errors.each { |attr,msg| @import_log << "#{attr} - #{msg}\n" }
544 541 end
545 542 end
546 543
547 544 end
548 545
549 546 def logout_users(users)
550 547 users.each do |user|
551 548 contest_stat = user.contest_stat(true)
552 549 if contest_stat and !contest_stat.forced_logout
553 550 contest_stat.forced_logout = true
554 551 contest_stat.save
555 552 end
556 553 end
557 554 end
558 555
559 556 def send_contest_update_notification_email(user, contest)
560 557 contest_title_name = GraderConfiguration['contest.name']
561 558 contest_name = contest.name
562 559 mail_subject = t('contest.notification.email_subject', {
563 560 :contest_title_name => contest_title_name,
564 561 :contest_name => contest_name })
565 562 mail_body = t('contest.notification.email_body', {
566 563 :full_name => user.full_name,
567 564 :contest_title_name => contest_title_name,
568 565 :contest_name => contest.name,
569 566 })
570 567
571 568 logger.info mail_body
572 569 send_mail(user.email, mail_subject, mail_body)
573 570 end
574 571
575 572 def find_contest_and_user_from_contest_id(id)
576 573 if id!='none'
577 574 @contest = Contest.find(id)
578 575 else
579 576 @contest = nil
@@ -1,319 +1,323
1 1 require 'digest/sha1'
2 2 require 'net/pop'
3 3 require 'net/https'
4 4 require 'net/http'
5 5 require 'json'
6 6
7 7 class User < ActiveRecord::Base
8 8
9 9 has_and_belongs_to_many :roles
10 10
11 11 #has_and_belongs_to_many :groups
12 12 has_many :groups_users, class_name: 'GroupUser'
13 13 has_many :groups, :through => :groups_users
14 14
15 15 has_many :test_requests, -> {order(submitted_at: :desc)}
16 16
17 17 has_many :messages, -> { order(created_at: :desc) },
18 18 :class_name => "Message",
19 19 :foreign_key => "sender_id"
20 20
21 21 has_many :replied_messages, -> { order(created_at: :desc) },
22 22 :class_name => "Message",
23 23 :foreign_key => "receiver_id"
24 24
25 25 has_many :logins
26 26
27 27 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
28 28
29 29 belongs_to :site
30 30 belongs_to :country
31 31
32 32 has_and_belongs_to_many :contests, -> { order(:name)}
33 33
34 34 scope :activated_users, -> {where activated: true}
35 35
36 36 validates_presence_of :login
37 37 validates_uniqueness_of :login
38 38 validates_format_of :login, :with => /\A[\_A-Za-z0-9]+\z/
39 39 validates_length_of :login, :within => 3..30
40 40
41 41 validates_presence_of :full_name
42 42 validates_length_of :full_name, :minimum => 1
43 43
44 44 validates_presence_of :password, :if => :password_required?
45 45 validates_length_of :password, :within => 4..50, :if => :password_required?
46 46 validates_confirmation_of :password, :if => :password_required?
47 47
48 48 validates_format_of :email,
49 49 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
50 50 :if => :email_validation?
51 51 validate :uniqueness_of_email_from_activated_users,
52 52 :if => :email_validation?
53 53 validate :enough_time_interval_between_same_email_registrations,
54 54 :if => :email_validation?
55 55
56 56 # these are for ytopc
57 57 # disable for now
58 58 #validates_presence_of :province
59 59
60 60 attr_accessor :password
61 61
62 62 before_save :encrypt_new_password
63 63 before_save :assign_default_site
64 64 before_save :assign_default_contest
65 65
66 66 # this is for will_paginate
67 67 cattr_reader :per_page
68 68 @@per_page = 50
69 69
70 70 def self.authenticate(login, password)
71 71 user = find_by_login(login)
72 72 if user
73 73 return user if user.authenticated?(password)
74 74 if user.authenticated_by_cucas?(password)
75 75 user.password = password
76 76 user.save
77 77 return user
78 78 end
79 79 end
80 80 end
81 81
82 82
83 83 def authenticated?(password)
84 84 if self.activated
85 85 hashed_password == User.encrypt(password,self.salt)
86 86 else
87 87 false
88 88 end
89 89 end
90 90
91 91 def authenticated_by_cucas?(password)
92 92 url = URI.parse('https://www.cas.chula.ac.th/cas/api/?q=studentAuthenticate')
93 93 appid = '41508763e340d5858c00f8c1a0f5a2bb'
94 94 appsecret ='d9cbb5863091dbe186fded85722a1e31'
95 95 post_args = {
96 96 'appid' => appid,
97 97 'appsecret' => appsecret,
98 98 'username' => login,
99 99 'password' => password
100 100 }
101 101
102 102 #simple call
103 103 begin
104 104 http = Net::HTTP.new('www.cas.chula.ac.th', 443)
105 105 http.use_ssl = true
106 106 http.verify_mode = OpenSSL::SSL::VERIFY_NONE
107 107 result = [ ]
108 108 http.start do |http|
109 109 req = Net::HTTP::Post.new('/cas/api/?q=studentAuthenticate')
110 110 #req = Net::HTTP::Post.new('/appX/prod/?q=studentAuthenticate')
111 111 #req = Net::HTTP::Post.new('/app2/prod/api/?q=studentAuthenticate')
112 112 param = "appid=#{appid}&appsecret=#{appsecret}&username=#{login}&password=#{password}"
113 113 resp = http.request(req,param)
114 114 result = JSON.parse resp.body
115 115 puts result
116 116 end
117 117 return true if result["type"] == "beanStudent"
118 118 rescue => e
119 119 puts e
120 120 puts e.message
121 121 return false
122 122 end
123 123 return false
124 124 end
125 125
126 126 def admin?
127 - self.roles.where(name: 'admin').count > 0
127 + has_role?('admin')
128 + end
129 +
130 + def has_role?(role)
131 + self.roles.where(name: role).count > 0
128 132 end
129 133
130 134 def email_for_editing
131 135 if self.email==nil
132 136 "(unknown)"
133 137 elsif self.email==''
134 138 "(blank)"
135 139 else
136 140 self.email
137 141 end
138 142 end
139 143
140 144 def email_for_editing=(e)
141 145 self.email=e
142 146 end
143 147
144 148 def alias_for_editing
145 149 if self.alias==nil
146 150 "(unknown)"
147 151 elsif self.alias==''
148 152 "(blank)"
149 153 else
150 154 self.alias
151 155 end
152 156 end
153 157
154 158 def alias_for_editing=(e)
155 159 self.alias=e
156 160 end
157 161
158 162 def activation_key
159 163 if self.hashed_password==nil
160 164 encrypt_new_password
161 165 end
162 166 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
163 167 end
164 168
165 169 def verify_activation_key(key)
166 170 key == activation_key
167 171 end
168 172
169 173 def self.random_password(length=5)
170 174 chars = 'abcdefghjkmnopqrstuvwxyz'
171 175 password = ''
172 176 length.times { password << chars[rand(chars.length - 1)] }
173 177 password
174 178 end
175 179
176 180 def self.find_non_admin_with_prefix(prefix='')
177 181 users = User.all
178 182 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
179 183 end
180 184
181 185 # Contest information
182 186
183 187 def self.find_users_with_no_contest()
184 188 users = User.all
185 189 return users.find_all { |u| u.contests.length == 0 }
186 190 end
187 191
188 192
189 193 def contest_time_left
190 194 if GraderConfiguration.contest_mode?
191 195 return nil if site==nil
192 196 return site.time_left
193 197 elsif GraderConfiguration.indv_contest_mode?
194 198 time_limit = GraderConfiguration.contest_time_limit
195 199 if time_limit == nil
196 200 return nil
197 201 end
198 202 if contest_stat==nil or contest_stat.started_at==nil
199 203 return (Time.now.gmtime + time_limit) - Time.now.gmtime
200 204 else
201 205 finish_time = contest_stat.started_at + time_limit
202 206 current_time = Time.now.gmtime
203 207 if current_time > finish_time
204 208 return 0
205 209 else
206 210 return finish_time - current_time
207 211 end
208 212 end
209 213 else
210 214 return nil
211 215 end
212 216 end
213 217
214 218 def contest_finished?
215 219 if GraderConfiguration.contest_mode?
216 220 return false if site==nil
217 221 return site.finished?
218 222 elsif GraderConfiguration.indv_contest_mode?
219 223 return false if self.contest_stat==nil
220 224 return contest_time_left == 0
221 225 else
222 226 return false
223 227 end
224 228 end
225 229
226 230 def contest_started?
227 231 if GraderConfiguration.indv_contest_mode?
228 232 stat = self.contest_stat
229 233 return ((stat != nil) and (stat.started_at != nil))
230 234 elsif GraderConfiguration.contest_mode?
231 235 return true if site==nil
232 236 return site.started
233 237 else
234 238 return true
235 239 end
236 240 end
237 241
238 242 def update_start_time
239 243 stat = self.contest_stat
240 244 if stat.nil? or stat.started_at.nil?
241 245 stat ||= UserContestStat.new(:user => self)
242 246 stat.started_at = Time.now.gmtime
243 247 stat.save
244 248 end
245 249 end
246 250
247 251 def problem_in_user_contests?(problem)
248 252 problem_contests = problem.contests.all
249 253
250 254 if problem_contests.length == 0 # this is public contest
251 255 return true
252 256 end
253 257
254 258 contests.each do |contest|
255 259 if problem_contests.find {|c| c.id == contest.id }
256 260 return true
257 261 end
258 262 end
259 263 return false
260 264 end
261 265
262 266 def available_problems_group_by_contests
263 267 contest_problems = []
264 268 pin = {}
265 269 contests.enabled.each do |contest|
266 270 available_problems = contest.problems.available
267 271 contest_problems << {
268 272 :contest => contest,
269 273 :problems => available_problems
270 274 }
271 275 available_problems.each {|p| pin[p.id] = true}
272 276 end
273 277 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
274 278 contest_problems << {
275 279 :contest => nil,
276 280 :problems => other_avaiable_problems
277 281 }
278 282 return contest_problems
279 283 end
280 284
281 285 def solve_all_available_problems?
282 286 available_problems.each do |p|
283 287 u = self
284 288 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
285 289 return false if !p or !sub or sub.points < p.full_score
286 290 end
287 291 return true
288 292 end
289 293
290 294 #get a list of available problem
291 295 def available_problems
292 296 # first, we check if this is normal mode
293 297 if not GraderConfiguration.multicontests?
294 298
295 299 #if this is a normal mode
296 300 #we show problem based on problem_group, if the config said so
297 301 if GraderConfiguration.use_problem_group?
298 302 return available_problems_in_group
299 303 else
300 304 return Problem.available_problems
301 305 end
302 306 else
303 307 #this is multi contest mode
304 308 contest_problems = []
305 309 pin = {}
306 310 contests.enabled.each do |contest|
307 311 contest.problems.available.each do |problem|
308 312 if not pin.has_key? problem.id
309 313 contest_problems << problem
310 314 end
311 315 pin[problem.id] = true
312 316 end
313 317 end
314 318 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
315 319 return contest_problems + other_avaiable_problems
316 320 end
317 321 end
318 322
319 323 # new feature, get list of available problem in all enabled group that the user belongs to
@@ -1,96 +1,96
1 1 %header.navbar.navbar-default.navbar-fixed-top
2 2 %nav
3 3 .container-fluid
4 4 .navbar-header
5 5 %button.navbar-toggle.collapsed{ data: {toggle: 'collapse', target: '#navbar-collapse'} }
6 6 %span.sr-only Togggle Navigation
7 7 %span.icon-bar
8 8 %span.icon-bar
9 9 %span.icon-bar
10 10 %a.navbar-brand{href: list_main_path}
11 11 %span.glyphicon.glyphicon-home
12 12 MAIN
13 13 .collapse.navbar-collapse#navbar-collapse
14 14 %ul.nav.navbar-nav
15 15 / submission
16 16 - if (@current_user!=nil) and (GraderConfiguration.show_tasks_to?(@current_user))
17 17 %li.dropdown
18 18 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
19 19 = "#{I18n.t 'menu.submissions'}"
20 20 %span.caret
21 21 %ul.dropdown-menu
22 22 = add_menu("View", 'submissions', 'index')
23 23 = add_menu("Self Test", 'test', 'index')
24 24 / hall of fame
25 25 - if GraderConfiguration['right.user_hall_of_fame']
26 26 = add_menu("#{I18n.t 'menu.hall_of_fame'}", 'report', 'problem_hof')
27 27 / display MODE button (with countdown in contest mode)
28 28 - if GraderConfiguration.analysis_mode?
29 29 %div.navbar-btn.btn.btn-success#countdown= "ANALYSIS MODE"
30 30 - elsif GraderConfiguration.time_limit_mode?
31 31 - if @current_user.contest_finished?
32 32 %div.navbar-btn.btn.btn-danger#countdown= "Contest is over"
33 33 - elsif !@current_user.contest_started?
34 34 %div.navbar-btn.btn.btn-primary#countdown= (t 'title_bar.contest_not_started')
35 35 - else
36 36 %div.navbar-btn.btn.btn-primary#countdown asdf
37 37 :javascript
38 38 $("#countdown").countdown({until: "+#{@current_user.contest_time_left.to_i}s", layout: 'Time left: {hnn}:{mnn}:{snn}'});
39 39 / admin section
40 40 - if (@current_user!=nil) and (session[:admin])
41 41 / management
42 42 %li.dropdown
43 43 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
44 44 Manage
45 45 %span.caret
46 46 %ul.dropdown-menu
47 47 = add_menu( 'Announcements', 'announcements', 'index')
48 48 = add_menu( 'Problems', 'problems', 'index')
49 49 = add_menu( 'Tags', 'tags', 'index')
50 50 = add_menu( 'Users', 'user_admin', 'index')
51 51 = add_menu( 'User Groups', 'groups', 'index')
52 52 = add_menu( 'Graders', 'graders', 'list')
53 53 = add_menu( 'Message ', 'messages', 'console')
54 54 %li.divider{role: 'separator'}
55 55 = add_menu( 'System config', 'configurations', 'index')
56 56 %li.divider{role: 'separator'}
57 57 = add_menu( 'Sites', 'sites', 'index')
58 58 = add_menu( 'Contests', 'contest_management', 'index')
59 59 / report
60 60 %li.dropdown
61 61 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
62 62 Report
63 63 %span.caret
64 64 %ul.dropdown-menu
65 65 = add_menu( 'Current Score', 'report', 'current_score')
66 66 = add_menu( 'Score Report', 'report', 'max_score')
67 67 = add_menu( 'Submission Report', 'report', 'submission')
68 68 = add_menu( 'Login Report', 'report', 'login')
69 69 - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
70 70 =link_to "#{ungraded} backlogs!",
71 - grader_list_path,
71 + graders_list_path,
72 72 class: 'navbar-btn btn btn-default btn-warning', data: {toggle: 'tooltip'},title: 'Number of ungraded submission'
73 73
74 74 %ul.nav.navbar-nav.navbar-right
75 75 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-question-sign')}".html_safe, 'main', 'help')
76 76 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-comment')}".html_safe, 'messages', 'index', {title: I18n.t('menu.messages'), data: {toggle: 'tooltip'}})
77 77 - if GraderConfiguration['system.user_setting_enabled']
78 78 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-cog', id: 'user_profile')}".html_safe, 'users', 'profile', {title: I18n.t('menu.settings'), data: {toggle: 'tooltip'}})
79 79 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-log-out')} #{@current_user.full_name}".html_safe, 'main', 'login', {title: I18n.t('menu.log_out'), data: {toggle: 'tooltip'}})
80 80
81 81 /
82 82 - if (@current_user!=nil) and (session[:admin])
83 83 %nav.navbar.navbar-fixed-top.navbar-inverse.secondnavbar
84 84 .container-fluid
85 85 .collapse.navbar-collapse
86 86 %ul.nav.navbar-nav
87 87 = add_menu( '[Announcements]', 'announcements', 'index')
88 88 = add_menu( '[Msg console]', 'messages', 'console')
89 89 = add_menu( '[Problems]', 'problems', 'index')
90 90 = add_menu( '[Users]', 'user_admin', 'index')
91 91 = add_menu( '[Results]', 'user_admin', 'user_stat')
92 92 = add_menu( '[Report]', 'report', 'multiple_login')
93 93 = add_menu( '[Graders]', 'graders', 'list')
94 94 = add_menu( '[Contests]', 'contest_management', 'index')
95 95 = add_menu( '[Sites]', 'sites', 'index')
96 96 = add_menu( '[System config]', 'configurations', 'index')
@@ -1,59 +1,63
1 1 :css
2 2 .fix-width {
3 3 font-family: "Consolas, Monaco, Droid Sans Mono,Mono, Monospace,Courier"
4 4 }
5 5
6 6 %h1 Problem stat: #{@problem.name}
7 7 %h2 Overview
8 8
9 + .row
10 + .col-md-2
11 + %strong Name:
12 + .col-md-10
13 + = @problem.full_name #in_place_editor_field :problem, :full_name, {}, :rows=>1
14 + = link_to_description_if_any "[#{t 'main.problem_desc'}] <span class='glyphicon glyphicon-file'></span>".html_safe, @problem
15 + .row
16 + .col-md-2.strong
17 + %strong Submissions:
18 + .col-md-10
19 + = @submissions.count
20 + .row
21 + .col-md-2.strong
22 + %strong Solved/Attemped User
23 + .col-md-10
24 + #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
9 25
10 - %table.info
11 - %thead
12 - %tr.info-head
13 - %th Stat
14 - %th Value
15 - %tbody
16 - %tr{class: cycle('info-even','info-odd')}
17 - %td Submissions
18 - %td= @submissions.count
19 - %tr{class: cycle('info-even','info-odd')}
20 - %td Solved/Attempted User
21 - %td #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
22 26
23 27 %h2 Submissions Count
24 28 = render partial: 'application/bar_graph', locals: { histogram: @histogram }
25 29
26 30 %h2 Submissions
27 31 - if @submissions and @submissions.count > 0
28 32 %table#main_table.table.table-condensed.table-striped
29 33 %thead
30 34 %tr
31 35 %th ID
32 36 %th Login
33 37 %th Name
34 38 %th Submitted_at
35 39 %th language
36 40 %th Points
37 41 %th comment
38 42 %th IP
39 43 %tbody
40 44 - row_odd,curr = true,''
41 45 - @submissions.each do |sub|
42 46 - next unless sub.user
43 47 - row_odd,curr = !row_odd, sub.user if curr != sub.user
44 48 %tr
45 49 %td= link_to sub.id, submission_path(sub)
46 50 %td= link_to sub.user.login, stat_user_path(sub.user)
47 51 %td= sub.user.full_name
48 52 %td{data: {order: sub.submitted_at}}= time_ago_in_words(sub.submitted_at) + " ago"
49 53 %td= sub.language.name
50 54 %td= sub.points
51 55 %td.fix-width= sub.grader_comment
52 56 %td= sub.ip_address
53 57 - else
54 58 No submission
55 59
56 60 :javascript
57 61 $("#main_table").DataTable({
58 62 paging: false
59 63 });
@@ -1,25 +1,54
1 - %h1 Administrators
2 -
3 - %table{:class => 'info'}
4 - %tr{:class => 'info-head'}
1 + %h1 Modify Role
2 + .row
3 + .col-md-6
4 + %h4 Administrators
5 + = form_tag modify_role_user_admin_index_path, method: 'post', class: 'form-inline' do
6 + = hidden_field_tag :role, 'admin'
7 + .form-group
8 + = label_tag :login, 'Grant admin role to:'
9 + = text_field_tag 'login',nil, class: 'form-control'
10 + .form-group
11 + = submit_tag 'Grant', class: 'btn btn-primary'
12 + %br
13 + %table.table.table-condense.table-hover.table-striped.table-bordered
14 + %thead{:class => 'info-head'}
5 15 %th #
6 16 %th Login
7 17 %th Full name
8 18 %th
9 19 - @admins.each_with_index do |user, i|
10 20 %tr
11 21 %td= i+1
12 22 %td= user.login
13 23 %td= user.full_name
14 24 %td
15 25 - if user.login!='root'
16 - = link_to '[revoke]', :action => 'revoke_admin', :id => user.id
17 - %hr
26 + = link_to '[revoke]', modify_role_user_admin_index_path( login: user.login, role: 'admin', commit: 'revoke')
27 + .col-md-6
28 + %h4 Teacher Assistants (TA)
29 + = form_tag modify_role_user_admin_index_path, method: 'post', class: 'form-inline' do
30 + = hidden_field_tag :role, 'TA'
31 + .form-group
32 + = label_tag :login, 'Grant TA role to:'
33 + = text_field_tag 'login',nil, class: 'form-control'
34 + .form-group
35 + = submit_tag 'Grant', class: 'btn btn-primary'
36 + %br
37 + %table.table.table-condense.table-hover.table-striped.table-bordered
38 + %thead{:class => 'info-head'}
39 + %th #
40 + %th Login
41 + %th Full name
42 + %th
43 + - @tas.each_with_index do |user, i|
44 + %tr
45 + %td= i+1
46 + %td= user.login
47 + %td= user.full_name
48 + %td
49 + - if user.login!='root'
50 + = link_to '[revoke]', modify_role_user_admin_index_path( login: user.login, role: 'TA', commit: 'revoke')
18 51
19 - = form_tag :action => 'grant_admin' do
20 - = label_tag :login, 'Grant admin permission to:'
21 - = text_field_tag 'login',nil, class: 'input-field'
22 - = submit_tag 'Grant', class: 'btn btn-primary'
23 52
24 53 %hr/
25 54 = link_to '[go back to index]', :action => 'index'
@@ -1,211 +1,211
1 1 Rails.application.routes.draw do
2 2 resources :tags
3 3 get "sources/direct_edit"
4 4
5 5 root :to => 'main#login'
6 6
7 7 #logins
8 8 match 'login/login', to: 'login#login', via: [:get,:post]
9 9
10 10 resources :contests
11 11 resources :sites
12 12 resources :test
13 13
14 14 resources :messages do
15 15 member do
16 16 get 'hide'
17 17 post 'reply'
18 18 end
19 19 collection do
20 20 get 'console'
21 21 get 'list_all'
22 22 end
23 23 end
24 24
25 25 resources :announcements do
26 26 member do
27 27 get 'toggle','toggle_front'
28 28 end
29 29 end
30 30
31 31 resources :problems do
32 32 member do
33 33 get 'toggle'
34 34 get 'toggle_test'
35 35 get 'toggle_view_testcase'
36 36 get 'stat'
37 37 end
38 38 collection do
39 39 get 'turn_all_off'
40 40 get 'turn_all_on'
41 41 get 'import'
42 42 get 'manage'
43 43 get 'quick_create'
44 44 post 'do_manage'
45 45 post 'do_import'
46 46 end
47 47 end
48 48
49 49 resources :groups do
50 50 member do
51 51 post 'add_user', to: 'groups#add_user', as: 'add_user'
52 52 delete 'remove_user/:user_id', to: 'groups#remove_user', as: 'remove_user'
53 53 delete 'remove_all_user', to: 'groups#remove_all_user', as: 'remove_all_user'
54 54 post 'add_problem', to: 'groups#add_problem', as: 'add_problem'
55 55 delete 'remove_problem/:problem_id', to: 'groups#remove_problem', as: 'remove_problem'
56 56 delete 'remove_all_problem', to: 'groups#remove_all_problem', as: 'remove_all_problem'
57 57 get 'toggle'
58 58 end
59 59 collection do
60 60
61 61 end
62 62 end
63 63
64 64 resources :testcases, only: [] do
65 65 member do
66 66 get 'download_input'
67 67 get 'download_sol'
68 68 end
69 69 collection do
70 70 get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem'
71 71 end
72 72 end
73 73
74 74 resources :grader_configuration, controller: 'configurations' do
75 75 collection do
76 76 get 'set_exam_right(/:value)', action: 'set_exam_right', as: 'set_exam_right'
77 77 end
78 78 end
79 79
80 80 resources :users do
81 81 member do
82 82 get 'toggle_activate', 'toggle_enable'
83 83 get 'stat'
84 84 end
85 85 collection do
86 86 get 'profile'
87 87 post 'chg_passwd'
88 88 end
89 89 end
90 90
91 91 resources :submissions do
92 92 member do
93 93 get 'download'
94 94 get 'compiler_msg'
95 95 get 'rejudge'
96 96 end
97 97 collection do
98 98 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
99 99 get 'direct_edit_problem/:problem_id(/:user_id)', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
100 100 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
101 101 end
102 102 end
103 103
104 104
105 105 #user admin
106 106 resources :user_admin do
107 107 collection do
108 108 match 'bulk_manage', via: [:get, :post]
109 109 get 'bulk_mail'
110 110 get 'user_stat'
111 111 get 'import'
112 112 get 'new_list'
113 113 get 'admin'
114 114 get 'active'
115 115 get 'mass_mailing'
116 - get 'revoke_admin'
117 - post 'grant_admin'
116 + match 'modify_role', via: [:get, :post]
118 117 match 'create_from_list', via: [:get, :post]
119 118 match 'random_all_passwords', via: [:get, :post]
120 119 end
121 120 member do
122 121 get 'clear_last_ip'
123 122 end
124 123 end
125 124
126 125 resources :contest_management, only: [:index] do
127 126 collection do
128 127 get 'user_stat'
129 128 get 'clear_stat'
130 129 get 'clear_all_stat'
131 130 get 'change_contest_mode'
132 131 end
133 132 end
134 133
135 134 #get 'user_admin', to: 'user_admin#index'
136 135 #get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin'
137 136 #post 'user_admin', to: 'user_admin#create'
138 137 #delete 'user_admin/:id', to: 'user_admin#destroy', as: 'user_admin_destroy'
139 138
140 139 #singular resource
141 140 #---- BEWARE ---- singular resource maps to plural controller by default, we can override by provide controller name directly
142 141 #report
143 142 resource :report, only: [], controller: 'report' do
144 143 get 'login'
145 144 get 'multiple_login'
146 145 get 'problem_hof(/:id)', action: 'problem_hof', as: 'problem_hof'
147 146 get 'current_score(/:group_id)', action: 'current_score', as: 'current_score'
148 147 get 'max_score'
149 148 post 'show_max_score'
150 149 get 'stuck'
151 150 get 'cheat_report'
152 151 post 'cheat_report'
153 152 get 'cheat_scrutinize'
154 153 post 'cheat_scrutinize'
155 154 get 'submission'
156 155 post 'submission_query'
157 156 get 'login_stat'
158 157 post 'login_stat'
159 158 get 'login'
160 159 post 'login_summary_query'
161 160 post 'login_detail_query'
162 161 end
163 162 #get 'report/current_score', to: 'report#current_score', as: 'report_current_score'
164 163 #get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
165 164 #get "report/login"
166 165 #get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
167 166 #post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score'
168 167
169 168 resource :main, only: [], controller: 'main' do
170 169 get 'login'
171 170 get 'logout'
172 171 get 'list'
173 172 get 'submission(/:id)', action: 'submission', as: 'main_submission'
174 173 get 'announcements'
175 174 get 'help'
176 175 post 'submit'
177 176 end
178 177 #main
179 178 #get "main/list"
180 179 #get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
181 180 #post 'main/submit', to: 'main#submit'
182 181 #get 'main/announcements', to: 'main#announcements'
183 182
184 183
185 184 #
186 185 get 'tasks/view/:file.:ext' => 'tasks#view'
187 186 get 'tasks/download/:id/:file.:ext' => 'tasks#download', as: 'download_task'
188 187 get 'heartbeat/:id/edit' => 'heartbeat#edit'
189 188
190 189 #grader
191 - get 'graders/list', to: 'graders#list', as: 'grader_list'
190 + #get 'graders/list', to: 'graders#list', as: 'grader_list'
192 191 namespace :graders do
193 192 get 'task/:id/:type', action: 'task', as: 'task'
194 193 get 'view/:id/:type', action: 'view', as: 'view'
195 194 get 'clear/:id', action: 'clear', as: 'clear'
196 - get 'stop'
197 - get 'stop_all'
198 - get 'clear_all'
199 - get 'clear_terminated'
200 195 get 'start_grading'
201 196 get 'start_exam'
197 + get 'clear_all'
198 + get 'stop_all'
202 199
200 + get 'stop'
201 + get 'clear_terminated'
202 + get 'list'
203 203 end
204 204
205 205
206 206 # See how all your routes lay out with "rake routes"
207 207
208 208 # This is a legacy wild controller route that's not recommended for RESTful applications.
209 209 # Note: This route will make all actions in every controller accessible via GET requests.
210 210 # match ':controller(/:action(/:id))(.:format)', via: [:get, :post]
211 211 end
@@ -36,253 +36,254
36 36 :key => 'system.mode',
37 37 :value_type => 'string',
38 38 :default_value => 'standard',
39 39 :description => 'Current modes are "standard", "contest", "indv-contest", and "analysis".'
40 40 },
41 41
42 42 {
43 43 :key => 'contest.name',
44 44 :value_type => 'string',
45 45 :default_value => 'Grader',
46 46 :description => 'This name will be shown on the user header bar.'
47 47 },
48 48
49 49 {
50 50 :key => 'contest.multisites',
51 51 :value_type => 'boolean',
52 52 :default_value => 'false',
53 53 :description => 'If the server is in contest mode and this option is true, on the log in of the admin a menu for site selections is shown.'
54 54 },
55 55
56 56 #---------------------------- right --------------------------------
57 57 {
58 58 :key => 'right.user_hall_of_fame',
59 59 :value_type => 'boolean',
60 60 :default_value => 'false',
61 61 :description => 'If true, any user can access hall of fame page.'
62 62 },
63 63
64 64 {
65 65 :key => 'right.multiple_ip_login',
66 66 :value_type => 'boolean',
67 67 :default_value => 'true',
68 68 :description => 'When change from true to false, a user can login from the first IP they logged into afterward.'
69 69 },
70 70
71 71 {
72 72 :key => 'right.user_view_submission',
73 73 :value_type => 'boolean',
74 74 :default_value => 'false',
75 75 :description => 'If true, any user can view submissions of every one.'
76 76 },
77 77
78 78 {
79 79 :key => 'right.bypass_agreement',
80 80 :value_type => 'boolean',
81 81 :default_value => 'true',
82 82 :description => 'When false, a user must accept usage agreement before login'
83 83 },
84 84
85 85 {
86 86 :key => 'right.heartbeat_response',
87 87 :value_type => 'string',
88 88 :default_value => 'OK',
89 89 :description => 'Heart beat response text'
90 90 },
91 91
92 92 {
93 93 :key => 'right.heartbeat_response_full',
94 94 :value_type => 'string',
95 95 :default_value => 'OK',
96 96 :description => 'Heart beat response text when user got full score (set this value to the empty string to disable this feature)'
97 97 },
98 98
99 99 {
100 100 :key => 'right.view_testcase',
101 101 :value_type => 'boolean',
102 102 :default_value => 'false',
103 103 :description => 'If true, any user can view/download test data'
104 104 },
105 105
106 106 {
107 107 :key => 'system.online_registration',
108 108 :value_type => 'boolean',
109 109 :default_value => 'false',
110 110 :description => 'This option enables online registration.'
111 111 },
112 112
113 113 # If Configuration['system.online_registration'] is true, the
114 114 # system allows online registration, and will use these
115 115 # information for sending confirmation emails.
116 116 {
117 117 :key => 'system.online_registration.smtp',
118 118 :value_type => 'string',
119 119 :default_value => 'smtp.somehost.com'
120 120 },
121 121
122 122 {
123 123 :key => 'system.online_registration.from',
124 124 :value_type => 'string',
125 125 :default_value => 'your.email@address'
126 126 },
127 127
128 128 {
129 129 :key => 'system.admin_email',
130 130 :value_type => 'string',
131 131 :default_value => 'admin@admin.email'
132 132 },
133 133
134 134 {
135 135 :key => 'system.user_setting_enabled',
136 136 :value_type => 'boolean',
137 137 :default_value => 'true',
138 138 :description => 'If this option is true, users can change their settings'
139 139 },
140 140
141 141 {
142 142 :key => 'system.user_setting_enabled',
143 143 :value_type => 'boolean',
144 144 :default_value => 'true',
145 145 :description => 'If this option is true, users can change their settings'
146 146 },
147 147
148 148 # If Configuration['contest.test_request.early_timeout'] is true
149 149 # the user will not be able to use test request at 30 minutes
150 150 # before the contest ends.
151 151 {
152 152 :key => 'contest.test_request.early_timeout',
153 153 :value_type => 'boolean',
154 154 :default_value => 'false'
155 155 },
156 156
157 157 {
158 158 :key => 'system.multicontests',
159 159 :value_type => 'boolean',
160 160 :default_value => 'false'
161 161 },
162 162
163 163 {
164 164 :key => 'contest.confirm_indv_contest_start',
165 165 :value_type => 'boolean',
166 166 :default_value => 'false'
167 167 },
168 168
169 169 {
170 170 :key => 'contest.default_contest_name',
171 171 :value_type => 'string',
172 172 :default_value => 'none',
173 173 :description => "New user will be assigned to this contest automatically, if it exists. Set to 'none' if there is no default contest."
174 174 },
175 175
176 176 {
177 177 :key => 'system.use_problem_group',
178 178 :value_type => 'boolean',
179 179 :default_value => 'false',
180 180 :description => "If true, available problem to the user will be only ones associated with the group of the user."
181 181 },
182 182
183 183
184 184 {
185 185 :key => 'right.whitelist_ignore',
186 186 :value_type => 'boolean',
187 187 :default_value => 'true',
188 188 :description => "If true, no IP check against whitelist_ip is perform. However, when false, non-admin user must have their ip in 'whitelist_ip' to be able to login."
189 189 },
190 190
191 191 {
192 192 :key => 'right.whitelist_ip',
193 193 :value_type => 'string',
194 194 :default_value => '0.0.0.0/0',
195 195 :description => "list of whitelist ip, given in comma separated CIDR notation. For example '192.168.90.0/23, 192.168.1.23/32'"
196 196 },
197 197
198 198 ]
199 199
200 200
201 201 def create_configuration_key(key,
202 202 value_type,
203 203 default_value,
204 204 description='')
205 205 conf = (GraderConfiguration.find_by_key(key) ||
206 206 GraderConfiguration.new(:key => key,
207 207 :value_type => value_type,
208 208 :value => default_value))
209 209 conf.description = description
210 210 conf.save
211 211 end
212 212
213 213 def seed_config
214 214 CONFIGURATIONS.each do |conf|
215 215 if conf.has_key? :description
216 216 desc = conf[:description]
217 217 else
218 218 desc = ''
219 219 end
220 220 create_configuration_key(conf[:key],
221 221 conf[:value_type],
222 222 conf[:default_value],
223 223 desc)
224 224 end
225 225 end
226 226
227 227 def seed_roles
228 + Role.find_or_create_by(name: 'TA')
228 229 return if Role.find_by_name('admin')
229 230
230 231 role = Role.create(:name => 'admin')
231 232 user_admin_right = Right.create(:name => 'user_admin',
232 233 :controller => 'user_admin',
233 234 :action => 'all')
234 235 problem_admin_right = Right.create(:name=> 'problem_admin',
235 236 :controller => 'problems',
236 237 :action => 'all')
237 238
238 239 graders_right = Right.create(:name => 'graders_admin',
239 240 :controller => 'graders',
240 241 :action => 'all')
241 242
242 243 role.rights << user_admin_right;
243 244 role.rights << problem_admin_right;
244 245 role.rights << graders_right;
245 246 role.save
246 247 end
247 248
248 249 def seed_root
249 250 return if User.find_by_login('root')
250 251
251 252 root = User.new(:login => 'root',
252 253 :full_name => 'Administrator',
253 254 :alias => 'root')
254 255 root.password = 'ioionrails';
255 256
256 257 class << root
257 258 public :encrypt_new_password
258 259 def valid?(context=nil)
259 260 true
260 261 end
261 262 end
262 263
263 264 root.encrypt_new_password
264 265
265 266 root.roles << Role.find_by_name('admin')
266 267
267 268 root.activated = true
268 269 root.save
269 270 end
270 271
271 272 def seed_users_and_roles
272 273 seed_roles
273 274 seed_root
274 275 end
275 276
276 277 def seed_more_languages
277 278 #Language.delete_all
278 279 Language.find_or_create_by( name: 'c', pretty_name: 'C', ext: 'c', common_ext: 'c' )
279 280 Language.find_or_create_by( name: 'cpp', pretty_name: 'C++', ext: 'cpp', common_ext: 'cpp,cc' )
280 281 Language.find_or_create_by( name: 'pas', pretty_name: 'Pascal', ext: 'pas', common_ext: 'pas' )
281 282 Language.find_or_create_by( name: 'ruby', pretty_name: 'Ruby', ext: 'rb', common_ext: 'rb' )
282 283 Language.find_or_create_by( name: 'python', pretty_name: 'Python', ext: 'py', common_ext: 'py' )
283 284 Language.find_or_create_by( name: 'java', pretty_name: 'Java', ext: 'java', common_ext: 'java' )
284 285 end
285 286
286 287 seed_config
287 288 seed_users_and_roles
288 289 seed_more_languages
You need to be logged in to leave comments. Login now