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

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