Description:
fix whitelisting bugs fix report bug
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r784:73e8782d729d - - 5 files changed: 58 inserted, 54 deleted

@@ -1,167 +1,168
1 require 'ipaddr'
1 require 'ipaddr'
2
2
3 class ApplicationController < ActionController::Base
3 class ApplicationController < ActionController::Base
4 protect_from_forgery
4 protect_from_forgery
5
5
6 before_action :current_user
6 before_action :current_user
7
7
8 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
8 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
9 MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login'
9 MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login'
10 - ALLOW_WHITELIST_IP_ONLY_CONF_KEY = 'right.allow_whitelist_ip_only'
10 + WHITELIST_IGNORE_CONF_KEY = 'right.whitelist_ignore'
11 WHITELIST_IP_CONF_KEY = 'right.whitelist_ip'
11 WHITELIST_IP_CONF_KEY = 'right.whitelist_ip'
12
12
13 #report and redirect for unauthorized activities
13 #report and redirect for unauthorized activities
14 def unauthorized_redirect(notice = 'You are not authorized to view the page you requested')
14 def unauthorized_redirect(notice = 'You are not authorized to view the page you requested')
15 flash[:notice] = notice
15 flash[:notice] = notice
16 redirect_to login_main_path
16 redirect_to login_main_path
17 end
17 end
18
18
19 # Returns the current logged-in user (if any).
19 # Returns the current logged-in user (if any).
20 def current_user
20 def current_user
21 return nil unless session[:user_id]
21 return nil unless session[:user_id]
22 @current_user ||= User.find(session[:user_id])
22 @current_user ||= User.find(session[:user_id])
23 end
23 end
24
24
25 def admin_authorization
25 def admin_authorization
26 return false unless check_valid_login
26 return false unless check_valid_login
27 user = User.includes(:roles).find(session[:user_id])
27 user = User.includes(:roles).find(session[:user_id])
28 unless user.admin?
28 unless user.admin?
29 unauthorized_redirect
29 unauthorized_redirect
30 return false
30 return false
31 end
31 end
32 return true
32 return true
33 end
33 end
34
34
35 def authorization_by_roles(allowed_roles)
35 def authorization_by_roles(allowed_roles)
36 return false unless check_valid_login
36 return false unless check_valid_login
37 user = User.find(session[:user_id])
37 user = User.find(session[:user_id])
38 unless user.roles.detect { |role| allowed_roles.member?(role.name) }
38 unless user.roles.detect { |role| allowed_roles.member?(role.name) }
39 unauthorized_redirect
39 unauthorized_redirect
40 return false
40 return false
41 end
41 end
42 end
42 end
43
43
44 def testcase_authorization
44 def testcase_authorization
45 #admin always has privileged
45 #admin always has privileged
46 if @current_user.admin?
46 if @current_user.admin?
47 return true
47 return true
48 end
48 end
49
49
50 unauthorized_redirect unless GraderConfiguration["right.view_testcase"]
50 unauthorized_redirect unless GraderConfiguration["right.view_testcase"]
51 end
51 end
52
52
53
53
54 protected
54 protected
55
55
56 #redirect to root (and also force logout)
56 #redirect to root (and also force logout)
57 #if the user is not logged_in or the system is in "ADMIN ONLY" mode
57 #if the user is not logged_in or the system is in "ADMIN ONLY" mode
58 def check_valid_login
58 def check_valid_login
59 #check if logged in
59 #check if logged in
60 unless session[:user_id]
60 unless session[:user_id]
61 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
61 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
62 unauthorized_redirect('You need to login but you cannot log in at this time')
62 unauthorized_redirect('You need to login but you cannot log in at this time')
63 else
63 else
64 unauthorized_redirect('You need to login')
64 unauthorized_redirect('You need to login')
65 end
65 end
66 return false
66 return false
67 end
67 end
68
68
69 # check if run in single user mode
69 # check if run in single user mode
70 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
70 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
71 if @current_user==nil || (!@current_user.admin?)
71 if @current_user==nil || (!@current_user.admin?)
72 unauthorized_redirect('You cannot log in at this time')
72 unauthorized_redirect('You cannot log in at this time')
73 return false
73 return false
74 end
74 end
75 end
75 end
76
76
77 # check if the user is enabled
77 # check if the user is enabled
78 unless @current_user.enabled? || @current_user.admin?
78 unless @current_user.enabled? || @current_user.admin?
79 unauthorized_redirect 'Your account is disabled'
79 unauthorized_redirect 'Your account is disabled'
80 return false
80 return false
81 end
81 end
82
82
83 # check if user ip is allowed
83 # check if user ip is allowed
84 - unless @current_user.admin? || !GraderConfiguration[ALLOW_WHITELIST_IP_ONLY_CONF_KEY]
84 + unless @current_user.admin? || GraderConfiguration[WHITELIST_IGNORE_CONF_KEY]
85 unless is_request_ip_allowed?
85 unless is_request_ip_allowed?
86 - unauthorized_redirect 'Your IP is not allowed'
86 + unauthorized_redirect 'Your IP is not allowed to login at this time.'
87 return false
87 return false
88 end
88 end
89 end
89 end
90
90
91 if GraderConfiguration.multicontests?
91 if GraderConfiguration.multicontests?
92 return true if @current_user.admin?
92 return true if @current_user.admin?
93 begin
93 begin
94 if @current_user.contest_stat(true).forced_logout
94 if @current_user.contest_stat(true).forced_logout
95 flash[:notice] = 'You have been automatically logged out.'
95 flash[:notice] = 'You have been automatically logged out.'
96 redirect_to :controller => 'main', :action => 'index'
96 redirect_to :controller => 'main', :action => 'index'
97 end
97 end
98 rescue
98 rescue
99 end
99 end
100 end
100 end
101 return true
101 return true
102 end
102 end
103
103
104 #redirect to root (and also force logout)
104 #redirect to root (and also force logout)
105 #if the user use different ip from the previous connection
105 #if the user use different ip from the previous connection
106 # only applicable when MULTIPLE_IP_LOGIN options is false only
106 # only applicable when MULTIPLE_IP_LOGIN options is false only
107 def authenticate_by_ip_address
107 def authenticate_by_ip_address
108 #this assume that we have already authenticate normally
108 #this assume that we have already authenticate normally
109 unless GraderConfiguration[MULTIPLE_IP_LOGIN_CONF_KEY]
109 unless GraderConfiguration[MULTIPLE_IP_LOGIN_CONF_KEY]
110 user = User.find(session[:user_id])
110 user = User.find(session[:user_id])
111 - puts "User admin #{user.admin?}"
112 if (!user.admin? && user.last_ip && user.last_ip != request.remote_ip)
111 if (!user.admin? && user.last_ip && user.last_ip != request.remote_ip)
113 flash[:notice] = "You cannot use the system from #{request.remote_ip}. Your last ip is #{user.last_ip}"
112 flash[:notice] = "You cannot use the system from #{request.remote_ip}. Your last ip is #{user.last_ip}"
114 - puts "hahaha"
115 redirect_to :controller => 'main', :action => 'login'
113 redirect_to :controller => 'main', :action => 'login'
116 return false
114 return false
117 end
115 end
118 unless user.last_ip
116 unless user.last_ip
119 user.last_ip = request.remote_ip
117 user.last_ip = request.remote_ip
120 user.save
118 user.save
121 end
119 end
122 end
120 end
123 return true
121 return true
124 end
122 end
125
123
126 def authorization
124 def authorization
127 return false unless check_valid_login
125 return false unless check_valid_login
128 user = User.find(session[:user_id])
126 user = User.find(session[:user_id])
129 unless user.roles.detect { |role|
127 unless user.roles.detect { |role|
130 role.rights.detect{ |right|
128 role.rights.detect{ |right|
131 right.controller == self.class.controller_name and
129 right.controller == self.class.controller_name and
132 (right.action == 'all' || right.action == action_name)
130 (right.action == 'all' || right.action == action_name)
133 }
131 }
134 }
132 }
135 flash[:notice] = 'You are not authorized to view the page you requested'
133 flash[:notice] = 'You are not authorized to view the page you requested'
136 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
134 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
137 redirect_to :controller => 'main', :action => 'login'
135 redirect_to :controller => 'main', :action => 'login'
138 return false
136 return false
139 end
137 end
140 end
138 end
141
139
142 def verify_time_limit
140 def verify_time_limit
143 return true if session[:user_id]==nil
141 return true if session[:user_id]==nil
144 user = User.find(session[:user_id], :include => :site)
142 user = User.find(session[:user_id], :include => :site)
145 return true if user==nil || user.site == nil
143 return true if user==nil || user.site == nil
146 if user.contest_finished?
144 if user.contest_finished?
147 flash[:notice] = 'Error: the contest you are participating is over.'
145 flash[:notice] = 'Error: the contest you are participating is over.'
148 redirect_to :back
146 redirect_to :back
149 return false
147 return false
150 end
148 end
151 return true
149 return true
152 end
150 end
153
151
154 def is_request_ip_allowed?
152 def is_request_ip_allowed?
155 - if GraderConfiguration[ALLOW_WHITELIST_IP_ONLY_CONF_KEY]
153 + unless GraderConfiguration[WHITELIST_IGNORE_CONF_KEY]
156 user_ip = IPAddr.new(request.remote_ip)
154 user_ip = IPAddr.new(request.remote_ip)
157 - GraderConfiguration[WHITELIST_IP_LIST_CONF_KEY].delete(' ').split(',').each do |ips|
155 +
156 + GraderConfiguration[WHITELIST_IP_CONF_KEY].delete(' ').split(',').each do |ips|
157 + puts "ip is #{ips}, user ip is #{user_ip}"
158 allow_ips = IPAddr.new(ips)
158 allow_ips = IPAddr.new(ips)
159 - unless allow_ips.includes(user_ip)
159 + if allow_ips.include?(user_ip)
160 - return false
160 + return true
161 end
161 end
162 end
162 end
163 + return false
163 end
164 end
164 return true
165 return true
165 end
166 end
166
167
167 end
168 end
@@ -372,156 +372,156
372 UNION
372 UNION
373 SELECT l2.*
373 SELECT l2.*
374 FROM logins l2 INNER JOIN
374 FROM logins l2 INNER JOIN
375 (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
375 (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
376 FROM logins l
376 FROM logins l
377 INNER JOIN users u ON l.user_id = u.id
377 INNER JOIN users u ON l.user_id = u.id
378 WHERE l.created_at >= '#{@since_time.in_time_zone("UTC")}' and l.created_at <= '#{@until_time.in_time_zone("UTC")}'
378 WHERE l.created_at >= '#{@since_time.in_time_zone("UTC")}' and l.created_at <= '#{@until_time.in_time_zone("UTC")}'
379 GROUP BY l.ip_address
379 GROUP BY l.ip_address
380 HAVING count > 1
380 HAVING count > 1
381 ) ml on ml.ip_address = l2.ip_address
381 ) ml on ml.ip_address = l2.ip_address
382 INNER JOIN users u ON l2.user_id = u.id
382 INNER JOIN users u ON l2.user_id = u.id
383 WHERE l2.created_at >= '#{@since_time.in_time_zone("UTC")}' and l2.created_at <= '#{@until_time.in_time_zone("UTC")}'
383 WHERE l2.created_at >= '#{@since_time.in_time_zone("UTC")}' and l2.created_at <= '#{@until_time.in_time_zone("UTC")}'
384 ORDER BY ip_address,created_at
384 ORDER BY ip_address,created_at
385 SQL
385 SQL
386 @mld = Login.find_by_sql(st)
386 @mld = Login.find_by_sql(st)
387
387
388 st = <<-SQL
388 st = <<-SQL
389 SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
389 SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
390 FROM submissions s INNER JOIN
390 FROM submissions s INNER JOIN
391 (SELECT u.id,COUNT(DISTINCT ip_address) as count,u.login,u.full_name
391 (SELECT u.id,COUNT(DISTINCT ip_address) as count,u.login,u.full_name
392 FROM logins l
392 FROM logins l
393 INNER JOIN users u ON l.user_id = u.id
393 INNER JOIN users u ON l.user_id = u.id
394 WHERE l.created_at >= ? and l.created_at <= ?
394 WHERE l.created_at >= ? and l.created_at <= ?
395 GROUP BY u.id
395 GROUP BY u.id
396 HAVING count > 1
396 HAVING count > 1
397 ) ml ON s.user_id = ml.id
397 ) ml ON s.user_id = ml.id
398 WHERE s.submitted_at >= ? and s.submitted_at <= ?
398 WHERE s.submitted_at >= ? and s.submitted_at <= ?
399 UNION
399 UNION
400 SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
400 SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
401 FROM submissions s INNER JOIN
401 FROM submissions s INNER JOIN
402 (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
402 (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
403 FROM logins l
403 FROM logins l
404 INNER JOIN users u ON l.user_id = u.id
404 INNER JOIN users u ON l.user_id = u.id
405 WHERE l.created_at >= ? and l.created_at <= ?
405 WHERE l.created_at >= ? and l.created_at <= ?
406 GROUP BY l.ip_address
406 GROUP BY l.ip_address
407 HAVING count > 1
407 HAVING count > 1
408 ) ml on ml.ip_address = s.ip_address
408 ) ml on ml.ip_address = s.ip_address
409 WHERE s.submitted_at >= ? and s.submitted_at <= ?
409 WHERE s.submitted_at >= ? and s.submitted_at <= ?
410 ORDER BY ip_address,submitted_at
410 ORDER BY ip_address,submitted_at
411 SQL
411 SQL
412 @subs = Submission.joins(:problem).find_by_sql([st,@since_time,@until_time,
412 @subs = Submission.joins(:problem).find_by_sql([st,@since_time,@until_time,
413 @since_time,@until_time,
413 @since_time,@until_time,
414 @since_time,@until_time,
414 @since_time,@until_time,
415 @since_time,@until_time])
415 @since_time,@until_time])
416
416
417 end
417 end
418
418
419 def cheat_scruntinize
419 def cheat_scruntinize
420 #convert date & time
420 #convert date & time
421 date_and_time = '%Y-%m-%d %H:%M'
421 date_and_time = '%Y-%m-%d %H:%M'
422 begin
422 begin
423 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
423 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
424 @since_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
424 @since_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
425 rescue
425 rescue
426 @since_time = Time.zone.now.ago( 90.minutes)
426 @since_time = Time.zone.now.ago( 90.minutes)
427 end
427 end
428 begin
428 begin
429 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
429 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
430 @until_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
430 @until_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i)
431 rescue
431 rescue
432 @until_time = Time.zone.now
432 @until_time = Time.zone.now
433 end
433 end
434
434
435 #convert sid
435 #convert sid
436 @sid = params[:SID].split(/[,\s]/) if params[:SID]
436 @sid = params[:SID].split(/[,\s]/) if params[:SID]
437 unless @sid and @sid.size > 0
437 unless @sid and @sid.size > 0
438 return
438 return
439 redirect_to actoin: :cheat_scruntinize
439 redirect_to actoin: :cheat_scruntinize
440 flash[:notice] = 'Please enter at least 1 student id'
440 flash[:notice] = 'Please enter at least 1 student id'
441 end
441 end
442 mark = Array.new(@sid.size,'?')
442 mark = Array.new(@sid.size,'?')
443 condition = "(u.login = " + mark.join(' OR u.login = ') + ')'
443 condition = "(u.login = " + mark.join(' OR u.login = ') + ')'
444
444
445 @st = <<-SQL
445 @st = <<-SQL
446 SELECT l.created_at as submitted_at ,-1 as id,u.login,u.full_name,l.ip_address,"" as problem_id,"" as points,l.user_id
446 SELECT l.created_at as submitted_at ,-1 as id,u.login,u.full_name,l.ip_address,"" as problem_id,"" as points,l.user_id
447 FROM logins l INNER JOIN users u on l.user_id = u.id
447 FROM logins l INNER JOIN users u on l.user_id = u.id
448 WHERE l.created_at >= ? AND l.created_at <= ? AND #{condition}
448 WHERE l.created_at >= ? AND l.created_at <= ? AND #{condition}
449 UNION
449 UNION
450 SELECT s.submitted_at,s.id,u.login,u.full_name,s.ip_address,s.problem_id,s.points,s.user_id
450 SELECT s.submitted_at,s.id,u.login,u.full_name,s.ip_address,s.problem_id,s.points,s.user_id
451 FROM submissions s INNER JOIN users u ON s.user_id = u.id
451 FROM submissions s INNER JOIN users u ON s.user_id = u.id
452 WHERE s.submitted_at >= ? AND s.submitted_at <= ? AND #{condition}
452 WHERE s.submitted_at >= ? AND s.submitted_at <= ? AND #{condition}
453 ORDER BY submitted_at
453 ORDER BY submitted_at
454 SQL
454 SQL
455
455
456 p = [@st,@since_time,@until_time] + @sid + [@since_time,@until_time] + @sid
456 p = [@st,@since_time,@until_time] + @sid + [@since_time,@until_time] + @sid
457 @logs = Submission.joins(:problem).find_by_sql(p)
457 @logs = Submission.joins(:problem).find_by_sql(p)
458
458
459
459
460
460
461
461
462
462
463 end
463 end
464
464
465 protected
465 protected
466
466
467 def calculate_max_score(problems, users,since_id,until_id, get_last_score = false)
467 def calculate_max_score(problems, users,since_id,until_id, get_last_score = false)
468 - #score[i] = user #i's user stat where i is the index (not id)
468 + #scorearray[i] = user #i's user stat where i is the index (not id)
469 scorearray = Array.new
469 scorearray = Array.new
470 users.each do |u|
470 users.each do |u|
471 ustat = Array.new
471 ustat = Array.new
472 ustat[0] = u
472 ustat[0] = u
473 problems.each do |p|
473 problems.each do |p|
474 unless get_last_score
474 unless get_last_score
475 #get max score
475 #get max score
476 max_points = 0
476 max_points = 0
477 Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub|
477 Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub|
478 max_points = sub.points if sub and sub.points and (sub.points > max_points)
478 max_points = sub.points if sub and sub.points and (sub.points > max_points)
479 end
479 end
480 ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)]
480 ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)]
481 else
481 else
482 #get latest score
482 #get latest score
483 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
483 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
484 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
484 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
485 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
485 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
486 else
486 else
487 ustat << [0,false]
487 ustat << [0,false]
488 end
488 end
489 end
489 end
490 end
490 end
491 scorearray << ustat
491 scorearray << ustat
492 end
492 end
493 return scorearray
493 return scorearray
494 end
494 end
495
495
496 def gen_csv_from_scorearray(scorearray,problem)
496 def gen_csv_from_scorearray(scorearray,problem)
497 CSV.generate do |csv|
497 CSV.generate do |csv|
498 #add header
498 #add header
499 header = ['User','Name', 'Activated?', 'Logged in', 'Contest']
499 header = ['User','Name', 'Activated?', 'Logged in', 'Contest']
500 problem.each { |p| header << p.name }
500 problem.each { |p| header << p.name }
501 header += ['Total','Passed']
501 header += ['Total','Passed']
502 csv << header
502 csv << header
503 #add data
503 #add data
504 scorearray.each do |sc|
504 scorearray.each do |sc|
505 total = num_passed = 0
505 total = num_passed = 0
506 row = Array.new
506 row = Array.new
507 sc.each_index do |i|
507 sc.each_index do |i|
508 if i == 0
508 if i == 0
509 row << sc[i].login
509 row << sc[i].login
510 row << sc[i].full_name
510 row << sc[i].full_name
511 row << sc[i].activated
511 row << sc[i].activated
512 row << (sc[i].try(:contest_stat).try(:started_at)!=nil ? 'yes' : 'no')
512 row << (sc[i].try(:contest_stat).try(:started_at)!=nil ? 'yes' : 'no')
513 row << sc[i].contests.collect {|c| c.name}.join(', ')
513 row << sc[i].contests.collect {|c| c.name}.join(', ')
514 else
514 else
515 row << sc[i][0]
515 row << sc[i][0]
516 total += sc[i][0]
516 total += sc[i][0]
517 num_passed += 1 if sc[i][1]
517 num_passed += 1 if sc[i][1]
518 end
518 end
519 end
519 end
520 row << total
520 row << total
521 row << num_passed
521 row << num_passed
522 csv << row
522 csv << row
523 end
523 end
524 end
524 end
525 end
525 end
526
526
527 end
527 end
@@ -1,69 +1,71
1 %table.table.sortable.table-striped.table-bordered.table-condensed
1 %table.table.sortable.table-striped.table-bordered.table-condensed
2 %thead
2 %thead
3 %tr
3 %tr
4 %th Login
4 %th Login
5 %th Name
5 %th Name
6 / %th Activated?
6 / %th Activated?
7 / %th Logged_in
7 / %th Logged_in
8 / %th Contest(s)
8 / %th Contest(s)
9 %th Remark
9 %th Remark
10 - @problems.each do |p|
10 - @problems.each do |p|
11 %th.text-right= p.name.gsub('_',' ')
11 %th.text-right= p.name.gsub('_',' ')
12 %th.text-right Total
12 %th.text-right Total
13 %th.text-right Passed
13 %th.text-right Passed
14 %tbody
14 %tbody
15 - - sum = Array.new(@problems.count,0)
15 + - sum = Array.new(@problems.count+1,0)
16 - - nonzero = Array.new(@problems.count,0)
16 + - nonzero = Array.new(@problems.count+1,0)
17 - - full = Array.new(@problems.count,0)
17 + - full = Array.new(@problems.count+1,0)
18 + - puts @scorearray
19 + - puts @problems.count
18 - @scorearray.each do |sc|
20 - @scorearray.each do |sc|
19 %tr
21 %tr
20 - total,num_passed = 0,0
22 - total,num_passed = 0,0
21 - sc.each_index do |i|
23 - sc.each_index do |i|
22 - if i == 0
24 - if i == 0
23 %td= link_to sc[i].login, stat_user_path(sc[i])
25 %td= link_to sc[i].login, stat_user_path(sc[i])
24 %td= sc[i].full_name
26 %td= sc[i].full_name
25 / %td= sc[i].activated
27 / %td= sc[i].activated
26 / %td= sc[i].try(:contest_stat).try(:started_at) ? 'yes' : 'no'
28 / %td= sc[i].try(:contest_stat).try(:started_at) ? 'yes' : 'no'
27 / %td= sc[i].contests.collect {|c| c.name}.join(', ')
29 / %td= sc[i].contests.collect {|c| c.name}.join(', ')
28 %td= sc[i].remark
30 %td= sc[i].remark
29 - else
31 - else
30 %td.text-right= sc[i][0]
32 %td.text-right= sc[i][0]
31 - total += sc[i][0]
33 - total += sc[i][0]
32 - num_passed += 1 if sc[i][1]
34 - num_passed += 1 if sc[i][1]
33 - sum[i] += sc[i][0]
35 - sum[i] += sc[i][0]
34 - nonzero[i] += 1 if sc[i][0] > 0
36 - nonzero[i] += 1 if sc[i][0] > 0
35 - full[i] += 1 if sc[i][1]
37 - full[i] += 1 if sc[i][1]
36 %td.text-right= total
38 %td.text-right= total
37 %td.text-right= num_passed
39 %td.text-right= num_passed
38 %tfoot
40 %tfoot
39 %tr
41 %tr
40 %td Summation
42 %td Summation
41 %td
43 %td
42 %td
44 %td
43 - sum.each.with_index do |s,i|
45 - sum.each.with_index do |s,i|
44 - next if i == 0
46 - next if i == 0
45 %td.text-right= number_with_delimiter(s)
47 %td.text-right= number_with_delimiter(s)
46 %td
48 %td
47 %td
49 %td
48 %tr
50 %tr
49 %td partial solver
51 %td partial solver
50 %td
52 %td
51 %td
53 %td
52 - nonzero.each.with_index do |s,i|
54 - nonzero.each.with_index do |s,i|
53 - next if i == 0
55 - next if i == 0
54 %td.text-right= number_with_delimiter(s)
56 %td.text-right= number_with_delimiter(s)
55 %td
57 %td
56 %td
58 %td
57 %tr
59 %tr
58 %td Full solver
60 %td Full solver
59 %td
61 %td
60 %td
62 %td
61 - full.each.with_index do |s,i|
63 - full.each.with_index do |s,i|
62 - next if i == 0
64 - next if i == 0
63 %td.text-right= number_with_delimiter(s)
65 %td.text-right= number_with_delimiter(s)
64 %td
66 %td
65 %td
67 %td
66
68
67
69
68 :javascript
70 :javascript
69 $.bootstrapSortable(true,'reversed')
71 $.bootstrapSortable(true,'reversed')
@@ -1,306 +1,307
1 # This file is auto-generated from the current state of the database. Instead
1 # This file is auto-generated from the current state of the database. Instead
2 # of editing this file, please use the migrations feature of Active Record to
2 # of editing this file, please use the migrations feature of Active Record to
3 # incrementally modify your database, and then regenerate this schema definition.
3 # incrementally modify your database, and then regenerate this schema definition.
4 #
4 #
5 # Note that this schema.rb definition is the authoritative source for your
5 # Note that this schema.rb definition is the authoritative source for your
6 # database schema. If you need to create the application database on another
6 # database schema. If you need to create the application database on another
7 # system, you should be using db:schema:load, not running all the migrations
7 # system, you should be using db:schema:load, not running all the migrations
8 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
8 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9 # you'll amass, the slower it'll run and the greater likelihood for issues).
9 # you'll amass, the slower it'll run and the greater likelihood for issues).
10 #
10 #
11 # It's strongly recommended that you check this file into your version control system.
11 # It's strongly recommended that you check this file into your version control system.
12
12
13 ActiveRecord::Schema.define(version: 2018_06_12_102327) do
13 ActiveRecord::Schema.define(version: 2018_06_12_102327) do
14
14
15 - create_table "announcements", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
15 + create_table "announcements", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
16 t.string "author"
16 t.string "author"
17 t.text "body"
17 t.text "body"
18 t.boolean "published"
18 t.boolean "published"
19 t.datetime "created_at"
19 t.datetime "created_at"
20 t.datetime "updated_at"
20 t.datetime "updated_at"
21 t.boolean "frontpage", default: false
21 t.boolean "frontpage", default: false
22 t.boolean "contest_only", default: false
22 t.boolean "contest_only", default: false
23 t.string "title"
23 t.string "title"
24 t.string "notes"
24 t.string "notes"
25 end
25 end
26
26
27 - create_table "contests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
27 + create_table "contests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
28 t.string "title"
28 t.string "title"
29 t.boolean "enabled"
29 t.boolean "enabled"
30 t.datetime "created_at"
30 t.datetime "created_at"
31 t.datetime "updated_at"
31 t.datetime "updated_at"
32 t.string "name"
32 t.string "name"
33 end
33 end
34
34
35 - create_table "contests_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
35 + create_table "contests_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
36 t.integer "contest_id"
36 t.integer "contest_id"
37 t.integer "problem_id"
37 t.integer "problem_id"
38 end
38 end
39
39
40 - create_table "contests_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
40 + create_table "contests_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
41 t.integer "contest_id"
41 t.integer "contest_id"
42 t.integer "user_id"
42 t.integer "user_id"
43 end
43 end
44
44
45 - create_table "countries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
45 + create_table "countries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
46 t.string "name"
46 t.string "name"
47 t.datetime "created_at"
47 t.datetime "created_at"
48 t.datetime "updated_at"
48 t.datetime "updated_at"
49 end
49 end
50
50
51 - create_table "descriptions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
51 + create_table "descriptions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
52 t.text "body"
52 t.text "body"
53 t.boolean "markdowned"
53 t.boolean "markdowned"
54 t.datetime "created_at"
54 t.datetime "created_at"
55 t.datetime "updated_at"
55 t.datetime "updated_at"
56 end
56 end
57
57
58 - create_table "grader_configurations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
58 + create_table "grader_configurations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
59 t.string "key"
59 t.string "key"
60 t.string "value_type"
60 t.string "value_type"
61 t.string "value"
61 t.string "value"
62 t.datetime "created_at"
62 t.datetime "created_at"
63 t.datetime "updated_at"
63 t.datetime "updated_at"
64 t.text "description"
64 t.text "description"
65 end
65 end
66
66
67 - create_table "grader_processes", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
67 + create_table "grader_processes", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
68 t.string "host"
68 t.string "host"
69 t.integer "pid"
69 t.integer "pid"
70 t.string "mode"
70 t.string "mode"
71 t.boolean "active"
71 t.boolean "active"
72 t.datetime "created_at"
72 t.datetime "created_at"
73 t.datetime "updated_at"
73 t.datetime "updated_at"
74 t.integer "task_id"
74 t.integer "task_id"
75 t.string "task_type"
75 t.string "task_type"
76 t.boolean "terminated"
76 t.boolean "terminated"
77 - t.index ["host", "pid"], name: "index_grader_processes_on_ip_and_pid"
77 + t.index ["host", "pid"], name: "index_grader_processes_on_host_and_pid"
78 end
78 end
79
79
80 - create_table "groups", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
80 + create_table "groups", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
81 t.string "name"
81 t.string "name"
82 t.string "description"
82 t.string "description"
83 end
83 end
84
84
85 - create_table "groups_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
85 + create_table "groups_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
86 t.integer "problem_id", null: false
86 t.integer "problem_id", null: false
87 t.integer "group_id", null: false
87 t.integer "group_id", null: false
88 t.index ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id"
88 t.index ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id"
89 end
89 end
90
90
91 - create_table "groups_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
91 + create_table "groups_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
92 t.integer "group_id", null: false
92 t.integer "group_id", null: false
93 t.integer "user_id", null: false
93 t.integer "user_id", null: false
94 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
94 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
95 end
95 end
96
96
97 create_table "heart_beats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
97 create_table "heart_beats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
98 t.integer "user_id"
98 t.integer "user_id"
99 t.string "ip_address"
99 t.string "ip_address"
100 - t.datetime "created_at", null: false
100 + t.datetime "created_at"
101 - t.datetime "updated_at", null: false
101 + t.datetime "updated_at"
102 t.string "status"
102 t.string "status"
103 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
103 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
104 end
104 end
105
105
106 - create_table "languages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
106 + create_table "languages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
107 t.string "name", limit: 10
107 t.string "name", limit: 10
108 t.string "pretty_name"
108 t.string "pretty_name"
109 t.string "ext", limit: 10
109 t.string "ext", limit: 10
110 t.string "common_ext"
110 t.string "common_ext"
111 end
111 end
112
112
113 create_table "logins", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
113 create_table "logins", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
114 t.integer "user_id"
114 t.integer "user_id"
115 t.string "ip_address"
115 t.string "ip_address"
116 - t.datetime "created_at", null: false
116 + t.datetime "created_at"
117 - t.datetime "updated_at", null: false
117 + t.datetime "updated_at"
118 end
118 end
119
119
120 - create_table "messages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
120 + create_table "messages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
121 t.integer "sender_id"
121 t.integer "sender_id"
122 t.integer "receiver_id"
122 t.integer "receiver_id"
123 t.integer "replying_message_id"
123 t.integer "replying_message_id"
124 t.text "body"
124 t.text "body"
125 t.boolean "replied"
125 t.boolean "replied"
126 t.datetime "created_at"
126 t.datetime "created_at"
127 t.datetime "updated_at"
127 t.datetime "updated_at"
128 end
128 end
129
129
130 - create_table "problems", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
130 + create_table "problems", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
131 t.string "name", limit: 30
131 t.string "name", limit: 30
132 t.string "full_name"
132 t.string "full_name"
133 t.integer "full_score"
133 t.integer "full_score"
134 t.date "date_added"
134 t.date "date_added"
135 t.boolean "available"
135 t.boolean "available"
136 t.string "url"
136 t.string "url"
137 t.integer "description_id"
137 t.integer "description_id"
138 t.boolean "test_allowed"
138 t.boolean "test_allowed"
139 t.boolean "output_only"
139 t.boolean "output_only"
140 t.string "description_filename"
140 t.string "description_filename"
141 t.boolean "view_testcase"
141 t.boolean "view_testcase"
142 end
142 end
143
143
144 - create_table "problems_tags", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
144 + create_table "problems_tags", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
145 t.integer "problem_id"
145 t.integer "problem_id"
146 t.integer "tag_id"
146 t.integer "tag_id"
147 t.index ["problem_id", "tag_id"], name: "index_problems_tags_on_problem_id_and_tag_id", unique: true
147 t.index ["problem_id", "tag_id"], name: "index_problems_tags_on_problem_id_and_tag_id", unique: true
148 t.index ["problem_id"], name: "index_problems_tags_on_problem_id"
148 t.index ["problem_id"], name: "index_problems_tags_on_problem_id"
149 t.index ["tag_id"], name: "index_problems_tags_on_tag_id"
149 t.index ["tag_id"], name: "index_problems_tags_on_tag_id"
150 end
150 end
151
151
152 - create_table "rights", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
152 + create_table "rights", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
153 t.string "name"
153 t.string "name"
154 t.string "controller"
154 t.string "controller"
155 t.string "action"
155 t.string "action"
156 end
156 end
157
157
158 - create_table "rights_roles", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
158 + create_table "rights_roles", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
159 t.integer "right_id"
159 t.integer "right_id"
160 t.integer "role_id"
160 t.integer "role_id"
161 t.index ["role_id"], name: "index_rights_roles_on_role_id"
161 t.index ["role_id"], name: "index_rights_roles_on_role_id"
162 end
162 end
163
163
164 - create_table "roles", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
164 + create_table "roles", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
165 t.string "name"
165 t.string "name"
166 end
166 end
167
167
168 - create_table "roles_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
168 + create_table "roles_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
169 t.integer "role_id"
169 t.integer "role_id"
170 t.integer "user_id"
170 t.integer "user_id"
171 t.index ["user_id"], name: "index_roles_users_on_user_id"
171 t.index ["user_id"], name: "index_roles_users_on_user_id"
172 end
172 end
173
173
174 - create_table "sessions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
174 + create_table "sessions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
175 t.string "session_id"
175 t.string "session_id"
176 t.text "data"
176 t.text "data"
177 t.datetime "updated_at"
177 t.datetime "updated_at"
178 t.index ["session_id"], name: "index_sessions_on_session_id"
178 t.index ["session_id"], name: "index_sessions_on_session_id"
179 t.index ["updated_at"], name: "index_sessions_on_updated_at"
179 t.index ["updated_at"], name: "index_sessions_on_updated_at"
180 end
180 end
181
181
182 - create_table "sites", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
182 + create_table "sites", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
183 t.string "name"
183 t.string "name"
184 t.boolean "started"
184 t.boolean "started"
185 t.datetime "start_time"
185 t.datetime "start_time"
186 t.datetime "created_at"
186 t.datetime "created_at"
187 t.datetime "updated_at"
187 t.datetime "updated_at"
188 t.integer "country_id"
188 t.integer "country_id"
189 t.string "password"
189 t.string "password"
190 end
190 end
191
191
192 create_table "submission_view_logs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
192 create_table "submission_view_logs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
193 t.integer "user_id"
193 t.integer "user_id"
194 t.integer "submission_id"
194 t.integer "submission_id"
195 - t.datetime "created_at", null: false
195 + t.datetime "created_at"
196 - t.datetime "updated_at", null: false
196 + t.datetime "updated_at"
197 end
197 end
198
198
199 - create_table "submissions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
199 + create_table "submissions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
200 t.integer "user_id"
200 t.integer "user_id"
201 t.integer "problem_id"
201 t.integer "problem_id"
202 t.integer "language_id"
202 t.integer "language_id"
203 t.text "source", limit: 16777215
203 t.text "source", limit: 16777215
204 t.binary "binary"
204 t.binary "binary"
205 t.datetime "submitted_at"
205 t.datetime "submitted_at"
206 t.datetime "compiled_at"
206 t.datetime "compiled_at"
207 t.text "compiler_message"
207 t.text "compiler_message"
208 t.datetime "graded_at"
208 t.datetime "graded_at"
209 t.integer "points"
209 t.integer "points"
210 t.text "grader_comment"
210 t.text "grader_comment"
211 t.integer "number"
211 t.integer "number"
212 t.string "source_filename"
212 t.string "source_filename"
213 t.float "max_runtime"
213 t.float "max_runtime"
214 t.integer "peak_memory"
214 t.integer "peak_memory"
215 t.integer "effective_code_length"
215 t.integer "effective_code_length"
216 t.string "ip_address"
216 t.string "ip_address"
217 t.index ["user_id", "problem_id", "number"], name: "index_submissions_on_user_id_and_problem_id_and_number", unique: true
217 t.index ["user_id", "problem_id", "number"], name: "index_submissions_on_user_id_and_problem_id_and_number", unique: true
218 t.index ["user_id", "problem_id"], name: "index_submissions_on_user_id_and_problem_id"
218 t.index ["user_id", "problem_id"], name: "index_submissions_on_user_id_and_problem_id"
219 end
219 end
220
220
221 - create_table "tags", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
221 + create_table "tags", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
222 t.string "name", null: false
222 t.string "name", null: false
223 t.text "description"
223 t.text "description"
224 t.boolean "public"
224 t.boolean "public"
225 t.datetime "created_at", null: false
225 t.datetime "created_at", null: false
226 t.datetime "updated_at", null: false
226 t.datetime "updated_at", null: false
227 end
227 end
228
228
229 - create_table "tasks", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
229 + create_table "tasks", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
230 t.integer "submission_id"
230 t.integer "submission_id"
231 t.datetime "created_at"
231 t.datetime "created_at"
232 t.integer "status"
232 t.integer "status"
233 t.datetime "updated_at"
233 t.datetime "updated_at"
234 t.index ["submission_id"], name: "index_tasks_on_submission_id"
234 t.index ["submission_id"], name: "index_tasks_on_submission_id"
235 end
235 end
236
236
237 - create_table "test_pairs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
237 + create_table "test_pairs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
238 t.integer "problem_id"
238 t.integer "problem_id"
239 t.text "input", limit: 16777215
239 t.text "input", limit: 16777215
240 t.text "solution", limit: 16777215
240 t.text "solution", limit: 16777215
241 t.datetime "created_at"
241 t.datetime "created_at"
242 t.datetime "updated_at"
242 t.datetime "updated_at"
243 end
243 end
244
244
245 - create_table "test_requests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
245 + create_table "test_requests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
246 t.integer "user_id"
246 t.integer "user_id"
247 t.integer "problem_id"
247 t.integer "problem_id"
248 t.integer "submission_id"
248 t.integer "submission_id"
249 t.string "input_file_name"
249 t.string "input_file_name"
250 t.string "output_file_name"
250 t.string "output_file_name"
251 t.string "running_stat"
251 t.string "running_stat"
252 t.integer "status"
252 t.integer "status"
253 t.datetime "updated_at"
253 t.datetime "updated_at"
254 t.datetime "submitted_at"
254 t.datetime "submitted_at"
255 t.datetime "compiled_at"
255 t.datetime "compiled_at"
256 t.text "compiler_message"
256 t.text "compiler_message"
257 t.datetime "graded_at"
257 t.datetime "graded_at"
258 t.string "grader_comment"
258 t.string "grader_comment"
259 t.datetime "created_at"
259 t.datetime "created_at"
260 t.float "running_time"
260 t.float "running_time"
261 t.string "exit_status"
261 t.string "exit_status"
262 t.integer "memory_usage"
262 t.integer "memory_usage"
263 t.index ["user_id", "problem_id"], name: "index_test_requests_on_user_id_and_problem_id"
263 t.index ["user_id", "problem_id"], name: "index_test_requests_on_user_id_and_problem_id"
264 end
264 end
265
265
266 - create_table "testcases", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
266 + create_table "testcases", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
267 t.integer "problem_id"
267 t.integer "problem_id"
268 t.integer "num"
268 t.integer "num"
269 t.integer "group"
269 t.integer "group"
270 t.integer "score"
270 t.integer "score"
271 t.text "input", limit: 4294967295
271 t.text "input", limit: 4294967295
272 t.text "sol", limit: 4294967295
272 t.text "sol", limit: 4294967295
273 t.datetime "created_at"
273 t.datetime "created_at"
274 t.datetime "updated_at"
274 t.datetime "updated_at"
275 t.index ["problem_id"], name: "index_testcases_on_problem_id"
275 t.index ["problem_id"], name: "index_testcases_on_problem_id"
276 end
276 end
277
277
278 - create_table "user_contest_stats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
278 + create_table "user_contest_stats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
279 t.integer "user_id"
279 t.integer "user_id"
280 t.datetime "started_at"
280 t.datetime "started_at"
281 t.datetime "created_at"
281 t.datetime "created_at"
282 t.datetime "updated_at"
282 t.datetime "updated_at"
283 + t.boolean "forced_logout"
283 end
284 end
284
285
285 - create_table "users", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
286 + create_table "users", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
286 t.string "login", limit: 50
287 t.string "login", limit: 50
287 t.string "full_name"
288 t.string "full_name"
288 t.string "hashed_password"
289 t.string "hashed_password"
289 t.string "salt", limit: 5
290 t.string "salt", limit: 5
290 t.string "alias"
291 t.string "alias"
291 t.string "email"
292 t.string "email"
292 t.integer "site_id"
293 t.integer "site_id"
293 t.integer "country_id"
294 t.integer "country_id"
294 t.boolean "activated", default: false
295 t.boolean "activated", default: false
295 t.datetime "created_at"
296 t.datetime "created_at"
296 t.datetime "updated_at"
297 t.datetime "updated_at"
297 t.string "section"
298 t.string "section"
298 t.boolean "enabled", default: true
299 t.boolean "enabled", default: true
299 t.string "remark"
300 t.string "remark"
300 t.string "last_ip"
301 t.string "last_ip"
301 t.index ["login"], name: "index_users_on_login", unique: true
302 t.index ["login"], name: "index_users_on_login", unique: true
302 end
303 end
303
304
304 add_foreign_key "problems_tags", "problems"
305 add_foreign_key "problems_tags", "problems"
305 add_foreign_key "problems_tags", "tags"
306 add_foreign_key "problems_tags", "tags"
306 end
307 end
@@ -7,282 +7,282
7 :description => 'Only admins can log in to the system when running under single user mode.'
7 :description => 'Only admins can log in to the system when running under single user mode.'
8 },
8 },
9
9
10 {
10 {
11 :key => 'ui.front.title',
11 :key => 'ui.front.title',
12 :value_type => 'string',
12 :value_type => 'string',
13 :default_value => 'Grader'
13 :default_value => 'Grader'
14 },
14 },
15
15
16 {
16 {
17 :key => 'ui.front.welcome_message',
17 :key => 'ui.front.welcome_message',
18 :value_type => 'string',
18 :value_type => 'string',
19 :default_value => 'Welcome!'
19 :default_value => 'Welcome!'
20 },
20 },
21
21
22 {
22 {
23 :key => 'ui.show_score',
23 :key => 'ui.show_score',
24 :value_type => 'boolean',
24 :value_type => 'boolean',
25 :default_value => 'true'
25 :default_value => 'true'
26 },
26 },
27
27
28 {
28 {
29 :key => 'contest.time_limit',
29 :key => 'contest.time_limit',
30 :value_type => 'string',
30 :value_type => 'string',
31 :default_value => 'unlimited',
31 :default_value => 'unlimited',
32 :description => 'Time limit in format hh:mm, or "unlimited" for contests with no time limits. This config is CACHED. Restart the server before the change can take effect.'
32 :description => 'Time limit in format hh:mm, or "unlimited" for contests with no time limits. This config is CACHED. Restart the server before the change can take effect.'
33 },
33 },
34
34
35 {
35 {
36 :key => 'system.mode',
36 :key => 'system.mode',
37 :value_type => 'string',
37 :value_type => 'string',
38 :default_value => 'standard',
38 :default_value => 'standard',
39 :description => 'Current modes are "standard", "contest", "indv-contest", and "analysis".'
39 :description => 'Current modes are "standard", "contest", "indv-contest", and "analysis".'
40 },
40 },
41
41
42 {
42 {
43 :key => 'contest.name',
43 :key => 'contest.name',
44 :value_type => 'string',
44 :value_type => 'string',
45 :default_value => 'Grader',
45 :default_value => 'Grader',
46 :description => 'This name will be shown on the user header bar.'
46 :description => 'This name will be shown on the user header bar.'
47 },
47 },
48
48
49 {
49 {
50 :key => 'contest.multisites',
50 :key => 'contest.multisites',
51 :value_type => 'boolean',
51 :value_type => 'boolean',
52 :default_value => 'false',
52 :default_value => 'false',
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.'
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 #---------------------------- right --------------------------------
56 #---------------------------- right --------------------------------
57 {
57 {
58 :key => 'right.user_hall_of_fame',
58 :key => 'right.user_hall_of_fame',
59 :value_type => 'boolean',
59 :value_type => 'boolean',
60 :default_value => 'false',
60 :default_value => 'false',
61 :description => 'If true, any user can access hall of fame page.'
61 :description => 'If true, any user can access hall of fame page.'
62 },
62 },
63
63
64 {
64 {
65 :key => 'right.multiple_ip_login',
65 :key => 'right.multiple_ip_login',
66 :value_type => 'boolean',
66 :value_type => 'boolean',
67 :default_value => 'true',
67 :default_value => 'true',
68 :description => 'When change from true to false, a user can login from the first IP they logged into afterward.'
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 :key => 'right.user_view_submission',
72 :key => 'right.user_view_submission',
73 :value_type => 'boolean',
73 :value_type => 'boolean',
74 :default_value => 'false',
74 :default_value => 'false',
75 :description => 'If true, any user can view submissions of every one.'
75 :description => 'If true, any user can view submissions of every one.'
76 },
76 },
77
77
78 {
78 {
79 :key => 'right.bypass_agreement',
79 :key => 'right.bypass_agreement',
80 :value_type => 'boolean',
80 :value_type => 'boolean',
81 :default_value => 'true',
81 :default_value => 'true',
82 :description => 'When false, a user must accept usage agreement before login'
82 :description => 'When false, a user must accept usage agreement before login'
83 },
83 },
84
84
85 {
85 {
86 :key => 'right.heartbeat_response',
86 :key => 'right.heartbeat_response',
87 :value_type => 'string',
87 :value_type => 'string',
88 :default_value => 'OK',
88 :default_value => 'OK',
89 :description => 'Heart beat response text'
89 :description => 'Heart beat response text'
90 },
90 },
91
91
92 {
92 {
93 :key => 'right.heartbeat_response_full',
93 :key => 'right.heartbeat_response_full',
94 :value_type => 'string',
94 :value_type => 'string',
95 :default_value => 'OK',
95 :default_value => 'OK',
96 :description => 'Heart beat response text when user got full score (set this value to the empty string to disable this feature)'
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 :key => 'right.view_testcase',
100 :key => 'right.view_testcase',
101 :value_type => 'boolean',
101 :value_type => 'boolean',
102 :default_value => 'false',
102 :default_value => 'false',
103 - :description => 'When true, any user can view/download test data'
103 + :description => 'If true, any user can view/download test data'
104 },
104 },
105
105
106 {
106 {
107 :key => 'system.online_registration',
107 :key => 'system.online_registration',
108 :value_type => 'boolean',
108 :value_type => 'boolean',
109 :default_value => 'false',
109 :default_value => 'false',
110 :description => 'This option enables online registration.'
110 :description => 'This option enables online registration.'
111 },
111 },
112
112
113 # If Configuration['system.online_registration'] is true, the
113 # If Configuration['system.online_registration'] is true, the
114 # system allows online registration, and will use these
114 # system allows online registration, and will use these
115 # information for sending confirmation emails.
115 # information for sending confirmation emails.
116 {
116 {
117 :key => 'system.online_registration.smtp',
117 :key => 'system.online_registration.smtp',
118 :value_type => 'string',
118 :value_type => 'string',
119 :default_value => 'smtp.somehost.com'
119 :default_value => 'smtp.somehost.com'
120 },
120 },
121
121
122 {
122 {
123 :key => 'system.online_registration.from',
123 :key => 'system.online_registration.from',
124 :value_type => 'string',
124 :value_type => 'string',
125 :default_value => 'your.email@address'
125 :default_value => 'your.email@address'
126 },
126 },
127
127
128 {
128 {
129 :key => 'system.admin_email',
129 :key => 'system.admin_email',
130 :value_type => 'string',
130 :value_type => 'string',
131 :default_value => 'admin@admin.email'
131 :default_value => 'admin@admin.email'
132 },
132 },
133
133
134 {
134 {
135 :key => 'system.user_setting_enabled',
135 :key => 'system.user_setting_enabled',
136 :value_type => 'boolean',
136 :value_type => 'boolean',
137 :default_value => 'true',
137 :default_value => 'true',
138 :description => 'If this option is true, users can change their settings'
138 :description => 'If this option is true, users can change their settings'
139 },
139 },
140
140
141 {
141 {
142 :key => 'system.user_setting_enabled',
142 :key => 'system.user_setting_enabled',
143 :value_type => 'boolean',
143 :value_type => 'boolean',
144 :default_value => 'true',
144 :default_value => 'true',
145 :description => 'If this option is true, users can change their settings'
145 :description => 'If this option is true, users can change their settings'
146 },
146 },
147
147
148 # If Configuration['contest.test_request.early_timeout'] is true
148 # If Configuration['contest.test_request.early_timeout'] is true
149 # the user will not be able to use test request at 30 minutes
149 # the user will not be able to use test request at 30 minutes
150 # before the contest ends.
150 # before the contest ends.
151 {
151 {
152 :key => 'contest.test_request.early_timeout',
152 :key => 'contest.test_request.early_timeout',
153 :value_type => 'boolean',
153 :value_type => 'boolean',
154 :default_value => 'false'
154 :default_value => 'false'
155 },
155 },
156
156
157 {
157 {
158 :key => 'system.multicontests',
158 :key => 'system.multicontests',
159 :value_type => 'boolean',
159 :value_type => 'boolean',
160 :default_value => 'false'
160 :default_value => 'false'
161 },
161 },
162
162
163 {
163 {
164 :key => 'contest.confirm_indv_contest_start',
164 :key => 'contest.confirm_indv_contest_start',
165 :value_type => 'boolean',
165 :value_type => 'boolean',
166 :default_value => 'false'
166 :default_value => 'false'
167 },
167 },
168
168
169 {
169 {
170 :key => 'contest.default_contest_name',
170 :key => 'contest.default_contest_name',
171 :value_type => 'string',
171 :value_type => 'string',
172 :default_value => 'none',
172 :default_value => 'none',
173 :description => "New user will be assigned to this contest automatically, if it exists. Set to 'none' if there is no default contest."
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 :key => 'system.use_problem_group',
177 :key => 'system.use_problem_group',
178 :value_type => 'boolean',
178 :value_type => 'boolean',
179 :default_value => 'false',
179 :default_value => 'false',
180 :description => "If true, available problem to the user will be only ones associated with the group of the user."
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 - :key => 'right.whitelist_ip_only',
185 + :key => 'right.whitelist_ignore',
186 :value_type => 'boolean',
186 :value_type => 'boolean',
187 - :default_value => 'false',
187 + :default_value => 'true',
188 - :description => "If true, non-admin user will be able to use the system only when their ip is in the 'whitelist_ip'."
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 :key => 'right.whitelist_ip',
192 :key => 'right.whitelist_ip',
193 :value_type => 'string',
193 :value_type => 'string',
194 :default_value => '0.0.0.0/0',
194 :default_value => '0.0.0.0/0',
195 - :description => "list of whitelist ip, given in comma separated CIDR notation. For example '161.200.92.0/23, 161.200.80.1/32'"
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 def create_configuration_key(key,
201 def create_configuration_key(key,
202 value_type,
202 value_type,
203 default_value,
203 default_value,
204 description='')
204 description='')
205 conf = (GraderConfiguration.find_by_key(key) ||
205 conf = (GraderConfiguration.find_by_key(key) ||
206 GraderConfiguration.new(:key => key,
206 GraderConfiguration.new(:key => key,
207 :value_type => value_type,
207 :value_type => value_type,
208 :value => default_value))
208 :value => default_value))
209 conf.description = description
209 conf.description = description
210 conf.save
210 conf.save
211 end
211 end
212
212
213 def seed_config
213 def seed_config
214 CONFIGURATIONS.each do |conf|
214 CONFIGURATIONS.each do |conf|
215 if conf.has_key? :description
215 if conf.has_key? :description
216 desc = conf[:description]
216 desc = conf[:description]
217 else
217 else
218 desc = ''
218 desc = ''
219 end
219 end
220 create_configuration_key(conf[:key],
220 create_configuration_key(conf[:key],
221 conf[:value_type],
221 conf[:value_type],
222 conf[:default_value],
222 conf[:default_value],
223 desc)
223 desc)
224 end
224 end
225 end
225 end
226
226
227 def seed_roles
227 def seed_roles
228 return if Role.find_by_name('admin')
228 return if Role.find_by_name('admin')
229
229
230 role = Role.create(:name => 'admin')
230 role = Role.create(:name => 'admin')
231 user_admin_right = Right.create(:name => 'user_admin',
231 user_admin_right = Right.create(:name => 'user_admin',
232 :controller => 'user_admin',
232 :controller => 'user_admin',
233 :action => 'all')
233 :action => 'all')
234 problem_admin_right = Right.create(:name=> 'problem_admin',
234 problem_admin_right = Right.create(:name=> 'problem_admin',
235 :controller => 'problems',
235 :controller => 'problems',
236 :action => 'all')
236 :action => 'all')
237
237
238 graders_right = Right.create(:name => 'graders_admin',
238 graders_right = Right.create(:name => 'graders_admin',
239 :controller => 'graders',
239 :controller => 'graders',
240 :action => 'all')
240 :action => 'all')
241
241
242 role.rights << user_admin_right;
242 role.rights << user_admin_right;
243 role.rights << problem_admin_right;
243 role.rights << problem_admin_right;
244 role.rights << graders_right;
244 role.rights << graders_right;
245 role.save
245 role.save
246 end
246 end
247
247
248 def seed_root
248 def seed_root
249 return if User.find_by_login('root')
249 return if User.find_by_login('root')
250
250
251 root = User.new(:login => 'root',
251 root = User.new(:login => 'root',
252 :full_name => 'Administrator',
252 :full_name => 'Administrator',
253 :alias => 'root')
253 :alias => 'root')
254 root.password = 'ioionrails';
254 root.password = 'ioionrails';
255
255
256 class << root
256 class << root
257 public :encrypt_new_password
257 public :encrypt_new_password
258 def valid?(context=nil)
258 def valid?(context=nil)
259 true
259 true
260 end
260 end
261 end
261 end
262
262
263 root.encrypt_new_password
263 root.encrypt_new_password
264
264
265 root.roles << Role.find_by_name('admin')
265 root.roles << Role.find_by_name('admin')
266
266
267 root.activated = true
267 root.activated = true
268 root.save
268 root.save
269 end
269 end
270
270
271 def seed_users_and_roles
271 def seed_users_and_roles
272 seed_roles
272 seed_roles
273 seed_root
273 seed_root
274 end
274 end
275
275
276 def seed_more_languages
276 def seed_more_languages
277 #Language.delete_all
277 #Language.delete_all
278 Language.find_or_create_by( name: 'c', pretty_name: 'C', ext: 'c', common_ext: 'c' )
278 Language.find_or_create_by( name: 'c', pretty_name: 'C', ext: 'c', common_ext: 'c' )
279 Language.find_or_create_by( name: 'cpp', pretty_name: 'C++', ext: 'cpp', common_ext: 'cpp,cc' )
279 Language.find_or_create_by( name: 'cpp', pretty_name: 'C++', ext: 'cpp', common_ext: 'cpp,cc' )
280 Language.find_or_create_by( name: 'pas', pretty_name: 'Pascal', ext: 'pas', common_ext: 'pas' )
280 Language.find_or_create_by( name: 'pas', pretty_name: 'Pascal', ext: 'pas', common_ext: 'pas' )
281 Language.find_or_create_by( name: 'ruby', pretty_name: 'Ruby', ext: 'rb', common_ext: 'rb' )
281 Language.find_or_create_by( name: 'ruby', pretty_name: 'Ruby', ext: 'rb', common_ext: 'rb' )
282 Language.find_or_create_by( name: 'python', pretty_name: 'Python', ext: 'py', common_ext: 'py' )
282 Language.find_or_create_by( name: 'python', pretty_name: 'Python', ext: 'py', common_ext: 'py' )
283 Language.find_or_create_by( name: 'java', pretty_name: 'Java', ext: 'java', common_ext: 'java' )
283 Language.find_or_create_by( name: 'java', pretty_name: 'Java', ext: 'java', common_ext: 'java' )
284 end
284 end
285
285
286 seed_config
286 seed_config
287 seed_users_and_roles
287 seed_users_and_roles
288 seed_more_languages
288 seed_more_languages
You need to be logged in to leave comments. Login now