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

r879:60919c3675f4 - - 13 files changed: 89 inserted, 106 deleted

@@ -149,188 +149,192
149 actionpack (>= 6.0.0)
149 actionpack (>= 6.0.0)
150 railties (>= 6.0.0)
150 railties (>= 6.0.0)
151 jbuilder (2.11.5)
151 jbuilder (2.11.5)
152 actionview (>= 5.0.0)
152 actionview (>= 5.0.0)
153 activesupport (>= 5.0.0)
153 activesupport (>= 5.0.0)
154 jquery-rails (4.5.0)
154 jquery-rails (4.5.0)
155 rails-dom-testing (>= 1, < 3)
155 rails-dom-testing (>= 1, < 3)
156 railties (>= 4.2.0)
156 railties (>= 4.2.0)
157 thor (>= 0.14, < 2.0)
157 thor (>= 0.14, < 2.0)
158 listen (3.0.8)
158 listen (3.0.8)
159 rb-fsevent (~> 0.9, >= 0.9.4)
159 rb-fsevent (~> 0.9, >= 0.9.4)
160 rb-inotify (~> 0.9, >= 0.9.7)
160 rb-inotify (~> 0.9, >= 0.9.7)
161 loofah (2.19.0)
161 loofah (2.19.0)
162 crass (~> 1.0.2)
162 crass (~> 1.0.2)
163 nokogiri (>= 1.5.9)
163 nokogiri (>= 1.5.9)
164 mail (2.7.1)
164 mail (2.7.1)
165 mini_mime (>= 0.1.1)
165 mini_mime (>= 0.1.1)
166 marcel (1.0.2)
166 marcel (1.0.2)
167 material_icons (2.2.1)
167 material_icons (2.2.1)
168 railties (>= 3.2)
168 railties (>= 3.2)
169 matrix (0.4.2)
169 matrix (0.4.2)
170 method_source (1.0.0)
170 method_source (1.0.0)
171 mini_mime (1.1.2)
171 mini_mime (1.1.2)
172 minitest (5.16.3)
172 minitest (5.16.3)
173 minitest-reporters (1.5.0)
173 minitest-reporters (1.5.0)
174 ansi
174 ansi
175 builder
175 builder
176 minitest (>= 5.0)
176 minitest (>= 5.0)
177 ruby-progressbar
177 ruby-progressbar
178 momentjs-rails (2.29.4.1)
178 momentjs-rails (2.29.4.1)
179 railties (>= 3.1)
179 railties (>= 3.1)
180 msgpack (1.5.6)
180 msgpack (1.5.6)
181 mysql2 (0.5.4)
181 mysql2 (0.5.4)
182 net-imap (0.2.3)
182 net-imap (0.2.3)
183 digest
183 digest
184 net-protocol
184 net-protocol
185 strscan
185 strscan
186 net-pop (0.1.1)
186 net-pop (0.1.1)
187 digest
187 digest
188 net-protocol
188 net-protocol
189 timeout
189 timeout
190 net-protocol (0.1.3)
190 net-protocol (0.1.3)
191 timeout
191 timeout
192 net-smtp (0.3.1)
192 net-smtp (0.3.1)
193 digest
193 digest
194 net-protocol
194 net-protocol
195 timeout
195 timeout
196 nio4r (2.5.8)
196 nio4r (2.5.8)
197 + nokogiri (1.13.8-x86_64-darwin)
198 + racc (~> 1.4)
197 nokogiri (1.13.8-x86_64-linux)
199 nokogiri (1.13.8-x86_64-linux)
198 racc (~> 1.4)
200 racc (~> 1.4)
199 popper_js (2.11.6)
201 popper_js (2.11.6)
200 public_suffix (5.0.0)
202 public_suffix (5.0.0)
201 puma (5.6.5)
203 puma (5.6.5)
202 nio4r (~> 2.0)
204 nio4r (~> 2.0)
203 racc (1.6.0)
205 racc (1.6.0)
204 rack (2.2.4)
206 rack (2.2.4)
205 rack-test (2.0.2)
207 rack-test (2.0.2)
206 rack (>= 1.3)
208 rack (>= 1.3)
207 rails (7.0.4)
209 rails (7.0.4)
208 actioncable (= 7.0.4)
210 actioncable (= 7.0.4)
209 actionmailbox (= 7.0.4)
211 actionmailbox (= 7.0.4)
210 actionmailer (= 7.0.4)
212 actionmailer (= 7.0.4)
211 actionpack (= 7.0.4)
213 actionpack (= 7.0.4)
212 actiontext (= 7.0.4)
214 actiontext (= 7.0.4)
213 actionview (= 7.0.4)
215 actionview (= 7.0.4)
214 activejob (= 7.0.4)
216 activejob (= 7.0.4)
215 activemodel (= 7.0.4)
217 activemodel (= 7.0.4)
216 activerecord (= 7.0.4)
218 activerecord (= 7.0.4)
217 activestorage (= 7.0.4)
219 activestorage (= 7.0.4)
218 activesupport (= 7.0.4)
220 activesupport (= 7.0.4)
219 bundler (>= 1.15.0)
221 bundler (>= 1.15.0)
220 railties (= 7.0.4)
222 railties (= 7.0.4)
221 rails-dom-testing (2.0.3)
223 rails-dom-testing (2.0.3)
222 activesupport (>= 4.2.0)
224 activesupport (>= 4.2.0)
223 nokogiri (>= 1.6)
225 nokogiri (>= 1.6)
224 rails-html-sanitizer (1.4.3)
226 rails-html-sanitizer (1.4.3)
225 loofah (~> 2.3)
227 loofah (~> 2.3)
226 railties (7.0.4)
228 railties (7.0.4)
227 actionpack (= 7.0.4)
229 actionpack (= 7.0.4)
228 activesupport (= 7.0.4)
230 activesupport (= 7.0.4)
229 method_source
231 method_source
230 rake (>= 12.2)
232 rake (>= 12.2)
231 thor (~> 1.0)
233 thor (~> 1.0)
232 zeitwerk (~> 2.5)
234 zeitwerk (~> 2.5)
233 rake (13.0.6)
235 rake (13.0.6)
234 rb-fsevent (0.11.2)
236 rb-fsevent (0.11.2)
235 rb-inotify (0.10.1)
237 rb-inotify (0.10.1)
236 ffi (~> 1.0)
238 ffi (~> 1.0)
237 rdiscount (2.2.0.2)
239 rdiscount (2.2.0.2)
238 regexp_parser (2.5.0)
240 regexp_parser (2.5.0)
239 rexml (3.2.5)
241 rexml (3.2.5)
240 rouge (4.0.0)
242 rouge (4.0.0)
241 ruby-progressbar (1.11.0)
243 ruby-progressbar (1.11.0)
242 ruby_parser (3.19.1)
244 ruby_parser (3.19.1)
243 sexp_processor (~> 4.16)
245 sexp_processor (~> 4.16)
244 rubyzip (2.3.2)
246 rubyzip (2.3.2)
245 sassc (2.4.0)
247 sassc (2.4.0)
246 ffi (~> 1.9)
248 ffi (~> 1.9)
247 sassc-rails (2.1.2)
249 sassc-rails (2.1.2)
248 railties (>= 4.0.0)
250 railties (>= 4.0.0)
249 sassc (>= 2.0)
251 sassc (>= 2.0)
250 sprockets (> 3.0)
252 sprockets (> 3.0)
251 sprockets-rails
253 sprockets-rails
252 tilt
254 tilt
253 selenium-webdriver (4.4.0)
255 selenium-webdriver (4.4.0)
254 childprocess (>= 0.5, < 5.0)
256 childprocess (>= 0.5, < 5.0)
255 rexml (~> 3.2, >= 3.2.5)
257 rexml (~> 3.2, >= 3.2.5)
256 rubyzip (>= 1.2.2, < 3.0)
258 rubyzip (>= 1.2.2, < 3.0)
257 websocket (~> 1.0)
259 websocket (~> 1.0)
258 sexp_processor (4.16.1)
260 sexp_processor (4.16.1)
259 spring (2.1.1)
261 spring (2.1.1)
260 spring-watcher-listen (2.0.1)
262 spring-watcher-listen (2.0.1)
261 listen (>= 2.7, < 4.0)
263 listen (>= 2.7, < 4.0)
262 spring (>= 1.2, < 3.0)
264 spring (>= 1.2, < 3.0)
263 sprockets (4.1.1)
265 sprockets (4.1.1)
264 concurrent-ruby (~> 1.0)
266 concurrent-ruby (~> 1.0)
265 rack (> 1, < 3)
267 rack (> 1, < 3)
266 sprockets-rails (3.4.2)
268 sprockets-rails (3.4.2)
267 actionpack (>= 5.2)
269 actionpack (>= 5.2)
268 activesupport (>= 5.2)
270 activesupport (>= 5.2)
269 sprockets (>= 3.0.0)
271 sprockets (>= 3.0.0)
272 + sqlite3 (1.5.0-x86_64-darwin)
270 sqlite3 (1.5.0-x86_64-linux)
273 sqlite3 (1.5.0-x86_64-linux)
271 strscan (3.0.4)
274 strscan (3.0.4)
272 temple (0.8.2)
275 temple (0.8.2)
273 thor (1.2.1)
276 thor (1.2.1)
274 tilt (2.0.11)
277 tilt (2.0.11)
275 timeout (0.3.0)
278 timeout (0.3.0)
276 tzinfo (2.0.5)
279 tzinfo (2.0.5)
277 concurrent-ruby (~> 1.0)
280 concurrent-ruby (~> 1.0)
278 web-console (4.2.0)
281 web-console (4.2.0)
279 actionview (>= 6.0.0)
282 actionview (>= 6.0.0)
280 activemodel (>= 6.0.0)
283 activemodel (>= 6.0.0)
281 bindex (>= 0.4.0)
284 bindex (>= 0.4.0)
282 railties (>= 6.0.0)
285 railties (>= 6.0.0)
283 webdrivers (5.1.0)
286 webdrivers (5.1.0)
284 nokogiri (~> 1.6)
287 nokogiri (~> 1.6)
285 rubyzip (>= 1.3.0)
288 rubyzip (>= 1.3.0)
286 selenium-webdriver (~> 4.0)
289 selenium-webdriver (~> 4.0)
287 websocket (1.2.9)
290 websocket (1.2.9)
288 websocket-driver (0.7.5)
291 websocket-driver (0.7.5)
289 websocket-extensions (>= 0.1.0)
292 websocket-extensions (>= 0.1.0)
290 websocket-extensions (0.1.5)
293 websocket-extensions (0.1.5)
291 xpath (3.2.0)
294 xpath (3.2.0)
292 nokogiri (~> 1.8)
295 nokogiri (~> 1.8)
293 zeitwerk (2.6.0)
296 zeitwerk (2.6.0)
294
297
295 PLATFORMS
298 PLATFORMS
299 + x86_64-darwin-20
296 x86_64-linux
300 x86_64-linux
297
301
298 DEPENDENCIES
302 DEPENDENCIES
299 ace-rails-ap
303 ace-rails-ap
300 best_in_place!
304 best_in_place!
301 bootsnap
305 bootsnap
302 bootstrap (~> 5.2)
306 bootstrap (~> 5.2)
303 byebug
307 byebug
304 capybara
308 capybara
305 coffee-rails
309 coffee-rails
306 fuzzy-string-match
310 fuzzy-string-match
307 haml
311 haml
308 haml-rails
312 haml-rails
309 importmap-rails (~> 1.1)
313 importmap-rails (~> 1.1)
310 jbuilder
314 jbuilder
311 jquery-rails
315 jquery-rails
312 listen (>= 3.0.5, < 3.2)
316 listen (>= 3.0.5, < 3.2)
313 mail
317 mail
314 material_icons
318 material_icons
315 minitest-reporters
319 minitest-reporters
316 momentjs-rails
320 momentjs-rails
317 mysql2
321 mysql2
318 puma
322 puma
319 rails (~> 7.0)
323 rails (~> 7.0)
320 rdiscount
324 rdiscount
321 rouge
325 rouge
322 sassc-rails
326 sassc-rails
323 selenium-webdriver
327 selenium-webdriver
324 simple_form!
328 simple_form!
325 spring
329 spring
326 spring-watcher-listen (~> 2.0.0)
330 spring-watcher-listen (~> 2.0.0)
327 sprockets-rails
331 sprockets-rails
328 sqlite3
332 sqlite3
329 web-console (>= 3.3.0)
333 web-console (>= 3.3.0)
330 webdrivers
334 webdrivers
331
335
332 RUBY VERSION
336 RUBY VERSION
333 ruby 3.1.2p20
337 ruby 3.1.2p20
334
338
335 BUNDLED WITH
339 BUNDLED WITH
336 2.3.22
340 2.3.22
@@ -1,120 +1,107
1 require 'ipaddr'
1 require 'ipaddr'
2 require "securerandom"
2 require "securerandom"
3
3
4 class ApplicationController < ActionController::Base
4 class ApplicationController < ActionController::Base
5 protect_from_forgery
5 protect_from_forgery
6
6
7 before_action :current_user
7 before_action :current_user
8 before_action :nav_announcement
8 before_action :nav_announcement
9 before_action :unique_visitor_id
9 before_action :unique_visitor_id
10 before_action :active_controller_action
10 before_action :active_controller_action
11
11
12 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
12 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
13 MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login'
13 MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login'
14 WHITELIST_IGNORE_CONF_KEY = 'right.whitelist_ignore'
14 WHITELIST_IGNORE_CONF_KEY = 'right.whitelist_ignore'
15 WHITELIST_IP_CONF_KEY = 'right.whitelist_ip'
15 WHITELIST_IP_CONF_KEY = 'right.whitelist_ip'
16
16
17 #report and redirect for unauthorized activities
17 #report and redirect for unauthorized activities
18 - def unauthorized_redirect(notice = 'You are not authorized to view the page you requested')
18 + def unauthorized_redirect(msg = 'You are not authorized to view the page you requested')
19 - flash[:notice] = notice
19 + redirect_to login_main_path, alert: msg
20 - redirect_to login_main_path
21 end
20 end
22
21
23 # Returns the current logged-in user (if any).
22 # Returns the current logged-in user (if any).
24 def current_user
23 def current_user
25 return nil unless session[:user_id]
24 return nil unless session[:user_id]
26 @current_user ||= User.find(session[:user_id])
25 @current_user ||= User.find(session[:user_id])
27 end
26 end
28
27
29 def nav_announcement
28 def nav_announcement
30 @nav_announcement = Announcement.where(on_nav_bar: true)
29 @nav_announcement = Announcement.where(on_nav_bar: true)
31 end
30 end
32
31
33 def active_controller_action
32 def active_controller_action
34 #so that we can override this value inside each action
33 #so that we can override this value inside each action
35 @active_controller = controller_name
34 @active_controller = controller_name
36 @active_action = action_name
35 @active_action = action_name
37 end
36 end
38
37
39 def admin_authorization
38 def admin_authorization
40 return false unless check_valid_login
39 return false unless check_valid_login
41 user = User.includes(:roles).find(session[:user_id])
40 user = User.includes(:roles).find(session[:user_id])
42 unless user.admin?
41 unless user.admin?
43 unauthorized_redirect
42 unauthorized_redirect
44 return false
43 return false
45 end
44 end
46 return true
45 return true
47 end
46 end
48
47
49 - #admin always count as every roles
48 + def authorization_by_roles(allowed_roles)
50 - def role_authorization(roles)
51 return false unless check_valid_login
49 return false unless check_valid_login
52 - user = User.find(session[:user_id])
50 + return true if @current_user.admin?
53 - return true if user.admin?
54 roles.each do |r|
51 roles.each do |r|
55 - return true if user.has_role?(r)
52 + return true if @current_user.has_role?(r)
56 end
53 end
57 unauthorized_redirect
54 unauthorized_redirect
58 end
55 end
59
56
60 - def authorization_by_roles(allowed_roles)
61 - return false unless check_valid_login
62 - unless @current_user.roles.detect { |role| allowed_roles.member?(role.name) }
63 - unauthorized_redirect
64 - return false
65 - end
66 - end
67 -
68 def testcase_authorization
57 def testcase_authorization
69 #admin always has privileged
58 #admin always has privileged
70 - if @current_user.admin?
59 + return true if @current_user.admin?
71 - return true
72 - end
73
60
74 unauthorized_redirect unless GraderConfiguration["right.view_testcase"]
61 unauthorized_redirect unless GraderConfiguration["right.view_testcase"]
75 end
62 end
76
63
77 def unique_visitor_id
64 def unique_visitor_id
78 unless cookies.encrypted[:uuid]
65 unless cookies.encrypted[:uuid]
79 value = SecureRandom.uuid
66 value = SecureRandom.uuid
80 cookies.encrypted[:uuid] = { value: value, expires: 20.year }
67 cookies.encrypted[:uuid] = { value: value, expires: 20.year }
81 end
68 end
82 end
69 end
83
70
84 protected
71 protected
85
72
86 #redirect to root (and also force logout)
73 #redirect to root (and also force logout)
87 #if the user is not logged_in or the system is in "ADMIN ONLY" mode
74 #if the user is not logged_in or the system is in "ADMIN ONLY" mode
88 def check_valid_login
75 def check_valid_login
89 #check if logged in
76 #check if logged in
90 unless session[:user_id]
77 unless session[:user_id]
91 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
78 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
92 unauthorized_redirect('You need to login but you cannot log in at this time')
79 unauthorized_redirect('You need to login but you cannot log in at this time')
93 else
80 else
94 unauthorized_redirect('You need to login')
81 unauthorized_redirect('You need to login')
95 end
82 end
96 return false
83 return false
97 end
84 end
98
85
99 # check if run in single user mode
86 # check if run in single user mode
100 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
87 if GraderConfiguration[SINGLE_USER_MODE_CONF_KEY]
101 if @current_user==nil || (!@current_user.admin?)
88 if @current_user==nil || (!@current_user.admin?)
102 unauthorized_redirect('You cannot log in at this time')
89 unauthorized_redirect('You cannot log in at this time')
103 return false
90 return false
104 end
91 end
105 end
92 end
106
93
107 # check if the user is enabled
94 # check if the user is enabled
108 unless @current_user.enabled? || @current_user.admin?
95 unless @current_user.enabled? || @current_user.admin?
109 unauthorized_redirect 'Your account is disabled'
96 unauthorized_redirect 'Your account is disabled'
110 return false
97 return false
111 end
98 end
112
99
113 # check if user ip is allowed
100 # check if user ip is allowed
114 unless @current_user.admin? || GraderConfiguration[WHITELIST_IGNORE_CONF_KEY]
101 unless @current_user.admin? || GraderConfiguration[WHITELIST_IGNORE_CONF_KEY]
115 unless is_request_ip_allowed?
102 unless is_request_ip_allowed?
116 unauthorized_redirect 'Your IP is not allowed to login at this time.'
103 unauthorized_redirect 'Your IP is not allowed to login at this time.'
117 return false
104 return false
118 end
105 end
119 end
106 end
120
107
@@ -1,99 +1,97
1 class LoginController < ApplicationController
1 class LoginController < ApplicationController
2
2
3 @@authenticators = []
3 @@authenticators = []
4 -
4 +
5 def index
5 def index
6 # show login screen
6 # show login screen
7 reset_session
7 reset_session
8 redirect_to :controller => 'main', :action => 'login'
8 redirect_to :controller => 'main', :action => 'login'
9 end
9 end
10
10
11 def login
11 def login
12 user = get_authenticated_user(params[:login], params[:password])
12 user = get_authenticated_user(params[:login], params[:password])
13 unless user
13 unless user
14 - flash[:notice] = 'Wrong password'
14 + redirect_to login_main_path, alert: 'Wrong password'
15 - redirect_to :controller => 'main', :action => 'login'
16 return
15 return
17 end
16 end
18
17
19 if (!GraderConfiguration['right.bypass_agreement']) and (!params[:accept_agree]) and !user.admin?
18 if (!GraderConfiguration['right.bypass_agreement']) and (!params[:accept_agree]) and !user.admin?
20 - flash[:notice] = 'You must accept the agreement before logging in'
19 + redirect_to login_main_path, alert: 'You must accept the agreement before logging in'
21 - redirect_to :controller => 'main', :action => 'login'
22 return
20 return
23 end
21 end
24
22
25 #store uuid when login
23 #store uuid when login
26 if user.last_ip.nil?
24 if user.last_ip.nil?
27 user.last_ip = cookies.encrypted[:uuid]
25 user.last_ip = cookies.encrypted[:uuid]
28 else
26 else
29 if user.last_ip != cookies.encrypted[:uuid]
27 if user.last_ip != cookies.encrypted[:uuid]
30 user.last_ip =cookies.encrypted[:uuid]
28 user.last_ip =cookies.encrypted[:uuid]
31 #log different login
29 #log different login
32 end
30 end
33 end
31 end
34
32
35 #process logging in
33 #process logging in
36 session[:user_id] = user.id
34 session[:user_id] = user.id
37 session[:admin] = user.admin?
35 session[:admin] = user.admin?
38
36
39 # clear forced logout flag for multicontests contest change
37 # clear forced logout flag for multicontests contest change
40 if GraderConfiguration.multicontests?
38 if GraderConfiguration.multicontests?
41 contest_stat = user.contest_stat
39 contest_stat = user.contest_stat
42 if contest_stat.respond_to? :forced_logout
40 if contest_stat.respond_to? :forced_logout
43 if contest_stat.forced_logout
41 if contest_stat.forced_logout
44 contest_stat.forced_logout = false
42 contest_stat.forced_logout = false
45 contest_stat.save
43 contest_stat.save
46 end
44 end
47 end
45 end
48 end
46 end
49
47
50 #save login information
48 #save login information
51 Login.create(user_id: user.id, ip_address: cookies.encrypted[:uuid])
49 Login.create(user_id: user.id, ip_address: cookies.encrypted[:uuid])
52
50
53 redirect_to :controller => 'main', :action => 'list'
51 redirect_to :controller => 'main', :action => 'list'
54 end
52 end
55
53
56 def site_login
54 def site_login
57 begin
55 begin
58 site = Site.find(params[:login][:site_id])
56 site = Site.find(params[:login][:site_id])
59 rescue ActiveRecord::RecordNotFound
57 rescue ActiveRecord::RecordNotFound
60 site = nil
58 site = nil
61 end
59 end
62 if site==nil
60 if site==nil
63 - flash[:notice] = 'Wrong site'
61 + flash[:alert] = 'Wrong site'
64 redirect_to :controller => 'main', :action => 'login' and return
62 redirect_to :controller => 'main', :action => 'login' and return
65 end
63 end
66 if (site.password) and (site.password == params[:login][:password])
64 if (site.password) and (site.password == params[:login][:password])
67 session[:site_id] = site.id
65 session[:site_id] = site.id
68 redirect_to :controller => 'site', :action => 'index'
66 redirect_to :controller => 'site', :action => 'index'
69 else
67 else
70 - flash[:notice] = 'Wrong site password'
68 + flash[:alert] = 'Wrong site password'
71 redirect_to :controller => 'site', :action => 'login'
69 redirect_to :controller => 'site', :action => 'login'
72 end
70 end
73 end
71 end
74
72
75 def logout
73 def logout
76 redirect_to root_path
74 redirect_to root_path
77 end
75 end
78
76
79 def self.add_authenticator(authenticator)
77 def self.add_authenticator(authenticator)
80 @@authenticators << authenticator
78 @@authenticators << authenticator
81 end
79 end
82
80
83 protected
81 protected
84
82
85 def get_authenticated_user(login, password)
83 def get_authenticated_user(login, password)
86 if @@authenticators.empty?
84 if @@authenticators.empty?
87 return User.authenticate(login, password)
85 return User.authenticate(login, password)
88 else
86 else
89 user = User.authenticate(login, password)
87 user = User.authenticate(login, password)
90 @@authenticators.each do |authenticator|
88 @@authenticators.each do |authenticator|
91 if not user
89 if not user
92 user = authenticator.authenticate(login, password)
90 user = authenticator.authenticate(login, password)
93 end
91 end
94 end
92 end
95 return user
93 return user
96 end
94 end
97 end
95 end
98
96
99 end
97 end
@@ -1,71 +1,70
1 class MainController < ApplicationController
1 class MainController < ApplicationController
2
2
3 before_action :check_valid_login, :except => [:login]
3 before_action :check_valid_login, :except => [:login]
4 before_action :check_viewability, :except => [:index, :login]
4 before_action :check_viewability, :except => [:index, :login]
5
5
6 append_before_action :confirm_and_update_start_time,
6 append_before_action :confirm_and_update_start_time,
7 :except => [:index,
7 :except => [:index,
8 :login,
8 :login,
9 :confirm_contest_start]
9 :confirm_contest_start]
10
10
11 # to prevent log in box to be shown when user logged out of the
11 # to prevent log in box to be shown when user logged out of the
12 # system only in some tab
12 # system only in some tab
13 prepend_before_action :reject_announcement_refresh_when_logged_out,
13 prepend_before_action :reject_announcement_refresh_when_logged_out,
14 :only => [:announcements]
14 :only => [:announcements]
15
15
16 before_action :authenticate_by_ip_address, :only => [:list]
16 before_action :authenticate_by_ip_address, :only => [:list]
17
17
18 #reset login, clear session
18 #reset login, clear session
19 #front page
19 #front page
20 def login
20 def login
21 - saved_notice = flash[:notice]
21 + #saved_notice = flash[:notice]
22 - reset_session
22 + #flash[:notice] = saved_notice
23 - flash.now[:notice] = saved_notice
24 @remote_ip = request.remote_ip
23 @remote_ip = request.remote_ip
25
24
26 # EXPERIMENT:
25 # EXPERIMENT:
27 # Hide login if in single user mode and the url does not
26 # Hide login if in single user mode and the url does not
28 # explicitly specify /login
27 # explicitly specify /login
29 #
28 #
30 # logger.info "PATH: #{request.path}"
29 # logger.info "PATH: #{request.path}"
31 # if GraderConfiguration['system.single_user_mode'] and
30 # if GraderConfiguration['system.single_user_mode'] and
32 # request.path!='/main/login'
31 # request.path!='/main/login'
33 # @hidelogin = true
32 # @hidelogin = true
34 # end
33 # end
35
34
36 @announcements = Announcement.frontpage
35 @announcements = Announcement.frontpage
37 render :action => 'login', locals: {skip_header: true}
36 render :action => 'login', locals: {skip_header: true}
38 end
37 end
39
38
40 def logout
39 def logout
41 reset_session
40 reset_session
42 redirect_to root_path
41 redirect_to root_path
43 end
42 end
44
43
45 def list
44 def list
46 prepare_list_information
45 prepare_list_information
47 end
46 end
48
47
49 def help
48 def help
50 @user = User.find(session[:user_id])
49 @user = User.find(session[:user_id])
51 end
50 end
52
51
53 def submit
52 def submit
54 user = User.find(session[:user_id])
53 user = User.find(session[:user_id])
55
54
56 @submission = Submission.new
55 @submission = Submission.new
57 @submission.problem_id = params[:submission][:problem_id]
56 @submission.problem_id = params[:submission][:problem_id]
58 @submission.user = user
57 @submission.user = user
59 @submission.language_id = 0
58 @submission.language_id = 0
60 if (params['file']) and (params['file']!='')
59 if (params['file']) and (params['file']!='')
61 @submission.source = File.open(params['file'].path,'r:UTF-8',&:read)
60 @submission.source = File.open(params['file'].path,'r:UTF-8',&:read)
62 @submission.source.encode!('UTF-8','UTF-8',invalid: :replace, replace: '')
61 @submission.source.encode!('UTF-8','UTF-8',invalid: :replace, replace: '')
63 @submission.source_filename = params['file'].original_filename
62 @submission.source_filename = params['file'].original_filename
64 end
63 end
65
64
66 if (params[:editor_text])
65 if (params[:editor_text])
67 language = Language.find_by_id(params[:language_id])
66 language = Language.find_by_id(params[:language_id])
68 @submission.source = params[:editor_text]
67 @submission.source = params[:editor_text]
69 @submission.source_filename = "live_edit.#{language.ext}"
68 @submission.source_filename = "live_edit.#{language.ext}"
70 @submission.language = language
69 @submission.language = language
71 end
70 end
@@ -1,53 +1,53
1 class SubmissionsController < ApplicationController
1 class SubmissionsController < ApplicationController
2 before_action :set_submission, only: [:show,:download,:compiler_msg,:rejudge,:set_tag, :edit]
2 before_action :set_submission, only: [:show,:download,:compiler_msg,:rejudge,:set_tag, :edit]
3 before_action :check_valid_login
3 before_action :check_valid_login
4 before_action :submission_authorization, only: [:show, :download, :edit]
4 before_action :submission_authorization, only: [:show, :download, :edit]
5 - before_action only: [:rejudge, :set_tag] do role_authorization([:ta]) end
5 + before_action only: [:rejudge, :set_tag] do authorization_by_roles([:ta]) end
6
6
7 # GET /submissions
7 # GET /submissions
8 # GET /submissions.json
8 # GET /submissions.json
9 # Show problem selection and user's submission of that problem
9 # Show problem selection and user's submission of that problem
10 def index
10 def index
11 @user = @current_user
11 @user = @current_user
12 @problems = @user.available_problems
12 @problems = @user.available_problems
13
13
14 if params[:problem_id]==nil
14 if params[:problem_id]==nil
15 @problem = nil
15 @problem = nil
16 @submissions = nil
16 @submissions = nil
17 else
17 else
18 @problem = Problem.find_by_id(params[:problem_id])
18 @problem = Problem.find_by_id(params[:problem_id])
19 if (@problem == nil) or (not @problem.available)
19 if (@problem == nil) or (not @problem.available)
20 redirect_to list_main_path
20 redirect_to list_main_path
21 flash[:error] = 'Authorization error: You have no right to view submissions for this problem'
21 flash[:error] = 'Authorization error: You have no right to view submissions for this problem'
22 return
22 return
23 end
23 end
24 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id).order(id: :desc)
24 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id).order(id: :desc)
25 end
25 end
26 end
26 end
27
27
28 # GET /submissions/1
28 # GET /submissions/1
29 # GET /submissions/1.json
29 # GET /submissions/1.json
30 def show
30 def show
31 #log the viewing
31 #log the viewing
32 user = User.find(session[:user_id])
32 user = User.find(session[:user_id])
33 SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin?
33 SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin?
34
34
35 @task = @submission.task
35 @task = @submission.task
36 end
36 end
37
37
38 def download
38 def download
39 send_data(@submission.source, {:filename => @submission.download_filename, :type => 'text/plain'})
39 send_data(@submission.source, {:filename => @submission.download_filename, :type => 'text/plain'})
40 end
40 end
41
41
42 def compiler_msg
42 def compiler_msg
43 respond_to do |format|
43 respond_to do |format|
44 format.js
44 format.js
45 end
45 end
46 end
46 end
47
47
48 #on-site new submission on specific problem
48 #on-site new submission on specific problem
49 def direct_edit_problem
49 def direct_edit_problem
50 @problem = Problem.find(params[:problem_id])
50 @problem = Problem.find(params[:problem_id])
51 unless @current_user.can_view_problem?(@problem)
51 unless @current_user.can_view_problem?(@problem)
52 unauthorized_redirect
52 unauthorized_redirect
53 return
53 return
@@ -1,61 +1,61
1 class TagsController < ApplicationController
1 class TagsController < ApplicationController
2 before_action :admin_authorization
2 before_action :admin_authorization
3 before_action :set_tag, only: [:show, :edit, :update, :destroy]
3 before_action :set_tag, only: [:show, :edit, :update, :destroy]
4
4
5 # GET /tags
5 # GET /tags
6 def index
6 def index
7 @tags = Tag.all
7 @tags = Tag.all
8 end
8 end
9
9
10 # GET /tags/1
10 # GET /tags/1
11 def show
11 def show
12 end
12 end
13
13
14 # GET /tags/new
14 # GET /tags/new
15 def new
15 def new
16 @tag = Tag.new
16 @tag = Tag.new
17 end
17 end
18
18
19 # GET /tags/1/edit
19 # GET /tags/1/edit
20 def edit
20 def edit
21 end
21 end
22
22
23 # POST /tags
23 # POST /tags
24 def create
24 def create
25 @tag = Tag.new(tag_params)
25 @tag = Tag.new(tag_params)
26
26
27 if @tag.save
27 if @tag.save
28 - redirect_to @tag, notice: 'Tag was successfully created.'
28 + redirect_to tags_path, notice: 'Tag was successfully created.'
29 else
29 else
30 render :new
30 render :new
31 end
31 end
32 end
32 end
33
33
34 # PATCH/PUT /tags/1
34 # PATCH/PUT /tags/1
35 def update
35 def update
36 if @tag.update(tag_params)
36 if @tag.update(tag_params)
37 redirect_to @tag, notice: 'Tag was successfully updated.'
37 redirect_to @tag, notice: 'Tag was successfully updated.'
38 else
38 else
39 render :edit
39 render :edit
40 end
40 end
41 end
41 end
42
42
43 # DELETE /tags/1
43 # DELETE /tags/1
44 def destroy
44 def destroy
45 #remove any association
45 #remove any association
46 ProblemTag.where(tag_id: @tag.id).destroy_all
46 ProblemTag.where(tag_id: @tag.id).destroy_all
47 @tag.destroy
47 @tag.destroy
48 redirect_to tags_url, notice: 'Tag was successfully destroyed.'
48 redirect_to tags_url, notice: 'Tag was successfully destroyed.'
49 end
49 end
50
50
51 private
51 private
52 # Use callbacks to share common setup or constraints between actions.
52 # Use callbacks to share common setup or constraints between actions.
53 def set_tag
53 def set_tag
54 @tag = Tag.find(params[:id])
54 @tag = Tag.find(params[:id])
55 end
55 end
56
56
57 # Only allow a trusted parameter "white list" through.
57 # Only allow a trusted parameter "white list" through.
58 def tag_params
58 def tag_params
59 params.require(:tag).permit(:name, :description, :public)
59 params.require(:tag).permit(:name, :description, :public)
60 end
60 end
61 end
61 end
@@ -1,23 +1,23
1 %h1 Groups
1 %h1 Groups
2
2
3 %p
3 %p
4 = link_to 'New Group', new_group_path, class: 'btn btn-success'
4 = link_to 'New Group', new_group_path, class: 'btn btn-success'
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 Enabled?
11 %th
11 %th
12 %tbody
12 %tbody
13 - @groups.each do |group|
13 - @groups.each do |group|
14 %tr{:class => "#{(group.enabled?) ? "success" : "danger"}", id: "group-#{group.id}"}
14 %tr{:class => "#{(group.enabled?) ? "success" : "danger"}", id: "group-#{group.id}"}
15 %td= group.name
15 %td= group.name
16 %td= group.description
16 %td= group.description
17 %td= toggle_button(group.enabled?, toggle_group_path(group), "group-enabled-#{group.id}", block: ' ')
17 %td= toggle_button(group.enabled?, toggle_group_path(group), "group-enabled-#{group.id}", block: ' ')
18 %td
18 %td
19 - = link_to 'Edit members and problems', group, class: 'btn btn-secondary btn-sm'
19 + = link_to 'Edit members and problems', group, class: 'btn btn-info btn-sm'
20 = link_to 'Destroy', group, :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn btn-danger btn-sm'
20 = link_to 'Destroy', group, :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn btn-danger btn-sm'
21
21
22 %br
22 %br
23
23
@@ -37,57 +37,57
37 %li.nav-item.dropdown.mx-2
37 %li.nav-item.dropdown.mx-2
38 %a.nav-link.dropdown-toggle.active-with-children{href: '#', 'data-bs': {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
38 %a.nav-link.dropdown-toggle.active-with-children{href: '#', 'data-bs': {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
39 Manage
39 Manage
40 %ul.dropdown-menu
40 %ul.dropdown-menu
41 %li= link_to 'Announcements', announcements_path, class: 'dropdown-item'+active_class_when(controller: :announcements)
41 %li= link_to 'Announcements', announcements_path, class: 'dropdown-item'+active_class_when(controller: :announcements)
42 %li= link_to 'Problems', problems_path, class: 'dropdown-item'+active_class_when(controller: :problems)
42 %li= link_to 'Problems', problems_path, class: 'dropdown-item'+active_class_when(controller: :problems)
43 %li= link_to 'Tags', tags_path, class: 'dropdown-item'+active_class_when(controller: :tags)
43 %li= link_to 'Tags', tags_path, class: 'dropdown-item'+active_class_when(controller: :tags)
44 %li= link_to 'Users', user_admin_index_path, class: 'dropdown-item'+active_class_when(controller: :user_admin)
44 %li= link_to 'Users', user_admin_index_path, class: 'dropdown-item'+active_class_when(controller: :user_admin)
45 %li= link_to 'User Groups', groups_path, class: 'dropdown-item'+active_class_when(controller: :groups)
45 %li= link_to 'User Groups', groups_path, class: 'dropdown-item'+active_class_when(controller: :groups)
46 %li= link_to 'Graders', graders_list_path, class: 'dropdown-item'+active_class_when(controller: :graders)
46 %li= link_to 'Graders', graders_list_path, class: 'dropdown-item'+active_class_when(controller: :graders)
47 %li= link_to 'Message ', console_messages_path, class: 'dropdown-item'+active_class_when(controller: :messages)
47 %li= link_to 'Message ', console_messages_path, class: 'dropdown-item'+active_class_when(controller: :messages)
48 %li
48 %li
49 %hr.dropdown-divider
49 %hr.dropdown-divider
50 %li= link_to 'System config', grader_configuration_index_path, class: 'dropdown-item'+active_class_when(controller: :grader_configuration)
50 %li= link_to 'System config', grader_configuration_index_path, class: 'dropdown-item'+active_class_when(controller: :grader_configuration)
51 %li
51 %li
52 %hr.dropdown-divider
52 %hr.dropdown-divider
53 %li= link_to 'Sites', sites_path, class: 'dropdown-item'+active_class_when(controller: :sites)
53 %li= link_to 'Sites', sites_path, class: 'dropdown-item'+active_class_when(controller: :sites)
54 %li= link_to 'Contests', contest_management_index_path, class: 'dropdown-item'+active_class_when(controller: :contest_management)
54 %li= link_to 'Contests', contest_management_index_path, class: 'dropdown-item'+active_class_when(controller: :contest_management)
55 -#
55 -#
56 / report
56 / report
57 %li.nav-item.dropdown.mx-2
57 %li.nav-item.dropdown.mx-2
58 %a.nav-link.dropdown-toggle.active-with-children{href: '#', 'data-bs': {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
58 %a.nav-link.dropdown-toggle.active-with-children{href: '#', 'data-bs': {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
59 Report
59 Report
60 %ul.dropdown-menu
60 %ul.dropdown-menu
61 %li= link_to 'Current Score', current_score_report_path, class: 'dropdown-item'+active_class_when(controller: :report, action: :current_score)
61 %li= link_to 'Current Score', current_score_report_path, class: 'dropdown-item'+active_class_when(controller: :report, action: :current_score)
62 %li= link_to 'Score Report', max_score_report_path, class: 'dropdown-item'+active_class_when(controller: :report, action: :max_score)
62 %li= link_to 'Score Report', max_score_report_path, class: 'dropdown-item'+active_class_when(controller: :report, action: :max_score)
63 %li= link_to 'Submission Report', submission_report_path, class: 'dropdown-item'+active_class_when(controller: :report, action: :submission)
63 %li= link_to 'Submission Report', submission_report_path, class: 'dropdown-item'+active_class_when(controller: :report, action: :submission)
64 %li= link_to 'Login Report', login_report_path, class: 'dropdown-item'+active_class_when(controller: :report, action: :login)
64 %li= link_to 'Login Report', login_report_path, class: 'dropdown-item'+active_class_when(controller: :report, action: :login)
65 - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
65 - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
66 =link_to "#{ungraded} backlogs!",
66 =link_to "#{ungraded} backlogs!",
67 graders_list_path,
67 graders_list_path,
68 class: 'navbar-btn btn btn-default btn-warning', data: {toggle: 'tooltip'},title: 'Number of ungraded submission'
68 class: 'navbar-btn btn btn-default btn-warning', data: {toggle: 'tooltip'},title: 'Number of ungraded submission'
69 / announcement
69 / announcement
70 - @nav_announcement.each do |ann|
70 - @nav_announcement.each do |ann|
71 %p.navbar-text
71 %p.navbar-text
72 = ann.body.html_safe
72 = ann.body.html_safe
73 %ul.navbar-nav
73 %ul.navbar-nav
74 %li.nav-item
74 %li.nav-item
75 %a.nav-link{href: help_main_path}
75 %a.nav-link{href: help_main_path}
76 %span.mi.mi-bs.md-18 help
76 %span.mi.mi-bs.md-18 help
77 %li.nav-item
77 %li.nav-item
78 %a.nav-link{href: messages_path}
78 %a.nav-link{href: messages_path}
79 %span.mi.mi-bs.md-18 chat
79 %span.mi.mi-bs.md-18 chat
80 - if GraderConfiguration['system.user_setting_enabled']
80 - if GraderConfiguration['system.user_setting_enabled']
81 %li.nav-item
81 %li.nav-item
82 %a.nav-link{href: profile_users_path}
82 %a.nav-link{href: profile_users_path}
83 %span.mi.mi-bs.md-18 settings
83 %span.mi.mi-bs.md-18 settings
84 %li.nav-item
84 %li.nav-item
85 - %a.nav-link{href: login_main_path}
85 + %a.nav-link{href: logout_main_path}
86 %span.mi.mi-bs.md-18 exit_to_app
86 %span.mi.mi-bs.md-18 exit_to_app
87 = @current_user.full_name
87 = @current_user.full_name
88 :javascript
88 :javascript
89 $('.active-with-children').each( (index,obj) => {
89 $('.active-with-children').each( (index,obj) => {
90 if ($(obj).siblings('.dropdown-menu').has('.active').length > 0) {
90 if ($(obj).siblings('.dropdown-menu').has('.active').length > 0) {
91 $(obj).addClass('active')
91 $(obj).addClass('active')
92 }
92 }
93 } )
93 } )
@@ -1,60 +1,59
1
1
2 .card
2 .card
3 .card-body
3 .card-body
4 .card-title
4 .card-title
5 %h3= GraderConfiguration['ui.front.welcome_message']
5 %h3= GraderConfiguration['ui.front.welcome_message']
6 - if !@hidelogin
6 - if !@hidelogin
7 .card-subtitle=t 'login.message'
7 .card-subtitle=t 'login.message'
8
8
9 - if flash[:notice]
9 - if flash[:notice]
10 - %hr/
10 + .alert.alert-danger
11 - %b= flash[:notice]
11 + = flash[:notice]
12 - %hr/
13
12
14 .card
13 .card
15 .card-body{ style: "background: #eeeeff;"}
14 .card-body{ style: "background: #eeeeff;"}
16 = form_with url: login_login_path do |f|
15 = form_with url: login_login_path do |f|
17 .mb-3
16 .mb-3
18 = f.label :login, "Login", class: 'form-label'
17 = f.label :login, "Login", class: 'form-label'
19 = f.text_field :login, class: 'form-control'
18 = f.text_field :login, class: 'form-control'
20 .mb-3
19 .mb-3
21 = f.label :password, "Password", class: 'form-label'
20 = f.label :password, "Password", class: 'form-label'
22 = f.password_field :password, class: 'form-control'
21 = f.password_field :password, class: 'form-control'
23 - unless GraderConfiguration['right.bypass_agreement']
22 - unless GraderConfiguration['right.bypass_agreement']
24 .col-sm-offset-3.col-sm-9
23 .col-sm-offset-3.col-sm-9
25 .checkbox
24 .checkbox
26 %label
25 %label
27 = check_box_tag 'accept_agree'
26 = check_box_tag 'accept_agree'
28 ΰΈ’ΰΈ­ΰΈ‘ΰΈ£ΰΈ±ΰΈšΰΈ‚ΰΉ‰ΰΈ­ΰΈ•ΰΈΰΈ₯ΰΈ‡ΰΈΰΈ²ΰΈ£ΰΉƒΰΈŠΰΉ‰ΰΈ‡ΰΈ²ΰΈ™
27 ΰΈ’ΰΈ­ΰΈ‘ΰΈ£ΰΈ±ΰΈšΰΈ‚ΰΉ‰ΰΈ­ΰΈ•ΰΈΰΈ₯ΰΈ‡ΰΈΰΈ²ΰΈ£ΰΉƒΰΈŠΰΉ‰ΰΈ‡ΰΈ²ΰΈ™
29 .mb-3
28 .mb-3
30 .col-sm-offset-3.col-sm-9
29 .col-sm-offset-3.col-sm-9
31 = submit_tag t('login.login_submit'), class: 'btn btn-primary'
30 = submit_tag t('login.login_submit'), class: 'btn btn-primary'
32 - else
31 - else
33 Login is not possible right now
32 Login is not possible right now
34
33
35 %br/
34 %br/
36
35
37 - if GraderConfiguration['system.online_registration']
36 - if GraderConfiguration['system.online_registration']
38 =t 'login.participation'
37 =t 'login.participation'
39 %b
38 %b
40 = "#{t 'login.please'} "
39 = "#{t 'login.please'} "
41 = link_to "#{t 'login.register'}", :controller => :users, :action => :new
40 = link_to "#{t 'login.register'}", :controller => :users, :action => :new
42 %br/
41 %br/
43 = link_to "#{t 'login.forget_password'}", :controller => :users, :action => :forget
42 = link_to "#{t 'login.forget_password'}", :controller => :users, :action => :forget
44 -#
43 -#
45 %br/
44 %br/
46
45
47 - if !@hidelogin
46 - if !@hidelogin
48 =t 'login.message'
47 =t 'login.message'
49 %br/
48 %br/
50 %br/
49 %br/
51
50
52 - if flash[:notice]
51 - if flash[:notice]
53 %hr/
52 %hr/
54 %b= flash[:notice]
53 %b= flash[:notice]
55 %hr/
54 %hr/
56
55
57 %div{ :style => "border: solid 1px gray; padding: 4px; background: #eeeeff;"}
56 %div{ :style => "border: solid 1px gray; padding: 4px; background: #eeeeff;"}
58 = form_tag login_login_path, {class: 'form-horizontal'} do
57 = form_tag login_login_path, {class: 'form-horizontal'} do
59 .form-group
58 .form-group
60 =label_tag :login, "Login",class: 'col-sm-3 control-label'
59 =label_tag :login, "Login",class: 'col-sm-3 control-label'
@@ -1,22 +1,7
1 - = form_for @tag do |f|
1 + = simple_form_for @tag do |f|
2 - - if @tag.errors.any?
3 - #error_explanation
4 - %h2= "#{pluralize(@tag.errors.count, "error")} prohibited this tag from being saved:"
5 - %ul
6 - - @tag.errors.full_messages.each do |msg|
7 - %li= msg
8 -
9 .row
2 .row
10 .col-md-6
3 .col-md-6
11 - .form-group.field
4 + = f.input :name
12 - = f.label :name
5 + = f.input :description
13 - = f.text_field :name, class: 'form-control'
6 + = f.input :public
14 - .form-group.field
7 + = f.submit 'Save', class: 'btn btn-primary'
15 - = f.label :description
16 - = f.text_area :description, class: 'form-control'
17 - .form-group.field
18 - = f.label :public
19 - = f.text_field :public, class: 'form-control'
20 - .actions
21 - = f.submit 'Save', class: 'btn btn-primary'
22 - .col-md-6
@@ -1,26 +1,26
1 %h1 Tags
1 %h1 Tags
2
2
3 = link_to 'New Tag', new_tag_path, class: 'btn btn-success'
3 = link_to 'New Tag', new_tag_path, class: 'btn btn-success'
4
4
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 Public
10 %th Public
11 %th
11 %th
12 %th
12 %th
13 %th
13 %th
14
14
15 %tbody
15 %tbody
16 - @tags.each do |tag|
16 - @tags.each do |tag|
17 %tr
17 %tr
18 %td= tag.name
18 %td= tag.name
19 %td= tag.description
19 %td= tag.description
20 %td= tag.public
20 %td= tag.public
21 - %td= link_to 'Show', tag
21 + %td= link_to 'Show', tag, class: 'btn btn-info'
22 - %td= link_to 'Edit', edit_tag_path(tag)
22 + %td= link_to 'Edit', edit_tag_path(tag), class: 'btn btn-info'
23 - %td= link_to 'Destroy', tag, :method => :delete, :data => { :confirm => 'Are you sure?' }
23 + %td= button_to 'Destroy', tag, :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn btn-danger'
24
24
25 %br
25 %br
26
26
@@ -31,61 +31,61
31 = f.submit 'Submit', class: 'btn btn-secondary'
31 = f.submit 'Submit', class: 'btn btn-secondary'
32
32
33
33
34 %p
34 %p
35 = link_to '+ New user', { :action => 'new' }, { class: 'btn btn-success '}
35 = link_to '+ New user', { :action => 'new' }, { class: 'btn btn-success '}
36 = link_to '+ New list of users', { :action => 'new_list' }, { class: 'btn btn-success '}
36 = link_to '+ New list of users', { :action => 'new_list' }, { class: 'btn btn-success '}
37 = link_to 'Bulk Manage', { action: :bulk_manage} , { class: 'btn btn-secondary btn-info'}
37 = link_to 'Bulk Manage', { action: :bulk_manage} , { class: 'btn btn-secondary btn-info'}
38 = link_to 'View administrators',{ :action => 'admin'}, { class: 'btn btn-secondary '}
38 = link_to 'View administrators',{ :action => 'admin'}, { class: 'btn btn-secondary '}
39 = link_to 'Random passwords',{ :action => 'random_all_passwords'}, { class: 'btn btn-secondary '}
39 = link_to 'Random passwords',{ :action => 'random_all_passwords'}, { class: 'btn btn-secondary '}
40 = link_to 'View active users',{ :action => 'active'}, { class: 'btn btn-secondary '}
40 = link_to 'View active users',{ :action => 'active'}, { class: 'btn btn-secondary '}
41 = link_to 'Mass mailing',{ :action => 'mass_mailing'}, { class: 'btn btn-secondary '}
41 = link_to 'Mass mailing',{ :action => 'mass_mailing'}, { class: 'btn btn-secondary '}
42
42
43 - if GraderConfiguration.multicontests?
43 - if GraderConfiguration.multicontests?
44 %br/
44 %br/
45 %b Multi-contest:
45 %b Multi-contest:
46 = link_to '[Manage bulk users in contests]', :action => 'contest_management'
46 = link_to '[Manage bulk users in contests]', :action => 'contest_management'
47 View users in:
47 View users in:
48 - @contests.each do |contest|
48 - @contests.each do |contest|
49 = link_to "[#{contest.name}]", :action => 'contests', :id => contest.id
49 = link_to "[#{contest.name}]", :action => 'contests', :id => contest.id
50 = link_to "[no contest]", :action => 'contests', :id => 'none'
50 = link_to "[no contest]", :action => 'contests', :id => 'none'
51
51
52 %table.table.table-hover.table-condense.datatable
52 %table.table.table-hover.table-condense.datatable
53 %thead
53 %thead
54 %th Login
54 %th Login
55 %th Full name
55 %th Full name
56 %th email
56 %th email
57 %th Remark
57 %th Remark
58 %th
58 %th
59 Activated
59 Activated
60 %sup{class: 'text-primary',data: {toggle: 'tooltip', placement: 'top'}, title: 'User has already confirmed the email?' } [?]
60 %sup{class: 'text-primary',data: {toggle: 'tooltip', placement: 'top'}, title: 'User has already confirmed the email?' } [?]
61 %th
61 %th
62 Enabled
62 Enabled
63 %sup{class: 'text-primary',data: {toggle: 'tooltip', placement: 'top'}, title: 'Allow the user to login?' } [?]
63 %sup{class: 'text-primary',data: {toggle: 'tooltip', placement: 'top'}, title: 'Allow the user to login?' } [?]
64 %th Last IP
64 %th Last IP
65 %th
65 %th
66 %th
66 %th
67 %th
67 %th
68 %th
68 %th
69 - for user in @users
69 - for user in @users
70 %tr
70 %tr
71 %td= link_to user.login, stat_user_path(user)
71 %td= link_to user.login, stat_user_path(user)
72 %td= user.full_name
72 %td= user.full_name
73 %td= user.email
73 %td= user.email
74 %td= user.remark
74 %td= user.remark
75 %td= toggle_button(user.activated?, toggle_activate_user_path(user),"toggle_activate_user_#{user.id}")
75 %td= toggle_button(user.activated?, toggle_activate_user_path(user),"toggle_activate_user_#{user.id}")
76 %td= toggle_button(user.enabled?, toggle_enable_user_path(user),"toggle_enable_user_#{user.id}")
76 %td= toggle_button(user.enabled?, toggle_enable_user_path(user),"toggle_enable_user_#{user.id}")
77 %td= user.last_ip
77 %td= user.last_ip
78 %td= link_to 'Clear IP', {:action => 'clear_last_ip', :id => user, :page=>params[:page]}, :confirm => 'This will reset last logging in ip of the user, are you sure?', class: 'btn btn-secondary btn-sm btn-block'
78 %td= link_to 'Clear IP', {:action => 'clear_last_ip', :id => user, :page=>params[:page]}, :confirm => 'This will reset last logging in ip of the user, are you sure?', class: 'btn btn-secondary btn-sm btn-block'
79 - %td= link_to 'Show', {:action => 'show', :id => user}, class: 'btn btn-secondary btn-sm btn-block'
79 + %td= link_to 'Show', {:action => 'show', :id => user}, class: 'btn btn-info btn-sm btn-block'
80 - %td= link_to 'Edit', {:action => 'edit', :id => user}, class: 'btn btn-secondary btn-sm btn-block'
80 + %td= link_to 'Edit', {:action => 'edit', :id => user}, class: 'btn btn-info btn-sm btn-block'
81 %td= link_to 'Destroy', {action: :destroy, id: user}, data: {confirm: 'Are you sure?'}, method: :delete, class: 'btn btn-danger btn-sm btn-block'
81 %td= link_to 'Destroy', {action: :destroy, id: user}, data: {confirm: 'Are you sure?'}, method: :delete, class: 'btn btn-danger btn-sm btn-block'
82 %br/
82 %br/
83 = link_to '+ New user', { :action => 'new' }, { class: 'btn btn-success '}
83 = link_to '+ New user', { :action => 'new' }, { class: 'btn btn-success '}
84 = link_to '+ New list of users', { :action => 'new_list' }, { class: 'btn btn-success '}
84 = link_to '+ New list of users', { :action => 'new_list' }, { class: 'btn btn-success '}
85
85
86 :javascript
86 :javascript
87 $(document).on('import-map-loaded',(e) => {
87 $(document).on('import-map-loaded',(e) => {
88 $('.datatable').DataTable({
88 $('.datatable').DataTable({
89 'pageLength': 50
89 'pageLength': 50
90 });
90 });
91 })
91 })
@@ -1,346 +1,357
1 # This file is auto-generated from the current state of the database. Instead
1 # This file is auto-generated from the current state of the database. Instead
2 # of editing this file, please use the migrations feature of Active Record to
2 # of editing this file, please use the migrations feature of Active Record to
3 # incrementally modify your database, and then regenerate this schema definition.
3 # incrementally modify your database, and then regenerate this schema definition.
4 #
4 #
5 # This file is the source Rails uses to define your schema when running `bin/rails
5 # This file is the source Rails uses to define your schema when running `bin/rails
6 # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
6 # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
7 # be faster and is potentially less error prone than running all of your
7 # be faster and is potentially less error prone than running all of your
8 # migrations from scratch. Old migrations may fail to apply correctly if those
8 # migrations from scratch. Old migrations may fail to apply correctly if those
9 # migrations use external dependencies or application code.
9 # migrations use external dependencies or application code.
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[7.0].define(version: 2022_09_27_074644) do
13 ActiveRecord::Schema[7.0].define(version: 2022_09_27_074644) do
14 - create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
14 + create_table "active_storage_attachments", charset: "latin1", force: :cascade do |t|
15 t.string "name", null: false
15 t.string "name", null: false
16 t.string "record_type", null: false
16 t.string "record_type", null: false
17 t.bigint "record_id", null: false
17 t.bigint "record_id", null: false
18 t.bigint "blob_id", null: false
18 t.bigint "blob_id", null: false
19 t.datetime "created_at", null: false
19 t.datetime "created_at", null: false
20 t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
20 t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
21 t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
21 t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
22 end
22 end
23
23
24 - create_table "active_storage_blobs", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
24 + create_table "active_storage_blobs", charset: "latin1", force: :cascade do |t|
25 t.string "key", null: false
25 t.string "key", null: false
26 t.string "filename", null: false
26 t.string "filename", null: false
27 t.string "content_type"
27 t.string "content_type"
28 t.text "metadata"
28 t.text "metadata"
29 t.string "service_name", null: false
29 t.string "service_name", null: false
30 t.bigint "byte_size", null: false
30 t.bigint "byte_size", null: false
31 t.string "checksum"
31 t.string "checksum"
32 t.datetime "created_at", null: false
32 t.datetime "created_at", null: false
33 t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
33 t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
34 end
34 end
35
35
36 - create_table "active_storage_variant_records", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
36 + create_table "active_storage_variant_records", charset: "latin1", force: :cascade do |t|
37 t.bigint "blob_id", null: false
37 t.bigint "blob_id", null: false
38 t.string "variation_digest", null: false
38 t.string "variation_digest", null: false
39 t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
39 t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
40 end
40 end
41
41
42 - create_table "announcements", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
42 + create_table "announcements", id: :integer, charset: "utf8", force: :cascade do |t|
43 t.string "author"
43 t.string "author"
44 - t.text "body"
44 + t.text "body", size: :medium
45 t.boolean "published"
45 t.boolean "published"
46 t.datetime "created_at", precision: nil, null: false
46 t.datetime "created_at", precision: nil, null: false
47 t.datetime "updated_at", precision: nil, null: false
47 t.datetime "updated_at", precision: nil, null: false
48 t.boolean "frontpage", default: false
48 t.boolean "frontpage", default: false
49 t.boolean "contest_only", default: false
49 t.boolean "contest_only", default: false
50 t.string "title"
50 t.string "title"
51 t.string "notes"
51 t.string "notes"
52 t.boolean "on_nav_bar", default: false
52 t.boolean "on_nav_bar", default: false
53 end
53 end
54
54
55 - create_table "contests", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
55 + create_table "contests", id: :integer, charset: "utf8", force: :cascade do |t|
56 t.string "title"
56 t.string "title"
57 t.boolean "enabled"
57 t.boolean "enabled"
58 t.datetime "created_at", precision: nil, null: false
58 t.datetime "created_at", precision: nil, null: false
59 t.datetime "updated_at", precision: nil, null: false
59 t.datetime "updated_at", precision: nil, null: false
60 t.string "name"
60 t.string "name"
61 end
61 end
62
62
63 - create_table "contests_problems", id: false, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
63 + create_table "contests_problems", id: false, charset: "utf8", force: :cascade do |t|
64 t.integer "contest_id"
64 t.integer "contest_id"
65 t.integer "problem_id"
65 t.integer "problem_id"
66 end
66 end
67
67
68 - create_table "contests_users", id: false, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
68 + create_table "contests_users", id: false, charset: "utf8", force: :cascade do |t|
69 t.integer "contest_id"
69 t.integer "contest_id"
70 t.integer "user_id"
70 t.integer "user_id"
71 end
71 end
72
72
73 - create_table "countries", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
73 + create_table "countries", id: :integer, charset: "utf8", force: :cascade do |t|
74 t.string "name"
74 t.string "name"
75 t.datetime "created_at", precision: nil, null: false
75 t.datetime "created_at", precision: nil, null: false
76 t.datetime "updated_at", precision: nil, null: false
76 t.datetime "updated_at", precision: nil, null: false
77 end
77 end
78
78
79 - create_table "descriptions", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
79 + create_table "descriptions", id: :integer, charset: "utf8", force: :cascade do |t|
80 - t.text "body"
80 + t.text "body", size: :medium
81 t.boolean "markdowned"
81 t.boolean "markdowned"
82 t.datetime "created_at", precision: nil, null: false
82 t.datetime "created_at", precision: nil, null: false
83 t.datetime "updated_at", precision: nil, null: false
83 t.datetime "updated_at", precision: nil, null: false
84 end
84 end
85
85
86 - create_table "grader_configurations", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
86 + create_table "grader_configurations", id: :integer, charset: "utf8", force: :cascade do |t|
87 t.string "key"
87 t.string "key"
88 t.string "value_type"
88 t.string "value_type"
89 t.string "value"
89 t.string "value"
90 t.datetime "created_at", precision: nil, null: false
90 t.datetime "created_at", precision: nil, null: false
91 t.datetime "updated_at", precision: nil, null: false
91 t.datetime "updated_at", precision: nil, null: false
92 - t.text "description"
92 + t.text "description", size: :medium
93 end
93 end
94
94
95 - create_table "grader_processes", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
95 + create_table "grader_processes", id: :integer, charset: "utf8", force: :cascade do |t|
96 t.string "host"
96 t.string "host"
97 t.integer "pid"
97 t.integer "pid"
98 t.string "mode"
98 t.string "mode"
99 t.boolean "active"
99 t.boolean "active"
100 t.datetime "created_at", precision: nil, null: false
100 t.datetime "created_at", precision: nil, null: false
101 t.datetime "updated_at", precision: nil, null: false
101 t.datetime "updated_at", precision: nil, null: false
102 t.integer "task_id"
102 t.integer "task_id"
103 t.string "task_type"
103 t.string "task_type"
104 t.boolean "terminated"
104 t.boolean "terminated"
105 t.index ["host", "pid"], name: "index_grader_processes_on_ip_and_pid"
105 t.index ["host", "pid"], name: "index_grader_processes_on_ip_and_pid"
106 end
106 end
107
107
108 create_table "groups", id: :integer, charset: "latin1", force: :cascade do |t|
108 create_table "groups", id: :integer, charset: "latin1", force: :cascade do |t|
109 t.string "name"
109 t.string "name"
110 t.string "description"
110 t.string "description"
111 t.boolean "enabled", default: true
111 t.boolean "enabled", default: true
112 end
112 end
113
113
114 create_table "groups_problems", id: false, charset: "latin1", force: :cascade do |t|
114 create_table "groups_problems", id: false, charset: "latin1", force: :cascade do |t|
115 t.integer "problem_id", null: false
115 t.integer "problem_id", null: false
116 t.integer "group_id", null: false
116 t.integer "group_id", null: false
117 t.index ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id"
117 t.index ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id"
118 end
118 end
119
119
120 create_table "groups_users", charset: "latin1", force: :cascade do |t|
120 create_table "groups_users", charset: "latin1", force: :cascade do |t|
121 t.integer "group_id", null: false
121 t.integer "group_id", null: false
122 t.integer "user_id", null: false
122 t.integer "user_id", null: false
123 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
123 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
124 end
124 end
125
125
126 - create_table "heart_beats", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
126 + create_table "heart_beats", id: :integer, charset: "latin1", force: :cascade do |t|
127 t.integer "user_id"
127 t.integer "user_id"
128 t.string "ip_address"
128 t.string "ip_address"
129 t.datetime "created_at", precision: nil, null: false
129 t.datetime "created_at", precision: nil, null: false
130 t.datetime "updated_at", precision: nil, null: false
130 t.datetime "updated_at", precision: nil, null: false
131 t.string "status"
131 t.string "status"
132 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
132 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
133 end
133 end
134
134
135 - create_table "languages", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
135 + create_table "languages", id: :integer, charset: "utf8", force: :cascade do |t|
136 t.string "name", limit: 10
136 t.string "name", limit: 10
137 t.string "pretty_name"
137 t.string "pretty_name"
138 t.string "ext", limit: 10
138 t.string "ext", limit: 10
139 t.string "common_ext"
139 t.string "common_ext"
140 end
140 end
141
141
142 - create_table "logins", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
142 + create_table "logins", id: :integer, charset: "latin1", force: :cascade do |t|
143 t.integer "user_id"
143 t.integer "user_id"
144 t.string "ip_address"
144 t.string "ip_address"
145 t.datetime "created_at", precision: nil, null: false
145 t.datetime "created_at", precision: nil, null: false
146 t.datetime "updated_at", precision: nil, null: false
146 t.datetime "updated_at", precision: nil, null: false
147 t.index ["user_id"], name: "index_logins_on_user_id"
147 t.index ["user_id"], name: "index_logins_on_user_id"
148 end
148 end
149
149
150 - create_table "messages", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
150 + create_table "messages", id: :integer, charset: "utf8", force: :cascade do |t|
151 t.integer "sender_id"
151 t.integer "sender_id"
152 t.integer "receiver_id"
152 t.integer "receiver_id"
153 t.integer "replying_message_id"
153 t.integer "replying_message_id"
154 - t.text "body"
154 + t.text "body", size: :medium
155 t.boolean "replied"
155 t.boolean "replied"
156 t.datetime "created_at", precision: nil, null: false
156 t.datetime "created_at", precision: nil, null: false
157 t.datetime "updated_at", precision: nil, null: false
157 t.datetime "updated_at", precision: nil, null: false
158 end
158 end
159
159
160 - create_table "problems", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
160 + create_table "problems", id: :bigint, default: nil, charset: "utf8", force: :cascade do |t|
161 - t.string "name", limit: 30
161 + t.string "name", limit: 100
162 t.string "full_name"
162 t.string "full_name"
163 t.integer "full_score"
163 t.integer "full_score"
164 t.date "date_added"
164 t.date "date_added"
165 t.boolean "available"
165 t.boolean "available"
166 t.string "url"
166 t.string "url"
167 t.integer "description_id"
167 t.integer "description_id"
168 t.boolean "test_allowed"
168 t.boolean "test_allowed"
169 t.boolean "output_only"
169 t.boolean "output_only"
170 t.string "description_filename"
170 t.string "description_filename"
171 t.boolean "view_testcase"
171 t.boolean "view_testcase"
172 t.integer "difficulty"
172 t.integer "difficulty"
173 t.text "description"
173 t.text "description"
174 t.boolean "markdown"
174 t.boolean "markdown"
175 end
175 end
176
176
177 - create_table "problems_tags", id: :integer, charset: "latin1", force: :cascade do |t|
177 + create_table "problems_tags", id: :bigint, default: nil, charset: "latin1", force: :cascade do |t|
178 - t.integer "problem_id"
178 + t.bigint "problem_id"
179 t.integer "tag_id"
179 t.integer "tag_id"
180 t.index ["problem_id", "tag_id"], name: "index_problems_tags_on_problem_id_and_tag_id", unique: true
180 t.index ["problem_id", "tag_id"], name: "index_problems_tags_on_problem_id_and_tag_id", unique: true
181 t.index ["problem_id"], name: "index_problems_tags_on_problem_id"
181 t.index ["problem_id"], name: "index_problems_tags_on_problem_id"
182 t.index ["tag_id"], name: "index_problems_tags_on_tag_id"
182 t.index ["tag_id"], name: "index_problems_tags_on_tag_id"
183 end
183 end
184
184
185 - create_table "rights", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
185 + create_table "rights", id: :integer, charset: "utf8", force: :cascade do |t|
186 t.string "name"
186 t.string "name"
187 t.string "controller"
187 t.string "controller"
188 t.string "action"
188 t.string "action"
189 end
189 end
190
190
191 - create_table "rights_roles", id: false, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
191 + create_table "rights_roles", id: false, charset: "utf8", force: :cascade do |t|
192 t.integer "right_id"
192 t.integer "right_id"
193 t.integer "role_id"
193 t.integer "role_id"
194 t.index ["role_id"], name: "index_rights_roles_on_role_id"
194 t.index ["role_id"], name: "index_rights_roles_on_role_id"
195 end
195 end
196
196
197 - create_table "roles", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
197 + create_table "roles", id: :integer, charset: "utf8", force: :cascade do |t|
198 t.string "name"
198 t.string "name"
199 end
199 end
200
200
201 - create_table "roles_users", id: false, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
201 + create_table "roles_users", id: false, charset: "utf8", force: :cascade do |t|
202 t.integer "role_id"
202 t.integer "role_id"
203 t.integer "user_id"
203 t.integer "user_id"
204 t.index ["user_id"], name: "index_roles_users_on_user_id"
204 t.index ["user_id"], name: "index_roles_users_on_user_id"
205 end
205 end
206
206
207 - create_table "sessions", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
207 + create_table "sessions", id: :integer, charset: "utf8", force: :cascade do |t|
208 t.string "session_id"
208 t.string "session_id"
209 - t.text "data"
209 + t.text "data", size: :medium
210 t.datetime "updated_at", precision: nil
210 t.datetime "updated_at", precision: nil
211 t.index ["session_id"], name: "index_sessions_on_session_id"
211 t.index ["session_id"], name: "index_sessions_on_session_id"
212 t.index ["updated_at"], name: "index_sessions_on_updated_at"
212 t.index ["updated_at"], name: "index_sessions_on_updated_at"
213 end
213 end
214
214
215 - create_table "sites", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
215 + create_table "sites", id: :integer, charset: "utf8", force: :cascade do |t|
216 t.string "name"
216 t.string "name"
217 t.boolean "started"
217 t.boolean "started"
218 t.datetime "start_time", precision: nil
218 t.datetime "start_time", precision: nil
219 t.datetime "created_at", precision: nil, null: false
219 t.datetime "created_at", precision: nil, null: false
220 t.datetime "updated_at", precision: nil, null: false
220 t.datetime "updated_at", precision: nil, null: false
221 t.integer "country_id"
221 t.integer "country_id"
222 t.string "password"
222 t.string "password"
223 end
223 end
224
224
225 - create_table "submission_view_logs", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
225 + create_table "solutions", charset: "latin1", force: :cascade do |t|
226 + t.string "solution"
227 + t.bigint "problem_id"
228 + t.bigint "submission_id"
229 + t.integer "type"
230 + t.index ["problem_id"], name: "index_solutions_on_problem_id"
231 + t.index ["submission_id"], name: "index_solutions_on_submission_id"
232 + end
233 +
234 + create_table "submission_view_logs", id: :integer, charset: "latin1", force: :cascade do |t|
226 t.integer "user_id"
235 t.integer "user_id"
227 t.integer "submission_id"
236 t.integer "submission_id"
228 t.datetime "created_at", precision: nil, null: false
237 t.datetime "created_at", precision: nil, null: false
229 t.datetime "updated_at", precision: nil, null: false
238 t.datetime "updated_at", precision: nil, null: false
230 end
239 end
231
240
232 - create_table "submissions", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
241 + create_table "submissions", id: :bigint, default: nil, charset: "utf8", force: :cascade do |t|
233 t.integer "user_id"
242 t.integer "user_id"
234 t.integer "problem_id"
243 t.integer "problem_id"
235 t.integer "language_id"
244 t.integer "language_id"
236 t.text "source", size: :medium
245 t.text "source", size: :medium
237 t.binary "binary"
246 t.binary "binary"
238 t.datetime "submitted_at", precision: nil
247 t.datetime "submitted_at", precision: nil
239 t.datetime "compiled_at", precision: nil
248 t.datetime "compiled_at", precision: nil
240 - t.text "compiler_message"
249 + t.text "compiler_message", size: :medium
241 t.datetime "graded_at", precision: nil
250 t.datetime "graded_at", precision: nil
242 t.integer "points"
251 t.integer "points"
243 - t.text "grader_comment"
252 + t.text "grader_comment", size: :medium
244 t.integer "number"
253 t.integer "number"
245 t.string "source_filename"
254 t.string "source_filename"
246 t.float "max_runtime"
255 t.float "max_runtime"
247 t.integer "peak_memory"
256 t.integer "peak_memory"
248 t.integer "effective_code_length"
257 t.integer "effective_code_length"
249 t.string "ip_address"
258 t.string "ip_address"
250 t.integer "tag", default: 0
259 t.integer "tag", default: 0
251 t.index ["submitted_at"], name: "index_submissions_on_submitted_at"
260 t.index ["submitted_at"], name: "index_submissions_on_submitted_at"
252 t.index ["user_id", "problem_id", "number"], name: "index_submissions_on_user_id_and_problem_id_and_number", unique: true
261 t.index ["user_id", "problem_id", "number"], name: "index_submissions_on_user_id_and_problem_id_and_number", unique: true
253 t.index ["user_id", "problem_id"], name: "index_submissions_on_user_id_and_problem_id"
262 t.index ["user_id", "problem_id"], name: "index_submissions_on_user_id_and_problem_id"
254 end
263 end
255
264
256 create_table "tags", id: :integer, charset: "latin1", force: :cascade do |t|
265 create_table "tags", id: :integer, charset: "latin1", force: :cascade do |t|
257 t.string "name", null: false
266 t.string "name", null: false
258 t.text "description"
267 t.text "description"
259 t.boolean "public"
268 t.boolean "public"
260 t.datetime "created_at", precision: nil, null: false
269 t.datetime "created_at", precision: nil, null: false
261 t.datetime "updated_at", precision: nil, null: false
270 t.datetime "updated_at", precision: nil, null: false
262 end
271 end
263
272
264 - create_table "tasks", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
273 + create_table "tasks", id: :integer, charset: "utf8", force: :cascade do |t|
265 t.integer "submission_id"
274 t.integer "submission_id"
266 t.datetime "created_at", precision: nil
275 t.datetime "created_at", precision: nil
267 t.integer "status"
276 t.integer "status"
268 t.datetime "updated_at", precision: nil
277 t.datetime "updated_at", precision: nil
269 t.index ["status"], name: "index_tasks_on_status"
278 t.index ["status"], name: "index_tasks_on_status"
270 t.index ["submission_id"], name: "index_tasks_on_submission_id"
279 t.index ["submission_id"], name: "index_tasks_on_submission_id"
271 end
280 end
272
281
273 - create_table "test_pairs", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
282 + create_table "test_pairs", id: :integer, charset: "utf8", force: :cascade do |t|
274 t.integer "problem_id"
283 t.integer "problem_id"
275 - t.text "input", size: :medium
284 + t.text "input", size: :long
276 - t.text "solution", size: :medium
285 + t.text "solution", size: :long
277 t.datetime "created_at", precision: nil, null: false
286 t.datetime "created_at", precision: nil, null: false
278 t.datetime "updated_at", precision: nil, null: false
287 t.datetime "updated_at", precision: nil, null: false
279 end
288 end
280
289
281 - create_table "test_requests", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
290 + create_table "test_requests", id: :integer, charset: "utf8", force: :cascade do |t|
282 t.integer "user_id"
291 t.integer "user_id"
283 t.integer "problem_id"
292 t.integer "problem_id"
284 t.integer "submission_id"
293 t.integer "submission_id"
285 t.string "input_file_name"
294 t.string "input_file_name"
286 t.string "output_file_name"
295 t.string "output_file_name"
287 t.string "running_stat"
296 t.string "running_stat"
288 t.integer "status"
297 t.integer "status"
289 t.datetime "updated_at", precision: nil, null: false
298 t.datetime "updated_at", precision: nil, null: false
290 t.datetime "submitted_at", precision: nil
299 t.datetime "submitted_at", precision: nil
291 t.datetime "compiled_at", precision: nil
300 t.datetime "compiled_at", precision: nil
292 - t.text "compiler_message"
301 + t.text "compiler_message", size: :medium
293 t.datetime "graded_at", precision: nil
302 t.datetime "graded_at", precision: nil
294 t.string "grader_comment"
303 t.string "grader_comment"
295 t.datetime "created_at", precision: nil, null: false
304 t.datetime "created_at", precision: nil, null: false
296 t.float "running_time"
305 t.float "running_time"
297 t.string "exit_status"
306 t.string "exit_status"
298 t.integer "memory_usage"
307 t.integer "memory_usage"
299 t.index ["user_id", "problem_id"], name: "index_test_requests_on_user_id_and_problem_id"
308 t.index ["user_id", "problem_id"], name: "index_test_requests_on_user_id_and_problem_id"
300 end
309 end
301
310
302 create_table "testcases", id: :integer, charset: "latin1", force: :cascade do |t|
311 create_table "testcases", id: :integer, charset: "latin1", force: :cascade do |t|
303 t.integer "problem_id"
312 t.integer "problem_id"
304 t.integer "num"
313 t.integer "num"
305 t.integer "group"
314 t.integer "group"
306 t.integer "score"
315 t.integer "score"
307 t.text "input", size: :long
316 t.text "input", size: :long
308 t.text "sol", size: :long
317 t.text "sol", size: :long
309 - t.datetime "created_at", precision: nil
318 + t.datetime "created_at", precision: nil, null: false
310 - t.datetime "updated_at", precision: nil
319 + t.datetime "updated_at", precision: nil, null: false
311 t.index ["problem_id"], name: "index_testcases_on_problem_id"
320 t.index ["problem_id"], name: "index_testcases_on_problem_id"
312 end
321 end
313
322
314 - create_table "user_contest_stats", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
323 + create_table "user_contest_stats", id: :integer, charset: "utf8", force: :cascade do |t|
315 t.integer "user_id"
324 t.integer "user_id"
316 t.datetime "started_at", precision: nil
325 t.datetime "started_at", precision: nil
317 t.datetime "created_at", precision: nil, null: false
326 t.datetime "created_at", precision: nil, null: false
318 t.datetime "updated_at", precision: nil, null: false
327 t.datetime "updated_at", precision: nil, null: false
319 t.boolean "forced_logout"
328 t.boolean "forced_logout"
320 end
329 end
321
330
322 - create_table "users", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
331 + create_table "users", id: :integer, charset: "utf8", force: :cascade do |t|
323 t.string "login", limit: 50
332 t.string "login", limit: 50
324 t.string "full_name"
333 t.string "full_name"
325 t.string "hashed_password"
334 t.string "hashed_password"
326 t.string "salt", limit: 5
335 t.string "salt", limit: 5
327 t.string "alias"
336 t.string "alias"
328 t.string "email"
337 t.string "email"
329 t.integer "site_id"
338 t.integer "site_id"
330 t.integer "country_id"
339 t.integer "country_id"
331 t.boolean "activated", default: false
340 t.boolean "activated", default: false
332 t.datetime "created_at", precision: nil
341 t.datetime "created_at", precision: nil
333 t.datetime "updated_at", precision: nil
342 t.datetime "updated_at", precision: nil
343 + t.string "section"
334 t.boolean "enabled", default: true
344 t.boolean "enabled", default: true
335 t.string "remark"
345 t.string "remark"
336 t.string "last_ip"
346 t.string "last_ip"
337 - t.string "section"
338 t.integer "default_language"
347 t.integer "default_language"
339 t.index ["login"], name: "index_users_on_login", unique: true
348 t.index ["login"], name: "index_users_on_login", unique: true
340 end
349 end
341
350
342 add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
351 add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
343 add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
352 add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
344 add_foreign_key "problems_tags", "problems"
353 add_foreign_key "problems_tags", "problems"
345 add_foreign_key "problems_tags", "tags"
354 add_foreign_key "problems_tags", "tags"
355 + add_foreign_key "solutions", "problems"
356 + add_foreign_key "solutions", "submissions"
346 end
357 end
You need to be logged in to leave comments. Login now