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

r801:33c0929c92ed - - 24 files changed: 201 inserted, 117 deleted

@@ -0,0 +1,8
1 + = render partial: 'toggle_button',
2 + locals: {button_id: "#group-enabled-#{@group.id}",button_on: @group.enabled }
3 + :plain
4 + r = $("#group-#{@group.id}");
5 + r.removeClass('success');
6 + r.removeClass('danger');
7 + r.addClass("#{@group.enabled? ? 'success' : 'danger'}");
8 +
@@ -0,0 +1,5
1 + class AddEnabledToGroup < ActiveRecord::Migration[5.2]
2 + def change
3 + add_column :groups, :enabled, :boolean, default: true
4 + end
5 + end
@@ -131,50 +131,51
131 }
131 }
132 }
132 }
133 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'
134 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
134 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
135 redirect_to :controller => 'main', :action => 'login'
135 redirect_to :controller => 'main', :action => 'login'
136 return false
136 return false
137 end
137 end
138 end
138 end
139
139
140 def verify_time_limit
140 def verify_time_limit
141 return true if session[:user_id]==nil
141 return true if session[:user_id]==nil
142 user = User.find(session[:user_id], :include => :site)
142 user = User.find(session[:user_id], :include => :site)
143 return true if user==nil || user.site == nil
143 return true if user==nil || user.site == nil
144 if user.contest_finished?
144 if user.contest_finished?
145 flash[:notice] = 'Error: the contest you are participating is over.'
145 flash[:notice] = 'Error: the contest you are participating is over.'
146 redirect_to :back
146 redirect_to :back
147 return false
147 return false
148 end
148 end
149 return true
149 return true
150 end
150 end
151
151
152 def is_request_ip_allowed?
152 def is_request_ip_allowed?
153 unless GraderConfiguration[WHITELIST_IGNORE_CONF_KEY]
153 unless GraderConfiguration[WHITELIST_IGNORE_CONF_KEY]
154 user_ip = IPAddr.new(request.remote_ip)
154 user_ip = IPAddr.new(request.remote_ip)
155 + allowed = GraderConfiguration[WHITELIST_IP_CONF_KEY] || ''
155
156
156 - GraderConfiguration[WHITELIST_IP_CONF_KEY].delete(' ').split(',').each do |ips|
157 + allowed.delete(' ').split(',').each do |ips|
157 allow_ips = IPAddr.new(ips)
158 allow_ips = IPAddr.new(ips)
158 if allow_ips.include?(user_ip)
159 if allow_ips.include?(user_ip)
159 return true
160 return true
160 end
161 end
161 end
162 end
162 return false
163 return false
163 end
164 end
164 return true
165 return true
165 end
166 end
166
167
167 #function for datatable ajax query
168 #function for datatable ajax query
168 #return record,total_count,filter_count
169 #return record,total_count,filter_count
169 def process_query_record(record,
170 def process_query_record(record,
170 total_count: nil,
171 total_count: nil,
171 select: '',
172 select: '',
172 global_search: [],
173 global_search: [],
173 no_search: false,
174 no_search: false,
174 force_order: '',
175 force_order: '',
175 date_filter: '', date_param_since: 'date_since',date_param_until: 'date_until',
176 date_filter: '', date_param_since: 'date_since',date_param_until: 'date_until',
176 hard_limit: nil)
177 hard_limit: nil)
177 arel_table = record.model.arel_table
178 arel_table = record.model.arel_table
178
179
179 if !no_search && params['search']
180 if !no_search && params['search']
180 global_value = record.model.sanitize_sql(params['search']['value'].strip.downcase)
181 global_value = record.model.sanitize_sql(params['search']['value'].strip.downcase)
@@ -1,75 +1,81
1 class GroupsController < ApplicationController
1 class GroupsController < ApplicationController
2 before_action :set_group, only: [:show, :edit, :update, :destroy,
2 before_action :set_group, only: [:show, :edit, :update, :destroy,
3 :add_user, :remove_user,:remove_all_user,
3 :add_user, :remove_user,:remove_all_user,
4 :add_problem, :remove_problem,:remove_all_problem,
4 :add_problem, :remove_problem,:remove_all_problem,
5 + :toggle,
5 ]
6 ]
6 before_action :admin_authorization
7 before_action :admin_authorization
7
8
8 # GET /groups
9 # GET /groups
9 def index
10 def index
10 @groups = Group.all
11 @groups = Group.all
11 end
12 end
12
13
13 # GET /groups/1
14 # GET /groups/1
14 def show
15 def show
15 end
16 end
16
17
17 # GET /groups/new
18 # GET /groups/new
18 def new
19 def new
19 @group = Group.new
20 @group = Group.new
20 end
21 end
21
22
22 # GET /groups/1/edit
23 # GET /groups/1/edit
23 def edit
24 def edit
24 end
25 end
25
26
26 # POST /groups
27 # POST /groups
27 def create
28 def create
28 @group = Group.new(group_params)
29 @group = Group.new(group_params)
29
30
30 if @group.save
31 if @group.save
31 redirect_to @group, notice: 'Group was successfully created.'
32 redirect_to @group, notice: 'Group was successfully created.'
32 else
33 else
33 render :new
34 render :new
34 end
35 end
35 end
36 end
36
37
37 # PATCH/PUT /groups/1
38 # PATCH/PUT /groups/1
38 def update
39 def update
39 if @group.update(group_params)
40 if @group.update(group_params)
40 redirect_to @group, notice: 'Group was successfully updated.'
41 redirect_to @group, notice: 'Group was successfully updated.'
41 else
42 else
42 render :edit
43 render :edit
43 end
44 end
44 end
45 end
45
46
46 # DELETE /groups/1
47 # DELETE /groups/1
47 def destroy
48 def destroy
48 @group.destroy
49 @group.destroy
49 redirect_to groups_url, notice: 'Group was successfully destroyed.'
50 redirect_to groups_url, notice: 'Group was successfully destroyed.'
50 end
51 end
51
52
53 + def toggle
54 + @group.enabled = @group.enabled? ? false : true
55 + @group.save
56 + end
57 +
52 def remove_user
58 def remove_user
53 user = User.find(params[:user_id])
59 user = User.find(params[:user_id])
54 @group.users.delete(user)
60 @group.users.delete(user)
55 redirect_to group_path(@group), flash: {success: "User #{user.login} was removed from the group #{@group.name}"}
61 redirect_to group_path(@group), flash: {success: "User #{user.login} was removed from the group #{@group.name}"}
56 end
62 end
57
63
58 def remove_all_user
64 def remove_all_user
59 @group.users.clear
65 @group.users.clear
60 redirect_to group_path(@group), alert: 'All users removed'
66 redirect_to group_path(@group), alert: 'All users removed'
61 end
67 end
62
68
63 def remove_all_problem
69 def remove_all_problem
64 @group.problems.clear
70 @group.problems.clear
65 redirect_to group_path(@group), alert: 'All problems removed'
71 redirect_to group_path(@group), alert: 'All problems removed'
66 end
72 end
67
73
68 def add_user
74 def add_user
69 user = User.find(params[:user_id])
75 user = User.find(params[:user_id])
70 begin
76 begin
71 @group.users << user
77 @group.users << user
72 redirect_to group_path(@group), flash: { success: "User #{user.login} was add to the group #{@group.name}"}
78 redirect_to group_path(@group), flash: { success: "User #{user.login} was add to the group #{@group.name}"}
73 rescue => e
79 rescue => e
74 redirect_to group_path(@group), alert: e.message
80 redirect_to group_path(@group), alert: e.message
75 end
81 end
@@ -78,27 +84,27
78 def remove_problem
84 def remove_problem
79 problem = Problem.find(params[:problem_id])
85 problem = Problem.find(params[:problem_id])
80 @group.problems.delete(problem)
86 @group.problems.delete(problem)
81 redirect_to group_path(@group), flash: {success: "Problem #{problem.name} was removed from the group #{@group.name}" }
87 redirect_to group_path(@group), flash: {success: "Problem #{problem.name} was removed from the group #{@group.name}" }
82 end
88 end
83
89
84 def add_problem
90 def add_problem
85 problem = Problem.find(params[:problem_id])
91 problem = Problem.find(params[:problem_id])
86 begin
92 begin
87 @group.problems << problem
93 @group.problems << problem
88 redirect_to group_path(@group), flash: {success: "Problem #{problem.name} was add to the group #{@group.name}" }
94 redirect_to group_path(@group), flash: {success: "Problem #{problem.name} was add to the group #{@group.name}" }
89 rescue => e
95 rescue => e
90 redirect_to group_path(@group), alert: e.message
96 redirect_to group_path(@group), alert: e.message
91 end
97 end
92 end
98 end
93
99
94 private
100 private
95 # Use callbacks to share common setup or constraints between actions.
101 # Use callbacks to share common setup or constraints between actions.
96 def set_group
102 def set_group
97 @group = Group.find(params[:id])
103 @group = Group.find(params[:id])
98 end
104 end
99
105
100 # Only allow a trusted parameter "white list" through.
106 # Only allow a trusted parameter "white list" through.
101 def group_params
107 def group_params
102 - params.require(:group).permit(:name, :description)
108 + params.require(:group).permit(:name, :description, :enabled)
103 end
109 end
104 end
110 end
@@ -167,49 +167,49
167
167
168 # announcement refreshing and hiding methods
168 # announcement refreshing and hiding methods
169
169
170 def announcements
170 def announcements
171 if params.has_key? 'recent'
171 if params.has_key? 'recent'
172 prepare_announcements(params[:recent])
172 prepare_announcements(params[:recent])
173 else
173 else
174 prepare_announcements
174 prepare_announcements
175 end
175 end
176 render(:partial => 'announcement',
176 render(:partial => 'announcement',
177 :collection => @announcements,
177 :collection => @announcements,
178 :locals => {:announcement_effect => true})
178 :locals => {:announcement_effect => true})
179 end
179 end
180
180
181 def confirm_contest_start
181 def confirm_contest_start
182 user = User.find(session[:user_id])
182 user = User.find(session[:user_id])
183 if request.method == 'POST'
183 if request.method == 'POST'
184 user.update_start_time
184 user.update_start_time
185 redirect_to :action => 'list'
185 redirect_to :action => 'list'
186 else
186 else
187 @contests = user.contests
187 @contests = user.contests
188 @user = user
188 @user = user
189 end
189 end
190 end
190 end
191 -
191 +
192 protected
192 protected
193
193
194 def prepare_announcements(recent=nil)
194 def prepare_announcements(recent=nil)
195 if GraderConfiguration.show_tasks_to?(@user)
195 if GraderConfiguration.show_tasks_to?(@user)
196 @announcements = Announcement.published(true)
196 @announcements = Announcement.published(true)
197 else
197 else
198 @announcements = Announcement.published
198 @announcements = Announcement.published
199 end
199 end
200 if recent!=nil
200 if recent!=nil
201 recent_id = recent.to_i
201 recent_id = recent.to_i
202 @announcements = @announcements.find_all { |a| a.id > recent_id }
202 @announcements = @announcements.find_all { |a| a.id > recent_id }
203 end
203 end
204 end
204 end
205
205
206 def prepare_list_information
206 def prepare_list_information
207 @user = User.find(session[:user_id])
207 @user = User.find(session[:user_id])
208 if not GraderConfiguration.multicontests?
208 if not GraderConfiguration.multicontests?
209 @problems = @user.available_problems
209 @problems = @user.available_problems
210 else
210 else
211 @contest_problems = @user.available_problems_group_by_contests
211 @contest_problems = @user.available_problems_group_by_contests
212 @problems = @user.available_problems
212 @problems = @user.available_problems
213 end
213 end
214 @prob_submissions = {}
214 @prob_submissions = {}
215 @problems.each do |p|
215 @problems.each do |p|
@@ -1,44 +1,44
1 class SubmissionsController < ApplicationController
1 class SubmissionsController < ApplicationController
2 before_action :check_valid_login
2 before_action :check_valid_login
3 before_action :submission_authorization, only: [:show, :download, :edit]
3 before_action :submission_authorization, only: [:show, :download, :edit]
4 before_action :admin_authorization, only: [:rejudge]
4 before_action :admin_authorization, only: [:rejudge]
5
5
6 # GET /submissions
6 # GET /submissions
7 # GET /submissions.json
7 # GET /submissions.json
8 # Show problem selection and user's submission of that problem
8 # Show problem selection and user's submission of that problem
9 def index
9 def index
10 @user = @current_user
10 @user = @current_user
11 @problems = @user.available_problems
11 @problems = @user.available_problems
12
12
13 if params[:problem_id]==nil
13 if params[:problem_id]==nil
14 @problem = nil
14 @problem = nil
15 @submissions = nil
15 @submissions = nil
16 else
16 else
17 @problem = Problem.find_by_id(params[:problem_id])
17 @problem = Problem.find_by_id(params[:problem_id])
18 if (@problem == nil) or (not @problem.available)
18 if (@problem == nil) or (not @problem.available)
19 - redirect_to main_list_path
19 + redirect_to list_main_path
20 - flash[:notice] = 'Error: submissions for that problem are not viewable.'
20 + flash[:error] = 'Authorization error: You have no right to view submissions for this problem'
21 return
21 return
22 end
22 end
23 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id).order(id: :desc)
23 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id).order(id: :desc)
24 end
24 end
25 end
25 end
26
26
27 # GET /submissions/1
27 # GET /submissions/1
28 # GET /submissions/1.json
28 # GET /submissions/1.json
29 def show
29 def show
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
@@ -73,40 +73,39
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 respond_to do |format|
78 respond_to do |format|
79 format.js
79 format.js
80 end
80 end
81 end
81 end
82
82
83 # GET /submissions/:id/rejudge
83 # GET /submissions/:id/rejudge
84 def rejudge
84 def rejudge
85 @submission = Submission.find(params[:id])
85 @submission = Submission.find(params[:id])
86 @task = @submission.task
86 @task = @submission.task
87 @task.status_inqueue! if @task
87 @task.status_inqueue! if @task
88 respond_to do |format|
88 respond_to do |format|
89 format.js
89 format.js
90 end
90 end
91 end
91 end
92
92
93 protected
93 protected
94
94
95 def submission_authorization
95 def submission_authorization
96 #admin always has privileged
96 #admin always has privileged
97 - if @current_user.admin?
97 + return true if @current_user.admin?
98 - return true
98 + return true if @current_user.has_role?('TA') && (['show','download'].include? action_name)
99 - end
100
99
101 sub = Submission.find(params[:id])
100 sub = Submission.find(params[:id])
102 if @current_user.available_problems.include? sub.problem
101 if @current_user.available_problems.include? sub.problem
103 return true if GraderConfiguration["right.user_view_submission"] or sub.user == @current_user
102 return true if GraderConfiguration["right.user_view_submission"] or sub.user == @current_user
104 end
103 end
105
104
106 #default to NO
105 #default to NO
107 unauthorized_redirect
106 unauthorized_redirect
108 return false
107 return false
109 end
108 end
110
109
111
110
112 end
111 end
@@ -6,59 +6,61
6 redirect_to :action => 'list'
6 redirect_to :action => 'list'
7 end
7 end
8
8
9 def list
9 def list
10 @problems = @user.available_problems
10 @problems = @user.available_problems
11 end
11 end
12
12
13 # this has contest-wide access control
13 # this has contest-wide access control
14 def view
14 def view
15 base_name = params[:file]
15 base_name = params[:file]
16 base_filename = File.basename("#{base_name}.#{params[:ext]}")
16 base_filename = File.basename("#{base_name}.#{params[:ext]}")
17 filename = "#{Problem.download_file_basedir}/#{base_filename}"
17 filename = "#{Problem.download_file_basedir}/#{base_filename}"
18
18
19 if !FileTest.exists?(filename)
19 if !FileTest.exists?(filename)
20 redirect_to :action => 'index' and return
20 redirect_to :action => 'index' and return
21 end
21 end
22
22
23 send_file_to_user(filename, base_filename)
23 send_file_to_user(filename, base_filename)
24 end
24 end
25
25
26 # this has problem-level access control
26 # this has problem-level access control
27 def download
27 def download
28 problem = Problem.find(params[:id])
28 problem = Problem.find(params[:id])
29 unless @current_user.can_view_problem? problem
29 unless @current_user.can_view_problem? problem
30 - flash[:notice] = 'You are not authorized to access this file'
30 + flash[:error] = 'You are not authorized to access this file'
31 - redirect_to :action => 'index' and return
31 + redirect_to list_main_path
32 + return
32 end
33 end
33
34
34 base_name = params[:file]
35 base_name = params[:file]
35 base_filename = File.basename("#{base_name}.#{params[:ext]}")
36 base_filename = File.basename("#{base_name}.#{params[:ext]}")
36 filename = "#{Problem.download_file_basedir}/#{params[:id]}/#{base_filename}"
37 filename = "#{Problem.download_file_basedir}/#{params[:id]}/#{base_filename}"
37
38
38 if !FileTest.exists?(filename)
39 if !FileTest.exists?(filename)
39 flash[:notice] = 'File does not exists'
40 flash[:notice] = 'File does not exists'
40 - redirect_to :action => 'index' and return
41 + redirect_to list_main_path
42 + return
41 end
43 end
42
44
43 send_file_to_user(filename, base_filename)
45 send_file_to_user(filename, base_filename)
44 end
46 end
45
47
46 protected
48 protected
47
49
48 def send_file_to_user(filename, base_filename)
50 def send_file_to_user(filename, base_filename)
49 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
51 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
50 response.headers['Content-Type'] = "application/force-download"
52 response.headers['Content-Type'] = "application/force-download"
51 response.headers['Content-Disposition'] = "attachment; filename=\"#{File.basename(filename)}\""
53 response.headers['Content-Disposition'] = "attachment; filename=\"#{File.basename(filename)}\""
52 response.headers["X-Sendfile"] = filename
54 response.headers["X-Sendfile"] = filename
53 response.headers['Content-length'] = File.size(filename)
55 response.headers['Content-length'] = File.size(filename)
54 render :nothing => true
56 render :nothing => true
55 else
57 else
56 if params[:ext]=='pdf'
58 if params[:ext]=='pdf'
57 content_type = 'application/pdf'
59 content_type = 'application/pdf'
58 else
60 else
59 content_type = 'application/octet-stream'
61 content_type = 'application/octet-stream'
60 end
62 end
61
63
62 send_file filename, :stream => false, :disposition => 'inline', :filename => base_filename, :type => content_type
64 send_file filename, :stream => false, :disposition => 'inline', :filename => base_filename, :type => content_type
63 end
65 end
64 end
66 end
@@ -37,79 +37,89
37 if @user.save
37 if @user.save
38 flash[:notice] = 'User was successfully created.'
38 flash[:notice] = 'User was successfully created.'
39 redirect_to :action => 'index'
39 redirect_to :action => 'index'
40 else
40 else
41 render :action => 'new'
41 render :action => 'new'
42 end
42 end
43 end
43 end
44
44
45 def clear_last_ip
45 def clear_last_ip
46 @user = User.find(params[:id])
46 @user = User.find(params[:id])
47 @user.last_ip = nil
47 @user.last_ip = nil
48 @user.save
48 @user.save
49 redirect_to action: 'index', page: params[:page]
49 redirect_to action: 'index', page: params[:page]
50 end
50 end
51
51
52 def create_from_list
52 def create_from_list
53 lines = params[:user_list]
53 lines = params[:user_list]
54
54
55 note = []
55 note = []
56 error_note = []
56 error_note = []
57 error_msg = nil
57 error_msg = nil
58 ok_user = []
58 ok_user = []
59
59
60 lines.split("\n").each do |line|
60 lines.split("\n").each do |line|
61 - items = line.chomp.split(',')
61 + #split with large limit, this will cause consecutive ',' to be result in a blank
62 + items = line.chomp.split(',',1000)
62 if items.length>=2
63 if items.length>=2
63 login = items[0]
64 login = items[0]
64 full_name = items[1]
65 full_name = items[1]
65 remark =''
66 remark =''
66 user_alias = ''
67 user_alias = ''
67
68
68 added_random_password = false
69 added_random_password = false
69 - if items.length >= 3 and items[2].chomp(" ").length > 0;
70 + added_password = false
70 - password = items[2].chomp(" ")
71 + if items.length >= 3
72 + if items[2].chomp(" ").length > 0
73 + password = items[2].chomp(" ")
74 + added_password = true
75 + end
71 else
76 else
72 password = random_password
77 password = random_password
73 added_random_password=true;
78 added_random_password=true;
74 end
79 end
75
80
76 if items.length>= 4 and items[3].chomp(" ").length > 0;
81 if items.length>= 4 and items[3].chomp(" ").length > 0;
77 user_alias = items[3].chomp(" ")
82 user_alias = items[3].chomp(" ")
78 else
83 else
79 user_alias = login
84 user_alias = login
80 end
85 end
81
86
87 +
88 + has_remark = false
82 if items.length>=5
89 if items.length>=5
83 remark = items[4].strip;
90 remark = items[4].strip;
91 + has_remark = true
84 end
92 end
85
93
86 user = User.find_by_login(login)
94 user = User.find_by_login(login)
87 if (user)
95 if (user)
88 user.full_name = full_name
96 user.full_name = full_name
89 - user.password = password
97 + user.remark = remark if has_remark
90 - user.remark = remark
98 + user.password = password if added_password || added_random_password
91 else
99 else
100 + #create a random password if none are given
101 + password = random_password unless password
92 user = User.new({:login => login,
102 user = User.new({:login => login,
93 :full_name => full_name,
103 :full_name => full_name,
94 :password => password,
104 :password => password,
95 :password_confirmation => password,
105 :password_confirmation => password,
96 :alias => user_alias,
106 :alias => user_alias,
97 :remark => remark})
107 :remark => remark})
98 end
108 end
99 user.activated = true
109 user.activated = true
100
110
101 if user.save
111 if user.save
102 if added_random_password
112 if added_random_password
103 note << "'#{login}' (+)"
113 note << "'#{login}' (+)"
104 else
114 else
105 note << login
115 note << login
106 end
116 end
107 ok_user << user
117 ok_user << user
108 else
118 else
109 error_note << "'#{login}'"
119 error_note << "'#{login}'"
110 error_msg = user.errors.full_messages.to_sentence unless error_msg
120 error_msg = user.errors.full_messages.to_sentence unless error_msg
111 end
121 end
112
122
113 end
123 end
114 end
124 end
115
125
@@ -324,78 +334,75
324 user.contest_stat.reset_timer_and_save
334 user.contest_stat.reset_timer_and_save
325 end
335 end
326
336
327 if params[:notification_emails]
337 if params[:notification_emails]
328 send_contest_update_notification_email(user, contest)
338 send_contest_update_notification_email(user, contest)
329 end
339 end
330
340
331 note << user.login
341 note << user.login
332 users << user
342 users << user
333 end
343 end
334 end
344 end
335
345
336 if params[:reset_timer]
346 if params[:reset_timer]
337 logout_users(users)
347 logout_users(users)
338 end
348 end
339
349
340 flash[:notice] = 'User(s) ' + note.join(', ') +
350 flash[:notice] = 'User(s) ' + note.join(', ') +
341 ' were successfully modified. '
351 ' were successfully modified. '
342 redirect_to :action => 'contest_management'
352 redirect_to :action => 'contest_management'
343 end
353 end
344
354
345 # admin management
355 # admin management
346
356
347 def admin
357 def admin
348 - @admins = User.all.find_all {|user| user.admin? }
358 + @admins = Role.where(name: 'admin').take.users
359 + @tas = Role.where(name: 'ta').take.users
349 end
360 end
350
361
351 - def grant_admin
362 + def modify_role
352 - login = params[:login]
363 + user = User.find_by_login(params[:login])
353 - user = User.find_by_login(login)
364 + role = Role.find_by_name(params[:role])
354 - if user!=nil
365 + unless user && role
355 - admin_role = Role.find_by_name('admin')
366 + flash[:error] = 'Unknown user or role'
356 - user.roles << admin_role
367 + redirect_to admin_user_admin_index_path
357 - else
368 + return
358 - flash[:notice] = 'Unknown user'
359 end
369 end
360 - flash[:notice] = 'User added as admins'
370 + if params[:commit] == 'Grant'
361 - redirect_to :action => 'admin'
371 + #grant role
362 - end
372 + user.roles << role
363 -
373 + flash[:notice] = "User '#{user.login}' has been granted the role '#{role.name}'"
364 - def revoke_admin
374 + else
365 - user = User.find(params[:id])
375 + #revoke role
366 - if user==nil
376 + if user.login == 'root' && role.name == 'admin'
367 - flash[:notice] = 'Unknown user'
377 + flash[:error] = 'You cannot revoke admisnistrator permission from root.'
368 - redirect_to :action => 'admin' and return
378 + redirect_to admin_user_admin_index_path
369 - elsif user.login == 'root'
379 + return
370 - flash[:notice] = 'You cannot revoke admisnistrator permission from root.'
380 + end
371 - redirect_to :action => 'admin' and return
381 + user.roles.delete(role)
382 + flash[:notice] = "The role '#{role.name}' has been revoked from User '#{user.login}'"
372 end
383 end
373 -
384 + redirect_to admin_user_admin_index_path
374 - admin_role = Role.find_by_name('admin')
375 - user.roles.delete(admin_role)
376 - flash[:notice] = 'User permission revoked'
377 - redirect_to :action => 'admin'
378 end
385 end
379
386
380 # mass mailing
387 # mass mailing
381
388
382 def mass_mailing
389 def mass_mailing
383 end
390 end
384
391
385 def bulk_mail
392 def bulk_mail
386 lines = params[:login_list]
393 lines = params[:login_list]
387 if !lines or lines.blank?
394 if !lines or lines.blank?
388 flash[:notice] = 'You entered an empty list.'
395 flash[:notice] = 'You entered an empty list.'
389 redirect_to :action => 'mass_mailing' and return
396 redirect_to :action => 'mass_mailing' and return
390 end
397 end
391
398
392 mail_subject = params[:subject]
399 mail_subject = params[:subject]
393 if !mail_subject or mail_subject.blank?
400 if !mail_subject or mail_subject.blank?
394 flash[:notice] = 'You entered an empty mail subject.'
401 flash[:notice] = 'You entered an empty mail subject.'
395 redirect_to :action => 'mass_mailing' and return
402 redirect_to :action => 'mass_mailing' and return
396 end
403 end
397
404
398 mail_body = params[:email_body]
405 mail_body = params[:email_body]
399 if !mail_body or mail_body.blank?
406 if !mail_body or mail_body.blank?
400 flash[:notice] = 'You entered an empty mail body.'
407 flash[:notice] = 'You entered an empty mail body.'
401 redirect_to :action => 'mass_mailing' and return
408 redirect_to :action => 'mass_mailing' and return
@@ -92,50 +92,51
92 end
92 end
93 st + time.strftime("%X")
93 st + time.strftime("%X")
94 end
94 end
95
95
96 def format_short_duration(duration)
96 def format_short_duration(duration)
97 return '' if duration==nil
97 return '' if duration==nil
98 d = duration.to_f
98 d = duration.to_f
99 return Time.at(d).gmtime.strftime("%X")
99 return Time.at(d).gmtime.strftime("%X")
100 end
100 end
101
101
102 def format_full_time_ago(time)
102 def format_full_time_ago(time)
103 st = time_ago_in_words(time) + ' ago (' + format_short_time(time) + ')'
103 st = time_ago_in_words(time) + ' ago (' + format_short_time(time) + ')'
104 end
104 end
105
105
106 def read_textfile(fname,max_size=2048)
106 def read_textfile(fname,max_size=2048)
107 begin
107 begin
108 File.open(fname).read(max_size)
108 File.open(fname).read(max_size)
109 rescue
109 rescue
110 nil
110 nil
111 end
111 end
112 end
112 end
113
113
114 def toggle_button(on,toggle_url,id, option={})
114 def toggle_button(on,toggle_url,id, option={})
115 btn_size = option[:size] || 'btn-xs'
115 btn_size = option[:size] || 'btn-xs'
116 + btn_block = option[:block] || 'btn-block'
116 link_to (on ? "Yes" : "No"), toggle_url,
117 link_to (on ? "Yes" : "No"), toggle_url,
117 - {class: "btn btn-block #{btn_size} btn-#{on ? 'success' : 'default'} ajax-toggle",
118 + {class: "btn #{btn_block} #{btn_size} btn-#{on ? 'success' : 'default'} ajax-toggle",
118 id: id,
119 id: id,
119 data: {remote: true, method: 'get'}}
120 data: {remote: true, method: 'get'}}
120 end
121 end
121
122
122 def get_ace_mode(language)
123 def get_ace_mode(language)
123 # return ace mode string from Language
124 # return ace mode string from Language
124
125
125 case language.pretty_name
126 case language.pretty_name
126 when 'Pascal'
127 when 'Pascal'
127 'ace/mode/pascal'
128 'ace/mode/pascal'
128 when 'C++','C'
129 when 'C++','C'
129 'ace/mode/c_cpp'
130 'ace/mode/c_cpp'
130 when 'Ruby'
131 when 'Ruby'
131 'ace/mode/ruby'
132 'ace/mode/ruby'
132 when 'Python'
133 when 'Python'
133 'ace/mode/python'
134 'ace/mode/python'
134 when 'Java'
135 when 'Java'
135 'ace/mode/java'
136 'ace/mode/java'
136 else
137 else
137 'ace/mode/c_cpp'
138 'ace/mode/c_cpp'
138 end
139 end
139 end
140 end
140
141
141
142
@@ -160,51 +161,48
160 " #{format_short_duration(user.contest_time_left)}"
161 " #{format_short_duration(user.contest_time_left)}"
161 end
162 end
162 end
163 end
163
164
164 #
165 #
165 # if the contest is in the anaysis mode
166 # if the contest is in the anaysis mode
166 if GraderConfiguration.analysis_mode?
167 if GraderConfiguration.analysis_mode?
167 header = <<ANALYSISMODE
168 header = <<ANALYSISMODE
168 <tr><td colspan="2" align="center">
169 <tr><td colspan="2" align="center">
169 <span class="contest-over-msg">ANALYSIS MODE</span>
170 <span class="contest-over-msg">ANALYSIS MODE</span>
170 </td></tr>
171 </td></tr>
171 ANALYSISMODE
172 ANALYSISMODE
172 end
173 end
173
174
174 contest_name = GraderConfiguration['contest.name']
175 contest_name = GraderConfiguration['contest.name']
175
176
176 #
177 #
177 # build real title bar
178 # build real title bar
178 result = <<TITLEBAR
179 result = <<TITLEBAR
179 <div class="title">
180 <div class="title">
180 <table>
181 <table>
181 #{header}
182 #{header}
182 <tr>
183 <tr>
183 <td class="left-col">
184 <td class="left-col">
184 - #{user.full_name}<br/>
185 - #{t 'title_bar.current_time'} #{format_short_time(Time.zone.now)}
186 - #{time_left}
187 <br/>
185 <br/>
188 </td>
186 </td>
189 <td class="right-col">#{contest_name}</td>
187 <td class="right-col">#{contest_name}</td>
190 </tr>
188 </tr>
191 </table>
189 </table>
192 </div>
190 </div>
193 TITLEBAR
191 TITLEBAR
194 result.html_safe
192 result.html_safe
195 end
193 end
196
194
197 def markdown(text)
195 def markdown(text)
198 markdown = RDiscount.new(text)
196 markdown = RDiscount.new(text)
199 markdown.to_html.html_safe
197 markdown.to_html.html_safe
200 end
198 end
201
199
202
200
203 BOOTSTRAP_FLASH_MSG = {
201 BOOTSTRAP_FLASH_MSG = {
204 success: 'alert-success',
202 success: 'alert-success',
205 error: 'alert-danger',
203 error: 'alert-danger',
206 alert: 'alert-danger',
204 alert: 'alert-danger',
207 notice: 'alert-info'
205 notice: 'alert-info'
208 }
206 }
209
207
210 def bootstrap_class_for(flash_type)
208 def bootstrap_class_for(flash_type)
@@ -1,20 +1,14
1 module MainHelper
1 module MainHelper
2
2
3 - def link_to_description_if_any(name, problem, options={})
3 + def link_to_description_if_any(name, problem)
4 if !problem.url.blank?
4 if !problem.url.blank?
5 - return link_to name, problem.url, options
5 + return link_to name, problem.url
6 elsif !problem.description_filename.blank?
6 elsif !problem.description_filename.blank?
7 - #build a link to a problem (via task controller)
8 basename, ext = problem.description_filename.split('.')
7 basename, ext = problem.description_filename.split('.')
9 - options[:controller] = 'tasks'
8 + return link_to name, download_task_path(problem.id,basename,ext), target: '_blank'
10 - options[:action] = 'download'
11 - options[:id] = problem.id
12 - options[:file] = basename
13 - options[:ext] = ext
14 - return link_to name, options
15 else
9 else
16 return ''
10 return ''
17 end
11 end
18 end
12 end
19
13
20 end
14 end
@@ -133,36 +133,36
133 end
133 end
134 end
134 end
135
135
136 # validation codes
136 # validation codes
137 def must_specify_language
137 def must_specify_language
138 return if self.source==nil
138 return if self.source==nil
139
139
140 # for output_only tasks
140 # for output_only tasks
141 return if self.problem!=nil and self.problem.output_only
141 return if self.problem!=nil and self.problem.output_only
142
142
143 if self.language == nil
143 if self.language == nil
144 errors.add('source',"Cannot detect language. Did you submit a correct source file?")
144 errors.add('source',"Cannot detect language. Did you submit a correct source file?")
145 end
145 end
146 end
146 end
147
147
148 def must_have_valid_problem
148 def must_have_valid_problem
149 return if self.source==nil
149 return if self.source==nil
150 if self.problem==nil
150 if self.problem==nil
151 errors.add('problem',"must be specified.")
151 errors.add('problem',"must be specified.")
152 else
152 else
153 #admin always have right
153 #admin always have right
154 return if self.user.admin?
154 return if self.user.admin?
155
155
156 #check if user has the right to submit the problem
156 #check if user has the right to submit the problem
157 - errors.add('problem',"must be valid.") if (!self.user.available_problems.include?(self.problem)) and (self.new_record?)
157 + errors[:base] << "Authorization error: you have no right to submit to this problem" if (!self.user.available_problems.include?(self.problem)) and (self.new_record?)
158 end
158 end
159 end
159 end
160
160
161 # callbacks
161 # callbacks
162 def assign_latest_number_if_new_recond
162 def assign_latest_number_if_new_recond
163 return if !self.new_record?
163 return if !self.new_record?
164 latest = Submission.find_last_by_user_and_problem(self.user_id, self.problem_id)
164 latest = Submission.find_last_by_user_and_problem(self.user_id, self.problem_id)
165 self.number = (latest==nil) ? 1 : latest.number + 1;
165 self.number = (latest==nil) ? 1 : latest.number + 1;
166 end
166 end
167
167
168 end
168 end
@@ -62,49 +62,53
62 before_save :encrypt_new_password
62 before_save :encrypt_new_password
63 before_save :assign_default_site
63 before_save :assign_default_site
64 before_save :assign_default_contest
64 before_save :assign_default_contest
65
65
66 # this is for will_paginate
66 # this is for will_paginate
67 cattr_reader :per_page
67 cattr_reader :per_page
68 @@per_page = 50
68 @@per_page = 50
69
69
70 def self.authenticate(login, password)
70 def self.authenticate(login, password)
71 user = find_by_login(login)
71 user = find_by_login(login)
72 if user
72 if user
73 return user if user.authenticated?(password)
73 return user if user.authenticated?(password)
74 end
74 end
75 end
75 end
76
76
77 def authenticated?(password)
77 def authenticated?(password)
78 if self.activated
78 if self.activated
79 hashed_password == User.encrypt(password,self.salt)
79 hashed_password == User.encrypt(password,self.salt)
80 else
80 else
81 false
81 false
82 end
82 end
83 end
83 end
84
84
85 def admin?
85 def admin?
86 - self.roles.where(name: 'admin').count > 0
86 + has_role?('admin')
87 + end
88 +
89 + def has_role?(role)
90 + self.roles.where(name: role).count > 0
87 end
91 end
88
92
89 def email_for_editing
93 def email_for_editing
90 if self.email==nil
94 if self.email==nil
91 "(unknown)"
95 "(unknown)"
92 elsif self.email==''
96 elsif self.email==''
93 "(blank)"
97 "(blank)"
94 else
98 else
95 self.email
99 self.email
96 end
100 end
97 end
101 end
98
102
99 def email_for_editing=(e)
103 def email_for_editing=(e)
100 self.email=e
104 self.email=e
101 end
105 end
102
106
103 def alias_for_editing
107 def alias_for_editing
104 if self.alias==nil
108 if self.alias==nil
105 "(unknown)"
109 "(unknown)"
106 elsif self.alias==''
110 elsif self.alias==''
107 "(blank)"
111 "(blank)"
108 else
112 else
109 self.alias
113 self.alias
110 end
114 end
@@ -254,71 +258,74
254 #if this is a normal mode
258 #if this is a normal mode
255 #we show problem based on problem_group, if the config said so
259 #we show problem based on problem_group, if the config said so
256 if GraderConfiguration.use_problem_group?
260 if GraderConfiguration.use_problem_group?
257 return available_problems_in_group
261 return available_problems_in_group
258 else
262 else
259 return Problem.available_problems
263 return Problem.available_problems
260 end
264 end
261 else
265 else
262 #this is multi contest mode
266 #this is multi contest mode
263 contest_problems = []
267 contest_problems = []
264 pin = {}
268 pin = {}
265 contests.enabled.each do |contest|
269 contests.enabled.each do |contest|
266 contest.problems.available.each do |problem|
270 contest.problems.available.each do |problem|
267 if not pin.has_key? problem.id
271 if not pin.has_key? problem.id
268 contest_problems << problem
272 contest_problems << problem
269 end
273 end
270 pin[problem.id] = true
274 pin[problem.id] = true
271 end
275 end
272 end
276 end
273 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
277 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
274 return contest_problems + other_avaiable_problems
278 return contest_problems + other_avaiable_problems
275 end
279 end
276 end
280 end
277
281
282 + # new feature, get list of available problem in all enabled group that the user belongs to
278 def available_problems_in_group
283 def available_problems_in_group
279 problem = []
284 problem = []
280 - self.groups.each do |group|
285 + self.groups.where(enabled: true).each do |group|
281 group.problems.where(available: true).each { |p| problem << p }
286 group.problems.where(available: true).each { |p| problem << p }
282 end
287 end
283 problem.uniq!
288 problem.uniq!
284 if problem
289 if problem
285 problem.sort! do |a,b|
290 problem.sort! do |a,b|
286 case
291 case
287 when a.date_added < b.date_added
292 when a.date_added < b.date_added
288 1
293 1
289 when a.date_added > b.date_added
294 when a.date_added > b.date_added
290 -1
295 -1
291 else
296 else
292 a.name <=> b.name
297 a.name <=> b.name
293 end
298 end
294 end
299 end
295 return problem
300 return problem
296 else
301 else
297 return []
302 return []
298 end
303 end
299 end
304 end
300
305
306 + #check if the user has the right to view that problem
307 + #this also consider group based problem policy
301 def can_view_problem?(problem)
308 def can_view_problem?(problem)
302 return true if admin?
309 return true if admin?
303 return available_problems.include? problem
310 return available_problems.include? problem
304 end
311 end
305
312
306 def self.clear_last_login
313 def self.clear_last_login
307 User.update_all(:last_ip => nil)
314 User.update_all(:last_ip => nil)
308 end
315 end
309
316
310 protected
317 protected
311 def encrypt_new_password
318 def encrypt_new_password
312 return if password.blank?
319 return if password.blank?
313 self.salt = (10+rand(90)).to_s
320 self.salt = (10+rand(90)).to_s
314 self.hashed_password = User.encrypt(self.password,self.salt)
321 self.hashed_password = User.encrypt(self.password,self.salt)
315 end
322 end
316
323
317 def assign_default_site
324 def assign_default_site
318 # have to catch error when migrating (because self.site is not available).
325 # have to catch error when migrating (because self.site is not available).
319 begin
326 begin
320 if self.site==nil
327 if self.site==nil
321 self.site = Site.find_by_name('default')
328 self.site = Site.find_by_name('default')
322 if self.site==nil
329 if self.site==nil
323 self.site = Site.find(1) # when 'default has be renamed'
330 self.site = Site.find(1) # when 'default has be renamed'
324 end
331 end
@@ -1,26 +1,26
1
1
2 %tr
2 %tr
3 %td{:align => "center"}
3 %td{:align => "center"}
4 = submission.number
4 = submission.number
5 %td.text-right
5 %td.text-right
6 = link_to "##{submission.id}", submission_path(submission.id)
6 = link_to "##{submission.id}", submission_path(submission.id)
7 %td
7 %td
8 = l submission.submitted_at, format: :long
8 = l submission.submitted_at, format: :long
9 = "( #{time_ago_in_words(submission.submitted_at)} ago)"
9 = "( #{time_ago_in_words(submission.submitted_at)} ago)"
10 %td
10 %td
11 = submission.source_filename
11 = submission.source_filename
12 = " (#{submission.language.pretty_name}) "
12 = " (#{submission.language.pretty_name}) "
13 - = link_to('[load]',{:action => 'source', :id => submission.id})
13 + = link_to '[load]', download_submission_path(submission)
14 %td
14 %td
15 - if submission.graded_at
15 - if submission.graded_at
16 = "Graded at #{format_short_time(submission.graded_at)}."
16 = "Graded at #{format_short_time(submission.graded_at)}."
17 %br/
17 %br/
18 = "Score: #{(submission.points*100/submission.problem.full_score).to_i} " if GraderConfiguration['ui.show_score']
18 = "Score: #{(submission.points*100/submission.problem.full_score).to_i} " if GraderConfiguration['ui.show_score']
19 = " ["
19 = " ["
20 %tt
20 %tt
21 = submission.grader_comment
21 = submission.grader_comment
22 = "]"
22 = "]"
23 %td
23 %td
24 = render :partial => 'compiler_message', :locals => {:compiler_message => submission.compiler_message }
24 = render :partial => 'compiler_message', :locals => {:compiler_message => submission.compiler_message }
25 %td
25 %td
26 = link_to 'Edit', edit_submission_path(submission.id), class: 'btn btn-success'
26 = link_to 'Edit', edit_submission_path(submission.id), class: 'btn btn-success'
@@ -1,40 +1,40
1 - content_for :head do
1 - content_for :head do
2 <meta http-equiv ="refresh" content="60"/>
2 <meta http-equiv ="refresh" content="60"/>
3
3
4 %h1 Grader information
4 %h1 Grader information
5
5
6 %p
6 %p
7 = link_to 'Refresh', { :action => 'list' }, class: 'btn btn-info'
7 = link_to 'Refresh', { :action => 'list' }, class: 'btn btn-info'
8
8
9 .panel.panel-primary
9 .panel.panel-primary
10 .panel-heading
10 .panel-heading
11 Grader control:
11 Grader control:
12 .panel-body
12 .panel-body
13 - =link_to 'Start Graders in grading env', { action: 'start_grading'}, class: 'btn btn-default', method: 'post'
13 + =link_to 'Start Graders in grading env', { action: 'start_grading'}, class: 'btn btn-default'
14 - =link_to 'Start Graders in exam env', { action: 'start_exam'}, class: 'btn btn-default', method: 'post'
14 + =link_to 'Start Graders in exam env', { action: 'start_exam'}, class: 'btn btn-default'
15 - =link_to 'Stop all running Graders', { action: 'stop_all'}, class: 'btn btn-default', method: 'post'
15 + =link_to 'Stop all running Graders', { action: 'stop_all'}, class: 'btn btn-default'
16 - =link_to 'Clear all data', { action: 'clear_all'}, class: 'btn btn-default', method: 'post'
16 + =link_to 'Clear all data', { action: 'clear_all'}, class: 'btn btn-default'
17
17
18 .row
18 .row
19 .col-md-6
19 .col-md-6
20 - if @last_task
20 - if @last_task
21 Last task:
21 Last task:
22 = link_to "#{@last_task.id}", :action => 'view', :id => @last_task.id, :type => 'Task'
22 = link_to "#{@last_task.id}", :action => 'view', :id => @last_task.id, :type => 'Task'
23
23
24 %br/
24 %br/
25
25
26 - if @last_test_request
26 - if @last_test_request
27 Last test_request:
27 Last test_request:
28 = link_to "#{@last_test_request.id}", :action => 'view', :id => @last_test_request.id, :type => 'TestRequest'
28 = link_to "#{@last_test_request.id}", :action => 'view', :id => @last_test_request.id, :type => 'TestRequest'
29
29
30 %h2 Current graders
30 %h2 Current graders
31
31
32 = render :partial => 'grader_list', :locals => {:grader_list => @grader_processes}
32 = render :partial => 'grader_list', :locals => {:grader_list => @grader_processes}
33
33
34 %h2 Stalled graders
34 %h2 Stalled graders
35
35
36 = render :partial => 'grader_list', :locals => {:grader_list => @stalled_processes}
36 = render :partial => 'grader_list', :locals => {:grader_list => @stalled_processes}
37
37
38 %h2 Terminated graders
38 %h2 Terminated graders
39
39
40 %p= link_to 'Clear data for terminated graders', { action: 'clear_terminated'}, class: 'btn btn-default', method: 'post'
40 %p= link_to 'Clear data for terminated graders', { action: 'clear_terminated'}, class: 'btn btn-default', method: 'post'
@@ -1,16 +1,27
1 = form_for @group do |f|
1 = form_for @group do |f|
2 - if @group.errors.any?
2 - if @group.errors.any?
3 #error_explanation
3 #error_explanation
4 %h2= "#{pluralize(@group.errors.count, "error")} prohibited this group from being saved:"
4 %h2= "#{pluralize(@group.errors.count, "error")} prohibited this group from being saved:"
5 %ul
5 %ul
6 - @group.errors.full_messages.each do |msg|
6 - @group.errors.full_messages.each do |msg|
7 %li= msg
7 %li= msg
8 -
8 + .row
9 - .form-group.field
9 + .col-md-6
10 - = f.label :name
10 + .form-group.field
11 - = f.text_field :name, class: 'form-control'
11 + = f.label :name
12 - .form-group.field
12 + = f.text_field :name, class: 'form-control'
13 - = f.label :description
13 + .row
14 - = f.text_field :description, class: 'form-control'
14 + .col-md-6
15 - .form-group.actions
15 + .form-group.field
16 - = f.submit 'Save', class: 'btn btn-primary'
16 + = f.label :description
17 + = f.text_field :description, class: 'form-control'
18 + .row
19 + .col-md-6
20 + .checkbox
21 + = f.label :enabled do
22 + = f.check_box :enabled
23 + Enabled
24 + .row
25 + .col-md-6
26 + .form-group.actions
27 + = f.submit 'Save', class: 'btn btn-primary'
@@ -1,22 +1,24
1 %h1 Groups
1 %h1 Groups
2
2
3 %p
3 %p
4 = link_to 'New Group', new_group_path, class: 'btn btn-primary'
4 = link_to 'New Group', new_group_path, class: 'btn btn-primary'
5 %table.table.table-hover
5 %table.table.table-hover
6 %thead
6 %thead
7 %tr
7 %tr
8 %th Name
8 %th Name
9 %th Description
9 %th Description
10 + %th Enabled?
10 %th
11 %th
11 %th
12 %th
12
13
13 %tbody
14 %tbody
14 - @groups.each do |group|
15 - @groups.each do |group|
15 - %tr
16 + %tr{:class => "#{(group.enabled?) ? "success" : "danger"}", id: "group-#{group.id}"}
16 %td= group.name
17 %td= group.name
17 %td= group.description
18 %td= group.description
19 + %td= toggle_button(group.enabled?, toggle_group_path(group), "group-enabled-#{group.id}", size: ' ', block: ' ')
18 %td= link_to 'View', group, class: 'btn btn-default'
20 %td= link_to 'View', group, class: 'btn btn-default'
19 %td= link_to 'Destroy', group, :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn btn-danger'
21 %td= link_to 'Destroy', group, :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn btn-danger'
20
22
21 %br
23 %br
22
24
@@ -47,49 +47,49
47 = add_menu( 'Announcements', 'announcements', 'index')
47 = add_menu( 'Announcements', 'announcements', 'index')
48 = add_menu( 'Problems', 'problems', 'index')
48 = add_menu( 'Problems', 'problems', 'index')
49 = add_menu( 'Tags', 'tags', 'index')
49 = add_menu( 'Tags', 'tags', 'index')
50 = add_menu( 'Users', 'user_admin', 'index')
50 = add_menu( 'Users', 'user_admin', 'index')
51 = add_menu( 'User Groups', 'groups', 'index')
51 = add_menu( 'User Groups', 'groups', 'index')
52 = add_menu( 'Graders', 'graders', 'list')
52 = add_menu( 'Graders', 'graders', 'list')
53 = add_menu( 'Message ', 'messages', 'console')
53 = add_menu( 'Message ', 'messages', 'console')
54 %li.divider{role: 'separator'}
54 %li.divider{role: 'separator'}
55 = add_menu( 'System config', 'configurations', 'index')
55 = add_menu( 'System config', 'configurations', 'index')
56 %li.divider{role: 'separator'}
56 %li.divider{role: 'separator'}
57 = add_menu( 'Sites', 'sites', 'index')
57 = add_menu( 'Sites', 'sites', 'index')
58 = add_menu( 'Contests', 'contest_management', 'index')
58 = add_menu( 'Contests', 'contest_management', 'index')
59 / report
59 / report
60 %li.dropdown
60 %li.dropdown
61 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
61 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
62 Report
62 Report
63 %span.caret
63 %span.caret
64 %ul.dropdown-menu
64 %ul.dropdown-menu
65 = add_menu( 'Current Score', 'report', 'current_score')
65 = add_menu( 'Current Score', 'report', 'current_score')
66 = add_menu( 'Score Report', 'report', 'max_score')
66 = add_menu( 'Score Report', 'report', 'max_score')
67 = add_menu( 'Submission Report', 'report', 'submission')
67 = add_menu( 'Submission Report', 'report', 'submission')
68 = add_menu( 'Login Report', 'report', 'login')
68 = add_menu( 'Login Report', 'report', 'login')
69 - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
69 - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
70 =link_to "#{ungraded} backlogs!",
70 =link_to "#{ungraded} backlogs!",
71 - grader_list_path,
71 + graders_list_path,
72 class: 'navbar-btn btn btn-default btn-warning', data: {toggle: 'tooltip'},title: 'Number of ungraded submission'
72 class: 'navbar-btn btn btn-default btn-warning', data: {toggle: 'tooltip'},title: 'Number of ungraded submission'
73
73
74 %ul.nav.navbar-nav.navbar-right
74 %ul.nav.navbar-nav.navbar-right
75 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-question-sign')}".html_safe, 'main', 'help')
75 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-question-sign')}".html_safe, 'main', 'help')
76 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-comment')}".html_safe, 'messages', 'index', {title: I18n.t('menu.messages'), data: {toggle: 'tooltip'}})
76 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-comment')}".html_safe, 'messages', 'index', {title: I18n.t('menu.messages'), data: {toggle: 'tooltip'}})
77 - if GraderConfiguration['system.user_setting_enabled']
77 - if GraderConfiguration['system.user_setting_enabled']
78 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-cog', id: 'user_profile')}".html_safe, 'users', 'profile', {title: I18n.t('menu.settings'), data: {toggle: 'tooltip'}})
78 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-cog', id: 'user_profile')}".html_safe, 'users', 'profile', {title: I18n.t('menu.settings'), data: {toggle: 'tooltip'}})
79 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-log-out')} #{@current_user.full_name}".html_safe, 'main', 'login', {title: I18n.t('menu.log_out'), data: {toggle: 'tooltip'}})
79 = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-log-out')} #{@current_user.full_name}".html_safe, 'main', 'login', {title: I18n.t('menu.log_out'), data: {toggle: 'tooltip'}})
80
80
81 /
81 /
82 - if (@current_user!=nil) and (session[:admin])
82 - if (@current_user!=nil) and (session[:admin])
83 %nav.navbar.navbar-fixed-top.navbar-inverse.secondnavbar
83 %nav.navbar.navbar-fixed-top.navbar-inverse.secondnavbar
84 .container-fluid
84 .container-fluid
85 .collapse.navbar-collapse
85 .collapse.navbar-collapse
86 %ul.nav.navbar-nav
86 %ul.nav.navbar-nav
87 = add_menu( '[Announcements]', 'announcements', 'index')
87 = add_menu( '[Announcements]', 'announcements', 'index')
88 = add_menu( '[Msg console]', 'messages', 'console')
88 = add_menu( '[Msg console]', 'messages', 'console')
89 = add_menu( '[Problems]', 'problems', 'index')
89 = add_menu( '[Problems]', 'problems', 'index')
90 = add_menu( '[Users]', 'user_admin', 'index')
90 = add_menu( '[Users]', 'user_admin', 'index')
91 = add_menu( '[Results]', 'user_admin', 'user_stat')
91 = add_menu( '[Results]', 'user_admin', 'user_stat')
92 = add_menu( '[Report]', 'report', 'multiple_login')
92 = add_menu( '[Report]', 'report', 'multiple_login')
93 = add_menu( '[Graders]', 'graders', 'list')
93 = add_menu( '[Graders]', 'graders', 'list')
94 = add_menu( '[Contests]', 'contest_management', 'index')
94 = add_menu( '[Contests]', 'contest_management', 'index')
95 = add_menu( '[Sites]', 'sites', 'index')
95 = add_menu( '[Sites]', 'sites', 'index')
@@ -22,26 +22,26
22
22
23 %p
23 %p
24 =raw t 'help.accept_only_language_specified'
24 =raw t 'help.accept_only_language_specified'
25
25
26 %p
26 %p
27 =raw t 'help.specifying_task'
27 =raw t 'help.specifying_task'
28
28
29 %p
29 %p
30 =raw t 'help.example_cpp'
30 =raw t 'help.example_cpp'
31
31
32 %table{:border => '1'}
32 %table{:border => '1'}
33 %tr
33 %tr
34 %td{:width => '300px'}
34 %td{:width => '300px'}
35 %tt <tt>/*<br/>LANG: C++<br/>TASK: mobiles<br/>*/</tt>
35 %tt <tt>/*<br/>LANG: C++<br/>TASK: mobiles<br/>*/</tt>
36
36
37 %p
37 %p
38 =raw t 'help.example_pas'
38 =raw t 'help.example_pas'
39
39
40 %table{:border => '1'}
40 %table{:border => '1'}
41 %tr
41 %tr
42 %td{:width => '300px'}
42 %td{:width => '300px'}
43 %tt <tt>{<br/>LANG: Pascal<br/>TASK: mobiles<br/>}</tt>
43 %tt <tt>{<br/>LANG: Pascal<br/>TASK: mobiles<br/>}</tt>
44
44
45 %p
45 %p
46 - = raw(t('help.ask_questions_at_messages',:message_link_name => (t 'menu.messages'),:url => url_for(:controller => 'messages', :action => 'list')))
46 + = raw(t('help.ask_questions_at_messages',:message_link_name => (t 'menu.messages'),url: messages_path ))
47
47
@@ -1,45 +1,49
1 :css
1 :css
2 .fix-width {
2 .fix-width {
3 font-family: "Consolas, Monaco, Droid Sans Mono,Mono, Monospace,Courier"
3 font-family: "Consolas, Monaco, Droid Sans Mono,Mono, Monospace,Courier"
4 }
4 }
5
5
6 %h1 Problem stat: #{@problem.name}
6 %h1 Problem stat: #{@problem.name}
7 %h2 Overview
7 %h2 Overview
8
8
9 + .row
10 + .col-md-2
11 + %strong Name:
12 + .col-md-10
13 + = @problem.full_name #in_place_editor_field :problem, :full_name, {}, :rows=>1
14 + = link_to_description_if_any "[#{t 'main.problem_desc'}] <span class='glyphicon glyphicon-file'></span>".html_safe, @problem
15 + .row
16 + .col-md-2.strong
17 + %strong Submissions:
18 + .col-md-10
19 + = @submissions.count
20 + .row
21 + .col-md-2.strong
22 + %strong Solved/Attemped User
23 + .col-md-10
24 + #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
9
25
10 - %table.info
11 - %thead
12 - %tr.info-head
13 - %th Stat
14 - %th Value
15 - %tbody
16 - %tr{class: cycle('info-even','info-odd')}
17 - %td Submissions
18 - %td= @submissions.count
19 - %tr{class: cycle('info-even','info-odd')}
20 - %td Solved/Attempted User
21 - %td #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
22
26
23 %h2 Submissions Count
27 %h2 Submissions Count
24 = render partial: 'application/bar_graph', locals: { histogram: @histogram }
28 = render partial: 'application/bar_graph', locals: { histogram: @histogram }
25
29
26 %h2 Submissions
30 %h2 Submissions
27 - if @submissions and @submissions.count > 0
31 - if @submissions and @submissions.count > 0
28 %table#main_table.table.table-condensed.table-striped
32 %table#main_table.table.table-condensed.table-striped
29 %thead
33 %thead
30 %tr
34 %tr
31 %th ID
35 %th ID
32 %th Login
36 %th Login
33 %th Name
37 %th Name
34 %th Submitted_at
38 %th Submitted_at
35 %th language
39 %th language
36 %th Points
40 %th Points
37 %th comment
41 %th comment
38 %th IP
42 %th IP
39 %tbody
43 %tbody
40 - row_odd,curr = true,''
44 - row_odd,curr = true,''
41 - @submissions.each do |sub|
45 - @submissions.each do |sub|
42 - next unless sub.user
46 - next unless sub.user
43 - row_odd,curr = !row_odd, sub.user if curr != sub.user
47 - row_odd,curr = !row_odd, sub.user if curr != sub.user
44 %tr
48 %tr
45 %td= link_to sub.id, submission_path(sub)
49 %td= link_to sub.id, submission_path(sub)
@@ -21,48 +21,49
21 e = ace.edit("editor")
21 e = ace.edit("editor")
22 e.setOptions({ maxLines: Infinity })
22 e.setOptions({ maxLines: Infinity })
23 e.setValue($("#data").text())
23 e.setValue($("#data").text())
24 e.gotoLine(1)
24 e.gotoLine(1)
25 e.getSession().setMode("#{get_ace_mode(@submission.language)}")
25 e.getSession().setMode("#{get_ace_mode(@submission.language)}")
26 e.setReadOnly(true)
26 e.setReadOnly(true)
27 .col-md-5
27 .col-md-5
28 %table.table.table-striped
28 %table.table.table-striped
29 %tr
29 %tr
30 %td.text-right
30 %td.text-right
31 %strong User
31 %strong User
32 %td
32 %td
33 - if @submission.user
33 - if @submission.user
34 = link_to "#{@submission.user.login}", stat_user_path(@submission.user)
34 = link_to "#{@submission.user.login}", stat_user_path(@submission.user)
35 = @submission.user.full_name
35 = @submission.user.full_name
36 - else
36 - else
37 = "(n/a)"
37 = "(n/a)"
38 %tr
38 %tr
39 %td.text-right
39 %td.text-right
40 %strong Task
40 %strong Task
41 %td
41 %td
42 - if @submission.problem!=nil
42 - if @submission.problem!=nil
43 = link_to "[#{@submission.problem.name}]", stat_problem_path(@submission.problem)
43 = link_to "[#{@submission.problem.name}]", stat_problem_path(@submission.problem)
44 = @submission.problem.full_name
44 = @submission.problem.full_name
45 + = link_to_description_if_any "[download] <span class='glyphicon glyphicon-file'></span>".html_safe, @submission.problem
45 - else
46 - else
46 = "(n/a)"
47 = "(n/a)"
47 %tr
48 %tr
48 %td.text-right
49 %td.text-right
49 %strong Tries
50 %strong Tries
50 %td= @submission.number
51 %td= @submission.number
51 %tr
52 %tr
52 %td.text-right
53 %td.text-right
53 %strong Language
54 %strong Language
54 %td= @submission.language.pretty_name
55 %td= @submission.language.pretty_name
55 %tr
56 %tr
56 %td.text-right
57 %td.text-right
57 %strong Submitted
58 %strong Submitted
58 %td #{time_ago_in_words(@submission.submitted_at)} ago (at #{@submission.submitted_at.to_formatted_s(:long)})
59 %td #{time_ago_in_words(@submission.submitted_at)} ago (at #{@submission.submitted_at.to_formatted_s(:long)})
59 %tr
60 %tr
60 %td.text-right
61 %td.text-right
61 %strong Graded
62 %strong Graded
62 - if @submission.graded_at
63 - if @submission.graded_at
63 %td #{time_ago_in_words(@submission.graded_at)} ago (at #{@submission.graded_at.to_formatted_s(:long)})
64 %td #{time_ago_in_words(@submission.graded_at)} ago (at #{@submission.graded_at.to_formatted_s(:long)})
64 - else
65 - else
65 %td -
66 %td -
66 %tr
67 %tr
67 %td.text-right
68 %td.text-right
68 %strong Points
69 %strong Points
@@ -1,25 +1,54
1 - %h1 Administrators
1 + %h1 Modify Role
2 + .row
3 + .col-md-6
4 + %h4 Administrators
5 + = form_tag modify_role_user_admin_index_path, method: 'post', class: 'form-inline' do
6 + = hidden_field_tag :role, 'admin'
7 + .form-group
8 + = label_tag :login, 'Grant admin role to:'
9 + = text_field_tag 'login',nil, class: 'form-control'
10 + .form-group
11 + = submit_tag 'Grant', class: 'btn btn-primary'
12 + %br
13 + %table.table.table-condense.table-hover.table-striped.table-bordered
14 + %thead{:class => 'info-head'}
15 + %th #
16 + %th Login
17 + %th Full name
18 + %th
19 + - @admins.each_with_index do |user, i|
20 + %tr
21 + %td= i+1
22 + %td= user.login
23 + %td= user.full_name
24 + %td
25 + - if user.login!='root'
26 + = link_to '[revoke]', modify_role_user_admin_index_path( login: user.login, role: 'admin', commit: 'revoke')
27 + .col-md-6
28 + %h4 Teacher Assistants (TA)
29 + = form_tag modify_role_user_admin_index_path, method: 'post', class: 'form-inline' do
30 + = hidden_field_tag :role, 'TA'
31 + .form-group
32 + = label_tag :login, 'Grant TA role to:'
33 + = text_field_tag 'login',nil, class: 'form-control'
34 + .form-group
35 + = submit_tag 'Grant', class: 'btn btn-primary'
36 + %br
37 + %table.table.table-condense.table-hover.table-striped.table-bordered
38 + %thead{:class => 'info-head'}
39 + %th #
40 + %th Login
41 + %th Full name
42 + %th
43 + - @tas.each_with_index do |user, i|
44 + %tr
45 + %td= i+1
46 + %td= user.login
47 + %td= user.full_name
48 + %td
49 + - if user.login!='root'
50 + = link_to '[revoke]', modify_role_user_admin_index_path( login: user.login, role: 'TA', commit: 'revoke')
2
51
3 - %table{:class => 'info'}
4 - %tr{:class => 'info-head'}
5 - %th #
6 - %th Login
7 - %th Full name
8 - %th
9 - - @admins.each_with_index do |user, i|
10 - %tr
11 - %td= i+1
12 - %td= user.login
13 - %td= user.full_name
14 - %td
15 - - if user.login!='root'
16 - = link_to '[revoke]', :action => 'revoke_admin', :id => user.id
17 - %hr
18 -
19 - = form_tag :action => 'grant_admin' do
20 - = label_tag :login, 'Grant admin permission to:'
21 - = text_field_tag 'login',nil, class: 'input-field'
22 - = submit_tag 'Grant', class: 'btn btn-primary'
23
52
24 %hr/
53 %hr/
25 = link_to '[go back to index]', :action => 'index'
54 = link_to '[go back to index]', :action => 'index'
@@ -5,41 +5,50
5 .row
5 .row
6 .col-md-6
6 .col-md-6
7 .panel.panel-default
7 .panel.panel-default
8 .panel-heading
8 .panel-heading
9 .panel-title Info
9 .panel-title Info
10 .panel-body
10 .panel-body
11 %ul
11 %ul
12 %li
12 %li
13 List of user information in this format:
13 List of user information in this format:
14 %tt user_id,name(,passwd(,alias(,remark)))
14 %tt user_id,name(,passwd(,alias(,remark)))
15 %li
15 %li
16 Note that
16 Note that
17 %tt passwd, alias
17 %tt passwd, alias
18 and
18 and
19 %tt remark
19 %tt remark
20 is optional.
20 is optional.
21 %li
21 %li
22 When
22 When
23 %tt passwd
23 %tt passwd
24 or
24 or
25 %tt alias
25 %tt alias
26 is empty, the original value will be used instead.
26 is empty, the original value will be used instead.
27 %li
27 %li
28 If the users with the same user_id already exists, existing information will be overwritten.
28 If the users with the same user_id already exists, existing information will be overwritten.
29 + Example:
30 + %ol
31 + %li
32 + %pre user1,Somchai Jaidee
33 + will create (or update) a user with login "user1" and setting the fullname to "Somchai Jaidee", also setting a random password.
34 + %li
35 + %pre user1,Somchai Jaidee,
36 + will create (or update) a user with login "user1" and and setting the fullname "Somchai Jaidee". No change is made to the password unless this is a new user. If this is a new user, a random password will be generated.
37 +
29
38
30 .row
39 .row
31 .col-md-6
40 .col-md-6
32 = form_tag :action => 'create_from_list' do
41 = form_tag :action => 'create_from_list' do
33 .form-group
42 .form-group
34 = submit_tag 'Create following users',class: 'btn btn-success'
43 = submit_tag 'Create following users',class: 'btn btn-success'
35 .form-group
44 .form-group
36 .div.checkbox
45 .div.checkbox
37 %label
46 %label
38 = check_box_tag :add_to_group
47 = check_box_tag :add_to_group
39 Also add these users to the following group
48 Also add these users to the following group
40 = select_tag "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_name]), id: 'group_name',class: 'select2'
49 = select_tag "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_name]), id: 'group_name',class: 'select2'
41 .form-group
50 .form-group
42 = text_area_tag 'user_list', nil, :rows => 50, :cols => 80
51 = text_area_tag 'user_list', nil, :rows => 50, :cols => 80
43 .col-md-6
52 .col-md-6
44
53
45
54
@@ -33,109 +33,108
33 get 'toggle'
33 get 'toggle'
34 get 'toggle_test'
34 get 'toggle_test'
35 get 'toggle_view_testcase'
35 get 'toggle_view_testcase'
36 get 'stat'
36 get 'stat'
37 end
37 end
38 collection do
38 collection do
39 get 'turn_all_off'
39 get 'turn_all_off'
40 get 'turn_all_on'
40 get 'turn_all_on'
41 get 'import'
41 get 'import'
42 get 'manage'
42 get 'manage'
43 get 'quick_create'
43 get 'quick_create'
44 post 'do_manage'
44 post 'do_manage'
45 post 'do_import'
45 post 'do_import'
46 end
46 end
47 end
47 end
48
48
49 resources :groups do
49 resources :groups do
50 member do
50 member do
51 post 'add_user', to: 'groups#add_user', as: 'add_user'
51 post 'add_user', to: 'groups#add_user', as: 'add_user'
52 delete 'remove_user/:user_id', to: 'groups#remove_user', as: 'remove_user'
52 delete 'remove_user/:user_id', to: 'groups#remove_user', as: 'remove_user'
53 delete 'remove_all_user', to: 'groups#remove_all_user', as: 'remove_all_user'
53 delete 'remove_all_user', to: 'groups#remove_all_user', as: 'remove_all_user'
54 post 'add_problem', to: 'groups#add_problem', as: 'add_problem'
54 post 'add_problem', to: 'groups#add_problem', as: 'add_problem'
55 delete 'remove_problem/:problem_id', to: 'groups#remove_problem', as: 'remove_problem'
55 delete 'remove_problem/:problem_id', to: 'groups#remove_problem', as: 'remove_problem'
56 delete 'remove_all_problem', to: 'groups#remove_all_problem', as: 'remove_all_problem'
56 delete 'remove_all_problem', to: 'groups#remove_all_problem', as: 'remove_all_problem'
57 + get 'toggle'
57 end
58 end
58 collection do
59 collection do
59
60
60 end
61 end
61 end
62 end
62
63
63 resources :testcases, only: [] do
64 resources :testcases, only: [] do
64 member do
65 member do
65 get 'download_input'
66 get 'download_input'
66 get 'download_sol'
67 get 'download_sol'
67 end
68 end
68 collection do
69 collection do
69 get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem'
70 get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem'
70 end
71 end
71 end
72 end
72
73
73 resources :grader_configuration, controller: 'configurations' do
74 resources :grader_configuration, controller: 'configurations' do
74 collection do
75 collection do
75 get 'set_exam_right(/:value)', action: 'set_exam_right', as: 'set_exam_right'
76 get 'set_exam_right(/:value)', action: 'set_exam_right', as: 'set_exam_right'
76 end
77 end
77 end
78 end
78
79
79 resources :users do
80 resources :users do
80 member do
81 member do
81 get 'toggle_activate', 'toggle_enable'
82 get 'toggle_activate', 'toggle_enable'
82 get 'stat'
83 get 'stat'
83 end
84 end
84 collection do
85 collection do
85 get 'profile'
86 get 'profile'
86 post 'chg_passwd'
87 post 'chg_passwd'
87 end
88 end
88 end
89 end
89
90
90 resources :submissions do
91 resources :submissions do
91 member do
92 member do
92 get 'download'
93 get 'download'
93 get 'compiler_msg'
94 get 'compiler_msg'
94 get 'rejudge'
95 get 'rejudge'
95 - get 'source'
96 end
96 end
97 collection do
97 collection do
98 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
98 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
99 get 'direct_edit_problem/:problem_id(/:user_id)', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
99 get 'direct_edit_problem/:problem_id(/:user_id)', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
100 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
100 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
101 end
101 end
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 + match 'modify_role', via: [:get, :post]
117 - post 'grant_admin'
118 match 'create_from_list', via: [:get, :post]
117 match 'create_from_list', via: [:get, :post]
119 match 'random_all_passwords', via: [:get, :post]
118 match 'random_all_passwords', via: [:get, :post]
120 end
119 end
121 member do
120 member do
122 get 'clear_last_ip'
121 get 'clear_last_ip'
123 end
122 end
124 end
123 end
125
124
126 resources :contest_management, only: [:index] do
125 resources :contest_management, only: [:index] do
127 collection do
126 collection do
128 get 'user_stat'
127 get 'user_stat'
129 get 'clear_stat'
128 get 'clear_stat'
130 get 'clear_all_stat'
129 get 'clear_all_stat'
131 get 'change_contest_mode'
130 get 'change_contest_mode'
132 end
131 end
133 end
132 end
134
133
135 #get 'user_admin', to: 'user_admin#index'
134 #get 'user_admin', to: 'user_admin#index'
136 #get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin'
135 #get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin'
137 #post 'user_admin', to: 'user_admin#create'
136 #post 'user_admin', to: 'user_admin#create'
138 #delete 'user_admin/:id', to: 'user_admin#destroy', as: 'user_admin_destroy'
137 #delete 'user_admin/:id', to: 'user_admin#destroy', as: 'user_admin_destroy'
139
138
140 #singular resource
139 #singular resource
141 #---- BEWARE ---- singular resource maps to plural controller by default, we can override by provide controller name directly
140 #---- BEWARE ---- singular resource maps to plural controller by default, we can override by provide controller name directly
@@ -163,49 +162,50
163 #get 'report/current_score', to: 'report#current_score', as: 'report_current_score'
162 #get 'report/current_score', to: 'report#current_score', as: 'report_current_score'
164 #get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
163 #get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
165 #get "report/login"
164 #get "report/login"
166 #get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
165 #get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
167 #post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score'
166 #post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score'
168
167
169 resource :main, only: [], controller: 'main' do
168 resource :main, only: [], controller: 'main' do
170 get 'login'
169 get 'login'
171 get 'logout'
170 get 'logout'
172 get 'list'
171 get 'list'
173 get 'submission(/:id)', action: 'submission', as: 'main_submission'
172 get 'submission(/:id)', action: 'submission', as: 'main_submission'
174 get 'announcements'
173 get 'announcements'
175 get 'help'
174 get 'help'
176 post 'submit'
175 post 'submit'
177 end
176 end
178 #main
177 #main
179 #get "main/list"
178 #get "main/list"
180 #get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
179 #get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
181 #post 'main/submit', to: 'main#submit'
180 #post 'main/submit', to: 'main#submit'
182 #get 'main/announcements', to: 'main#announcements'
181 #get 'main/announcements', to: 'main#announcements'
183
182
184
183
185 #
184 #
186 get 'tasks/view/:file.:ext' => 'tasks#view'
185 get 'tasks/view/:file.:ext' => 'tasks#view'
187 - get 'tasks/download/:id/:file.:ext' => 'tasks#download'
186 + get 'tasks/download/:id/:file.:ext' => 'tasks#download', as: 'download_task'
188 get 'heartbeat/:id/edit' => 'heartbeat#edit'
187 get 'heartbeat/:id/edit' => 'heartbeat#edit'
189
188
190 #grader
189 #grader
191 - get 'graders/list', to: 'graders#list', as: 'grader_list'
190 + #get 'graders/list', to: 'graders#list', as: 'grader_list'
192 namespace :graders do
191 namespace :graders do
193 get 'task/:id/:type', action: 'task', as: 'task'
192 get 'task/:id/:type', action: 'task', as: 'task'
194 get 'view/:id/:type', action: 'view', as: 'view'
193 get 'view/:id/:type', action: 'view', as: 'view'
195 get 'clear/:id', action: 'clear', as: 'clear'
194 get 'clear/:id', action: 'clear', as: 'clear'
196 - get 'stop'
197 - get 'stop_all'
198 - get 'clear_all'
199 - get 'clear_terminated'
200 get 'start_grading'
195 get 'start_grading'
201 get 'start_exam'
196 get 'start_exam'
197 + get 'clear_all'
198 + get 'stop_all'
202
199
200 + get 'stop'
201 + get 'clear_terminated'
202 + get 'list'
203 end
203 end
204
204
205
205
206 # See how all your routes lay out with "rake routes"
206 # See how all your routes lay out with "rake routes"
207
207
208 # This is a legacy wild controller route that's not recommended for RESTful applications.
208 # This is a legacy wild controller route that's not recommended for RESTful applications.
209 # Note: This route will make all actions in every controller accessible via GET requests.
209 # Note: This route will make all actions in every controller accessible via GET requests.
210 # match ':controller(/:action(/:id))(.:format)', via: [:get, :post]
210 # match ':controller(/:action(/:id))(.:format)', via: [:get, :post]
211 end
211 end
@@ -204,48 +204,49
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 + Role.find_or_create_by(name: 'TA')
228 return if Role.find_by_name('admin')
229 return if Role.find_by_name('admin')
229
230
230 role = Role.create(:name => 'admin')
231 role = Role.create(:name => 'admin')
231 user_admin_right = Right.create(:name => 'user_admin',
232 user_admin_right = Right.create(:name => 'user_admin',
232 :controller => 'user_admin',
233 :controller => 'user_admin',
233 :action => 'all')
234 :action => 'all')
234 problem_admin_right = Right.create(:name=> 'problem_admin',
235 problem_admin_right = Right.create(:name=> 'problem_admin',
235 :controller => 'problems',
236 :controller => 'problems',
236 :action => 'all')
237 :action => 'all')
237
238
238 graders_right = Right.create(:name => 'graders_admin',
239 graders_right = Right.create(:name => 'graders_admin',
239 :controller => 'graders',
240 :controller => 'graders',
240 :action => 'all')
241 :action => 'all')
241
242
242 role.rights << user_admin_right;
243 role.rights << user_admin_right;
243 role.rights << problem_admin_right;
244 role.rights << problem_admin_right;
244 role.rights << graders_right;
245 role.rights << graders_right;
245 role.save
246 role.save
246 end
247 end
247
248
248 def seed_root
249 def seed_root
249 return if User.find_by_login('root')
250 return if User.find_by_login('root')
250
251
251 root = User.new(:login => 'root',
252 root = User.new(:login => 'root',
You need to be logged in to leave comments. Login now