Description:
- fix authorization for viewing submission, only admin can view all problems all the time, normal user depends on right.view_submission and problem.available? - add max score query
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r593:a1d7330b2f43 - - 6 files changed: 106 inserted, 7 deleted

@@ -0,0 +1,43
1 + %h1 Maximum score
2 +
3 + = form_tag report_max_score_path
4 + .row
5 + .col-md-4
6 + .panel.panel-primary
7 + .panel-heading
8 + Problems
9 + .panel-body
10 + = label_tag :problems, "Problems"
11 + = select 'problems', 'problem_id', [[(t 'main.specified_in_header'),'-1']] + Problem.all.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]}, {:selected => '-1'}, { class: 'select2 form-control' }
12 + .col-md-4
13 + .panel.panel-primary
14 + .panel-heading
15 + Submission range
16 + .panel-body
17 + .form-group
18 + = label_tag :from, "From"
19 + = text_field_tag 'from_id', nil, class: "form-control"
20 + .form-group
21 + = label_tag :from, "To"
22 + = text_field_tag 'to_id', nil, class: "form-control"
23 + .col-md-4
24 + .panel.panel-primary
25 + .panel-heading
26 + Users
27 + .panel-body
28 + .radio
29 + %label
30 + = radio_button_tag 'users', 'all', true
31 + All users
32 + .radio
33 + %label
34 + = radio_button_tag 'users', 'enabled'
35 + Only enabled users
36 + .row
37 + .col-md-12
38 + = button_tag 'Show', class: "btn btn-primary btn-large"
39 + = button_tag 'Download CSV', class: "btn btn-primary btn-large"
40 + /.col-md-4.col-md-offset-1
41 + / = button_tag 'Show', class: "btn btn-primary btn-block"
42 + /.col-md-4.col-md-offset-2
43 + / = button_tag 'Download CSV', class: "btn btn-primary btn-block"
@@ -1,29 +1,33
1 1 # See http://help.github.com/ignore-files/ for more about ignoring files.
2 2 #
3 3 # If you find yourself ignoring temporary files generated by your text editor
4 4 # or operating system, you probably want to add a global ignore instead:
5 5 # git config --global core.excludesfile ~/.gitignore_global
6 6
7 7 # Ignore bundler config
8 8 /.bundle
9 9
10 10 # Ignore the default SQLite database.
11 11 /db/*.sqlite3
12 12
13 13 # Ignore all logfiles and tempfiles.
14 14 /log/*.log
15 15 /tmp
16 16
17 17 *~
18 18
19 19 /vendor/plugins/rails_upgrade
20 20
21 21 #ignore public assets???
22 22 /public/assets
23 23 /public
24 24
25 25 /data
26 26
27 27 #ignore .orig and .swp
28 28 *.orig
29 29 *.swp
30 +
31 + #ignore rvm setting file
32 + .ruby-gemset
33 + .ruby-version
@@ -1,124 +1,128
1 1 class ApplicationController < ActionController::Base
2 2 protect_from_forgery
3 3
4 4 before_filter :current_user
5 5
6 6 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
7 7 MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login'
8 8
9 + #report and redirect for unauthorized activities
10 + def unauthorized_redirect
11 + flash[:notice] = 'You are not authorized to view the page you requested'
12 + redirect_to :controller => 'main', :action => 'login'
13 + end
14 +
9 15 # Returns the current logged-in user (if any).
10 16 def current_user
11 17 return nil unless session[:user_id]
12 18 @current_user ||= User.find(session[:user_id])
13 19 end
14 20
15 21 def admin_authorization
16 22 return false unless authenticate
17 23 user = User.find(session[:user_id], :include => ['roles'])
18 24 unless user.admin?
19 - flash[:notice] = 'You are not authorized to view the page you requested'
20 - redirect_to :controller => 'main', :action => 'login' unless user.admin?
25 + unauthorized_redirect
21 26 return false
22 27 end
23 28 return true
24 29 end
25 30
26 31 def authorization_by_roles(allowed_roles)
27 32 return false unless authenticate
28 33 user = User.find(session[:user_id])
29 34 unless user.roles.detect { |role| allowed_roles.member?(role.name) }
30 - flash[:notice] = 'You are not authorized to view the page you requested'
31 - redirect_to :controller => 'main', :action => 'login'
35 + unauthorized_redirect
32 36 return false
33 37 end
34 38 end
35 39
36 40 protected
37 41
38 42 def authenticate
39 43 unless session[:user_id]
40 44 flash[:notice] = 'You need to login'
41 45 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
42 46 flash[:notice] = 'You need to login but you cannot log in at this time'
43 47 end
44 48 redirect_to :controller => 'main', :action => 'login'
45 49 return false
46 50 end
47 51
48 52 # check if run in single user mode
49 53 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
50 54 user = User.find_by_id(session[:user_id])
51 55 if user==nil or (not user.admin?)
52 56 flash[:notice] = 'You cannot log in at this time'
53 57 redirect_to :controller => 'main', :action => 'login'
54 58 return false
55 59 end
56 60 unless user.enabled?
57 61 flash[:notice] = 'Your account is disabled'
58 62 redirect_to :controller => 'main', :action => 'login'
59 63 return false
60 64 end
61 65 return true
62 66 end
63 67
64 68 if GraderConfiguration.multicontests?
65 69 user = User.find(session[:user_id])
66 70 return true if user.admin?
67 71 begin
68 72 if user.contest_stat(true).forced_logout
69 73 flash[:notice] = 'You have been automatically logged out.'
70 74 redirect_to :controller => 'main', :action => 'index'
71 75 end
72 76 rescue
73 77 end
74 78 end
75 79 return true
76 80 end
77 81
78 82 def authenticate_by_ip_address
79 83 #this assume that we have already authenticate normally
80 84 unless GraderConfiguration[MULTIPLE_IP_LOGIN_CONF_KEY]
81 85 user = User.find(session[:user_id])
82 86 if (not user.admin? and user.last_ip and user.last_ip != request.remote_ip)
83 87 flash[:notice] = "You cannot use the system from #{request.remote_ip}. Your last ip is #{user.last_ip}"
84 88 redirect_to :controller => 'main', :action => 'login'
85 89 puts "CHEAT: user #{user.login} tried to login from '#{request.remote_ip}' while last ip is '#{user.last_ip}' at #{Time.zone.now}"
86 90 return false
87 91 end
88 92 unless user.last_ip
89 93 user.last_ip = request.remote_ip
90 94 user.save
91 95 end
92 96 end
93 97 return true
94 98 end
95 99
96 100 def authorization
97 101 return false unless authenticate
98 102 user = User.find(session[:user_id])
99 103 unless user.roles.detect { |role|
100 104 role.rights.detect{ |right|
101 105 right.controller == self.class.controller_name and
102 106 (right.action == 'all' or right.action == action_name)
103 107 }
104 108 }
105 109 flash[:notice] = 'You are not authorized to view the page you requested'
106 110 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
107 111 redirect_to :controller => 'main', :action => 'login'
108 112 return false
109 113 end
110 114 end
111 115
112 116 def verify_time_limit
113 117 return true if session[:user_id]==nil
114 118 user = User.find(session[:user_id], :include => :site)
115 119 return true if user==nil or user.site == nil
116 120 if user.contest_finished?
117 121 flash[:notice] = 'Error: the contest you are participating is over.'
118 122 redirect_to :back
119 123 return false
120 124 end
121 125 return true
122 126 end
123 127
124 128 end
@@ -1,107 +1,114
1 1 class GradersController < ApplicationController
2 2
3 3 before_filter :admin_authorization, except: [ :submission ]
4 4 before_filter(only: [:submission]) {
5 + #check if authenticated
5 6 return false unless authenticate
6 7
7 - if GraderConfiguration["right.user_view_submission"]
8 - return true;
8 + #admin always has privileged
9 + if @current_user.admin?
10 + return true
9 11 end
10 12
11 - admin_authorization
13 + if GraderConfiguration["right.user_view_submission"] and Submission.find(params[:id]).problem.available?
14 + return true
15 + else
16 + unauthorized_redirect
17 + return false
18 + end
12 19 }
13 20
14 21 verify :method => :post, :only => ['clear_all',
15 22 'start_exam',
16 23 'start_grading',
17 24 'stop_all',
18 25 'clear_terminated'],
19 26 :redirect_to => {:action => 'index'}
20 27
21 28 def index
22 29 redirect_to :action => 'list'
23 30 end
24 31
25 32 def list
26 33 @grader_processes = GraderProcess.find_running_graders
27 34 @stalled_processes = GraderProcess.find_stalled_process
28 35
29 36 @terminated_processes = GraderProcess.find_terminated_graders
30 37
31 38 @last_task = Task.find(:first,
32 39 :order => 'created_at DESC')
33 40 @last_test_request = TestRequest.find(:first,
34 41 :order => 'created_at DESC')
35 42 @submission = Submission.order("id desc").limit(20)
36 43 @backlog_submission = Submission.where('graded_at is null')
37 44 end
38 45
39 46 def clear
40 47 grader_proc = GraderProcess.find(params[:id])
41 48 grader_proc.destroy if grader_proc!=nil
42 49 redirect_to :action => 'list'
43 50 end
44 51
45 52 def clear_terminated
46 53 GraderProcess.find_terminated_graders.each do |p|
47 54 p.destroy
48 55 end
49 56 redirect_to :action => 'list'
50 57 end
51 58
52 59 def clear_all
53 60 GraderProcess.find(:all).each do |p|
54 61 p.destroy
55 62 end
56 63 redirect_to :action => 'list'
57 64 end
58 65
59 66 def view
60 67 if params[:type]=='Task'
61 68 redirect_to :action => 'task', :id => params[:id]
62 69 else
63 70 redirect_to :action => 'test_request', :id => params[:id]
64 71 end
65 72 end
66 73
67 74 def test_request
68 75 @test_request = TestRequest.find(params[:id])
69 76 end
70 77
71 78 def task
72 79 @task = Task.find(params[:id])
73 80 end
74 81
75 82 def submission
76 83 @submission = Submission.find(params[:id])
77 84 formatter = Rouge::Formatters::HTML.new(css_class: 'highlight', line_numbers: true )
78 85 lexer = case @submission.language.name
79 86 when "c" then Rouge::Lexers::C.new
80 87 when "cpp" then Rouge::Lexers::Cpp.new
81 88 when "pas" then Rouge::Lexers::Pas.new
82 89 when "ruby" then Rouge::Lexers::Ruby.new
83 90 when "python" then Rouge::Lexers::Python.new
84 91 when "java" then Rouge::Lexers::Java.new
85 92 when "php" then Rouge::Lexers::PHP.new
86 93 end
87 94 @formatted_code = formatter.format(lexer.lex(@submission.source))
88 95 @css_style = Rouge::Themes::ThankfulEyes.render(scope: '.highlight')
89 96
90 97 user = User.find(session[:user_id])
91 98 SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin?
92 99
93 100 end
94 101
95 102 # various grader controls
96 103
97 104 def stop
98 105 grader_proc = GraderProcess.find(params[:id])
99 106 GraderScript.stop_grader(grader_proc.pid)
100 107 flash[:notice] = 'Grader stopped. It may not disappear now, but it should disappear shortly.'
101 108 redirect_to :action => 'list'
102 109 end
103 110
104 111 def stop_all
105 112 GraderScript.stop_graders(GraderProcess.find_running_graders +
106 113 GraderProcess.find_stalled_process)
107 114 flash[:notice] = 'Graders stopped. They may not disappear now, but they should disappear shortly.'
@@ -1,110 +1,149
1 1 class ReportController < ApplicationController
2 2
3 3 before_filter :admin_authorization, only: [:login_stat,:submission_stat, :stuck, :cheat_report, :cheat_scruntinize]
4 4
5 5 before_filter(only: [:problem_hof]) { |c|
6 6 return false unless authenticate
7 7
8 8 if GraderConfiguration["right.user_view_submission"]
9 9 return true;
10 10 end
11 11
12 12 admin_authorization
13 13 }
14 14
15 + def show_max_score
16 + end
17 +
18 + def get_max_score
19 + #process list of problems
20 +
21 + #process submission range
22 + if params[:commit] == 'download csv'
23 + @problems = Problem.all
24 + else
25 + @problems = Problem.find_available_problems
26 + end
27 + @users = User.find(:all, :include => [:contests, :contest_stat])
28 + @scorearray = Array.new
29 + #set up range from param
30 + since_id = params.fetch(:since_id, 0).to_i
31 + until_id = params.fetch(:until_id, 0).to_i
32 + @users.each do |u|
33 + ustat = Array.new
34 + ustat[0] = u
35 + @problems.each do |p|
36 + max_points = 0
37 + Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub|
38 + max_points = sub.points if sub and sub.points and (sub.points > max_points)
39 + end
40 + ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)]
41 + end
42 + @scorearray << ustat
43 + end
44 +
45 + if params[:commit] == 'download csv' then
46 + csv = gen_csv_from_scorearray(@scorearray,@problems)
47 + send_data csv, filename: 'max_score.csv'
48 + else
49 + render template: 'user_admin/user_stat'
50 + end
51 +
52 + end
53 +
15 54 def score
16 55 if params[:commit] == 'download csv'
17 56 @problems = Problem.all
18 57 else
19 58 @problems = Problem.find_available_problems
20 59 end
21 60 @users = User.includes(:contests, :contest_stat).where(enabled: true) #find(:all, :include => [:contests, :contest_stat]).where(enabled: true)
22 61 @scorearray = Array.new
23 62 @users.each do |u|
24 63 ustat = Array.new
25 64 ustat[0] = u
26 65 @problems.each do |p|
27 66 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
28 67 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
29 68 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
30 69 else
31 70 ustat << [0,false]
32 71 end
33 72 end
34 73 @scorearray << ustat
35 74 end
36 75 if params[:commit] == 'download csv' then
37 76 csv = gen_csv_from_scorearray(@scorearray,@problems)
38 77 send_data csv, filename: 'last_score.csv'
39 78 else
40 79 render template: 'user_admin/user_stat'
41 80 end
42 81
43 82 end
44 83
45 84 def login_stat
46 85 @logins = Array.new
47 86
48 87 date_and_time = '%Y-%m-%d %H:%M'
49 88 begin
50 89 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
51 90 @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)
52 91 rescue
53 92 @since_time = DateTime.new(1000,1,1)
54 93 end
55 94 begin
56 95 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
57 96 @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)
58 97 rescue
59 98 @until_time = DateTime.new(3000,1,1)
60 99 end
61 100
62 101 User.all.each do |user|
63 102 @logins << { id: user.id,
64 103 login: user.login,
65 104 full_name: user.full_name,
66 105 count: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
67 106 user.id,@since_time,@until_time)
68 107 .count(:id),
69 108 min: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
70 109 user.id,@since_time,@until_time)
71 110 .minimum(:created_at),
72 111 max: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
73 112 user.id,@since_time,@until_time)
74 113 .maximum(:created_at),
75 114 ip: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
76 115 user.id,@since_time,@until_time)
77 116 .select(:ip_address).uniq
78 117
79 118 }
80 119 end
81 120 end
82 121
83 122 def submission_stat
84 123
85 124 date_and_time = '%Y-%m-%d %H:%M'
86 125 begin
87 126 @since_time = DateTime.strptime(params[:since_datetime],date_and_time)
88 127 rescue
89 128 @since_time = DateTime.new(1000,1,1)
90 129 end
91 130 begin
92 131 @until_time = DateTime.strptime(params[:until_datetime],date_and_time)
93 132 rescue
94 133 @until_time = DateTime.new(3000,1,1)
95 134 end
96 135
97 136 @submissions = {}
98 137
99 138 User.find_each do |user|
100 139 @submissions[user.id] = { login: user.login, full_name: user.full_name, count: 0, sub: { } }
101 140 end
102 141
103 142 Submission.where("submitted_at >= ? AND submitted_at <= ?",@since_time,@until_time).find_each do |s|
104 143 if @submissions[s.user_id]
105 144 if not @submissions[s.user_id][:sub].has_key?(s.problem_id)
106 145 a = Problem.find_by_id(s.problem_id)
107 146 @submissions[s.user_id][:sub][s.problem_id] =
108 147 { prob_name: (a ? a.full_name : '(NULL)'),
109 148 sub_ids: [s.id] }
110 149 else
@@ -1,65 +1,67
1 1 CafeGrader::Application.routes.draw do
2 2 get "sources/direct_edit"
3 3
4 4 root :to => 'main#login'
5 5
6 6 resources :contests
7 7
8 8 resources :sites
9 9
10 10 resources :announcements do
11 11 member do
12 12 get 'toggle','toggle_front'
13 13 end
14 14 end
15 15
16 16 resources :problems do
17 17 member do
18 18 get 'toggle'
19 19 get 'toggle_test'
20 20 end
21 21 collection do
22 22 get 'turn_all_off'
23 23 get 'turn_all_on'
24 24 get 'import'
25 25 get 'manage'
26 26 end
27 27 end
28 28
29 29 resources :grader_configuration, controller: 'configurations'
30 30
31 31 resources :users do
32 32 member do
33 33 get 'toggle_activate', 'toggle_enable'
34 34 end
35 35 end
36 36
37 37 #source code edit
38 38 get 'sources/direct_edit/:pid', to: 'sources#direct_edit', as: 'direct_edit'
39 39 get 'sources/direct_edit_submission/:sid', to: 'sources#direct_edit_submission', as: 'direct_edit_submission'
40 40 get 'sources/get_latest_submission_status/:uid/:pid', to: 'sources#get_latest_submission_status', as: 'get_latest_submission_status'
41 41
42 42
43 43 match 'tasks/view/:file.:ext' => 'tasks#view'
44 44 match 'tasks/download/:id/:file.:ext' => 'tasks#download'
45 45 match 'heartbeat/:id/edit' => 'heartbeat#edit'
46 46
47 47 #main
48 48 get "main/list"
49 49 get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
50 50
51 51 #report
52 52 get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
53 53 get "report/login"
54 + get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
54 55
55 56 #grader
56 57 get 'graders/list', to: 'graders#list', as: 'grader_list'
58 +
57 59
58 60 match 'heartbeat/:id/edit' => 'heartbeat#edit'
59 61
60 62 # See how all your routes lay out with "rake routes"
61 63
62 64 # This is a legacy wild controller route that's not recommended for RESTful applications.
63 65 # Note: This route will make all actions in every controller accessible via GET requests.
64 66 match ':controller(/:action(/:id))(.:format)'
65 67 end
You need to be logged in to leave comments. Login now