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

r834:825a2986c8ea - - 19 files changed: 140 inserted, 89 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
@@ -149,14 +149,15
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
@@ -1,10 +1,11
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
@@ -46,12 +47,17
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
@@ -96,9 +102,9
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
@@ -13,14 +13,14
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
@@ -24,23 +24,25
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
@@ -62,43 +62,53
62 note = []
62 note = []
63 error_note = []
63 error_note = []
64 error_msg = nil
64 error_msg = nil
65 ok_user = []
65 ok_user = []
66
66
67 lines.split("\n").each do |line|
67 lines.split("\n").each do |line|
68 - items = line.chomp.split(',')
68 + #split with large limit, this will cause consecutive ',' to be result in a blank
69 + items = line.chomp.split(',',1000)
69 if items.length>=2
70 if items.length>=2
70 login = items[0]
71 login = items[0]
71 full_name = items[1]
72 full_name = items[1]
72 remark =''
73 remark =''
73 user_alias = ''
74 user_alias = ''
74
75
75 added_random_password = false
76 added_random_password = false
76 - if items.length >= 3 and items[2].chomp(" ").length > 0;
77 + added_password = false
78 + if items.length >= 3
79 + if items[2].chomp(" ").length > 0
77 password = items[2].chomp(" ")
80 password = items[2].chomp(" ")
81 + added_password = true
82 + end
78 else
83 else
79 password = random_password
84 password = random_password
80 added_random_password=true;
85 added_random_password=true;
81 end
86 end
82
87
83 if items.length>= 4 and items[3].chomp(" ").length > 0;
88 if items.length>= 4 and items[3].chomp(" ").length > 0;
84 user_alias = items[3].chomp(" ")
89 user_alias = items[3].chomp(" ")
85 else
90 else
86 user_alias = login
91 user_alias = login
87 end
92 end
88
93
94 +
95 + has_remark = false
89 if items.length>=5
96 if items.length>=5
90 remark = items[4].strip;
97 remark = items[4].strip;
98 + has_remark = true
91 end
99 end
92
100
93 user = User.find_by_login(login)
101 user = User.find_by_login(login)
94 if (user)
102 if (user)
95 user.full_name = full_name
103 user.full_name = full_name
96 - user.password = password
104 + user.remark = remark if has_remark
97 - user.remark = remark
105 + user.password = password if added_password || added_random_password
98 else
106 else
107 + #create a random password if none are given
108 + password = random_password unless password
99 user = User.new({:login => login,
109 user = User.new({:login => login,
100 :full_name => full_name,
110 :full_name => full_name,
101 :password => password,
111 :password => password,
102 :password_confirmation => password,
112 :password_confirmation => password,
103 :alias => user_alias,
113 :alias => user_alias,
104 :remark => remark})
114 :remark => remark})
@@ -110,14 +110,15
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
@@ -178,15 +179,12
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>
@@ -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
@@ -151,13 +151,13
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?
@@ -313,15 +313,16
313 end
313 end
314 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
314 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
315 return contest_problems + other_avaiable_problems
315 return contest_problems + other_avaiable_problems
316 end
316 end
317 end
317 end
318
318
319 + # new feature, get list of available problem in all enabled group that the user belongs to
319 def available_problems_in_group
320 def available_problems_in_group
320 problem = []
321 problem = []
321 - self.groups.each do |group|
322 + self.groups.where(enabled: true).each do |group|
322 group.problems.where(available: true).each { |p| problem << p }
323 group.problems.where(available: true).each { |p| problem << p }
323 end
324 end
324 problem.uniq!
325 problem.uniq!
325 if problem
326 if problem
326 problem.sort! do |a,b|
327 problem.sort! do |a,b|
327 case
328 case
@@ -336,12 +337,14
336 return problem
337 return problem
337 else
338 else
338 return []
339 return []
339 end
340 end
340 end
341 end
341
342
343 + #check if the user has the right to view that problem
344 + #this also consider group based problem policy
342 def can_view_problem?(problem)
345 def can_view_problem?(problem)
343 return true if admin?
346 return true if admin?
344 return available_problems.include? problem
347 return available_problems.include? problem
345 end
348 end
346
349
347 def self.clear_last_login
350 def self.clear_last_login
@@ -7,13 +7,13
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 = " ["
@@ -2,15 +2,26
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 + .col-md-6
9 .form-group.field
10 .form-group.field
10 = f.label :name
11 = f.label :name
11 = f.text_field :name, class: 'form-control'
12 = f.text_field :name, class: 'form-control'
13 + .row
14 + .col-md-6
12 .form-group.field
15 .form-group.field
13 = f.label :description
16 = f.label :description
14 = f.text_field :description, class: 'form-control'
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
15 .form-group.actions
26 .form-group.actions
16 = f.submit 'Save', class: 'btn btn-primary'
27 = f.submit 'Save', class: 'btn btn-primary'
@@ -4,19 +4,21
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
@@ -40,8 +40,8
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
@@ -39,12 +39,13
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
@@ -23,12 +23,21
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'
@@ -51,12 +51,13
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
@@ -89,13 +90,12
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
@@ -174,13 +174,13
174 #post 'main/submit', to: 'main#submit'
174 #post 'main/submit', to: 'main#submit'
175 #get 'main/announcements', to: 'main#announcements'
175 #get 'main/announcements', to: 'main#announcements'
176
176
177
177
178 #
178 #
179 get 'tasks/view/:file.:ext' => 'tasks#view'
179 get 'tasks/view/:file.:ext' => 'tasks#view'
180 - get 'tasks/download/:id/:file.:ext' => 'tasks#download'
180 + get 'tasks/download/:id/:file.:ext' => 'tasks#download', as: 'download_task'
181 get 'heartbeat/:id/edit' => 'heartbeat#edit'
181 get 'heartbeat/:id/edit' => 'heartbeat#edit'
182
182
183 #grader
183 #grader
184 get 'graders/list', to: 'graders#list', as: 'grader_list'
184 get 'graders/list', to: 'graders#list', as: 'grader_list'
185 namespace :graders do
185 namespace :graders do
186 get 'task/:id/:type', action: 'task', as: 'task'
186 get 'task/:id/:type', action: 'task', as: 'task'
@@ -7,82 +7,83
7 # system, you should be using db:schema:load, not running all the migrations
7 # system, you should be using db:schema:load, not running all the migrations
8 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
8 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9 # you'll amass, the slower it'll run and the greater likelihood for issues).
9 # you'll amass, the slower it'll run and the greater likelihood for issues).
10 #
10 #
11 # It's strongly recommended that you check this file into your version control system.
11 # It's strongly recommended that you check this file into your version control system.
12
12
13 - ActiveRecord::Schema.define(version: 2018_06_12_102327) do
13 + ActiveRecord::Schema.define(version: 2020_08_13_083020) do
14
14
15 - create_table "announcements", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
15 + create_table "announcements", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
16 t.string "author"
16 t.string "author"
17 t.text "body"
17 t.text "body"
18 t.boolean "published"
18 t.boolean "published"
19 - t.datetime "created_at"
19 + t.datetime "created_at", null: false
20 - t.datetime "updated_at"
20 + t.datetime "updated_at", null: false
21 t.boolean "frontpage", default: false
21 t.boolean "frontpage", default: false
22 t.boolean "contest_only", default: false
22 t.boolean "contest_only", default: false
23 t.string "title"
23 t.string "title"
24 t.string "notes"
24 t.string "notes"
25 end
25 end
26
26
27 - create_table "contests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
27 + create_table "contests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
28 t.string "title"
28 t.string "title"
29 t.boolean "enabled"
29 t.boolean "enabled"
30 - t.datetime "created_at"
30 + t.datetime "created_at", null: false
31 - t.datetime "updated_at"
31 + t.datetime "updated_at", null: false
32 t.string "name"
32 t.string "name"
33 end
33 end
34
34
35 - create_table "contests_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
35 + create_table "contests_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
36 t.integer "contest_id"
36 t.integer "contest_id"
37 t.integer "problem_id"
37 t.integer "problem_id"
38 end
38 end
39
39
40 - create_table "contests_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
40 + create_table "contests_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
41 t.integer "contest_id"
41 t.integer "contest_id"
42 t.integer "user_id"
42 t.integer "user_id"
43 end
43 end
44
44
45 - create_table "countries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
45 + create_table "countries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
46 t.string "name"
46 t.string "name"
47 - t.datetime "created_at"
47 + t.datetime "created_at", null: false
48 - t.datetime "updated_at"
48 + t.datetime "updated_at", null: false
49 end
49 end
50
50
51 - create_table "descriptions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
51 + create_table "descriptions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
52 t.text "body"
52 t.text "body"
53 t.boolean "markdowned"
53 t.boolean "markdowned"
54 - t.datetime "created_at"
54 + t.datetime "created_at", null: false
55 - t.datetime "updated_at"
55 + t.datetime "updated_at", null: false
56 end
56 end
57
57
58 - create_table "grader_configurations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
58 + create_table "grader_configurations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
59 t.string "key"
59 t.string "key"
60 t.string "value_type"
60 t.string "value_type"
61 t.string "value"
61 t.string "value"
62 - t.datetime "created_at"
62 + t.datetime "created_at", null: false
63 - t.datetime "updated_at"
63 + t.datetime "updated_at", null: false
64 t.text "description"
64 t.text "description"
65 end
65 end
66
66
67 - create_table "grader_processes", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
67 + create_table "grader_processes", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
68 t.string "host"
68 t.string "host"
69 t.integer "pid"
69 t.integer "pid"
70 t.string "mode"
70 t.string "mode"
71 t.boolean "active"
71 t.boolean "active"
72 - t.datetime "created_at"
72 + t.datetime "created_at", null: false
73 - t.datetime "updated_at"
73 + t.datetime "updated_at", null: false
74 t.integer "task_id"
74 t.integer "task_id"
75 t.string "task_type"
75 t.string "task_type"
76 t.boolean "terminated"
76 t.boolean "terminated"
77 - t.index ["host", "pid"], name: "index_grader_processes_on_host_and_pid"
77 + t.index ["host", "pid"], name: "index_grader_processes_on_ip_and_pid"
78 end
78 end
79
79
80 create_table "groups", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
80 create_table "groups", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
81 t.string "name"
81 t.string "name"
82 t.string "description"
82 t.string "description"
83 + t.boolean "enabled", default: true
83 end
84 end
84
85
85 create_table "groups_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
86 create_table "groups_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
86 t.integer "problem_id", null: false
87 t.integer "problem_id", null: false
87 t.integer "group_id", null: false
88 t.integer "group_id", null: false
88 t.index ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id"
89 t.index ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id"
@@ -91,46 +92,46
91 create_table "groups_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
92 create_table "groups_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
92 t.integer "group_id", null: false
93 t.integer "group_id", null: false
93 t.integer "user_id", null: false
94 t.integer "user_id", null: false
94 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
95 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
95 end
96 end
96
97
97 - create_table "heart_beats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
98 + create_table "heart_beats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
98 t.integer "user_id"
99 t.integer "user_id"
99 t.string "ip_address"
100 t.string "ip_address"
100 - t.datetime "created_at"
101 + t.datetime "created_at", null: false
101 - t.datetime "updated_at"
102 + t.datetime "updated_at", null: false
102 t.string "status"
103 t.string "status"
103 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
104 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
104 end
105 end
105
106
106 - create_table "languages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
107 + create_table "languages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
107 t.string "name", limit: 10
108 t.string "name", limit: 10
108 t.string "pretty_name"
109 t.string "pretty_name"
109 t.string "ext", limit: 10
110 t.string "ext", limit: 10
110 t.string "common_ext"
111 t.string "common_ext"
111 end
112 end
112
113
113 - create_table "logins", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
114 + create_table "logins", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
114 t.integer "user_id"
115 t.integer "user_id"
115 t.string "ip_address"
116 t.string "ip_address"
116 - t.datetime "created_at"
117 + t.datetime "created_at", null: false
117 - t.datetime "updated_at"
118 + t.datetime "updated_at", null: false
118 end
119 end
119
120
120 - create_table "messages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
121 + create_table "messages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
121 t.integer "sender_id"
122 t.integer "sender_id"
122 t.integer "receiver_id"
123 t.integer "receiver_id"
123 t.integer "replying_message_id"
124 t.integer "replying_message_id"
124 t.text "body"
125 t.text "body"
125 t.boolean "replied"
126 t.boolean "replied"
126 - t.datetime "created_at"
127 + t.datetime "created_at", null: false
127 - t.datetime "updated_at"
128 + t.datetime "updated_at", null: false
128 end
129 end
129
130
130 - create_table "problems", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
131 + create_table "problems", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
131 t.string "name", limit: 30
132 t.string "name", limit: 30
132 t.string "full_name"
133 t.string "full_name"
133 t.integer "full_score"
134 t.integer "full_score"
134 t.date "date_added"
135 t.date "date_added"
135 t.boolean "available"
136 t.boolean "available"
136 t.string "url"
137 t.string "url"
@@ -146,60 +147,60
146 t.integer "tag_id"
147 t.integer "tag_id"
147 t.index ["problem_id", "tag_id"], name: "index_problems_tags_on_problem_id_and_tag_id", unique: true
148 t.index ["problem_id", "tag_id"], name: "index_problems_tags_on_problem_id_and_tag_id", unique: true
148 t.index ["problem_id"], name: "index_problems_tags_on_problem_id"
149 t.index ["problem_id"], name: "index_problems_tags_on_problem_id"
149 t.index ["tag_id"], name: "index_problems_tags_on_tag_id"
150 t.index ["tag_id"], name: "index_problems_tags_on_tag_id"
150 end
151 end
151
152
152 - create_table "rights", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
153 + create_table "rights", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
153 t.string "name"
154 t.string "name"
154 t.string "controller"
155 t.string "controller"
155 t.string "action"
156 t.string "action"
156 end
157 end
157
158
158 - create_table "rights_roles", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
159 + create_table "rights_roles", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
159 t.integer "right_id"
160 t.integer "right_id"
160 t.integer "role_id"
161 t.integer "role_id"
161 t.index ["role_id"], name: "index_rights_roles_on_role_id"
162 t.index ["role_id"], name: "index_rights_roles_on_role_id"
162 end
163 end
163
164
164 - create_table "roles", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
165 + create_table "roles", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
165 t.string "name"
166 t.string "name"
166 end
167 end
167
168
168 - create_table "roles_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
169 + create_table "roles_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
169 t.integer "role_id"
170 t.integer "role_id"
170 t.integer "user_id"
171 t.integer "user_id"
171 t.index ["user_id"], name: "index_roles_users_on_user_id"
172 t.index ["user_id"], name: "index_roles_users_on_user_id"
172 end
173 end
173
174
174 - create_table "sessions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
175 + create_table "sessions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
175 t.string "session_id"
176 t.string "session_id"
176 t.text "data"
177 t.text "data"
177 t.datetime "updated_at"
178 t.datetime "updated_at"
178 t.index ["session_id"], name: "index_sessions_on_session_id"
179 t.index ["session_id"], name: "index_sessions_on_session_id"
179 t.index ["updated_at"], name: "index_sessions_on_updated_at"
180 t.index ["updated_at"], name: "index_sessions_on_updated_at"
180 end
181 end
181
182
182 - create_table "sites", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
183 + create_table "sites", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
183 t.string "name"
184 t.string "name"
184 t.boolean "started"
185 t.boolean "started"
185 t.datetime "start_time"
186 t.datetime "start_time"
186 - t.datetime "created_at"
187 + t.datetime "created_at", null: false
187 - t.datetime "updated_at"
188 + t.datetime "updated_at", null: false
188 t.integer "country_id"
189 t.integer "country_id"
189 t.string "password"
190 t.string "password"
190 end
191 end
191
192
192 - create_table "submission_view_logs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
193 + create_table "submission_view_logs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
193 t.integer "user_id"
194 t.integer "user_id"
194 t.integer "submission_id"
195 t.integer "submission_id"
195 - t.datetime "created_at"
196 + t.datetime "created_at", null: false
196 - t.datetime "updated_at"
197 + t.datetime "updated_at", null: false
197 end
198 end
198
199
199 - create_table "submissions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
200 + create_table "submissions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
200 t.integer "user_id"
201 t.integer "user_id"
201 t.integer "problem_id"
202 t.integer "problem_id"
202 t.integer "language_id"
203 t.integer "language_id"
203 t.text "source", limit: 16777215
204 t.text "source", limit: 16777215
204 t.binary "binary"
205 t.binary "binary"
205 t.datetime "submitted_at"
206 t.datetime "submitted_at"
@@ -223,43 +224,43
223 t.text "description"
224 t.text "description"
224 t.boolean "public"
225 t.boolean "public"
225 t.datetime "created_at", null: false
226 t.datetime "created_at", null: false
226 t.datetime "updated_at", null: false
227 t.datetime "updated_at", null: false
227 end
228 end
228
229
229 - create_table "tasks", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
230 + create_table "tasks", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
230 t.integer "submission_id"
231 t.integer "submission_id"
231 t.datetime "created_at"
232 t.datetime "created_at"
232 t.integer "status"
233 t.integer "status"
233 t.datetime "updated_at"
234 t.datetime "updated_at"
234 t.index ["submission_id"], name: "index_tasks_on_submission_id"
235 t.index ["submission_id"], name: "index_tasks_on_submission_id"
235 end
236 end
236
237
237 - create_table "test_pairs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
238 + create_table "test_pairs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
238 t.integer "problem_id"
239 t.integer "problem_id"
239 t.text "input", limit: 16777215
240 t.text "input", limit: 16777215
240 t.text "solution", limit: 16777215
241 t.text "solution", limit: 16777215
241 - t.datetime "created_at"
242 + t.datetime "created_at", null: false
242 - t.datetime "updated_at"
243 + t.datetime "updated_at", null: false
243 end
244 end
244
245
245 - create_table "test_requests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
246 + create_table "test_requests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
246 t.integer "user_id"
247 t.integer "user_id"
247 t.integer "problem_id"
248 t.integer "problem_id"
248 t.integer "submission_id"
249 t.integer "submission_id"
249 t.string "input_file_name"
250 t.string "input_file_name"
250 t.string "output_file_name"
251 t.string "output_file_name"
251 t.string "running_stat"
252 t.string "running_stat"
252 t.integer "status"
253 t.integer "status"
253 - t.datetime "updated_at"
254 + t.datetime "updated_at", null: false
254 t.datetime "submitted_at"
255 t.datetime "submitted_at"
255 t.datetime "compiled_at"
256 t.datetime "compiled_at"
256 t.text "compiler_message"
257 t.text "compiler_message"
257 t.datetime "graded_at"
258 t.datetime "graded_at"
258 t.string "grader_comment"
259 t.string "grader_comment"
259 - t.datetime "created_at"
260 + t.datetime "created_at", null: false
260 t.float "running_time"
261 t.float "running_time"
261 t.string "exit_status"
262 t.string "exit_status"
262 t.integer "memory_usage"
263 t.integer "memory_usage"
263 t.index ["user_id", "problem_id"], name: "index_test_requests_on_user_id_and_problem_id"
264 t.index ["user_id", "problem_id"], name: "index_test_requests_on_user_id_and_problem_id"
264 end
265 end
265
266
@@ -272,36 +273,36
272 t.text "sol", limit: 4294967295
273 t.text "sol", limit: 4294967295
273 t.datetime "created_at"
274 t.datetime "created_at"
274 t.datetime "updated_at"
275 t.datetime "updated_at"
275 t.index ["problem_id"], name: "index_testcases_on_problem_id"
276 t.index ["problem_id"], name: "index_testcases_on_problem_id"
276 end
277 end
277
278
278 - create_table "user_contest_stats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
279 + create_table "user_contest_stats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
279 t.integer "user_id"
280 t.integer "user_id"
280 t.datetime "started_at"
281 t.datetime "started_at"
281 - t.datetime "created_at"
282 + t.datetime "created_at", null: false
282 - t.datetime "updated_at"
283 + t.datetime "updated_at", null: false
283 t.boolean "forced_logout"
284 t.boolean "forced_logout"
284 end
285 end
285
286
286 - create_table "users", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
287 + create_table "users", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
287 t.string "login", limit: 50
288 t.string "login", limit: 50
288 t.string "full_name"
289 t.string "full_name"
289 t.string "hashed_password"
290 t.string "hashed_password"
290 t.string "salt", limit: 5
291 t.string "salt", limit: 5
291 t.string "alias"
292 t.string "alias"
292 t.string "email"
293 t.string "email"
293 t.integer "site_id"
294 t.integer "site_id"
294 t.integer "country_id"
295 t.integer "country_id"
295 t.boolean "activated", default: false
296 t.boolean "activated", default: false
296 t.datetime "created_at"
297 t.datetime "created_at"
297 t.datetime "updated_at"
298 t.datetime "updated_at"
298 - t.string "section"
299 t.boolean "enabled", default: true
299 t.boolean "enabled", default: true
300 t.string "remark"
300 t.string "remark"
301 t.string "last_ip"
301 t.string "last_ip"
302 + t.string "section"
302 t.index ["login"], name: "index_users_on_login", unique: true
303 t.index ["login"], name: "index_users_on_login", unique: true
303 end
304 end
304
305
305 add_foreign_key "problems_tags", "problems"
306 add_foreign_key "problems_tags", "problems"
306 add_foreign_key "problems_tags", "tags"
307 add_foreign_key "problems_tags", "tags"
307 end
308 end
You need to be logged in to leave comments. Login now