Description:
tags / problems
Commit status:
[Not Reviewed]
References:
Diff options:
Comments:
0 Commit comments
0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
r879:60919c3675f4 - - 13 files changed: 87 inserted, 104 deleted
@@ -5,332 +5,336 | |||||
|
5 | specs: |
|
5 | specs: |
|
6 | simple_form (5.1.0) |
|
6 | simple_form (5.1.0) |
|
7 | actionpack (>= 5.2) |
|
7 | actionpack (>= 5.2) |
|
8 | activemodel (>= 5.2) |
|
8 | activemodel (>= 5.2) |
|
9 |
|
9 | ||
|
10 | GIT |
|
10 | GIT |
|
11 | remote: https://github.com/mmotherwell/best_in_place |
|
11 | remote: https://github.com/mmotherwell/best_in_place |
|
12 | revision: 88eb3052623a9a6cd346864d2aca05021c2f80d0 |
|
12 | revision: 88eb3052623a9a6cd346864d2aca05021c2f80d0 |
|
13 | specs: |
|
13 | specs: |
|
14 | best_in_place (3.1.1) |
|
14 | best_in_place (3.1.1) |
|
15 | actionpack (>= 3.2) |
|
15 | actionpack (>= 3.2) |
|
16 | railties (>= 3.2) |
|
16 | railties (>= 3.2) |
|
17 |
|
17 | ||
|
18 | GEM |
|
18 | GEM |
|
19 | remote: https://rubygems.org/ |
|
19 | remote: https://rubygems.org/ |
|
20 | specs: |
|
20 | specs: |
|
21 | RubyInline (3.12.6) |
|
21 | RubyInline (3.12.6) |
|
22 | ZenTest (~> 4.3) |
|
22 | ZenTest (~> 4.3) |
|
23 | ZenTest (4.12.1) |
|
23 | ZenTest (4.12.1) |
|
24 | ace-rails-ap (4.4) |
|
24 | ace-rails-ap (4.4) |
|
25 | actioncable (7.0.4) |
|
25 | actioncable (7.0.4) |
|
26 | actionpack (= 7.0.4) |
|
26 | actionpack (= 7.0.4) |
|
27 | activesupport (= 7.0.4) |
|
27 | activesupport (= 7.0.4) |
|
28 | nio4r (~> 2.0) |
|
28 | nio4r (~> 2.0) |
|
29 | websocket-driver (>= 0.6.1) |
|
29 | websocket-driver (>= 0.6.1) |
|
30 | actionmailbox (7.0.4) |
|
30 | actionmailbox (7.0.4) |
|
31 | actionpack (= 7.0.4) |
|
31 | actionpack (= 7.0.4) |
|
32 | activejob (= 7.0.4) |
|
32 | activejob (= 7.0.4) |
|
33 | activerecord (= 7.0.4) |
|
33 | activerecord (= 7.0.4) |
|
34 | activestorage (= 7.0.4) |
|
34 | activestorage (= 7.0.4) |
|
35 | activesupport (= 7.0.4) |
|
35 | activesupport (= 7.0.4) |
|
36 | mail (>= 2.7.1) |
|
36 | mail (>= 2.7.1) |
|
37 | net-imap |
|
37 | net-imap |
|
38 | net-pop |
|
38 | net-pop |
|
39 | net-smtp |
|
39 | net-smtp |
|
40 | actionmailer (7.0.4) |
|
40 | actionmailer (7.0.4) |
|
41 | actionpack (= 7.0.4) |
|
41 | actionpack (= 7.0.4) |
|
42 | actionview (= 7.0.4) |
|
42 | actionview (= 7.0.4) |
|
43 | activejob (= 7.0.4) |
|
43 | activejob (= 7.0.4) |
|
44 | activesupport (= 7.0.4) |
|
44 | activesupport (= 7.0.4) |
|
45 | mail (~> 2.5, >= 2.5.4) |
|
45 | mail (~> 2.5, >= 2.5.4) |
|
46 | net-imap |
|
46 | net-imap |
|
47 | net-pop |
|
47 | net-pop |
|
48 | net-smtp |
|
48 | net-smtp |
|
49 | rails-dom-testing (~> 2.0) |
|
49 | rails-dom-testing (~> 2.0) |
|
50 | actionpack (7.0.4) |
|
50 | actionpack (7.0.4) |
|
51 | actionview (= 7.0.4) |
|
51 | actionview (= 7.0.4) |
|
52 | activesupport (= 7.0.4) |
|
52 | activesupport (= 7.0.4) |
|
53 | rack (~> 2.0, >= 2.2.0) |
|
53 | rack (~> 2.0, >= 2.2.0) |
|
54 | rack-test (>= 0.6.3) |
|
54 | rack-test (>= 0.6.3) |
|
55 | rails-dom-testing (~> 2.0) |
|
55 | rails-dom-testing (~> 2.0) |
|
56 | rails-html-sanitizer (~> 1.0, >= 1.2.0) |
|
56 | rails-html-sanitizer (~> 1.0, >= 1.2.0) |
|
57 | actiontext (7.0.4) |
|
57 | actiontext (7.0.4) |
|
58 | actionpack (= 7.0.4) |
|
58 | actionpack (= 7.0.4) |
|
59 | activerecord (= 7.0.4) |
|
59 | activerecord (= 7.0.4) |
|
60 | activestorage (= 7.0.4) |
|
60 | activestorage (= 7.0.4) |
|
61 | activesupport (= 7.0.4) |
|
61 | activesupport (= 7.0.4) |
|
62 | globalid (>= 0.6.0) |
|
62 | globalid (>= 0.6.0) |
|
63 | nokogiri (>= 1.8.5) |
|
63 | nokogiri (>= 1.8.5) |
|
64 | actionview (7.0.4) |
|
64 | actionview (7.0.4) |
|
65 | activesupport (= 7.0.4) |
|
65 | activesupport (= 7.0.4) |
|
66 | builder (~> 3.1) |
|
66 | builder (~> 3.1) |
|
67 | erubi (~> 1.4) |
|
67 | erubi (~> 1.4) |
|
68 | rails-dom-testing (~> 2.0) |
|
68 | rails-dom-testing (~> 2.0) |
|
69 | rails-html-sanitizer (~> 1.1, >= 1.2.0) |
|
69 | rails-html-sanitizer (~> 1.1, >= 1.2.0) |
|
70 | activejob (7.0.4) |
|
70 | activejob (7.0.4) |
|
71 | activesupport (= 7.0.4) |
|
71 | activesupport (= 7.0.4) |
|
72 | globalid (>= 0.3.6) |
|
72 | globalid (>= 0.3.6) |
|
73 | activemodel (7.0.4) |
|
73 | activemodel (7.0.4) |
|
74 | activesupport (= 7.0.4) |
|
74 | activesupport (= 7.0.4) |
|
75 | activerecord (7.0.4) |
|
75 | activerecord (7.0.4) |
|
76 | activemodel (= 7.0.4) |
|
76 | activemodel (= 7.0.4) |
|
77 | activesupport (= 7.0.4) |
|
77 | activesupport (= 7.0.4) |
|
78 | activestorage (7.0.4) |
|
78 | activestorage (7.0.4) |
|
79 | actionpack (= 7.0.4) |
|
79 | actionpack (= 7.0.4) |
|
80 | activejob (= 7.0.4) |
|
80 | activejob (= 7.0.4) |
|
81 | activerecord (= 7.0.4) |
|
81 | activerecord (= 7.0.4) |
|
82 | activesupport (= 7.0.4) |
|
82 | activesupport (= 7.0.4) |
|
83 | marcel (~> 1.0) |
|
83 | marcel (~> 1.0) |
|
84 | mini_mime (>= 1.1.0) |
|
84 | mini_mime (>= 1.1.0) |
|
85 | activesupport (7.0.4) |
|
85 | activesupport (7.0.4) |
|
86 | concurrent-ruby (~> 1.0, >= 1.0.2) |
|
86 | concurrent-ruby (~> 1.0, >= 1.0.2) |
|
87 | i18n (>= 1.6, < 2) |
|
87 | i18n (>= 1.6, < 2) |
|
88 | minitest (>= 5.1) |
|
88 | minitest (>= 5.1) |
|
89 | tzinfo (~> 2.0) |
|
89 | tzinfo (~> 2.0) |
|
90 | addressable (2.8.1) |
|
90 | addressable (2.8.1) |
|
91 | public_suffix (>= 2.0.2, < 6.0) |
|
91 | public_suffix (>= 2.0.2, < 6.0) |
|
92 | ansi (1.5.0) |
|
92 | ansi (1.5.0) |
|
93 | autoprefixer-rails (10.4.7.0) |
|
93 | autoprefixer-rails (10.4.7.0) |
|
94 | execjs (~> 2) |
|
94 | execjs (~> 2) |
|
95 | bindex (0.8.1) |
|
95 | bindex (0.8.1) |
|
96 | bootsnap (1.13.0) |
|
96 | bootsnap (1.13.0) |
|
97 | msgpack (~> 1.2) |
|
97 | msgpack (~> 1.2) |
|
98 | bootstrap (5.2.1) |
|
98 | bootstrap (5.2.1) |
|
99 | autoprefixer-rails (>= 9.1.0) |
|
99 | autoprefixer-rails (>= 9.1.0) |
|
100 | popper_js (>= 2.11.6, < 3) |
|
100 | popper_js (>= 2.11.6, < 3) |
|
101 | sassc-rails (>= 2.0.0) |
|
101 | sassc-rails (>= 2.0.0) |
|
102 | builder (3.2.4) |
|
102 | builder (3.2.4) |
|
103 | byebug (11.1.3) |
|
103 | byebug (11.1.3) |
|
104 | capybara (3.37.1) |
|
104 | capybara (3.37.1) |
|
105 | addressable |
|
105 | addressable |
|
106 | matrix |
|
106 | matrix |
|
107 | mini_mime (>= 0.1.3) |
|
107 | mini_mime (>= 0.1.3) |
|
108 | nokogiri (~> 1.8) |
|
108 | nokogiri (~> 1.8) |
|
109 | rack (>= 1.6.0) |
|
109 | rack (>= 1.6.0) |
|
110 | rack-test (>= 0.6.3) |
|
110 | rack-test (>= 0.6.3) |
|
111 | regexp_parser (>= 1.5, < 3.0) |
|
111 | regexp_parser (>= 1.5, < 3.0) |
|
112 | xpath (~> 3.2) |
|
112 | xpath (~> 3.2) |
|
113 | childprocess (4.1.0) |
|
113 | childprocess (4.1.0) |
|
114 | coffee-rails (5.0.0) |
|
114 | coffee-rails (5.0.0) |
|
115 | coffee-script (>= 2.2.0) |
|
115 | coffee-script (>= 2.2.0) |
|
116 | railties (>= 5.2.0) |
|
116 | railties (>= 5.2.0) |
|
117 | coffee-script (2.4.1) |
|
117 | coffee-script (2.4.1) |
|
118 | coffee-script-source |
|
118 | coffee-script-source |
|
119 | execjs |
|
119 | execjs |
|
120 | coffee-script-source (1.12.2) |
|
120 | coffee-script-source (1.12.2) |
|
121 | concurrent-ruby (1.1.10) |
|
121 | concurrent-ruby (1.1.10) |
|
122 | crass (1.0.6) |
|
122 | crass (1.0.6) |
|
123 | digest (3.1.0) |
|
123 | digest (3.1.0) |
|
124 | erubi (1.11.0) |
|
124 | erubi (1.11.0) |
|
125 | erubis (2.7.0) |
|
125 | erubis (2.7.0) |
|
126 | execjs (2.8.1) |
|
126 | execjs (2.8.1) |
|
127 | ffi (1.15.5) |
|
127 | ffi (1.15.5) |
|
128 | fuzzy-string-match (1.0.1) |
|
128 | fuzzy-string-match (1.0.1) |
|
129 | RubyInline (>= 3.8.6) |
|
129 | RubyInline (>= 3.8.6) |
|
130 | globalid (1.0.0) |
|
130 | globalid (1.0.0) |
|
131 | activesupport (>= 5.0) |
|
131 | activesupport (>= 5.0) |
|
132 | haml (5.2.2) |
|
132 | haml (5.2.2) |
|
133 | temple (>= 0.8.0) |
|
133 | temple (>= 0.8.0) |
|
134 | tilt |
|
134 | tilt |
|
135 | haml-rails (2.0.1) |
|
135 | haml-rails (2.0.1) |
|
136 | actionpack (>= 5.1) |
|
136 | actionpack (>= 5.1) |
|
137 | activesupport (>= 5.1) |
|
137 | activesupport (>= 5.1) |
|
138 | haml (>= 4.0.6, < 6.0) |
|
138 | haml (>= 4.0.6, < 6.0) |
|
139 | html2haml (>= 1.0.1) |
|
139 | html2haml (>= 1.0.1) |
|
140 | railties (>= 5.1) |
|
140 | railties (>= 5.1) |
|
141 | html2haml (2.2.0) |
|
141 | html2haml (2.2.0) |
|
142 | erubis (~> 2.7.0) |
|
142 | erubis (~> 2.7.0) |
|
143 | haml (>= 4.0, < 6) |
|
143 | haml (>= 4.0, < 6) |
|
144 | nokogiri (>= 1.6.0) |
|
144 | nokogiri (>= 1.6.0) |
|
145 | ruby_parser (~> 3.5) |
|
145 | ruby_parser (~> 3.5) |
|
146 | i18n (1.12.0) |
|
146 | i18n (1.12.0) |
|
147 | concurrent-ruby (~> 1.0) |
|
147 | concurrent-ruby (~> 1.0) |
|
148 | importmap-rails (1.1.5) |
|
148 | importmap-rails (1.1.5) |
|
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 |
|
317 | ||
|
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,264 +1,251 | |||||
|
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( |
|
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 | ||
|
121 | if GraderConfiguration.multicontests? |
|
108 | if GraderConfiguration.multicontests? |
|
122 | return true if @current_user.admin? |
|
109 | return true if @current_user.admin? |
|
123 | begin |
|
110 | begin |
|
124 | if @current_user.contest_stat(true).forced_logout |
|
111 | if @current_user.contest_stat(true).forced_logout |
|
125 | flash[:notice] = 'You have been automatically logged out.' |
|
112 | flash[:notice] = 'You have been automatically logged out.' |
|
126 | redirect_to :controller => 'main', :action => 'index' |
|
113 | redirect_to :controller => 'main', :action => 'index' |
|
127 | end |
|
114 | end |
|
128 | rescue |
|
115 | rescue |
|
129 | end |
|
116 | end |
|
130 | end |
|
117 | end |
|
131 | return true |
|
118 | return true |
|
132 | end |
|
119 | end |
|
133 |
|
120 | ||
|
134 | #redirect to root (and also force logout) |
|
121 | #redirect to root (and also force logout) |
|
135 | #if the user use different ip from the previous connection |
|
122 | #if the user use different ip from the previous connection |
|
136 | # only applicable when MULTIPLE_IP_LOGIN options is false only |
|
123 | # only applicable when MULTIPLE_IP_LOGIN options is false only |
|
137 | def authenticate_by_ip_address |
|
124 | def authenticate_by_ip_address |
|
138 | #this assume that we have already authenticate normally |
|
125 | #this assume that we have already authenticate normally |
|
139 | unless GraderConfiguration[MULTIPLE_IP_LOGIN_CONF_KEY] |
|
126 | unless GraderConfiguration[MULTIPLE_IP_LOGIN_CONF_KEY] |
|
140 | user = User.find(session[:user_id]) |
|
127 | user = User.find(session[:user_id]) |
|
141 | if (!user.admin? && user.last_ip && user.last_ip != request.remote_ip) |
|
128 | if (!user.admin? && user.last_ip && user.last_ip != request.remote_ip) |
|
142 | flash[:notice] = "You cannot use the system from #{request.remote_ip}. Your last ip is #{user.last_ip}" |
|
129 | flash[:notice] = "You cannot use the system from #{request.remote_ip}. Your last ip is #{user.last_ip}" |
|
143 | redirect_to :controller => 'main', :action => 'login' |
|
130 | redirect_to :controller => 'main', :action => 'login' |
|
144 | return false |
|
131 | return false |
|
145 | end |
|
132 | end |
|
146 | unless user.last_ip |
|
133 | unless user.last_ip |
|
147 | user.last_ip = request.remote_ip |
|
134 | user.last_ip = request.remote_ip |
|
148 | user.save |
|
135 | user.save |
|
149 | end |
|
136 | end |
|
150 | end |
|
137 | end |
|
151 | return true |
|
138 | return true |
|
152 | end |
|
139 | end |
|
153 |
|
140 | ||
|
154 | def authorization |
|
141 | def authorization |
|
155 | return false unless check_valid_login |
|
142 | return false unless check_valid_login |
|
156 | user = User.find(session[:user_id]) |
|
143 | user = User.find(session[:user_id]) |
|
157 | unless user.roles.detect { |role| |
|
144 | unless user.roles.detect { |role| |
|
158 | role.rights.detect{ |right| |
|
145 | role.rights.detect{ |right| |
|
159 | right.controller == self.class.controller_name and |
|
146 | right.controller == self.class.controller_name and |
|
160 | (right.action == 'all' || right.action == action_name) |
|
147 | (right.action == 'all' || right.action == action_name) |
|
161 | } |
|
148 | } |
|
162 | } |
|
149 | } |
|
163 | flash[:notice] = 'You are not authorized to view the page you requested' |
|
150 | flash[:notice] = 'You are not authorized to view the page you requested' |
|
164 | #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login') |
|
151 | #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login') |
|
165 | redirect_to :controller => 'main', :action => 'login' |
|
152 | redirect_to :controller => 'main', :action => 'login' |
|
166 | return false |
|
153 | return false |
|
167 | end |
|
154 | end |
|
168 | end |
|
155 | end |
|
169 |
|
156 | ||
|
170 | def verify_time_limit |
|
157 | def verify_time_limit |
|
171 | return true if session[:user_id]==nil |
|
158 | return true if session[:user_id]==nil |
|
172 | user = User.find(session[:user_id], :include => :site) |
|
159 | user = User.find(session[:user_id], :include => :site) |
|
173 | return true if user==nil || user.site == nil |
|
160 | return true if user==nil || user.site == nil |
|
174 | if user.contest_finished? |
|
161 | if user.contest_finished? |
|
175 | flash[:notice] = 'Error: the contest you are participating is over.' |
|
162 | flash[:notice] = 'Error: the contest you are participating is over.' |
|
176 | redirect_to :back |
|
163 | redirect_to :back |
|
177 | return false |
|
164 | return false |
|
178 | end |
|
165 | end |
|
179 | return true |
|
166 | return true |
|
180 | end |
|
167 | end |
|
181 |
|
168 | ||
|
182 | def is_request_ip_allowed? |
|
169 | def is_request_ip_allowed? |
|
183 | unless GraderConfiguration[WHITELIST_IGNORE_CONF_KEY] |
|
170 | unless GraderConfiguration[WHITELIST_IGNORE_CONF_KEY] |
|
184 | user_ip = IPAddr.new(request.remote_ip) |
|
171 | user_ip = IPAddr.new(request.remote_ip) |
|
185 | allowed = GraderConfiguration[WHITELIST_IP_CONF_KEY] || '' |
|
172 | allowed = GraderConfiguration[WHITELIST_IP_CONF_KEY] || '' |
|
186 |
|
173 | ||
|
187 | allowed.delete(' ').split(',').each do |ips| |
|
174 | allowed.delete(' ').split(',').each do |ips| |
|
188 | allow_ips = IPAddr.new(ips) |
|
175 | allow_ips = IPAddr.new(ips) |
|
189 | if allow_ips.include?(user_ip) |
|
176 | if allow_ips.include?(user_ip) |
|
190 | return true |
|
177 | return true |
|
191 | end |
|
178 | end |
|
192 | end |
|
179 | end |
|
193 | return false |
|
180 | return false |
|
194 | end |
|
181 | end |
|
195 | return true |
|
182 | return true |
|
196 | end |
|
183 | end |
|
197 |
|
184 | ||
|
198 | #function for datatable ajax query |
|
185 | #function for datatable ajax query |
|
199 | #return record,total_count,filter_count |
|
186 | #return record,total_count,filter_count |
|
200 | def process_query_record(record, |
|
187 | def process_query_record(record, |
|
201 | total_count: nil, |
|
188 | total_count: nil, |
|
202 | select: '', |
|
189 | select: '', |
|
203 | global_search: [], |
|
190 | global_search: [], |
|
204 | no_search: false, |
|
191 | no_search: false, |
|
205 | force_order: '', |
|
192 | force_order: '', |
|
206 | date_filter: '', date_param_since: 'date_since',date_param_until: 'date_until', |
|
193 | date_filter: '', date_param_since: 'date_since',date_param_until: 'date_until', |
|
207 | hard_limit: nil) |
|
194 | hard_limit: nil) |
|
208 | arel_table = record.model.arel_table |
|
195 | arel_table = record.model.arel_table |
|
209 |
|
196 | ||
|
210 | if !no_search && params['search'] |
|
197 | if !no_search && params['search'] |
|
211 | global_value = record.model.sanitize_sql(params['search']['value'].strip.downcase) |
|
198 | global_value = record.model.sanitize_sql(params['search']['value'].strip.downcase) |
|
212 | if !global_value.blank? |
|
199 | if !global_value.blank? |
|
213 | global_value.split.each do |value| |
|
200 | global_value.split.each do |value| |
|
214 | global_where = global_search.map{|f| "LOWER(#{f}) like '%#{value}%'"}.join(' OR ') |
|
201 | global_where = global_search.map{|f| "LOWER(#{f}) like '%#{value}%'"}.join(' OR ') |
|
215 | record = record.where(global_where) |
|
202 | record = record.where(global_where) |
|
216 | end |
|
203 | end |
|
217 | end |
|
204 | end |
|
218 |
|
205 | ||
|
219 | params['columns'].each do |i, col| |
|
206 | params['columns'].each do |i, col| |
|
220 | if !col['search']['value'].blank? |
|
207 | if !col['search']['value'].blank? |
|
221 | record = record.where(arel_table[col['name']].lower.matches("%#{col['search']['value'].strip.downcase}%")) |
|
208 | record = record.where(arel_table[col['name']].lower.matches("%#{col['search']['value'].strip.downcase}%")) |
|
222 | end |
|
209 | end |
|
223 | end |
|
210 | end |
|
224 | end |
|
211 | end |
|
225 |
|
212 | ||
|
226 | if !date_filter.blank? |
|
213 | if !date_filter.blank? |
|
227 | param_since = params[date_param_since] |
|
214 | param_since = params[date_param_since] |
|
228 | param_until = params[date_param_until] |
|
215 | param_until = params[date_param_until] |
|
229 | date_since = Time.zone.parse( param_since ) || Time.new(1,1,1) rescue Time.new(1,1,1) |
|
216 | date_since = Time.zone.parse( param_since ) || Time.new(1,1,1) rescue Time.new(1,1,1) |
|
230 | date_until = Time.zone.parse( param_until ) || Time.zone.now() rescue Time.zone.now() |
|
217 | date_until = Time.zone.parse( param_until ) || Time.zone.now() rescue Time.zone.now() |
|
231 | date_range = date_since..(date_until.end_of_day) |
|
218 | date_range = date_since..(date_until.end_of_day) |
|
232 | record = record.where(date_filter.to_sym => date_range) |
|
219 | record = record.where(date_filter.to_sym => date_range) |
|
233 | end |
|
220 | end |
|
234 |
|
221 | ||
|
235 | if force_order.blank? |
|
222 | if force_order.blank? |
|
236 | if params['order'] |
|
223 | if params['order'] |
|
237 | params['order'].each do |i, o| |
|
224 | params['order'].each do |i, o| |
|
238 | colName = params['columns'][o['column']]['name'] |
|
225 | colName = params['columns'][o['column']]['name'] |
|
239 | colName = "#{record.model.table_name}.#{colName}" if colName.upcase == 'ID' |
|
226 | colName = "#{record.model.table_name}.#{colName}" if colName.upcase == 'ID' |
|
240 | record = record.order("#{colName} #{o['dir'].casecmp('desc') != 0 ? 'ASC' : 'DESC'}") unless colName.blank? |
|
227 | record = record.order("#{colName} #{o['dir'].casecmp('desc') != 0 ? 'ASC' : 'DESC'}") unless colName.blank? |
|
241 | end |
|
228 | end |
|
242 | end |
|
229 | end |
|
243 | else |
|
230 | else |
|
244 | record = record.order(force_order) |
|
231 | record = record.order(force_order) |
|
245 | end |
|
232 | end |
|
246 |
|
233 | ||
|
247 | filterCount = record.count(record.model.primary_key) |
|
234 | filterCount = record.count(record.model.primary_key) |
|
248 | # if .group() is used, filterCount might be like {id_1: count_1, id_2: count_2, ...} |
|
235 | # if .group() is used, filterCount might be like {id_1: count_1, id_2: count_2, ...} |
|
249 | # so we should count the result again.. |
|
236 | # so we should count the result again.. |
|
250 | if filterCount.is_a? Hash |
|
237 | if filterCount.is_a? Hash |
|
251 | filterCount = filterCount.count |
|
238 | filterCount = filterCount.count |
|
252 | end |
|
239 | end |
|
253 |
|
240 | ||
|
254 |
|
241 | ||
|
255 | record = record.offset(params['start'] || 0) |
|
242 | record = record.offset(params['start'] || 0) |
|
256 | record = record.limit(hard_limit) |
|
243 | record = record.limit(hard_limit) |
|
257 | if (params['length']) |
|
244 | if (params['length']) |
|
258 | limit = params['length'].to_i |
|
245 | limit = params['length'].to_i |
|
259 | limit == hard_limit if (hard_limit && hard_limit < limit) |
|
246 | limit == hard_limit if (hard_limit && hard_limit < limit) |
|
260 | record = record.limit(limit) |
|
247 | record = record.limit(limit) |
|
261 | end |
|
248 | end |
|
262 | if (!select.blank?) |
|
249 | if (!select.blank?) |
|
263 | record = record.select(select) |
|
250 | record = record.select(select) |
|
264 | end |
|
251 | end |
@@ -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 |
- |
|
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[: |
|
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[: |
|
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,215 +1,214 | |||||
|
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 |
|
72 |
|
71 | ||
|
73 | @submission.submitted_at = Time.new.gmtime |
|
72 | @submission.submitted_at = Time.new.gmtime |
|
74 | @submission.ip_address = cookies.encrypted[:uuid] |
|
73 | @submission.ip_address = cookies.encrypted[:uuid] |
|
75 |
|
74 | ||
|
76 | if @current_user.admin? == false && GraderConfiguration.time_limit_mode? && @current_user.contest_finished? |
|
75 | if @current_user.admin? == false && GraderConfiguration.time_limit_mode? && @current_user.contest_finished? |
|
77 | @submission.errors.add(:base,"The contest is over.") |
|
76 | @submission.errors.add(:base,"The contest is over.") |
|
78 | prepare_list_information |
|
77 | prepare_list_information |
|
79 | render :action => 'list' and return |
|
78 | render :action => 'list' and return |
|
80 | end |
|
79 | end |
|
81 |
|
80 | ||
|
82 | if @submission.valid?(@current_user) |
|
81 | if @submission.valid?(@current_user) |
|
83 | if @submission.save == false |
|
82 | if @submission.save == false |
|
84 | flash[:notice] = 'Error saving your submission' |
|
83 | flash[:notice] = 'Error saving your submission' |
|
85 | elsif Task.create(:submission_id => @submission.id, |
|
84 | elsif Task.create(:submission_id => @submission.id, |
|
86 | :status => Task::STATUS_INQUEUE) == false |
|
85 | :status => Task::STATUS_INQUEUE) == false |
|
87 | flash[:notice] = 'Error adding your submission to task queue' |
|
86 | flash[:notice] = 'Error adding your submission to task queue' |
|
88 | end |
|
87 | end |
|
89 | else |
|
88 | else |
|
90 | prepare_list_information |
|
89 | prepare_list_information |
|
91 | render :action => 'list' and return |
|
90 | render :action => 'list' and return |
|
92 | end |
|
91 | end |
|
93 | redirect_to edit_submission_path(@submission) |
|
92 | redirect_to edit_submission_path(@submission) |
|
94 | end |
|
93 | end |
|
95 |
|
94 | ||
|
96 | def source |
|
95 | def source |
|
97 | submission = Submission.find(params[:id]) |
|
96 | submission = Submission.find(params[:id]) |
|
98 | if ((submission.user_id == session[:user_id]) and |
|
97 | if ((submission.user_id == session[:user_id]) and |
|
99 | (submission.problem != nil) and |
|
98 | (submission.problem != nil) and |
|
100 | (submission.problem.available)) |
|
99 | (submission.problem.available)) |
|
101 | send_data(submission.source, |
|
100 | send_data(submission.source, |
|
102 | {:filename => submission.download_filename, |
|
101 | {:filename => submission.download_filename, |
|
103 | :type => 'text/plain'}) |
|
102 | :type => 'text/plain'}) |
|
104 | else |
|
103 | else |
|
105 | flash[:notice] = 'Error viewing source' |
|
104 | flash[:notice] = 'Error viewing source' |
|
106 | redirect_to :action => 'list' |
|
105 | redirect_to :action => 'list' |
|
107 | end |
|
106 | end |
|
108 | end |
|
107 | end |
|
109 |
|
108 | ||
|
110 | def compiler_msg |
|
109 | def compiler_msg |
|
111 | @submission = Submission.find(params[:id]) |
|
110 | @submission = Submission.find(params[:id]) |
|
112 | if @submission.user_id == session[:user_id] |
|
111 | if @submission.user_id == session[:user_id] |
|
113 | render :action => 'compiler_msg', :layout => 'empty' |
|
112 | render :action => 'compiler_msg', :layout => 'empty' |
|
114 | else |
|
113 | else |
|
115 | flash[:notice] = 'Error viewing source' |
|
114 | flash[:notice] = 'Error viewing source' |
|
116 | redirect_to :action => 'list' |
|
115 | redirect_to :action => 'list' |
|
117 | end |
|
116 | end |
|
118 | end |
|
117 | end |
|
119 |
|
118 | ||
|
120 | def result |
|
119 | def result |
|
121 | if !GraderConfiguration.show_grading_result |
|
120 | if !GraderConfiguration.show_grading_result |
|
122 | redirect_to :action => 'list' and return |
|
121 | redirect_to :action => 'list' and return |
|
123 | end |
|
122 | end |
|
124 | @user = User.find(session[:user_id]) |
|
123 | @user = User.find(session[:user_id]) |
|
125 | @submission = Submission.find(params[:id]) |
|
124 | @submission = Submission.find(params[:id]) |
|
126 | if @submission.user!=@user |
|
125 | if @submission.user!=@user |
|
127 | flash[:notice] = 'You are not allowed to view result of other users.' |
|
126 | flash[:notice] = 'You are not allowed to view result of other users.' |
|
128 | redirect_to :action => 'list' and return |
|
127 | redirect_to :action => 'list' and return |
|
129 | end |
|
128 | end |
|
130 | prepare_grading_result(@submission) |
|
129 | prepare_grading_result(@submission) |
|
131 | end |
|
130 | end |
|
132 |
|
131 | ||
|
133 | def load_output |
|
132 | def load_output |
|
134 | if !GraderConfiguration.show_grading_result or params[:num]==nil |
|
133 | if !GraderConfiguration.show_grading_result or params[:num]==nil |
|
135 | redirect_to :action => 'list' and return |
|
134 | redirect_to :action => 'list' and return |
|
136 | end |
|
135 | end |
|
137 | @user = User.find(session[:user_id]) |
|
136 | @user = User.find(session[:user_id]) |
|
138 | @submission = Submission.find(params[:id]) |
|
137 | @submission = Submission.find(params[:id]) |
|
139 | if @submission.user!=@user |
|
138 | if @submission.user!=@user |
|
140 | flash[:notice] = 'You are not allowed to view result of other users.' |
|
139 | flash[:notice] = 'You are not allowed to view result of other users.' |
|
141 | redirect_to :action => 'list' and return |
|
140 | redirect_to :action => 'list' and return |
|
142 | end |
|
141 | end |
|
143 | case_num = params[:num].to_i |
|
142 | case_num = params[:num].to_i |
|
144 | out_filename = output_filename(@user.login, |
|
143 | out_filename = output_filename(@user.login, |
|
145 | @submission.problem.name, |
|
144 | @submission.problem.name, |
|
146 | @submission.id, |
|
145 | @submission.id, |
|
147 | case_num) |
|
146 | case_num) |
|
148 | if !FileTest.exists?(out_filename) |
|
147 | if !FileTest.exists?(out_filename) |
|
149 | flash[:notice] = 'Output not found.' |
|
148 | flash[:notice] = 'Output not found.' |
|
150 | redirect_to :action => 'list' and return |
|
149 | redirect_to :action => 'list' and return |
|
151 | end |
|
150 | end |
|
152 |
|
151 | ||
|
153 | if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE |
|
152 | if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE |
|
154 | response.headers['Content-Type'] = "application/force-download" |
|
153 | response.headers['Content-Type'] = "application/force-download" |
|
155 | response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\"" |
|
154 | response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\"" |
|
156 | response.headers["X-Sendfile"] = out_filename |
|
155 | response.headers["X-Sendfile"] = out_filename |
|
157 | response.headers['Content-length'] = File.size(out_filename) |
|
156 | response.headers['Content-length'] = File.size(out_filename) |
|
158 | render :nothing => true |
|
157 | render :nothing => true |
|
159 | else |
|
158 | else |
|
160 | send_file out_filename, :stream => false, :filename => "output-#{case_num}.txt", :type => "text/plain" |
|
159 | send_file out_filename, :stream => false, :filename => "output-#{case_num}.txt", :type => "text/plain" |
|
161 | end |
|
160 | end |
|
162 | end |
|
161 | end |
|
163 |
|
162 | ||
|
164 | def error |
|
163 | def error |
|
165 | @user = User.find(session[:user_id]) |
|
164 | @user = User.find(session[:user_id]) |
|
166 | end |
|
165 | end |
|
167 |
|
166 | ||
|
168 | # announcement refreshing and hiding methods |
|
167 | # announcement refreshing and hiding methods |
|
169 |
|
168 | ||
|
170 | def announcements |
|
169 | def announcements |
|
171 | if params.has_key? 'recent' |
|
170 | if params.has_key? 'recent' |
|
172 | prepare_announcements(params[:recent]) |
|
171 | prepare_announcements(params[:recent]) |
|
173 | else |
|
172 | else |
|
174 | prepare_announcements |
|
173 | prepare_announcements |
|
175 | end |
|
174 | end |
|
176 | render(:partial => 'announcement', |
|
175 | render(:partial => 'announcement', |
|
177 | :collection => @announcements, |
|
176 | :collection => @announcements, |
|
178 | :locals => {:announcement_effect => true}) |
|
177 | :locals => {:announcement_effect => true}) |
|
179 | end |
|
178 | end |
|
180 |
|
179 | ||
|
181 | def confirm_contest_start |
|
180 | def confirm_contest_start |
|
182 | user = User.find(session[:user_id]) |
|
181 | user = User.find(session[:user_id]) |
|
183 | if request.method == 'POST' |
|
182 | if request.method == 'POST' |
|
184 | user.update_start_time |
|
183 | user.update_start_time |
|
185 | redirect_to :action => 'list' |
|
184 | redirect_to :action => 'list' |
|
186 | else |
|
185 | else |
|
187 | @contests = user.contests |
|
186 | @contests = user.contests |
|
188 | @user = user |
|
187 | @user = user |
|
189 | end |
|
188 | end |
|
190 | end |
|
189 | end |
|
191 |
|
190 | ||
|
192 | protected |
|
191 | protected |
|
193 |
|
192 | ||
|
194 | def prepare_announcements(recent=nil) |
|
193 | def prepare_announcements(recent=nil) |
|
195 | if GraderConfiguration.show_tasks_to?(@user) |
|
194 | if GraderConfiguration.show_tasks_to?(@user) |
|
196 | @announcements = Announcement.published(true) |
|
195 | @announcements = Announcement.published(true) |
|
197 | else |
|
196 | else |
|
198 | @announcements = Announcement.published |
|
197 | @announcements = Announcement.published |
|
199 | end |
|
198 | end |
|
200 | if recent!=nil |
|
199 | if recent!=nil |
|
201 | recent_id = recent.to_i |
|
200 | recent_id = recent.to_i |
|
202 | @announcements = @announcements.find_all { |a| a.id > recent_id } |
|
201 | @announcements = @announcements.find_all { |a| a.id > recent_id } |
|
203 | end |
|
202 | end |
|
204 | end |
|
203 | end |
|
205 |
|
204 | ||
|
206 | def prepare_list_information |
|
205 | def prepare_list_information |
|
207 | @user = User.find(session[:user_id]) |
|
206 | @user = User.find(session[:user_id]) |
|
208 | if not GraderConfiguration.multicontests? |
|
207 | if not GraderConfiguration.multicontests? |
|
209 | @problems = @user.available_problems |
|
208 | @problems = @user.available_problems |
|
210 | else |
|
209 | else |
|
211 | @contest_problems = @user.available_problems_group_by_contests |
|
210 | @contest_problems = @user.available_problems_group_by_contests |
|
212 | @problems = @user.available_problems |
|
211 | @problems = @user.available_problems |
|
213 | end |
|
212 | end |
|
214 | @prob_submissions = {} |
|
213 | @prob_submissions = {} |
|
215 | @problems.each do |p| |
|
214 | @problems.each do |p| |
@@ -1,115 +1,115 | |||||
|
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 |
|
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 |
|
54 | end |
|
54 | end |
|
55 | @source = '' |
|
55 | @source = '' |
|
56 | if (params[:view_latest]) |
|
56 | if (params[:view_latest]) |
|
57 | sub = Submission.find_last_by_user_and_problem(@current_user.id,@problem.id) |
|
57 | sub = Submission.find_last_by_user_and_problem(@current_user.id,@problem.id) |
|
58 | @source = @submission.source.to_s if @submission and @submission.source |
|
58 | @source = @submission.source.to_s if @submission and @submission.source |
|
59 | end |
|
59 | end |
|
60 | render 'edit' |
|
60 | render 'edit' |
|
61 | end |
|
61 | end |
|
62 |
|
62 | ||
|
63 | # GET /submissions/1/edit |
|
63 | # GET /submissions/1/edit |
|
64 | def edit |
|
64 | def edit |
|
65 | @source = @submission.source.to_s |
|
65 | @source = @submission.source.to_s |
|
66 | @problem = @submission.problem |
|
66 | @problem = @submission.problem |
|
67 | @lang_id = @submission.language.id |
|
67 | @lang_id = @submission.language.id |
|
68 | end |
|
68 | end |
|
69 |
|
69 | ||
|
70 |
|
70 | ||
|
71 | def get_latest_submission_status |
|
71 | def get_latest_submission_status |
|
72 | @problem = Problem.find(params[:pid]) |
|
72 | @problem = Problem.find(params[:pid]) |
|
73 | @submission = Submission.find_last_by_user_and_problem(params[:uid],params[:pid]) |
|
73 | @submission = Submission.find_last_by_user_and_problem(params[:uid],params[:pid]) |
|
74 | respond_to do |format| |
|
74 | respond_to do |format| |
|
75 | format.js |
|
75 | format.js |
|
76 | end |
|
76 | end |
|
77 | end |
|
77 | end |
|
78 |
|
78 | ||
|
79 | # GET /submissions/:id/rejudge |
|
79 | # GET /submissions/:id/rejudge |
|
80 | def rejudge |
|
80 | def rejudge |
|
81 | @task = @submission.task |
|
81 | @task = @submission.task |
|
82 | @task.status_inqueue! if @task |
|
82 | @task.status_inqueue! if @task |
|
83 | respond_to do |format| |
|
83 | respond_to do |format| |
|
84 | format.js |
|
84 | format.js |
|
85 | end |
|
85 | end |
|
86 | end |
|
86 | end |
|
87 |
|
87 | ||
|
88 | def set_tag |
|
88 | def set_tag |
|
89 | @submission.update(tag: params[:tag]) |
|
89 | @submission.update(tag: params[:tag]) |
|
90 | redirect_to @submission |
|
90 | redirect_to @submission |
|
91 | end |
|
91 | end |
|
92 |
|
92 | ||
|
93 | protected |
|
93 | protected |
|
94 |
|
94 | ||
|
95 | def submission_authorization |
|
95 | def submission_authorization |
|
96 | #admin always has privileged |
|
96 | #admin always has privileged |
|
97 | return true if @current_user.admin? |
|
97 | return true if @current_user.admin? |
|
98 | return true if @current_user.has_role?('ta') && (['show','download'].include? action_name) |
|
98 | return true if @current_user.has_role?('ta') && (['show','download'].include? action_name) |
|
99 |
|
99 | ||
|
100 | sub = Submission.find(params[:id]) |
|
100 | sub = Submission.find(params[:id]) |
|
101 | if @current_user.available_problems.include? sub.problem |
|
101 | if @current_user.available_problems.include? sub.problem |
|
102 | return true if GraderConfiguration["right.user_view_submission"] or sub.user == @current_user |
|
102 | return true if GraderConfiguration["right.user_view_submission"] or sub.user == @current_user |
|
103 | end |
|
103 | end |
|
104 |
|
104 | ||
|
105 | #default to NO |
|
105 | #default to NO |
|
106 | unauthorized_redirect |
|
106 | unauthorized_redirect |
|
107 | return false |
|
107 | return false |
|
108 | end |
|
108 | end |
|
109 |
|
109 | ||
|
110 | def set_submission |
|
110 | def set_submission |
|
111 | @submission = Submission.find(params[:id]) |
|
111 | @submission = Submission.find(params[:id]) |
|
112 | end |
|
112 | end |
|
113 |
|
113 | ||
|
114 |
|
114 | ||
|
115 | end |
|
115 | end |
@@ -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 |
|
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- |
|
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 |
@@ -1,93 +1,93 | |||||
|
1 | %header |
|
1 | %header |
|
2 | %nav.navbar.fixed-top.navbar-dark.bg-primary.navbar-expand-lg |
|
2 | %nav.navbar.fixed-top.navbar-dark.bg-primary.navbar-expand-lg |
|
3 | .container-fluid |
|
3 | .container-fluid |
|
4 | %a.navbar-brand{href: list_main_path} |
|
4 | %a.navbar-brand{href: list_main_path} |
|
5 | %span.mi.mi-bs home |
|
5 | %span.mi.mi-bs home |
|
6 | MAIN |
|
6 | MAIN |
|
7 | %button.navbar-toggler.collapsed{ type: :button, 'data-bs': {toggle: 'collapse', target: '#navbar-collapse'} } |
|
7 | %button.navbar-toggler.collapsed{ type: :button, 'data-bs': {toggle: 'collapse', target: '#navbar-collapse'} } |
|
8 | %span.navbar-toggler-icon |
|
8 | %span.navbar-toggler-icon |
|
9 | .collapse.navbar-collapse#navbar-collapse |
|
9 | .collapse.navbar-collapse#navbar-collapse |
|
10 | %ul.navbar-nav.me-auto.mb-2.mb-lg-0 |
|
10 | %ul.navbar-nav.me-auto.mb-2.mb-lg-0 |
|
11 | / submission |
|
11 | / submission |
|
12 | - if (@current_user!=nil) and (GraderConfiguration.show_tasks_to?(@current_user)) |
|
12 | - if (@current_user!=nil) and (GraderConfiguration.show_tasks_to?(@current_user)) |
|
13 | %li.nav-item.dropdown.mx-2 |
|
13 | %li.nav-item.dropdown.mx-2 |
|
14 | %a.nav-link.dropdown-toggle.active-with-children{href: '#', 'data-bs': {toggle:'dropdown'}, aria: {expanded:"false"}, role: "button"} |
|
14 | %a.nav-link.dropdown-toggle.active-with-children{href: '#', 'data-bs': {toggle:'dropdown'}, aria: {expanded:"false"}, role: "button"} |
|
15 | = "#{I18n.t 'menu.submissions'}" |
|
15 | = "#{I18n.t 'menu.submissions'}" |
|
16 | %ul.dropdown-menu |
|
16 | %ul.dropdown-menu |
|
17 | %li= link_to 'View', submissions_path, class: 'dropdown-item '+active_class_when(controller: :submissions) |
|
17 | %li= link_to 'View', submissions_path, class: 'dropdown-item '+active_class_when(controller: :submissions) |
|
18 | %li= link_to 'Self Test', test_index_path, class:'dropdown-item' |
|
18 | %li= link_to 'Self Test', test_index_path, class:'dropdown-item' |
|
19 | / hall of fame |
|
19 | / hall of fame |
|
20 | - if GraderConfiguration['right.user_hall_of_fame'] |
|
20 | - if GraderConfiguration['right.user_hall_of_fame'] |
|
21 | %li= link_to "#{I18n.t 'menu.hall_of_fame'}", problem_hof_report_path, class: 'nav-link mx-2'+active_class_when(controller: :report, action: :problem_hof) |
|
21 | %li= link_to "#{I18n.t 'menu.hall_of_fame'}", problem_hof_report_path, class: 'nav-link mx-2'+active_class_when(controller: :report, action: :problem_hof) |
|
22 | / display MODE button (with countdown in contest mode) |
|
22 | / display MODE button (with countdown in contest mode) |
|
23 | - if GraderConfiguration.analysis_mode? |
|
23 | - if GraderConfiguration.analysis_mode? |
|
24 | %div.btn.btn-success#countdown= "ANALYSIS MODE" |
|
24 | %div.btn.btn-success#countdown= "ANALYSIS MODE" |
|
25 | - elsif GraderConfiguration.time_limit_mode? |
|
25 | - elsif GraderConfiguration.time_limit_mode? |
|
26 | - if @current_user.contest_finished? |
|
26 | - if @current_user.contest_finished? |
|
27 | %div.btn.btn-danger#countdown= "Contest is over" |
|
27 | %div.btn.btn-danger#countdown= "Contest is over" |
|
28 | - elsif !@current_user.contest_started? |
|
28 | - elsif !@current_user.contest_started? |
|
29 | %div.btn.btn-primary#countdown= (t 'title_bar.contest_not_started') |
|
29 | %div.btn.btn-primary#countdown= (t 'title_bar.contest_not_started') |
|
30 | - else |
|
30 | - else |
|
31 | %div.btn.btn-primary#countdown asdf |
|
31 | %div.btn.btn-primary#countdown asdf |
|
32 | :javascript |
|
32 | :javascript |
|
33 | $("#countdown").countdown({until: "+#{@current_user.contest_time_left.to_i}s", layout: 'Time left: {hnn}:{mnn}:{snn}'}); |
|
33 | $("#countdown").countdown({until: "+#{@current_user.contest_time_left.to_i}s", layout: 'Time left: {hnn}:{mnn}:{snn}'}); |
|
34 | / admin section |
|
34 | / admin section |
|
35 | - if (@current_user!=nil) and (session[:admin]) |
|
35 | - if (@current_user!=nil) and (session[:admin]) |
|
36 | / management |
|
36 | / management |
|
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: log |
|
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,88 +1,87 | |||||
|
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 |
- |
|
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' |
|
61 | .col-sm-9 |
|
60 | .col-sm-9 |
|
62 | =text_field_tag :login, nil, class: 'form-control' |
|
61 | =text_field_tag :login, nil, class: 'form-control' |
|
63 | .form-group |
|
62 | .form-group |
|
64 | =label_tag :password, "Password", class: 'col-sm-3 control-label' |
|
63 | =label_tag :password, "Password", class: 'col-sm-3 control-label' |
|
65 | .col-sm-9 |
|
64 | .col-sm-9 |
|
66 | =password_field_tag :password, nil, class: 'form-control' |
|
65 | =password_field_tag :password, nil, class: 'form-control' |
|
67 | - unless GraderConfiguration['right.bypass_agreement'] |
|
66 | - unless GraderConfiguration['right.bypass_agreement'] |
|
68 | .form-group |
|
67 | .form-group |
|
69 | .col-sm-offset-3.col-sm-9 |
|
68 | .col-sm-offset-3.col-sm-9 |
|
70 | .checkbox |
|
69 | .checkbox |
|
71 | %label |
|
70 | %label |
|
72 | = check_box_tag 'accept_agree' |
|
71 | = check_box_tag 'accept_agree' |
|
73 | ΰΈ’ΰΈΰΈ‘ΰΈ£ΰΈ±ΰΈΰΈΰΉΰΈΰΈΰΈΰΈ₯ΰΈΰΈΰΈ²ΰΈ£ΰΉΰΈΰΉΰΈΰΈ²ΰΈ |
|
72 | ΰΈ’ΰΈΰΈ‘ΰΈ£ΰΈ±ΰΈΰΈΰΉΰΈΰΈΰΈΰΈ₯ΰΈΰΈΰΈ²ΰΈ£ΰΉΰΈΰΉΰΈΰΈ²ΰΈ |
|
74 |
|
73 | ||
|
75 | .form-group |
|
74 | .form-group |
|
76 | .col-sm-offset-3.col-sm-9 |
|
75 | .col-sm-offset-3.col-sm-9 |
|
77 | = submit_tag t('login.login_submit'), class: 'btn btn-primary' |
|
76 | = submit_tag t('login.login_submit'), class: 'btn btn-primary' |
|
78 | - else |
|
77 | - else |
|
79 |
|
78 | ||
|
80 | %br/ |
|
79 | %br/ |
|
81 |
|
80 | ||
|
82 | - if GraderConfiguration['system.online_registration'] |
|
81 | - if GraderConfiguration['system.online_registration'] |
|
83 | =t 'login.participation' |
|
82 | =t 'login.participation' |
|
84 | %b |
|
83 | %b |
|
85 | = "#{t 'login.please'} " |
|
84 | = "#{t 'login.please'} " |
|
86 | = link_to "#{t 'login.register'}", :controller => :users, :action => :new |
|
85 | = link_to "#{t 'login.register'}", :controller => :users, :action => :new |
|
87 | %br/ |
|
86 | %br/ |
|
88 | = link_to "#{t 'login.forget_password'}", :controller => :users, :action => :forget |
|
87 | = link_to "#{t 'login.forget_password'}", :controller => :users, :action => :forget |
@@ -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 |
|
||
|
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 |
|
|
7 | = 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= |
|
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 |
@@ -1,91 +1,91 | |||||
|
1 | %h1 Users |
|
1 | %h1 Users |
|
2 |
|
2 | ||
|
3 | .card.border-success.mb-3 |
|
3 | .card.border-success.mb-3 |
|
4 | .card-header.text-bg-success.border-success |
|
4 | .card-header.text-bg-success.border-success |
|
5 | Quick Add |
|
5 | Quick Add |
|
6 | .card-body |
|
6 | .card-body |
|
7 | = form_with url: user_admin_index_path, scope: :user, class: 'row row-cols-lg-auto g-3 align-items-center' do |f| |
|
7 | = form_with url: user_admin_index_path, scope: :user, class: 'row row-cols-lg-auto g-3 align-items-center' do |f| |
|
8 | .col-12 |
|
8 | .col-12 |
|
9 | = f.text_field 'login', :size => 10,class: 'form-control', placeholder: 'login' |
|
9 | = f.text_field 'login', :size => 10,class: 'form-control', placeholder: 'login' |
|
10 | .form-group |
|
10 | .form-group |
|
11 | = f.text_field 'full_name', :size => 10,class: 'form-control', placeholder: 'full name' |
|
11 | = f.text_field 'full_name', :size => 10,class: 'form-control', placeholder: 'full name' |
|
12 | .form-group |
|
12 | .form-group |
|
13 | = f.password_field 'password', :size => 10,class: 'form-control', placeholder: 'password' |
|
13 | = f.password_field 'password', :size => 10,class: 'form-control', placeholder: 'password' |
|
14 | .form-group |
|
14 | .form-group |
|
15 | = f.password_field 'password_confirmation', :size => 10,class: 'form-control', placeholder: 'password confirmation' |
|
15 | = f.password_field 'password_confirmation', :size => 10,class: 'form-control', placeholder: 'password confirmation' |
|
16 | .form-group |
|
16 | .form-group |
|
17 | = f.text_field 'email', :size => 10,class: 'form-control', placeholder: 'email' |
|
17 | = f.text_field 'email', :size => 10,class: 'form-control', placeholder: 'email' |
|
18 | =submit_tag "Create", class: 'btn btn-success align-items-bottom' |
|
18 | =submit_tag "Create", class: 'btn btn-success align-items-bottom' |
|
19 |
|
19 | ||
|
20 | .card.border-success.mb-3 |
|
20 | .card.border-success.mb-3 |
|
21 | .card-header.text-bg-success.border-success |
|
21 | .card-header.text-bg-success.border-success |
|
22 | Import from site management |
|
22 | Import from site management |
|
23 | .card-body |
|
23 | .card-body |
|
24 | = form_with url: import_user_admin_index_path, :multipart => true do |f| |
|
24 | = form_with url: import_user_admin_index_path, :multipart => true do |f| |
|
25 | .row |
|
25 | .row |
|
26 | .col-auto |
|
26 | .col-auto |
|
27 | = f.label :file, 'File:', class: 'col-form-label' |
|
27 | = f.label :file, 'File:', class: 'col-form-label' |
|
28 | .col-auto |
|
28 | .col-auto |
|
29 | = f.file_field :file, class: 'form-control' |
|
29 | = f.file_field :file, class: 'form-control' |
|
30 | .col-auto |
|
30 | .col-auto |
|
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- |
|
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- |
|
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: " |
|
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: " |
|
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: " |
|
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: "utf8 |
|
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: "utf8 |
|
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: "utf8 |
|
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: "utf8 |
|
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: "utf8 |
|
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: "utf8 |
|
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: "utf8 |
|
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: "utf8 |
|
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: " |
|
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: "utf8 |
|
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: " |
|
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: "utf8 |
|
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: : |
|
160 | + create_table "problems", id: :bigint, default: nil, charset: "utf8", force: :cascade do |t| |
|
161 |
- t.string "name", limit: |
|
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: : |
|
177 | + create_table "problems_tags", id: :bigint, default: nil, charset: "latin1", force: :cascade do |t| |
|
178 |
- t.int |
|
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: "utf8 |
|
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: "utf8 |
|
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: "utf8 |
|
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: "utf8 |
|
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: "utf8 |
|
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: "utf8 |
|
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 "s |
|
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: : |
|
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: "utf8 |
|
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: "utf8 |
|
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: : |
|
284 | + t.text "input", size: :long |
|
276 |
- t.text "solution", size: : |
|
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: "utf8 |
|
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: "utf8 |
|
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: "utf8 |
|
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