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

r787:6a311ff47066 - - 13 files changed: 81 inserted, 75 deleted

@@ -1,167 +1,167
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|
158 allow_ips = IPAddr.new(ips)
157 allow_ips = IPAddr.new(ips)
159 - unless allow_ips.includes(user_ip)
158 + if allow_ips.include?(user_ip)
160 - return false
159 + return true
161 end
160 end
162 end
161 end
162 + return false
163 end
163 end
164 return true
164 return true
165 end
165 end
166
166
167 end
167 end
@@ -1,71 +1,72
1 class MainController < ApplicationController
1 class MainController < ApplicationController
2
2
3 before_action :check_valid_login, :except => [:login]
3 before_action :check_valid_login, :except => [:login]
4 before_action :check_viewability, :except => [:index, :login]
4 before_action :check_viewability, :except => [:index, :login]
5
5
6 append_before_action :confirm_and_update_start_time,
6 append_before_action :confirm_and_update_start_time,
7 :except => [:index,
7 :except => [:index,
8 :login,
8 :login,
9 :confirm_contest_start]
9 :confirm_contest_start]
10
10
11 # to prevent log in box to be shown when user logged out of the
11 # to prevent log in box to be shown when user logged out of the
12 # system only in some tab
12 # system only in some tab
13 prepend_before_action :reject_announcement_refresh_when_logged_out,
13 prepend_before_action :reject_announcement_refresh_when_logged_out,
14 :only => [:announcements]
14 :only => [:announcements]
15
15
16 before_action :authenticate_by_ip_address, :only => [:list]
16 before_action :authenticate_by_ip_address, :only => [:list]
17
17
18 #reset login, clear session
18 #reset login, clear session
19 #front page
19 #front page
20 def login
20 def login
21 saved_notice = flash[:notice]
21 saved_notice = flash[:notice]
22 reset_session
22 reset_session
23 flash.now[:notice] = saved_notice
23 flash.now[:notice] = saved_notice
24 + @remote_ip = request.remote_ip
24
25
25 # EXPERIMENT:
26 # EXPERIMENT:
26 # Hide login if in single user mode and the url does not
27 # Hide login if in single user mode and the url does not
27 # explicitly specify /login
28 # explicitly specify /login
28 #
29 #
29 # logger.info "PATH: #{request.path}"
30 # logger.info "PATH: #{request.path}"
30 # if GraderConfiguration['system.single_user_mode'] and
31 # if GraderConfiguration['system.single_user_mode'] and
31 # request.path!='/main/login'
32 # request.path!='/main/login'
32 # @hidelogin = true
33 # @hidelogin = true
33 # end
34 # end
34
35
35 @announcements = Announcement.frontpage
36 @announcements = Announcement.frontpage
36 render :action => 'login', :layout => 'empty'
37 render :action => 'login', :layout => 'empty'
37 end
38 end
38
39
39 def logout
40 def logout
40 reset_session
41 reset_session
41 redirect_to root_path
42 redirect_to root_path
42 end
43 end
43
44
44 def list
45 def list
45 prepare_list_information
46 prepare_list_information
46 end
47 end
47
48
48 def help
49 def help
49 @user = User.find(session[:user_id])
50 @user = User.find(session[:user_id])
50 end
51 end
51
52
52 def submit
53 def submit
53 user = User.find(session[:user_id])
54 user = User.find(session[:user_id])
54
55
55 @submission = Submission.new
56 @submission = Submission.new
56 @submission.problem_id = params[:submission][:problem_id]
57 @submission.problem_id = params[:submission][:problem_id]
57 @submission.user = user
58 @submission.user = user
58 @submission.language_id = 0
59 @submission.language_id = 0
59 if (params['file']) and (params['file']!='')
60 if (params['file']) and (params['file']!='')
60 @submission.source = File.open(params['file'].path,'r:UTF-8',&:read)
61 @submission.source = File.open(params['file'].path,'r:UTF-8',&:read)
61 @submission.source.encode!('UTF-8','UTF-8',invalid: :replace, replace: '')
62 @submission.source.encode!('UTF-8','UTF-8',invalid: :replace, replace: '')
62 @submission.source_filename = params['file'].original_filename
63 @submission.source_filename = params['file'].original_filename
63 end
64 end
64
65
65 if (params[:editor_text])
66 if (params[:editor_text])
66 language = Language.find_by_id(params[:language_id])
67 language = Language.find_by_id(params[:language_id])
67 @submission.source = params[:editor_text]
68 @submission.source = params[:editor_text]
68 @submission.source_filename = "live_edit.#{language.ext}"
69 @submission.source_filename = "live_edit.#{language.ext}"
69 @submission.language = language
70 @submission.language = language
70 end
71 end
71
72
@@ -420,96 +420,97
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 + #scorearray[i] = user #i's user stat where i is the index (not id)
468 scorearray = Array.new
469 scorearray = Array.new
469 users.each do |u|
470 users.each do |u|
470 ustat = Array.new
471 ustat = Array.new
471 ustat[0] = u
472 ustat[0] = u
472 problems.each do |p|
473 problems.each do |p|
473 unless get_last_score
474 unless get_last_score
474 #get max score
475 #get max score
475 max_points = 0
476 max_points = 0
476 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|
477 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)
478 end
479 end
479 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)]
480 else
481 else
481 #get latest score
482 #get latest score
482 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)
483 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
484 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)]
485 else
486 else
486 ustat << [0,false]
487 ustat << [0,false]
487 end
488 end
488 end
489 end
489 end
490 end
490 scorearray << ustat
491 scorearray << ustat
491 end
492 end
492 return scorearray
493 return scorearray
493 end
494 end
494
495
495 def gen_csv_from_scorearray(scorearray,problem)
496 def gen_csv_from_scorearray(scorearray,problem)
496 CSV.generate do |csv|
497 CSV.generate do |csv|
497 #add header
498 #add header
498 header = ['User','Name', 'Activated?', 'Logged in', 'Contest']
499 header = ['User','Name', 'Activated?', 'Logged in', 'Contest']
499 problem.each { |p| header << p.name }
500 problem.each { |p| header << p.name }
500 header += ['Total','Passed']
501 header += ['Total','Passed']
501 csv << header
502 csv << header
502 #add data
503 #add data
503 scorearray.each do |sc|
504 scorearray.each do |sc|
504 total = num_passed = 0
505 total = num_passed = 0
505 row = Array.new
506 row = Array.new
506 sc.each_index do |i|
507 sc.each_index do |i|
507 if i == 0
508 if i == 0
508 row << sc[i].login
509 row << sc[i].login
509 row << sc[i].full_name
510 row << sc[i].full_name
510 row << sc[i].activated
511 row << sc[i].activated
511 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')
512 row << sc[i].contests.collect {|c| c.name}.join(', ')
513 row << sc[i].contests.collect {|c| c.name}.join(', ')
513 else
514 else
514 row << sc[i][0]
515 row << sc[i][0]
515 total += sc[i][0]
516 total += sc[i][0]
@@ -30,86 +30,83
30 @submission = Submission.find(params[:id])
30 @submission = Submission.find(params[:id])
31
31
32 #log the viewing
32 #log the viewing
33 user = User.find(session[:user_id])
33 user = User.find(session[:user_id])
34 SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin?
34 SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin?
35
35
36 @task = @submission.task
36 @task = @submission.task
37 end
37 end
38
38
39 def download
39 def download
40 @submission = Submission.find(params[:id])
40 @submission = Submission.find(params[:id])
41 send_data(@submission.source, {:filename => @submission.download_filename, :type => 'text/plain'})
41 send_data(@submission.source, {:filename => @submission.download_filename, :type => 'text/plain'})
42 end
42 end
43
43
44 def compiler_msg
44 def compiler_msg
45 @submission = Submission.find(params[:id])
45 @submission = Submission.find(params[:id])
46 respond_to do |format|
46 respond_to do |format|
47 format.js
47 format.js
48 end
48 end
49 end
49 end
50
50
51 #on-site new submission on specific problem
51 #on-site new submission on specific problem
52 def direct_edit_problem
52 def direct_edit_problem
53 @problem = Problem.find(params[:problem_id])
53 @problem = Problem.find(params[:problem_id])
54 unless @current_user.can_view_problem?(@problem)
54 unless @current_user.can_view_problem?(@problem)
55 unauthorized_redirect
55 unauthorized_redirect
56 return
56 return
57 end
57 end
58 @source = ''
58 @source = ''
59 if (params[:view_latest])
59 if (params[:view_latest])
60 sub = Submission.find_last_by_user_and_problem(@current_user.id,@problem.id)
60 sub = Submission.find_last_by_user_and_problem(@current_user.id,@problem.id)
61 @source = @submission.source.to_s if @submission and @submission.source
61 @source = @submission.source.to_s if @submission and @submission.source
62 end
62 end
63 render 'edit'
63 render 'edit'
64 end
64 end
65
65
66 # GET /submissions/1/edit
66 # GET /submissions/1/edit
67 def edit
67 def edit
68 @submission = Submission.find(params[:id])
68 @submission = Submission.find(params[:id])
69 @source = @submission.source.to_s
69 @source = @submission.source.to_s
70 @problem = @submission.problem
70 @problem = @submission.problem
71 @lang_id = @submission.language.id
71 @lang_id = @submission.language.id
72 end
72 end
73
73
74
74
75 def get_latest_submission_status
75 def get_latest_submission_status
76 @problem = Problem.find(params[:pid])
76 @problem = Problem.find(params[:pid])
77 @submission = Submission.find_last_by_user_and_problem(params[:uid],params[:pid])
77 @submission = Submission.find_last_by_user_and_problem(params[:uid],params[:pid])
78 - puts User.find(params[:uid]).login
79 - puts Problem.find(params[:pid]).name
80 - puts 'nil' unless @submission
81 respond_to do |format|
78 respond_to do |format|
82 format.js
79 format.js
83 end
80 end
84 end
81 end
85
82
86 # GET /submissions/:id/rejudge
83 # GET /submissions/:id/rejudge
87 def rejudge
84 def rejudge
88 @submission = Submission.find(params[:id])
85 @submission = Submission.find(params[:id])
89 @task = @submission.task
86 @task = @submission.task
90 @task.status_inqueue! if @task
87 @task.status_inqueue! if @task
91 respond_to do |format|
88 respond_to do |format|
92 format.js
89 format.js
93 end
90 end
94 end
91 end
95
92
96 protected
93 protected
97
94
98 def submission_authorization
95 def submission_authorization
99 #admin always has privileged
96 #admin always has privileged
100 if @current_user.admin?
97 if @current_user.admin?
101 return true
98 return true
102 end
99 end
103
100
104 sub = Submission.find(params[:id])
101 sub = Submission.find(params[:id])
105 if @current_user.available_problems.include? sub.problem
102 if @current_user.available_problems.include? sub.problem
106 return true if GraderConfiguration["right.user_view_submission"] or sub.user == @current_user
103 return true if GraderConfiguration["right.user_view_submission"] or sub.user == @current_user
107 end
104 end
108
105
109 #default to NO
106 #default to NO
110 unauthorized_redirect
107 unauthorized_redirect
111 return false
108 return false
112 end
109 end
113
110
114
111
115 end
112 end
@@ -16,167 +16,171
16 @paginated = true
16 @paginated = true
17 end
17 end
18 @users = User.all
18 @users = User.all
19 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
19 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
20 @contests = Contest.enabled
20 @contests = Contest.enabled
21 end
21 end
22
22
23 def active
23 def active
24 sessions = ActiveRecord::SessionStore::Session.where("updated_at >= ?", 60.minutes.ago)
24 sessions = ActiveRecord::SessionStore::Session.where("updated_at >= ?", 60.minutes.ago)
25 @users = []
25 @users = []
26 sessions.each do |session|
26 sessions.each do |session|
27 if session.data[:user_id]
27 if session.data[:user_id]
28 @users << User.find(session.data[:user_id])
28 @users << User.find(session.data[:user_id])
29 end
29 end
30 end
30 end
31 end
31 end
32
32
33 def show
33 def show
34 @user = User.find(params[:id])
34 @user = User.find(params[:id])
35 end
35 end
36
36
37 def new
37 def new
38 @user = User.new
38 @user = User.new
39 end
39 end
40
40
41 def create
41 def create
42 @user = User.new(user_params)
42 @user = User.new(user_params)
43 @user.activated = true
43 @user.activated = true
44 if @user.save
44 if @user.save
45 flash[:notice] = 'User was successfully created.'
45 flash[:notice] = 'User was successfully created.'
46 redirect_to :action => 'index'
46 redirect_to :action => 'index'
47 else
47 else
48 render :action => 'new'
48 render :action => 'new'
49 end
49 end
50 end
50 end
51
51
52 def clear_last_ip
52 def clear_last_ip
53 @user = User.find(params[:id])
53 @user = User.find(params[:id])
54 @user.last_ip = nil
54 @user.last_ip = nil
55 @user.save
55 @user.save
56 redirect_to action: 'index', page: params[:page]
56 redirect_to action: 'index', page: params[:page]
57 end
57 end
58
58
59 def create_from_list
59 def create_from_list
60 lines = params[:user_list]
60 lines = params[:user_list]
61
61
62 note = []
62 note = []
63 error_note = []
63 error_note = []
64 + error_msg = nil
64 ok_user = []
65 ok_user = []
65
66
66 lines.split("\n").each do |line|
67 lines.split("\n").each do |line|
67 items = line.chomp.split(',')
68 items = line.chomp.split(',')
68 if items.length>=2
69 if items.length>=2
69 login = items[0]
70 login = items[0]
70 full_name = items[1]
71 full_name = items[1]
71 remark =''
72 remark =''
72 user_alias = ''
73 user_alias = ''
73
74
74 added_random_password = false
75 added_random_password = false
75 if items.length >= 3 and items[2].chomp(" ").length > 0;
76 if items.length >= 3 and items[2].chomp(" ").length > 0;
76 password = items[2].chomp(" ")
77 password = items[2].chomp(" ")
77 else
78 else
78 password = random_password
79 password = random_password
79 - add_random_password=true;
80 + added_random_password=true;
80 end
81 end
81
82
82 if items.length>= 4 and items[3].chomp(" ").length > 0;
83 if items.length>= 4 and items[3].chomp(" ").length > 0;
83 user_alias = items[3].chomp(" ")
84 user_alias = items[3].chomp(" ")
84 else
85 else
85 user_alias = login
86 user_alias = login
86 end
87 end
87
88
88 if items.length>=5
89 if items.length>=5
89 remark = items[4].strip;
90 remark = items[4].strip;
90 end
91 end
91
92
92 user = User.find_by_login(login)
93 user = User.find_by_login(login)
93 if (user)
94 if (user)
94 user.full_name = full_name
95 user.full_name = full_name
95 user.password = password
96 user.password = password
96 user.remark = remark
97 user.remark = remark
97 else
98 else
98 user = User.new({:login => login,
99 user = User.new({:login => login,
99 - :full_name => full_name,
100 + :full_name => full_name,
100 - :password => password,
101 + :password => password,
101 - :password_confirmation => password,
102 + :password_confirmation => password,
102 - :alias => user_alias,
103 + :alias => user_alias,
103 - :remark => remark})
104 + :remark => remark})
104 end
105 end
105 user.activated = true
106 user.activated = true
106
107
107 if user.save
108 if user.save
108 if added_random_password
109 if added_random_password
109 note << "'#{login}' (+)"
110 note << "'#{login}' (+)"
110 else
111 else
111 note << login
112 note << login
112 end
113 end
113 ok_user << user
114 ok_user << user
114 else
115 else
115 - error_note << "#{login}"
116 + error_note << "'#{login}'"
117 + error_msg = user.errors.full_messages.to_sentence unless error_msg
116 end
118 end
117
119
118 end
120 end
119 end
121 end
120
122
121 #add to group
123 #add to group
122 if params[:add_to_group]
124 if params[:add_to_group]
123 group = Group.where(id: params[:group_id]).first
125 group = Group.where(id: params[:group_id]).first
124 if group
126 if group
125 group.users << ok_user
127 group.users << ok_user
126 end
128 end
127 end
129 end
128
130
129 # show flash
131 # show flash
130 - flash[:success] = 'User(s) ' + note.join(', ') +
132 + if note.size > 0
131 - ' were successfully created. ' +
133 + flash[:success] = 'User(s) ' + note.join(', ') +
132 - '( (+) - created with random passwords.)'
134 + ' were successfully created. ' +
135 + '( (+) - created with random passwords.)'
136 + end
133 if error_note.size > 0
137 if error_note.size > 0
134 - flash[:error] = "Following user(s) failed to be created: " + error_note.join(', ')
138 + flash[:error] = "Following user(s) failed to be created: " + error_note.join(', ') + ". The error of the first failed one are: " + error_msg;
135 end
139 end
136 redirect_to :action => 'index'
140 redirect_to :action => 'index'
137 end
141 end
138
142
139 def edit
143 def edit
140 @user = User.find(params[:id])
144 @user = User.find(params[:id])
141 end
145 end
142
146
143 def update
147 def update
144 @user = User.find(params[:id])
148 @user = User.find(params[:id])
145 if @user.update_attributes(user_params)
149 if @user.update_attributes(user_params)
146 flash[:notice] = 'User was successfully updated.'
150 flash[:notice] = 'User was successfully updated.'
147 redirect_to :action => 'show', :id => @user
151 redirect_to :action => 'show', :id => @user
148 else
152 else
149 render :action => 'edit'
153 render :action => 'edit'
150 end
154 end
151 end
155 end
152
156
153 def destroy
157 def destroy
154 User.find(params[:id]).destroy
158 User.find(params[:id]).destroy
155 redirect_to :action => 'index'
159 redirect_to :action => 'index'
156 end
160 end
157
161
158 def user_stat
162 def user_stat
159 if params[:commit] == 'download csv'
163 if params[:commit] == 'download csv'
160 @problems = Problem.all
164 @problems = Problem.all
161 else
165 else
162 @problems = Problem.available_problems
166 @problems = Problem.available_problems
163 end
167 end
164 @users = User.includes(:contests, :contest_stat).where(enabled: true)
168 @users = User.includes(:contests, :contest_stat).where(enabled: true)
165 @scorearray = Array.new
169 @scorearray = Array.new
166 @users.each do |u|
170 @users.each do |u|
167 ustat = Array.new
171 ustat = Array.new
168 ustat[0] = u
172 ustat[0] = u
169 @problems.each do |p|
173 @problems.each do |p|
170 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
174 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
171 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
175 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
172 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
176 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
173 else
177 else
174 ustat << [0,false]
178 ustat << [0,false]
175 end
179 end
176 end
180 end
177 @scorearray << ustat
181 @scorearray << ustat
178 end
182 end
179 if params[:commit] == 'download csv' then
183 if params[:commit] == 'download csv' then
180 csv = gen_csv_from_scorearray(@scorearray,@problems)
184 csv = gen_csv_from_scorearray(@scorearray,@problems)
181 send_data csv, filename: 'last_score.csv'
185 send_data csv, filename: 'last_score.csv'
182 else
186 else
@@ -1,80 +1,82
1 .container-fluid
1 .container-fluid
2 .row
2 .row
3 .col-md-6
3 .col-md-6
4 %h1 Group #{@group.name}
4 %h1 Group #{@group.name}
5 .row
5 .row
6 .col-md-6
6 .col-md-6
7 %b Description:
7 %b Description:
8 = @group.description
8 = @group.description
9 %br
9 %br
10 = link_to 'Edit', edit_group_path(@group), class: 'btn btn-primary'
10 = link_to 'Edit', edit_group_path(@group), class: 'btn btn-primary'
11 .row
11 .row
12 .col-md-12
12 .col-md-12
13 %h1 Group details
13 %h1 Group details
14 .row
14 .row
15 .col-md-6
15 .col-md-6
16 .panel.panel-default
16 .panel.panel-default
17 .panel-heading
17 .panel-heading
18 .panel-title Users in this group
18 .panel-title Users in this group
19 .panel-body
19 .panel-body
20 %ul
20 %ul
21 %li
21 %li
22 If you want to add several users to a group, it may be easier to just re-import those users in
22 If you want to add several users to a group, it may be easier to just re-import those users in
23 = link_to 'New list of users', new_list_user_admin_index_path
23 = link_to 'New list of users', new_list_user_admin_index_path
24 - page
24 + page. You can also use
25 + = link_to 'Bulk Manage User', bulk_manage_user_admin_index_path
26 + page.
25 =form_tag add_user_group_path(@group), class: 'form-inline' do
27 =form_tag add_user_group_path(@group), class: 'form-inline' do
26 .form-group
28 .form-group
27 =label_tag :user_id, "User"
29 =label_tag :user_id, "User"
28 - =select_tag :user_id, options_from_collection_for_select(User.all,'id','full_name'), class: 'select2'
30 + =select_tag :user_id, options_from_collection_for_select(User.all,'id','full_name'), class: 'select2', style: 'width: 10em';
29 =submit_tag "Add",class: 'btn btn-primary'
31 =submit_tag "Add",class: 'btn btn-primary'
30
32
31
33
32 %table.table.table-hover
34 %table.table.table-hover
33 %thead
35 %thead
34 %tr
36 %tr
35 %th Login
37 %th Login
36 %th Full name
38 %th Full name
37 %th Remark
39 %th Remark
38 %th= link_to 'Remove All', remove_all_user_group_path(@group), method: :delete, :data => { :confirm => "Remove ALL USERS from group?" }, class: 'btn btn-danger btn-sm'
40 %th= link_to 'Remove All', remove_all_user_group_path(@group), method: :delete, :data => { :confirm => "Remove ALL USERS from group?" }, class: 'btn btn-danger btn-sm'
39
41
40 %tbody
42 %tbody
41 - @group.users.each do |user|
43 - @group.users.each do |user|
42 %tr
44 %tr
43 %td= user.login
45 %td= user.login
44 %td= user.full_name
46 %td= user.full_name
45 %td= user.remark
47 %td= user.remark
46 %td= link_to 'Remove', remove_user_group_path(@group,user), :method => :delete, :data => { :confirm => "Remove #{user.full_name}?" }, class: 'btn btn-danger btn-sm'
48 %td= link_to 'Remove', remove_user_group_path(@group,user), :method => :delete, :data => { :confirm => "Remove #{user.full_name}?" }, class: 'btn btn-danger btn-sm'
47 .col-md-6
49 .col-md-6
48 .panel.panel-default
50 .panel.panel-default
49 .panel-heading
51 .panel-heading
50 .panel-title Problems
52 .panel-title Problems
51 .panel-body
53 .panel-body
52 %ul
54 %ul
53 %li
55 %li
54 If you want to add several problem to a group, it may be easier to bulk manage them in the
56 If you want to add several problem to a group, it may be easier to bulk manage them in the
55 - = link_to 'Bulk Manage', manage_problems_path
57 + = link_to 'Bulk Manage Problems', manage_problems_path
56 page
58 page
57 =form_tag add_problem_group_path(@group), class: 'form-inline' do
59 =form_tag add_problem_group_path(@group), class: 'form-inline' do
58 .form-group
60 .form-group
59 =label_tag :problem_id, "Problem"
61 =label_tag :problem_id, "Problem"
60 - =select_tag :problem_id, options_from_collection_for_select(Problem.all,'id','full_name'), class: 'select2'
62 + =select_tag :problem_id, options_from_collection_for_select(Problem.all,'id','full_name'), class: 'select2', style: 'width: 10em';
61 =submit_tag "Add",class: 'btn btn-primary'
63 =submit_tag "Add",class: 'btn btn-primary'
62
64
63
65
64 %table.table.table-hover
66 %table.table.table-hover
65 %thead
67 %thead
66 %tr
68 %tr
67 %th name
69 %th name
68 %th Full name
70 %th Full name
69 %th Full score
71 %th Full score
70 %th= link_to 'Remove All', remove_all_problem_group_path(@group), method: :delete, :data => { :confirm => "Remove ALL PROBLEMS from group?" }, class: 'btn btn-danger btn-sm'
72 %th= link_to 'Remove All', remove_all_problem_group_path(@group), method: :delete, :data => { :confirm => "Remove ALL PROBLEMS from group?" }, class: 'btn btn-danger btn-sm'
71
73
72 %tbody
74 %tbody
73 - @group.problems.each do |problem|
75 - @group.problems.each do |problem|
74 %tr
76 %tr
75 %td= problem.name
77 %td= problem.name
76 %td= problem.full_name
78 %td= problem.full_name
77 %td= problem.full_score
79 %td= problem.full_score
78 %td= link_to 'Remove', remove_problem_group_path(@group,problem), :method => :delete, :data => { :confirm => "Remove #{problem.full_name}?" }, class: 'btn btn-danger btn-sm'
80 %td= link_to 'Remove', remove_problem_group_path(@group,problem), :method => :delete, :data => { :confirm => "Remove #{problem.full_name}?" }, class: 'btn btn-danger btn-sm'
79
81
80
82
@@ -1,11 +1,12
1 %h1= GraderConfiguration['ui.front.title']
1 %h1= GraderConfiguration['ui.front.title']
2
2
3 .row
3 .row
4 .col-md-6
4 .col-md-6
5 - if @announcements.length!=0
5 - if @announcements.length!=0
6 .announcementbox{:style => 'margin-top: 0px'}
6 .announcementbox{:style => 'margin-top: 0px'}
7 %span{:class => 'title'}
7 %span{:class => 'title'}
8 Announcements
8 Announcements
9 = render :partial => 'announcement', :collection => @announcements
9 = render :partial => 'announcement', :collection => @announcements
10 .col-md-4{style: "padding-left: 20px;"}
10 .col-md-4{style: "padding-left: 20px;"}
11 = render :partial => 'login_box'
11 = render :partial => 'login_box'
12 + = "current ip is #{@remote_ip}"
@@ -1,65 +1,65
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(@scorearray[0].count,0)
15 + - sum = Array.new(@problems.count+1,0)
16 - - nonzero = Array.new(@scorearray[0].count,0)
16 + - nonzero = Array.new(@problems.count+1,0)
17 - - full = Array.new(@scorearray[0].count,0)
17 + - full = Array.new(@problems.count+1,0)
18 - @scorearray.each do |sc|
18 - @scorearray.each do |sc|
19 %tr
19 %tr
20 - total,num_passed = 0,0
20 - total,num_passed = 0,0
21 - sc.each_index do |i|
21 - sc.each_index do |i|
22 - if i == 0
22 - if i == 0
23 %td= link_to sc[i].login, stat_user_path(sc[i])
23 %td= link_to sc[i].login, stat_user_path(sc[i])
24 %td= sc[i].full_name
24 %td= sc[i].full_name
25 / %td= sc[i].activated
25 / %td= sc[i].activated
26 / %td= sc[i].try(:contest_stat).try(:started_at) ? 'yes' : 'no'
26 / %td= sc[i].try(:contest_stat).try(:started_at) ? 'yes' : 'no'
27 / %td= sc[i].contests.collect {|c| c.name}.join(', ')
27 / %td= sc[i].contests.collect {|c| c.name}.join(', ')
28 %td= sc[i].remark
28 %td= sc[i].remark
29 - else
29 - else
30 %td.text-right= sc[i][0]
30 %td.text-right= sc[i][0]
31 - total += sc[i][0]
31 - total += sc[i][0]
32 - num_passed += 1 if sc[i][1]
32 - num_passed += 1 if sc[i][1]
33 - sum[i] += sc[i][0]
33 - sum[i] += sc[i][0]
34 - nonzero[i] += 1 if sc[i][0] > 0
34 - nonzero[i] += 1 if sc[i][0] > 0
35 - full[i] += 1 if sc[i][1]
35 - full[i] += 1 if sc[i][1]
36 %td.text-right= total
36 %td.text-right= total
37 %td.text-right= num_passed
37 %td.text-right= num_passed
38 %tfoot
38 %tfoot
39 %tr
39 %tr
40 %td Summation
40 %td Summation
41 %td
41 %td
42 %td
42 %td
43 - sum.each.with_index do |s,i|
43 - sum.each.with_index do |s,i|
44 - next if i == 0
44 - next if i == 0
45 %td.text-right= number_with_delimiter(s)
45 %td.text-right= number_with_delimiter(s)
46 %td
46 %td
47 %td
47 %td
48 %tr
48 %tr
49 %td partial solver
49 %td partial solver
50 %td
50 %td
51 %td
51 %td
52 - nonzero.each.with_index do |s,i|
52 - nonzero.each.with_index do |s,i|
53 - next if i == 0
53 - next if i == 0
54 %td.text-right= number_with_delimiter(s)
54 %td.text-right= number_with_delimiter(s)
55 %td
55 %td
56 %td
56 %td
57 %tr
57 %tr
58 %td Full solver
58 %td Full solver
59 %td
59 %td
60 %td
60 %td
61 - full.each.with_index do |s,i|
61 - full.each.with_index do |s,i|
62 - next if i == 0
62 - next if i == 0
63 %td.text-right= number_with_delimiter(s)
63 %td.text-right= number_with_delimiter(s)
64 %td
64 %td
65 %td
65 %td
@@ -1,11 +1,11
1 .container-fluid
1 .container-fluid
2 %h1 Current Score
2 %h1 Current Score
3 = form_tag current_score_report_path, method: 'get' do
3 = form_tag current_score_report_path, method: 'get' do
4 Show only users from this group
4 Show only users from this group
5 - = select_tag "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_name]), id: 'group_name',class: 'select2'
5 + = select_tag "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_id]), id: 'group_name',class: 'select2', style: 'width: 20em';
6 = submit_tag 'Apply',class: 'btn btn-default'
6 = submit_tag 'Apply',class: 'btn btn-default'
7
7
8 %br
8 %br
9
9
10
10
11 = render "score_table"
11 = render "score_table"
@@ -102,97 +102,96
102 end
102 end
103
103
104
104
105 #user admin
105 #user admin
106 resources :user_admin do
106 resources :user_admin do
107 collection do
107 collection do
108 match 'bulk_manage', via: [:get, :post]
108 match 'bulk_manage', via: [:get, :post]
109 get 'bulk_mail'
109 get 'bulk_mail'
110 get 'user_stat'
110 get 'user_stat'
111 get 'import'
111 get 'import'
112 get 'new_list'
112 get 'new_list'
113 get 'admin'
113 get 'admin'
114 get 'active'
114 get 'active'
115 get 'mass_mailing'
115 get 'mass_mailing'
116 get 'revoke_admin'
116 get 'revoke_admin'
117 post 'grant_admin'
117 post 'grant_admin'
118 match 'create_from_list', via: [:get, :post]
118 match 'create_from_list', via: [:get, :post]
119 match 'random_all_passwords', via: [:get, :post]
119 match 'random_all_passwords', via: [:get, :post]
120 end
120 end
121 member do
121 member do
122 get 'clear_last_ip'
122 get 'clear_last_ip'
123 end
123 end
124 end
124 end
125
125
126 resources :contest_management, only: [:index] do
126 resources :contest_management, only: [:index] do
127 collection do
127 collection do
128 get 'user_stat'
128 get 'user_stat'
129 get 'clear_stat'
129 get 'clear_stat'
130 get 'clear_all_stat'
130 get 'clear_all_stat'
131 get 'change_contest_mode'
131 get 'change_contest_mode'
132 end
132 end
133 end
133 end
134
134
135 #get 'user_admin', to: 'user_admin#index'
135 #get 'user_admin', to: 'user_admin#index'
136 #get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin'
136 #get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin'
137 #post 'user_admin', to: 'user_admin#create'
137 #post 'user_admin', to: 'user_admin#create'
138 #delete 'user_admin/:id', to: 'user_admin#destroy', as: 'user_admin_destroy'
138 #delete 'user_admin/:id', to: 'user_admin#destroy', as: 'user_admin_destroy'
139
139
140 #singular resource
140 #singular resource
141 #---- BEWARE ---- singular resource maps to plural controller by default, we can override by provide controller name directly
141 #---- BEWARE ---- singular resource maps to plural controller by default, we can override by provide controller name directly
142 #report
142 #report
143 resource :report, only: [], controller: 'report' do
143 resource :report, only: [], controller: 'report' do
144 get 'login'
144 get 'login'
145 get 'multiple_login'
145 get 'multiple_login'
146 get 'problem_hof(/:id)', action: 'problem_hof', as: 'problem_hof'
146 get 'problem_hof(/:id)', action: 'problem_hof', as: 'problem_hof'
147 get 'current_score(/:group_id)', action: 'current_score', as: 'current_score'
147 get 'current_score(/:group_id)', action: 'current_score', as: 'current_score'
148 get 'max_score'
148 get 'max_score'
149 post 'show_max_score'
149 post 'show_max_score'
150 - get 'problem_hof(/:id)', action: 'problem_hof', as: 'problem_hof'
151 get 'stuck'
150 get 'stuck'
152 get 'cheat_report'
151 get 'cheat_report'
153 post 'cheat_report'
152 post 'cheat_report'
154 get 'cheat_scruntinize'
153 get 'cheat_scruntinize'
155 post 'cheat_scruntinize'
154 post 'cheat_scruntinize'
156 end
155 end
157 #get 'report/current_score', to: 'report#current_score', as: 'report_current_score'
156 #get 'report/current_score', to: 'report#current_score', as: 'report_current_score'
158 #get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
157 #get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
159 #get "report/login"
158 #get "report/login"
160 #get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
159 #get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
161 #post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score'
160 #post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score'
162
161
163 resource :main, only: [], controller: 'main' do
162 resource :main, only: [], controller: 'main' do
164 get 'login'
163 get 'login'
165 get 'logout'
164 get 'logout'
166 get 'list'
165 get 'list'
167 get 'submission(/:id)', action: 'submission', as: 'main_submission'
166 get 'submission(/:id)', action: 'submission', as: 'main_submission'
168 get 'announcements'
167 get 'announcements'
169 get 'help'
168 get 'help'
170 post 'submit'
169 post 'submit'
171 end
170 end
172 #main
171 #main
173 #get "main/list"
172 #get "main/list"
174 #get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
173 #get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
175 #post 'main/submit', to: 'main#submit'
174 #post 'main/submit', to: 'main#submit'
176 #get 'main/announcements', to: 'main#announcements'
175 #get 'main/announcements', to: 'main#announcements'
177
176
178
177
179 #
178 #
180 get 'tasks/view/:file.:ext' => 'tasks#view'
179 get 'tasks/view/:file.:ext' => 'tasks#view'
181 get 'tasks/download/:id/:file.:ext' => 'tasks#download'
180 get 'tasks/download/:id/:file.:ext' => 'tasks#download'
182 get 'heartbeat/:id/edit' => 'heartbeat#edit'
181 get 'heartbeat/:id/edit' => 'heartbeat#edit'
183
182
184 #grader
183 #grader
185 get 'graders/list', to: 'graders#list', as: 'grader_list'
184 get 'graders/list', to: 'graders#list', as: 'grader_list'
186 namespace :graders do
185 namespace :graders do
187 get 'task/:id/:type', action: 'task', as: 'task'
186 get 'task/:id/:type', action: 'task', as: 'task'
188 get 'view/:id/:type', action: 'view', as: 'view'
187 get 'view/:id/:type', action: 'view', as: 'view'
189 get 'clear/:id', action: 'clear', as: 'clear'
188 get 'clear/:id', action: 'clear', as: 'clear'
190 get 'stop'
189 get 'stop'
191 get 'stop_all'
190 get 'stop_all'
192 get 'clear_all'
191 get 'clear_all'
193 get 'clear_terminated'
192 get 'clear_terminated'
194 get 'start_grading'
193 get 'start_grading'
195 get 'start_exam'
194 get 'start_exam'
196
195
197 end
196 end
198
197
@@ -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
@@ -55,234 +55,234
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
@@ -5,97 +5,97
5 # visit users_url
5 # visit users_url
6 #
6 #
7 # assert_selector "h1", text: "User"
7 # assert_selector "h1", text: "User"
8 # end
8 # end
9
9
10 test "add new user and edit" do
10 test "add new user and edit" do
11 login('admin','admin')
11 login('admin','admin')
12 within 'header' do
12 within 'header' do
13 click_on 'Manage'
13 click_on 'Manage'
14 click_on 'Users', match: :first
14 click_on 'Users', match: :first
15 end
15 end
16
16
17 assert_text "Users"
17 assert_text "Users"
18 assert_text "New user"
18 assert_text "New user"
19
19
20 click_on "New user", match: :first
20 click_on "New user", match: :first
21 fill_in 'Login', with: 'test1'
21 fill_in 'Login', with: 'test1'
22 fill_in 'Full name', with: 'test1 McTestface'
22 fill_in 'Full name', with: 'test1 McTestface'
23 fill_in 'e-mail', with: 'a@a.com'
23 fill_in 'e-mail', with: 'a@a.com'
24 fill_in 'Password', with: 'abcdef'
24 fill_in 'Password', with: 'abcdef'
25 fill_in 'Password confirmation', with: 'abcdef'
25 fill_in 'Password confirmation', with: 'abcdef'
26
26
27 click_on 'Create'
27 click_on 'Create'
28
28
29 assert_text 'User was successfully created'
29 assert_text 'User was successfully created'
30 assert_text 'a@a.com'
30 assert_text 'a@a.com'
31 assert_text 'test1 McTestface'
31 assert_text 'test1 McTestface'
32
32
33 within('tr', text: 'McTestface') do
33 within('tr', text: 'McTestface') do
34 click_on 'Edit'
34 click_on 'Edit'
35 end
35 end
36
36
37 fill_in 'Alias', with: 'hahaha'
37 fill_in 'Alias', with: 'hahaha'
38 fill_in 'Remark', with: 'section 2'
38 fill_in 'Remark', with: 'section 2'
39 click_on 'Update User'
39 click_on 'Update User'
40
40
41 assert_text 'section 2'
41 assert_text 'section 2'
42 end
42 end
43
43
44 test "add multiple users" do
44 test "add multiple users" do
45 login 'admin', 'admin'
45 login 'admin', 'admin'
46 within 'header' do
46 within 'header' do
47 click_on 'Manage'
47 click_on 'Manage'
48 click_on 'Users', match: :first
48 click_on 'Users', match: :first
49 end
49 end
50
50
51 click_on 'New list of users', match: :first
51 click_on 'New list of users', match: :first
52 find(:css, 'textarea').fill_in with:"abc1,Boaty McBoatface,abcdef,alias1,remark1,\nabc2,Boaty2 McSecond,acbdef123,aias2,remark2"
52 find(:css, 'textarea').fill_in with:"abc1,Boaty McBoatface,abcdef,alias1,remark1,\nabc2,Boaty2 McSecond,acbdef123,aias2,remark2"
53 - click_on 'create users'
53 + click_on 'Create following users'
54
54
55 assert_text('remark1')
55 assert_text('remark1')
56 assert_text('remark2')
56 assert_text('remark2')
57 end
57 end
58
58
59 test "grant admin right" do
59 test "grant admin right" do
60 login 'admin', 'admin'
60 login 'admin', 'admin'
61 within 'header' do
61 within 'header' do
62 click_on 'Manage'
62 click_on 'Manage'
63 click_on 'Users', match: :first
63 click_on 'Users', match: :first
64 end
64 end
65
65
66 click_on "View administrator"
66 click_on "View administrator"
67 fill_in 'login', with: 'john'
67 fill_in 'login', with: 'john'
68 click_on "Grant"
68 click_on "Grant"
69
69
70 visit logout_main_path
70 visit logout_main_path
71 login 'john','hello'
71 login 'john','hello'
72 within 'header' do
72 within 'header' do
73 click_on 'Manage'
73 click_on 'Manage'
74 click_on 'Problem', match: :first
74 click_on 'Problem', match: :first
75 end
75 end
76 assert_text "Turn off all problems"
76 assert_text "Turn off all problems"
77 end
77 end
78
78
79 test "try using admin from normal user" do
79 test "try using admin from normal user" do
80 login 'admin','admin'
80 login 'admin','admin'
81 visit bulk_manage_user_admin_index_path
81 visit bulk_manage_user_admin_index_path
82 assert_current_path bulk_manage_user_admin_index_path
82 assert_current_path bulk_manage_user_admin_index_path
83 visit logout_main_path
83 visit logout_main_path
84
84
85 login 'jack','morning'
85 login 'jack','morning'
86 visit bulk_manage_user_admin_index_path
86 visit bulk_manage_user_admin_index_path
87 assert_text 'You are not authorized'
87 assert_text 'You are not authorized'
88 assert_current_path login_main_path
88 assert_current_path login_main_path
89
89
90 login 'james','morning'
90 login 'james','morning'
91 visit new_list_user_admin_index_path
91 visit new_list_user_admin_index_path
92 assert_text 'You are not authorized'
92 assert_text 'You are not authorized'
93 assert_current_path login_main_path
93 assert_current_path login_main_path
94 end
94 end
95
95
96 test "login then change password" do
96 test "login then change password" do
97 newpassword = '1234asdf'
97 newpassword = '1234asdf'
98 login 'john', 'hello'
98 login 'john', 'hello'
99 visit profile_users_path
99 visit profile_users_path
100
100
101 fill_in 'password', with: newpassword
101 fill_in 'password', with: newpassword
You need to be logged in to leave comments. Login now