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

r489:915396c14fc6 - - 23 files changed: 123 inserted, 159 deleted

@@ -1,63 +1,63
1 source 'https://rubygems.org'
1 source 'https://rubygems.org'
2
2
3 - gem 'rails', '3.2.19'
3 + gem 'rails', '3.2.21'
4
4
5 # Bundle edge Rails instead:
5 # Bundle edge Rails instead:
6 # gem 'rails', :git => 'git://github.com/rails/rails.git'
6 # gem 'rails', :git => 'git://github.com/rails/rails.git'
7
7
8 gem 'mysql2'
8 gem 'mysql2'
9
9
10 # Gems used only for assets and not required
10 # Gems used only for assets and not required
11 # in production environments by default.
11 # in production environments by default.
12 group :assets do
12 group :assets do
13 - gem 'sass-rails', '~> 3.2.3'
13 + gem 'sass-rails', '~> 3.2.6'
14 - gem 'coffee-rails', '~> 3.2.1'
14 + gem 'coffee-rails', '~> 3.2.2'
15
15
16 # See https://github.com/sstephenson/execjs#readme for more supported runtimes
16 # See https://github.com/sstephenson/execjs#readme for more supported runtimes
17 # gem 'therubyracer', :platforms => :ruby
17 # gem 'therubyracer', :platforms => :ruby
18
18
19 - gem 'uglifier', '>= 1.0.3'
19 + gem 'uglifier'
20 end
20 end
21
21
22 gem 'prototype-rails'
22 gem 'prototype-rails'
23
23
24 # To use ActiveModel has_secure_password
24 # To use ActiveModel has_secure_password
25 # gem 'bcrypt-ruby', '~> 3.0.0'
25 # gem 'bcrypt-ruby', '~> 3.0.0'
26
26
27 # To use Jbuilder templates for JSON
27 # To use Jbuilder templates for JSON
28 # gem 'jbuilder'
28 # gem 'jbuilder'
29
29
30 # Use unicorn as the app server
30 # Use unicorn as the app server
31 # gem 'unicorn'
31 # gem 'unicorn'
32
32
33 # Deploy with Capistrano
33 # Deploy with Capistrano
34 # gem 'capistrano'
34 # gem 'capistrano'
35
35
36 # To use debugger
36 # To use debugger
37 # gem 'debugger'
37 # gem 'debugger'
38 #
38 #
39
39
40 #in-place editor
40 #in-place editor
41 gem 'best_in_place', '~> 3.0.1'
41 gem 'best_in_place', '~> 3.0.1'
42
42
43 # jquery addition
43 # jquery addition
44 gem 'jquery-rails'
44 gem 'jquery-rails'
45 gem 'jquery-ui-sass-rails'
45 gem 'jquery-ui-sass-rails'
46 gem 'jquery-timepicker-addon-rails'
46 gem 'jquery-timepicker-addon-rails'
47 gem 'jquery-tablesorter'
47 gem 'jquery-tablesorter'
48
48
49 #syntax highlighter
49 #syntax highlighter
50 gem 'rouge'
50 gem 'rouge'
51
51
52 - gem "haml"
52 + gem 'haml'
53 - gem "mail"
53 + gem 'mail'
54 - gem "rdiscount"
54 + gem 'rdiscount'
55 - gem "test-unit"
55 + gem 'test-unit'
56 - gem 'will_paginate', '~> 3.0.0'
56 + gem 'will_paginate', '~> 3.0.7'
57 gem 'dynamic_form'
57 gem 'dynamic_form'
58 gem 'in_place_editing'
58 gem 'in_place_editing'
59 - gem 'verification', :git => 'git://github.com/sikachu/verification.git'
59 + gem 'verification', :git => 'https://github.com/sikachu/verification.git'
60
60
61 group :test, :development do
61 group :test, :development do
62 - gem "rspec-rails", "~> 2.0"
62 + gem 'rspec-rails', '~> 2.99.0'
63 end
63 end
@@ -1,175 +1,175
1 GIT
1 GIT
2 - remote: git://github.com/sikachu/verification.git
2 + remote: https://github.com/sikachu/verification.git
3 revision: 76eaf51b13276ecae54bd9cd115832595d2ff56d
3 revision: 76eaf51b13276ecae54bd9cd115832595d2ff56d
4 specs:
4 specs:
5 verification (1.0.3)
5 verification (1.0.3)
6 actionpack (>= 3.0.0, < 5.0)
6 actionpack (>= 3.0.0, < 5.0)
7 activesupport (>= 3.0.0, < 5.0)
7 activesupport (>= 3.0.0, < 5.0)
8
8
9 GEM
9 GEM
10 remote: https://rubygems.org/
10 remote: https://rubygems.org/
11 specs:
11 specs:
12 - actionmailer (3.2.19)
12 + actionmailer (3.2.21)
13 - actionpack (= 3.2.19)
13 + actionpack (= 3.2.21)
14 mail (~> 2.5.4)
14 mail (~> 2.5.4)
15 - actionpack (3.2.19)
15 + actionpack (3.2.21)
16 - activemodel (= 3.2.19)
16 + activemodel (= 3.2.21)
17 - activesupport (= 3.2.19)
17 + activesupport (= 3.2.21)
18 builder (~> 3.0.0)
18 builder (~> 3.0.0)
19 erubis (~> 2.7.0)
19 erubis (~> 2.7.0)
20 journey (~> 1.0.4)
20 journey (~> 1.0.4)
21 rack (~> 1.4.5)
21 rack (~> 1.4.5)
22 rack-cache (~> 1.2)
22 rack-cache (~> 1.2)
23 rack-test (~> 0.6.1)
23 rack-test (~> 0.6.1)
24 sprockets (~> 2.2.1)
24 sprockets (~> 2.2.1)
25 - activemodel (3.2.19)
25 + activemodel (3.2.21)
26 - activesupport (= 3.2.19)
26 + activesupport (= 3.2.21)
27 builder (~> 3.0.0)
27 builder (~> 3.0.0)
28 - activerecord (3.2.19)
28 + activerecord (3.2.21)
29 - activemodel (= 3.2.19)
29 + activemodel (= 3.2.21)
30 - activesupport (= 3.2.19)
30 + activesupport (= 3.2.21)
31 arel (~> 3.0.2)
31 arel (~> 3.0.2)
32 tzinfo (~> 0.3.29)
32 tzinfo (~> 0.3.29)
33 - activeresource (3.2.19)
33 + activeresource (3.2.21)
34 - activemodel (= 3.2.19)
34 + activemodel (= 3.2.21)
35 - activesupport (= 3.2.19)
35 + activesupport (= 3.2.21)
36 - activesupport (3.2.19)
36 + activesupport (3.2.21)
37 i18n (~> 0.6, >= 0.6.4)
37 i18n (~> 0.6, >= 0.6.4)
38 multi_json (~> 1.0)
38 multi_json (~> 1.0)
39 arel (3.0.3)
39 arel (3.0.3)
40 - best_in_place (3.0.2)
40 + best_in_place (3.0.3)
41 actionpack (>= 3.2)
41 actionpack (>= 3.2)
42 railties (>= 3.2)
42 railties (>= 3.2)
43 builder (3.0.4)
43 builder (3.0.4)
44 coffee-rails (3.2.2)
44 coffee-rails (3.2.2)
45 coffee-script (>= 2.2.0)
45 coffee-script (>= 2.2.0)
46 railties (~> 3.2.0)
46 railties (~> 3.2.0)
47 coffee-script (2.3.0)
47 coffee-script (2.3.0)
48 coffee-script-source
48 coffee-script-source
49 execjs
49 execjs
50 - coffee-script-source (1.7.1)
50 + coffee-script-source (1.9.0)
51 diff-lcs (1.2.5)
51 diff-lcs (1.2.5)
52 dynamic_form (1.1.4)
52 dynamic_form (1.1.4)
53 erubis (2.7.0)
53 erubis (2.7.0)
54 - execjs (2.2.1)
54 + execjs (2.3.0)
55 - haml (4.0.5)
55 + haml (4.0.6)
56 tilt
56 tilt
57 hike (1.2.3)
57 hike (1.2.3)
58 - i18n (0.6.11)
58 + i18n (0.7.0)
59 in_place_editing (1.2.0)
59 in_place_editing (1.2.0)
60 journey (1.0.4)
60 journey (1.0.4)
61 - jquery-rails (3.1.1)
61 + jquery-rails (3.1.2)
62 railties (>= 3.0, < 5.0)
62 railties (>= 3.0, < 5.0)
63 thor (>= 0.14, < 2.0)
63 thor (>= 0.14, < 2.0)
64 - jquery-tablesorter (1.12.7)
64 + jquery-tablesorter (1.13.4)
65 railties (>= 3.1, < 5)
65 railties (>= 3.1, < 5)
66 jquery-timepicker-addon-rails (1.4.1)
66 jquery-timepicker-addon-rails (1.4.1)
67 railties (>= 3.1)
67 railties (>= 3.1)
68 jquery-ui-rails (4.0.3)
68 jquery-ui-rails (4.0.3)
69 jquery-rails
69 jquery-rails
70 railties (>= 3.1.0)
70 railties (>= 3.1.0)
71 jquery-ui-sass-rails (4.0.3.0)
71 jquery-ui-sass-rails (4.0.3.0)
72 jquery-rails
72 jquery-rails
73 jquery-ui-rails (= 4.0.3)
73 jquery-ui-rails (= 4.0.3)
74 railties (>= 3.1.0)
74 railties (>= 3.1.0)
75 - json (1.8.1)
75 + json (1.8.2)
76 mail (2.5.4)
76 mail (2.5.4)
77 mime-types (~> 1.16)
77 mime-types (~> 1.16)
78 treetop (~> 1.4.8)
78 treetop (~> 1.4.8)
79 mime-types (1.25.1)
79 mime-types (1.25.1)
80 multi_json (1.10.1)
80 multi_json (1.10.1)
81 - mysql2 (0.3.16)
81 + mysql2 (0.3.17)
82 polyglot (0.3.5)
82 polyglot (0.3.5)
83 - power_assert (0.1.3)
83 + power_assert (0.2.2)
84 prototype-rails (3.2.1)
84 prototype-rails (3.2.1)
85 rails (~> 3.2)
85 rails (~> 3.2)
86 rack (1.4.5)
86 rack (1.4.5)
87 rack-cache (1.2)
87 rack-cache (1.2)
88 rack (>= 0.4)
88 rack (>= 0.4)
89 rack-ssl (1.3.4)
89 rack-ssl (1.3.4)
90 rack
90 rack
91 - rack-test (0.6.2)
91 + rack-test (0.6.3)
92 rack (>= 1.0)
92 rack (>= 1.0)
93 - rails (3.2.19)
93 + rails (3.2.21)
94 - actionmailer (= 3.2.19)
94 + actionmailer (= 3.2.21)
95 - actionpack (= 3.2.19)
95 + actionpack (= 3.2.21)
96 - activerecord (= 3.2.19)
96 + activerecord (= 3.2.21)
97 - activeresource (= 3.2.19)
97 + activeresource (= 3.2.21)
98 - activesupport (= 3.2.19)
98 + activesupport (= 3.2.21)
99 bundler (~> 1.0)
99 bundler (~> 1.0)
100 - railties (= 3.2.19)
100 + railties (= 3.2.21)
101 - railties (3.2.19)
101 + railties (3.2.21)
102 - actionpack (= 3.2.19)
102 + actionpack (= 3.2.21)
103 - activesupport (= 3.2.19)
103 + activesupport (= 3.2.21)
104 rack-ssl (~> 1.3.2)
104 rack-ssl (~> 1.3.2)
105 rake (>= 0.8.7)
105 rake (>= 0.8.7)
106 rdoc (~> 3.4)
106 rdoc (~> 3.4)
107 thor (>= 0.14.6, < 2.0)
107 thor (>= 0.14.6, < 2.0)
108 - rake (10.3.2)
108 + rake (10.4.2)
109 - rdiscount (2.1.7.1)
109 + rdiscount (2.1.8)
110 rdoc (3.12.2)
110 rdoc (3.12.2)
111 json (~> 1.4)
111 json (~> 1.4)
112 - rouge (1.6.2)
112 + rouge (1.8.0)
113 - rspec-collection_matchers (1.0.0)
113 + rspec-collection_matchers (1.1.2)
114 rspec-expectations (>= 2.99.0.beta1)
114 rspec-expectations (>= 2.99.0.beta1)
115 rspec-core (2.99.2)
115 rspec-core (2.99.2)
116 rspec-expectations (2.99.2)
116 rspec-expectations (2.99.2)
117 diff-lcs (>= 1.1.3, < 2.0)
117 diff-lcs (>= 1.1.3, < 2.0)
118 - rspec-mocks (2.99.2)
118 + rspec-mocks (2.99.3)
119 rspec-rails (2.99.0)
119 rspec-rails (2.99.0)
120 actionpack (>= 3.0)
120 actionpack (>= 3.0)
121 activemodel (>= 3.0)
121 activemodel (>= 3.0)
122 activesupport (>= 3.0)
122 activesupport (>= 3.0)
123 railties (>= 3.0)
123 railties (>= 3.0)
124 rspec-collection_matchers
124 rspec-collection_matchers
125 rspec-core (~> 2.99.0)
125 rspec-core (~> 2.99.0)
126 rspec-expectations (~> 2.99.0)
126 rspec-expectations (~> 2.99.0)
127 rspec-mocks (~> 2.99.0)
127 rspec-mocks (~> 2.99.0)
128 - sass (3.4.1)
128 + sass (3.4.11)
129 sass-rails (3.2.6)
129 sass-rails (3.2.6)
130 railties (~> 3.2.0)
130 railties (~> 3.2.0)
131 sass (>= 3.1.10)
131 sass (>= 3.1.10)
132 tilt (~> 1.3)
132 tilt (~> 1.3)
133 - sprockets (2.2.2)
133 + sprockets (2.2.3)
134 hike (~> 1.2)
134 hike (~> 1.2)
135 multi_json (~> 1.0)
135 multi_json (~> 1.0)
136 rack (~> 1.0)
136 rack (~> 1.0)
137 tilt (~> 1.1, != 1.3.0)
137 tilt (~> 1.1, != 1.3.0)
138 - test-unit (3.0.1)
138 + test-unit (3.0.9)
139 power_assert
139 power_assert
140 thor (0.19.1)
140 thor (0.19.1)
141 tilt (1.4.1)
141 tilt (1.4.1)
142 treetop (1.4.15)
142 treetop (1.4.15)
143 polyglot
143 polyglot
144 polyglot (>= 0.3.1)
144 polyglot (>= 0.3.1)
145 - tzinfo (0.3.41)
145 + tzinfo (0.3.43)
146 - uglifier (2.5.3)
146 + uglifier (2.7.0)
147 execjs (>= 0.3.0)
147 execjs (>= 0.3.0)
148 json (>= 1.8.0)
148 json (>= 1.8.0)
149 will_paginate (3.0.7)
149 will_paginate (3.0.7)
150
150
151 PLATFORMS
151 PLATFORMS
152 ruby
152 ruby
153
153
154 DEPENDENCIES
154 DEPENDENCIES
155 best_in_place (~> 3.0.1)
155 best_in_place (~> 3.0.1)
156 - coffee-rails (~> 3.2.1)
156 + coffee-rails (~> 3.2.2)
157 dynamic_form
157 dynamic_form
158 haml
158 haml
159 in_place_editing
159 in_place_editing
160 jquery-rails
160 jquery-rails
161 jquery-tablesorter
161 jquery-tablesorter
162 jquery-timepicker-addon-rails
162 jquery-timepicker-addon-rails
163 jquery-ui-sass-rails
163 jquery-ui-sass-rails
164 mail
164 mail
165 mysql2
165 mysql2
166 prototype-rails
166 prototype-rails
167 - rails (= 3.2.19)
167 + rails (= 3.2.21)
168 rdiscount
168 rdiscount
169 rouge
169 rouge
170 - rspec-rails (~> 2.0)
170 + rspec-rails (~> 2.99.0)
171 - sass-rails (~> 3.2.3)
171 + sass-rails (~> 3.2.6)
172 test-unit
172 test-unit
173 - uglifier (>= 1.0.3)
173 + uglifier
174 verification!
174 verification!
175 - will_paginate (~> 3.0.0)
175 + will_paginate (~> 3.0.7)
@@ -1,50 +1,50
1 class ContestManagementController < ApplicationController
1 class ContestManagementController < ApplicationController
2
2
3 before_filter :admin_authorization
3 before_filter :admin_authorization
4
4
5 def index
5 def index
6 @num_contests = Contest.count()
6 @num_contests = Contest.count()
7 end
7 end
8
8
9 def user_stat
9 def user_stat
10 if not GraderConfiguration.indv_contest_mode?
10 if not GraderConfiguration.indv_contest_mode?
11 redirect_to :action => 'index' and return
11 redirect_to :action => 'index' and return
12 end
12 end
13
13
14 @users = User.find(:all)
14 @users = User.find(:all)
15 @start_times = {}
15 @start_times = {}
16 UserContestStat.find(:all).each do |stat|
16 UserContestStat.find(:all).each do |stat|
17 @start_times[stat.user_id] = stat.started_at
17 @start_times[stat.user_id] = stat.started_at
18 end
18 end
19 end
19 end
20
20
21 def clear_stat
21 def clear_stat
22 user = User.find(params[:id])
22 user = User.find(params[:id])
23 if user.contest_stat!=nil
23 if user.contest_stat!=nil
24 user.contest_stat.destroy
24 user.contest_stat.destroy
25 end
25 end
26 redirect_to :action => 'user_stat'
26 redirect_to :action => 'user_stat'
27 end
27 end
28
28
29 def clear_all_stat
29 def clear_all_stat
30 if not GraderConfiguration.indv_contest_mode?
30 if not GraderConfiguration.indv_contest_mode?
31 redirect_to :action => 'index' and return
31 redirect_to :action => 'index' and return
32 end
32 end
33
33
34 UserContestStat.delete_all()
34 UserContestStat.delete_all()
35 flash[:notice] = 'All start time statistic cleared.'
35 flash[:notice] = 'All start time statistic cleared.'
36 redirect_to :action => 'index'
36 redirect_to :action => 'index'
37 end
37 end
38
38
39 def change_contest_mode
39 def change_contest_mode
40 - if ['standard', 'contest', 'indv-contest'].include? params[:id]
40 + if ['standard', 'contest', 'indv-contest', 'analysis'].include? params[:id]
41 config = GraderConfiguration.find_by_key('system.mode')
41 config = GraderConfiguration.find_by_key('system.mode')
42 config.value = params[:id]
42 config.value = params[:id]
43 config.save
43 config.save
44 else
44 else
45 flash[:notice] = 'Wrong contest mode value'
45 flash[:notice] = 'Wrong contest mode value'
46 end
46 end
47 redirect_to :action => 'index'
47 redirect_to :action => 'index'
48 end
48 end
49
49
50 end
50 end
@@ -1,293 +1,293
1 class MainController < ApplicationController
1 class MainController < ApplicationController
2
2
3 before_filter :authenticate, :except => [:index, :login]
3 before_filter :authenticate, :except => [:index, :login]
4 before_filter :check_viewability, :except => [:index, :login]
4 before_filter :check_viewability, :except => [:index, :login]
5
5
6 append_before_filter :confirm_and_update_start_time,
6 append_before_filter :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_filter :reject_announcement_refresh_when_logged_out,
13 prepend_before_filter :reject_announcement_refresh_when_logged_out,
14 :only => [:announcements]
14 :only => [:announcements]
15
15
16 # COMMENTED OUT: filter in each action instead
16 # COMMENTED OUT: filter in each action instead
17 # before_filter :verify_time_limit, :only => [:submit]
17 # before_filter :verify_time_limit, :only => [:submit]
18
18
19 verify :method => :post, :only => [:submit],
19 verify :method => :post, :only => [:submit],
20 :redirect_to => { :action => :index }
20 :redirect_to => { :action => :index }
21
21
22 # COMMENT OUT: only need when having high load
22 # COMMENT OUT: only need when having high load
23 # caches_action :index, :login
23 # caches_action :index, :login
24
24
25 # NOTE: This method is not actually needed, 'config/routes.rb' has
25 # NOTE: This method is not actually needed, 'config/routes.rb' has
26 # assigned action login as a default action.
26 # assigned action login as a default action.
27 def index
27 def index
28 redirect_to :action => 'login'
28 redirect_to :action => 'login'
29 end
29 end
30
30
31 def login
31 def login
32 saved_notice = flash[:notice]
32 saved_notice = flash[:notice]
33 reset_session
33 reset_session
34 flash.now[:notice] = saved_notice
34 flash.now[:notice] = saved_notice
35
35
36 # EXPERIMENT:
36 # EXPERIMENT:
37 # Hide login if in single user mode and the url does not
37 # Hide login if in single user mode and the url does not
38 # explicitly specify /login
38 # explicitly specify /login
39 #
39 #
40 # logger.info "PATH: #{request.path}"
40 # logger.info "PATH: #{request.path}"
41 # if GraderConfiguration['system.single_user_mode'] and
41 # if GraderConfiguration['system.single_user_mode'] and
42 # request.path!='/main/login'
42 # request.path!='/main/login'
43 # @hidelogin = true
43 # @hidelogin = true
44 # end
44 # end
45
45
46 @announcements = Announcement.find_for_frontpage
46 @announcements = Announcement.find_for_frontpage
47 render :action => 'login', :layout => 'empty'
47 render :action => 'login', :layout => 'empty'
48 end
48 end
49
49
50 def list
50 def list
51 prepare_list_information
51 prepare_list_information
52 end
52 end
53
53
54 def help
54 def help
55 @user = User.find(session[:user_id])
55 @user = User.find(session[:user_id])
56 end
56 end
57
57
58 def submit
58 def submit
59 user = User.find(session[:user_id])
59 user = User.find(session[:user_id])
60
60
61 @submission = Submission.new
61 @submission = Submission.new
62 @submission.problem_id = params[:submission][:problem_id]
62 @submission.problem_id = params[:submission][:problem_id]
63 @submission.user = user
63 @submission.user = user
64 @submission.language_id = 0
64 @submission.language_id = 0
65 if (params['file']) and (params['file']!='')
65 if (params['file']) and (params['file']!='')
66 @submission.source = File.open(params['file'].path,'r:UTF-8',&:read)
66 @submission.source = File.open(params['file'].path,'r:UTF-8',&:read)
67 @submission.source.encode!('UTF-8','UTF-8',invalid: :replace, replace: '')
67 @submission.source.encode!('UTF-8','UTF-8',invalid: :replace, replace: '')
68 @submission.source_filename = params['file'].original_filename
68 @submission.source_filename = params['file'].original_filename
69 end
69 end
70 @submission.submitted_at = Time.new.gmtime
70 @submission.submitted_at = Time.new.gmtime
71 @submission.ip_address = request.remote_ip
71 @submission.ip_address = request.remote_ip
72
72
73 if GraderConfiguration.time_limit_mode? and user.contest_finished?
73 if GraderConfiguration.time_limit_mode? and user.contest_finished?
74 - @submission.errors.add_to_base "The contest is over."
74 + @submission.errors.add(:base,"The contest is over.")
75 prepare_list_information
75 prepare_list_information
76 render :action => 'list' and return
76 render :action => 'list' and return
77 end
77 end
78
78
79 if @submission.valid?
79 if @submission.valid?
80 if @submission.save == false
80 if @submission.save == false
81 flash[:notice] = 'Error saving your submission'
81 flash[:notice] = 'Error saving your submission'
82 elsif Task.create(:submission_id => @submission.id,
82 elsif Task.create(:submission_id => @submission.id,
83 :status => Task::STATUS_INQUEUE) == false
83 :status => Task::STATUS_INQUEUE) == false
84 flash[:notice] = 'Error adding your submission to task queue'
84 flash[:notice] = 'Error adding your submission to task queue'
85 end
85 end
86 else
86 else
87 prepare_list_information
87 prepare_list_information
88 render :action => 'list' and return
88 render :action => 'list' and return
89 end
89 end
90 redirect_to :action => 'list'
90 redirect_to :action => 'list'
91 end
91 end
92
92
93 def source
93 def source
94 submission = Submission.find(params[:id])
94 submission = Submission.find(params[:id])
95 if ((submission.user_id == session[:user_id]) and
95 if ((submission.user_id == session[:user_id]) and
96 (submission.problem != nil) and
96 (submission.problem != nil) and
97 (submission.problem.available))
97 (submission.problem.available))
98 send_data(submission.source,
98 send_data(submission.source,
99 {:filename => submission.download_filename,
99 {:filename => submission.download_filename,
100 :type => 'text/plain'})
100 :type => 'text/plain'})
101 else
101 else
102 flash[:notice] = 'Error viewing source'
102 flash[:notice] = 'Error viewing source'
103 redirect_to :action => 'list'
103 redirect_to :action => 'list'
104 end
104 end
105 end
105 end
106
106
107 def compiler_msg
107 def compiler_msg
108 @submission = Submission.find(params[:id])
108 @submission = Submission.find(params[:id])
109 if @submission.user_id == session[:user_id]
109 if @submission.user_id == session[:user_id]
110 render :action => 'compiler_msg', :layout => 'empty'
110 render :action => 'compiler_msg', :layout => 'empty'
111 else
111 else
112 flash[:notice] = 'Error viewing source'
112 flash[:notice] = 'Error viewing source'
113 redirect_to :action => 'list'
113 redirect_to :action => 'list'
114 end
114 end
115 end
115 end
116
116
117 def submission
117 def submission
118 @user = User.find(session[:user_id])
118 @user = User.find(session[:user_id])
119 @problems = @user.available_problems
119 @problems = @user.available_problems
120 if params[:id]==nil
120 if params[:id]==nil
121 @problem = nil
121 @problem = nil
122 @submissions = nil
122 @submissions = nil
123 else
123 else
124 @problem = Problem.find_by_name(params[:id])
124 @problem = Problem.find_by_name(params[:id])
125 if not @problem.available
125 if not @problem.available
126 redirect_to :action => 'list'
126 redirect_to :action => 'list'
127 flash[:notice] = 'Error: submissions for that problem are not viewable.'
127 flash[:notice] = 'Error: submissions for that problem are not viewable.'
128 return
128 return
129 end
129 end
130 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
130 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
131 end
131 end
132 end
132 end
133
133
134 def result
134 def result
135 if !GraderConfiguration.show_grading_result
135 if !GraderConfiguration.show_grading_result
136 redirect_to :action => 'list' and return
136 redirect_to :action => 'list' and return
137 end
137 end
138 @user = User.find(session[:user_id])
138 @user = User.find(session[:user_id])
139 @submission = Submission.find(params[:id])
139 @submission = Submission.find(params[:id])
140 if @submission.user!=@user
140 if @submission.user!=@user
141 flash[:notice] = 'You are not allowed to view result of other users.'
141 flash[:notice] = 'You are not allowed to view result of other users.'
142 redirect_to :action => 'list' and return
142 redirect_to :action => 'list' and return
143 end
143 end
144 prepare_grading_result(@submission)
144 prepare_grading_result(@submission)
145 end
145 end
146
146
147 def load_output
147 def load_output
148 if !GraderConfiguration.show_grading_result or params[:num]==nil
148 if !GraderConfiguration.show_grading_result or params[:num]==nil
149 redirect_to :action => 'list' and return
149 redirect_to :action => 'list' and return
150 end
150 end
151 @user = User.find(session[:user_id])
151 @user = User.find(session[:user_id])
152 @submission = Submission.find(params[:id])
152 @submission = Submission.find(params[:id])
153 if @submission.user!=@user
153 if @submission.user!=@user
154 flash[:notice] = 'You are not allowed to view result of other users.'
154 flash[:notice] = 'You are not allowed to view result of other users.'
155 redirect_to :action => 'list' and return
155 redirect_to :action => 'list' and return
156 end
156 end
157 case_num = params[:num].to_i
157 case_num = params[:num].to_i
158 out_filename = output_filename(@user.login,
158 out_filename = output_filename(@user.login,
159 @submission.problem.name,
159 @submission.problem.name,
160 @submission.id,
160 @submission.id,
161 case_num)
161 case_num)
162 if !FileTest.exists?(out_filename)
162 if !FileTest.exists?(out_filename)
163 flash[:notice] = 'Output not found.'
163 flash[:notice] = 'Output not found.'
164 redirect_to :action => 'list' and return
164 redirect_to :action => 'list' and return
165 end
165 end
166
166
167 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
167 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
168 response.headers['Content-Type'] = "application/force-download"
168 response.headers['Content-Type'] = "application/force-download"
169 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
169 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
170 response.headers["X-Sendfile"] = out_filename
170 response.headers["X-Sendfile"] = out_filename
171 response.headers['Content-length'] = File.size(out_filename)
171 response.headers['Content-length'] = File.size(out_filename)
172 render :nothing => true
172 render :nothing => true
173 else
173 else
174 send_file out_filename, :stream => false, :filename => "output-#{case_num}.txt", :type => "text/plain"
174 send_file out_filename, :stream => false, :filename => "output-#{case_num}.txt", :type => "text/plain"
175 end
175 end
176 end
176 end
177
177
178 def error
178 def error
179 @user = User.find(session[:user_id])
179 @user = User.find(session[:user_id])
180 end
180 end
181
181
182 # announcement refreshing and hiding methods
182 # announcement refreshing and hiding methods
183
183
184 def announcements
184 def announcements
185 if params.has_key? 'recent'
185 if params.has_key? 'recent'
186 prepare_announcements(params[:recent])
186 prepare_announcements(params[:recent])
187 else
187 else
188 prepare_announcements
188 prepare_announcements
189 end
189 end
190 render(:partial => 'announcement',
190 render(:partial => 'announcement',
191 :collection => @announcements,
191 :collection => @announcements,
192 :locals => {:announcement_effect => true})
192 :locals => {:announcement_effect => true})
193 end
193 end
194
194
195 def confirm_contest_start
195 def confirm_contest_start
196 user = User.find(session[:user_id])
196 user = User.find(session[:user_id])
197 - if request.method == :post
197 + if request.method == 'POST'
198 user.update_start_time
198 user.update_start_time
199 redirect_to :action => 'list'
199 redirect_to :action => 'list'
200 else
200 else
201 @contests = user.contests
201 @contests = user.contests
202 @user = user
202 @user = user
203 end
203 end
204 end
204 end
205
205
206 protected
206 protected
207
207
208 def prepare_announcements(recent=nil)
208 def prepare_announcements(recent=nil)
209 if GraderConfiguration.show_tasks_to?(@user)
209 if GraderConfiguration.show_tasks_to?(@user)
210 @announcements = Announcement.find_published(true)
210 @announcements = Announcement.find_published(true)
211 else
211 else
212 @announcements = Announcement.find_published
212 @announcements = Announcement.find_published
213 end
213 end
214 if recent!=nil
214 if recent!=nil
215 recent_id = recent.to_i
215 recent_id = recent.to_i
216 @announcements = @announcements.find_all { |a| a.id > recent_id }
216 @announcements = @announcements.find_all { |a| a.id > recent_id }
217 end
217 end
218 end
218 end
219
219
220 def prepare_list_information
220 def prepare_list_information
221 @user = User.find(session[:user_id])
221 @user = User.find(session[:user_id])
222 if not GraderConfiguration.multicontests?
222 if not GraderConfiguration.multicontests?
223 @problems = @user.available_problems
223 @problems = @user.available_problems
224 else
224 else
225 @contest_problems = @user.available_problems_group_by_contests
225 @contest_problems = @user.available_problems_group_by_contests
226 @problems = @user.available_problems
226 @problems = @user.available_problems
227 end
227 end
228 @prob_submissions = {}
228 @prob_submissions = {}
229 @problems.each do |p|
229 @problems.each do |p|
230 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
230 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
231 if sub!=nil
231 if sub!=nil
232 @prob_submissions[p.id] = { :count => sub.number, :submission => sub }
232 @prob_submissions[p.id] = { :count => sub.number, :submission => sub }
233 else
233 else
234 @prob_submissions[p.id] = { :count => 0, :submission => nil }
234 @prob_submissions[p.id] = { :count => 0, :submission => nil }
235 end
235 end
236 end
236 end
237 prepare_announcements
237 prepare_announcements
238 end
238 end
239
239
240 def check_viewability
240 def check_viewability
241 @user = User.find(session[:user_id])
241 @user = User.find(session[:user_id])
242 if (!GraderConfiguration.show_tasks_to?(@user)) and
242 if (!GraderConfiguration.show_tasks_to?(@user)) and
243 ((action_name=='submission') or (action_name=='submit'))
243 ((action_name=='submission') or (action_name=='submit'))
244 redirect_to :action => 'list' and return
244 redirect_to :action => 'list' and return
245 end
245 end
246 end
246 end
247
247
248 def prepare_grading_result(submission)
248 def prepare_grading_result(submission)
249 if GraderConfiguration.task_grading_info.has_key? submission.problem.name
249 if GraderConfiguration.task_grading_info.has_key? submission.problem.name
250 grading_info = GraderConfiguration.task_grading_info[submission.problem.name]
250 grading_info = GraderConfiguration.task_grading_info[submission.problem.name]
251 else
251 else
252 # guess task info from problem.full_score
252 # guess task info from problem.full_score
253 cases = submission.problem.full_score / 10
253 cases = submission.problem.full_score / 10
254 grading_info = {
254 grading_info = {
255 'testruns' => cases,
255 'testruns' => cases,
256 'testcases' => cases
256 'testcases' => cases
257 }
257 }
258 end
258 end
259 @test_runs = []
259 @test_runs = []
260 if grading_info['testruns'].is_a? Integer
260 if grading_info['testruns'].is_a? Integer
261 trun_count = grading_info['testruns']
261 trun_count = grading_info['testruns']
262 trun_count.times do |i|
262 trun_count.times do |i|
263 @test_runs << [ read_grading_result(@user.login,
263 @test_runs << [ read_grading_result(@user.login,
264 submission.problem.name,
264 submission.problem.name,
265 submission.id,
265 submission.id,
266 i+1) ]
266 i+1) ]
267 end
267 end
268 else
268 else
269 grading_info['testruns'].keys.sort.each do |num|
269 grading_info['testruns'].keys.sort.each do |num|
270 run = []
270 run = []
271 testrun = grading_info['testruns'][num]
271 testrun = grading_info['testruns'][num]
272 testrun.each do |c|
272 testrun.each do |c|
273 run << read_grading_result(@user.login,
273 run << read_grading_result(@user.login,
274 submission.problem.name,
274 submission.problem.name,
275 submission.id,
275 submission.id,
276 c)
276 c)
277 end
277 end
278 @test_runs << run
278 @test_runs << run
279 end
279 end
280 end
280 end
281 end
281 end
282
282
283 def grading_result_dir(user_name, problem_name, submission_id, case_num)
283 def grading_result_dir(user_name, problem_name, submission_id, case_num)
284 return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
284 return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
285 end
285 end
286
286
287 def output_filename(user_name, problem_name, submission_id, case_num)
287 def output_filename(user_name, problem_name, submission_id, case_num)
288 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
288 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
289 return "#{dir}/output.txt"
289 return "#{dir}/output.txt"
290 end
290 end
291
291
292 def read_grading_result(user_name, problem_name, submission_id, case_num)
292 def read_grading_result(user_name, problem_name, submission_id, case_num)
293 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
293 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
@@ -1,85 +1,86
1 class MessagesController < ApplicationController
1 class MessagesController < ApplicationController
2
2
3 before_filter :authenticate
3 before_filter :authenticate
4
4
5 verify :method => :post, :only => ['create'],
5 verify :method => :post, :only => ['create'],
6 :redirect_to => { :action => 'list' }
6 :redirect_to => { :action => 'list' }
7
7
8 before_filter :admin_authorization, :only => ['console','show',
8 before_filter :admin_authorization, :only => ['console','show',
9 'reply','hide','list_all']
9 'reply','hide','list_all']
10
10
11 def list
11 def list
12 @user = User.find(session[:user_id])
12 @user = User.find(session[:user_id])
13 @messages = Message.find_all_sent_by_user(@user)
13 @messages = Message.find_all_sent_by_user(@user)
14 end
14 end
15
15
16 def console
16 def console
17 @user = User.find(session[:user_id])
17 @user = User.find(session[:user_id])
18 @messages = Message.find_all_system_unreplied_messages
18 @messages = Message.find_all_system_unreplied_messages
19 end
19 end
20
20
21 def show
21 def show
22 @message = Message.find(params[:id])
22 @message = Message.find(params[:id])
23 end
23 end
24
24
25 def list_all
25 def list_all
26 @user = User.find(session[:user_id])
26 @user = User.find(session[:user_id])
27 @messages = Message.where(receiver_id: nil).order(:created_at)
27 @messages = Message.where(receiver_id: nil).order(:created_at)
28 end
28 end
29
29
30 def create
30 def create
31 user = User.find(session[:user_id])
31 user = User.find(session[:user_id])
32 @message = Message.new(params[:message])
32 @message = Message.new(params[:message])
33 @message.sender = user
33 @message.sender = user
34 - if !@message.save
34 + if @message.body == '' or !@message.save
35 - render :action => 'list' and return
35 + flash[:notice] = 'An error occurred'
36 else
36 else
37 flash[:notice] = 'New message posted'
37 flash[:notice] = 'New message posted'
38 + end
38 redirect_to :action => 'list'
39 redirect_to :action => 'list'
39 end
40 end
40 - end
41
41
42 def reply
42 def reply
43 user = User.find(session[:user_id])
43 user = User.find(session[:user_id])
44 @message = Message.new(params[:r_message])
44 @message = Message.new(params[:r_message])
45 @message.sender = user
45 @message.sender = user
46 - if !@message.save
46 + if @message.body == '' or !@message.save
47 - render :action => 'show' and return
47 + flash[:notice] = 'An error occurred'
48 + redirect_to :action => 'show', :id => @message.replying_message_id
48 else
49 else
49 flash[:notice] = 'Message replied'
50 flash[:notice] = 'Message replied'
50 rep_msg = @message.replying_message
51 rep_msg = @message.replying_message
51 rep_msg.replied = true
52 rep_msg.replied = true
52 rep_msg.save
53 rep_msg.save
53 redirect_to :action => 'console'
54 redirect_to :action => 'console'
54 end
55 end
55 end
56 end
56
57
57 def hide
58 def hide
58 message = Message.find(params[:id])
59 message = Message.find(params[:id])
59 message.replied = true
60 message.replied = true
60 message.save
61 message.save
61 - flash[:notice] = 'Message hided (just marked replied)'
62 + flash[:notice] = 'Message hidden (just marked replied)'
62 redirect_to :action => 'console'
63 redirect_to :action => 'console'
63 end
64 end
64
65
65 protected
66 protected
66 def build_replying_message_hierarchy(user)
67 def build_replying_message_hierarchy(user)
67 @all_messages = {}
68 @all_messages = {}
68
69
69
70
70 # manually build replies hierarchy (to improve efficiency)
71 # manually build replies hierarchy (to improve efficiency)
71 [@messages, @replied_messages].each do |collection|
72 [@messages, @replied_messages].each do |collection|
72 collection.each do |m|
73 collection.each do |m|
73 @all_messages[m.id] = {:msg => m, :replies => []}
74 @all_messages[m.id] = {:msg => m, :replies => []}
74 end
75 end
75 end
76 end
76
77
77 @all_messages.each do |m|
78 @all_messages.each do |m|
78 rep_id = m.replying_message_id
79 rep_id = m.replying_message_id
79 if @all_messages[rep_id]!=nil
80 if @all_messages[rep_id]!=nil
80 @all_messages[rep_id][:replies] << m
81 @all_messages[rep_id][:replies] << m
81 end
82 end
82 end
83 end
83 end
84 end
84
85
85 end
86 end
@@ -1,118 +1,118
1 class TestController < ApplicationController
1 class TestController < ApplicationController
2
2
3 before_filter :authenticate, :check_viewability
3 before_filter :authenticate, :check_viewability
4
4
5 #
5 #
6 # COMMENT OUT: filter in each action instead
6 # COMMENT OUT: filter in each action instead
7 #
7 #
8 # before_filter :verify_time_limit, :only => [:submit]
8 # before_filter :verify_time_limit, :only => [:submit]
9
9
10 verify :method => :post, :only => [:submit],
10 verify :method => :post, :only => [:submit],
11 :redirect_to => { :action => :index }
11 :redirect_to => { :action => :index }
12
12
13 def index
13 def index
14 prepare_index_information
14 prepare_index_information
15 end
15 end
16
16
17 def submit
17 def submit
18 @user = User.find(session[:user_id])
18 @user = User.find(session[:user_id])
19
19
20 @submitted_test_request = TestRequest.new_from_form_params(@user,params[:test_request])
20 @submitted_test_request = TestRequest.new_from_form_params(@user,params[:test_request])
21
21
22 if ! @submitted_test_request.errors.empty?
22 if ! @submitted_test_request.errors.empty?
23 prepare_index_information
23 prepare_index_information
24 render :action => 'index' and return
24 render :action => 'index' and return
25 end
25 end
26
26
27 if GraderConfiguration.time_limit_mode?
27 if GraderConfiguration.time_limit_mode?
28 if @user.contest_finished?
28 if @user.contest_finished?
29 - @submitted_test_request.errors.add_to_base('Contest is over.')
29 + @submitted_test_request.errors.add(:base,'Contest is over.')
30 prepare_index_information
30 prepare_index_information
31 render :action => 'index' and return
31 render :action => 'index' and return
32 end
32 end
33
33
34 if !GraderConfiguration.allow_test_request(@user)
34 if !GraderConfiguration.allow_test_request(@user)
35 prepare_index_information
35 prepare_index_information
36 flash[:notice] = 'Test request is not allowed during the last 30 minutes'
36 flash[:notice] = 'Test request is not allowed during the last 30 minutes'
37 redirect_to :action => 'index' and return
37 redirect_to :action => 'index' and return
38 end
38 end
39 end
39 end
40
40
41 if @submitted_test_request.save
41 if @submitted_test_request.save
42 redirect_to :action => 'index'
42 redirect_to :action => 'index'
43 else
43 else
44 prepare_index_information
44 prepare_index_information
45 render :action => 'index'
45 render :action => 'index'
46 end
46 end
47 end
47 end
48
48
49 def read
49 def read
50 user = User.find(session[:user_id])
50 user = User.find(session[:user_id])
51 begin
51 begin
52 test_request = TestRequest.find(params[:id])
52 test_request = TestRequest.find(params[:id])
53 rescue
53 rescue
54 test_request = nil
54 test_request = nil
55 end
55 end
56 if test_request==nil or test_request.user_id != user.id
56 if test_request==nil or test_request.user_id != user.id
57 flash[:notice] = 'Invalid output'
57 flash[:notice] = 'Invalid output'
58 redirect_to :action => 'index'
58 redirect_to :action => 'index'
59 return
59 return
60 end
60 end
61 if test_request.output_file_name!=nil
61 if test_request.output_file_name!=nil
62 data = File.open(test_request.output_file_name).read(2048)
62 data = File.open(test_request.output_file_name).read(2048)
63 if data==nil
63 if data==nil
64 data=""
64 data=""
65 end
65 end
66 send_data(data,
66 send_data(data,
67 {:filename => 'output.txt',
67 {:filename => 'output.txt',
68 :type => 'text/plain'})
68 :type => 'text/plain'})
69 return
69 return
70 end
70 end
71 redirect_to :action => 'index'
71 redirect_to :action => 'index'
72 end
72 end
73
73
74 def result
74 def result
75 @user = User.find(session[:user_id])
75 @user = User.find(session[:user_id])
76 begin
76 begin
77 @test_request = TestRequest.find(params[:id])
77 @test_request = TestRequest.find(params[:id])
78 rescue
78 rescue
79 @test_request = nil
79 @test_request = nil
80 end
80 end
81 if @test_request==nil or @test_request.user_id != @user.id
81 if @test_request==nil or @test_request.user_id != @user.id
82 flash[:notice] = 'Invalid request'
82 flash[:notice] = 'Invalid request'
83 redirect_to :action => 'index'
83 redirect_to :action => 'index'
84 return
84 return
85 end
85 end
86 end
86 end
87
87
88 protected
88 protected
89
89
90 def prepare_index_information
90 def prepare_index_information
91 @user = User.find(session[:user_id])
91 @user = User.find(session[:user_id])
92 @submissions = Submission.find_last_for_all_available_problems(@user.id)
92 @submissions = Submission.find_last_for_all_available_problems(@user.id)
93 all_problems = @submissions.collect { |submission| submission.problem }
93 all_problems = @submissions.collect { |submission| submission.problem }
94 @problems = []
94 @problems = []
95 all_problems.each do |problem|
95 all_problems.each do |problem|
96 if problem.test_allowed
96 if problem.test_allowed
97 @problems << problem
97 @problems << problem
98 end
98 end
99 end
99 end
100 @test_requests = []
100 @test_requests = []
101 @user.test_requests.each do |ts|
101 @user.test_requests.each do |ts|
102 if ts.problem and ts.problem.available
102 if ts.problem and ts.problem.available
103 @test_requests << ts
103 @test_requests << ts
104 end
104 end
105 end
105 end
106 end
106 end
107
107
108 def check_viewability
108 def check_viewability
109 user = User.find(session[:user_id])
109 user = User.find(session[:user_id])
110 if !GraderConfiguration.show_tasks_to?(user)
110 if !GraderConfiguration.show_tasks_to?(user)
111 redirect_to :controller => 'main', :action => 'list'
111 redirect_to :controller => 'main', :action => 'list'
112 end
112 end
113 if (!GraderConfiguration.show_submitbox_to?(user)) and (action_name=='submit')
113 if (!GraderConfiguration.show_submitbox_to?(user)) and (action_name=='submit')
114 redirect_to :controller => 'test', :action => 'index'
114 redirect_to :controller => 'test', :action => 'index'
115 end
115 end
116 end
116 end
117
117
118 end
118 end
@@ -1,256 +1,248
1 require 'csv'
1 require 'csv'
2
2
3 class UserAdminController < ApplicationController
3 class UserAdminController < ApplicationController
4
4
5 -
6 include MailHelperMethods
5 include MailHelperMethods
7
6
8 before_filter :admin_authorization
7 before_filter :admin_authorization
9
8
10 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
9 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
11 verify :method => :post, :only => [ :destroy,
10 verify :method => :post, :only => [ :destroy,
12 :create, :create_from_list,
11 :create, :create_from_list,
13 :update,
12 :update,
14 :manage_contest,
13 :manage_contest,
15 :bulk_mail
14 :bulk_mail
16 ],
15 ],
17 :redirect_to => { :action => :list }
16 :redirect_to => { :action => :list }
18
17
19 def index
18 def index
20 list
19 list
21 render :action => 'list'
20 render :action => 'list'
22 end
21 end
23
22
24 def list
23 def list
25 @user_count = User.count
24 @user_count = User.count
26 if params[:page] == 'all'
25 if params[:page] == 'all'
27 @users = User.all
26 @users = User.all
28 @paginated = false
27 @paginated = false
29 else
28 else
30 @users = User.paginate :page => params[:page]
29 @users = User.paginate :page => params[:page]
31 @paginated = true
30 @paginated = true
32 end
31 end
33 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
32 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
34 @contests = Contest.enabled
33 @contests = Contest.enabled
35 end
34 end
36
35
37 def active
36 def active
38 sessions = ActiveRecord::SessionStore::Session.find(:all, :conditions => ["updated_at >= ?", 60.minutes.ago])
37 sessions = ActiveRecord::SessionStore::Session.find(:all, :conditions => ["updated_at >= ?", 60.minutes.ago])
39 @users = []
38 @users = []
40 sessions.each do |session|
39 sessions.each do |session|
41 if session.data[:user_id]
40 if session.data[:user_id]
42 @users << User.find(session.data[:user_id])
41 @users << User.find(session.data[:user_id])
43 end
42 end
44 end
43 end
45 end
44 end
46
45
47 def show
46 def show
48 @user = User.find(params[:id])
47 @user = User.find(params[:id])
49 end
48 end
50
49
51 def new
50 def new
52 @user = User.new
51 @user = User.new
53 end
52 end
54
53
55 def create
54 def create
56 @user = User.new(params[:user])
55 @user = User.new(params[:user])
57 @user.activated = true
56 @user.activated = true
58 if @user.save
57 if @user.save
59 flash[:notice] = 'User was successfully created.'
58 flash[:notice] = 'User was successfully created.'
60 redirect_to :action => 'list'
59 redirect_to :action => 'list'
61 else
60 else
62 render :action => 'new'
61 render :action => 'new'
63 end
62 end
64 end
63 end
65
64
66 def create_from_list
65 def create_from_list
67 lines = params[:user_list]
66 lines = params[:user_list]
68
67
69 note = []
68 note = []
70
69
71 lines.split("\n").each do |line|
70 lines.split("\n").each do |line|
72 items = line.chomp.split(',')
71 items = line.chomp.split(',')
73 if items.length>=2
72 if items.length>=2
74 login = items[0]
73 login = items[0]
75 full_name = items[1]
74 full_name = items[1]
76
75
77 added_random_password = false
76 added_random_password = false
78 if items.length>=3
77 if items.length>=3
79 password = items[2].chomp(" ")
78 password = items[2].chomp(" ")
80 user_alias = (items.length>=4) ? items[3] : login
79 user_alias = (items.length>=4) ? items[3] : login
81 else
80 else
82 password = random_password
81 password = random_password
83 user_alias = (items.length>=4) ? items[3] : login
82 user_alias = (items.length>=4) ? items[3] : login
84 added_random_password = true
83 added_random_password = true
85 end
84 end
86
85
87 user = User.find_by_login(login)
86 user = User.find_by_login(login)
88 if (user)
87 if (user)
89 user.full_name = full_name
88 user.full_name = full_name
90 user.password = password
89 user.password = password
91 else
90 else
92 user = User.new({:login => login,
91 user = User.new({:login => login,
93 :full_name => full_name,
92 :full_name => full_name,
94 :password => password,
93 :password => password,
95 :password_confirmation => password,
94 :password_confirmation => password,
96 :alias => user_alias})
95 :alias => user_alias})
97 end
96 end
98 user.activated = true
97 user.activated = true
99 user.save
98 user.save
100
99
101 if added_random_password
100 if added_random_password
102 note << "'#{login}' (+)"
101 note << "'#{login}' (+)"
103 else
102 else
104 note << login
103 note << login
105 end
104 end
106 end
105 end
107 end
106 end
108 flash[:notice] = 'User(s) ' + note.join(', ') +
107 flash[:notice] = 'User(s) ' + note.join(', ') +
109 ' were successfully created. ' +
108 ' were successfully created. ' +
110 '( (+) - created with random passwords.)'
109 '( (+) - created with random passwords.)'
111 redirect_to :action => 'list'
110 redirect_to :action => 'list'
112 end
111 end
113
112
114 def edit
113 def edit
115 @user = User.find(params[:id])
114 @user = User.find(params[:id])
116 end
115 end
117
116
118 def update
117 def update
119 @user = User.find(params[:id])
118 @user = User.find(params[:id])
120 if @user.update_attributes(params[:user])
119 if @user.update_attributes(params[:user])
121 flash[:notice] = 'User was successfully updated.'
120 flash[:notice] = 'User was successfully updated.'
122 redirect_to :action => 'show', :id => @user
121 redirect_to :action => 'show', :id => @user
123 else
122 else
124 render :action => 'edit'
123 render :action => 'edit'
125 end
124 end
126 end
125 end
127
126
128 def destroy
127 def destroy
129 User.find(params[:id]).destroy
128 User.find(params[:id]).destroy
130 redirect_to :action => 'list'
129 redirect_to :action => 'list'
131 end
130 end
132
131
133 def user_stat
132 def user_stat
134 if params[:commit] == 'download csv'
133 if params[:commit] == 'download csv'
135 @problems = Problem.all
134 @problems = Problem.all
136 else
135 else
137 @problems = Problem.find_available_problems
136 @problems = Problem.find_available_problems
138 end
137 end
139 @users = User.find(:all, :include => [:contests, :contest_stat])
138 @users = User.find(:all, :include => [:contests, :contest_stat])
140 @scorearray = Array.new
139 @scorearray = Array.new
141 @users.each do |u|
140 @users.each do |u|
142 ustat = Array.new
141 ustat = Array.new
143 ustat[0] = u
142 ustat[0] = u
144 @problems.each do |p|
143 @problems.each do |p|
145 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
144 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
146 if (sub!=nil) and (sub.points!=nil)
145 if (sub!=nil) and (sub.points!=nil)
147 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
146 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
148 else
147 else
149 ustat << [0,false]
148 ustat << [0,false]
150 end
149 end
151 end
150 end
152 @scorearray << ustat
151 @scorearray << ustat
153 end
152 end
154 -
155 - if params[:commit] == 'download csv' then
156 - csv = gen_csv_from_scorearray(@scorearray,@problems)
157 - send_data csv, filename: 'last_score.csv'
158 - else
159 - render template: 'user_admin/user_stat'
160 - end
161 end
153 end
162
154
163 def user_stat_max
155 def user_stat_max
164 if params[:commit] == 'download csv'
156 if params[:commit] == 'download csv'
165 @problems = Problem.all
157 @problems = Problem.all
166 else
158 else
167 @problems = Problem.find_available_problems
159 @problems = Problem.find_available_problems
168 end
160 end
169 @users = User.find(:all, :include => [:contests, :contest_stat])
161 @users = User.find(:all, :include => [:contests, :contest_stat])
170 @scorearray = Array.new
162 @scorearray = Array.new
171 #set up range from param
163 #set up range from param
172 since_id = params.fetch(:since_id, 0).to_i
164 since_id = params.fetch(:since_id, 0).to_i
173 until_id = params.fetch(:until_id, 0).to_i
165 until_id = params.fetch(:until_id, 0).to_i
174 @users.each do |u|
166 @users.each do |u|
175 ustat = Array.new
167 ustat = Array.new
176 ustat[0] = u
168 ustat[0] = u
177 @problems.each do |p|
169 @problems.each do |p|
178 max_points = 0
170 max_points = 0
179 Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub|
171 Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub|
180 max_points = sub.points if sub and sub.points and (sub.points > max_points)
172 max_points = sub.points if sub and sub.points and (sub.points > max_points)
181 end
173 end
182 ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)]
174 ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)]
183 end
175 end
184 @scorearray << ustat
176 @scorearray << ustat
185 end
177 end
186
178
187 if params[:commit] == 'download csv' then
179 if params[:commit] == 'download csv' then
188 csv = gen_csv_from_scorearray(@scorearray,@problems)
180 csv = gen_csv_from_scorearray(@scorearray,@problems)
189 send_data csv, filename: 'max_score.csv'
181 send_data csv, filename: 'max_score.csv'
190 else
182 else
191 render template: 'user_admin/user_stat'
183 render template: 'user_admin/user_stat'
192 end
184 end
193 end
185 end
194
186
195 def import
187 def import
196 if params[:file]==''
188 if params[:file]==''
197 flash[:notice] = 'Error importing no file'
189 flash[:notice] = 'Error importing no file'
198 redirect_to :action => 'list' and return
190 redirect_to :action => 'list' and return
199 end
191 end
200 import_from_file(params[:file])
192 import_from_file(params[:file])
201 end
193 end
202
194
203 def random_all_passwords
195 def random_all_passwords
204 users = User.find(:all)
196 users = User.find(:all)
205 @prefix = params[:prefix] || ''
197 @prefix = params[:prefix] || ''
206 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
198 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
207 @changed = false
199 @changed = false
208 if request.request_method == 'POST'
200 if request.request_method == 'POST'
209 @non_admin_users.each do |user|
201 @non_admin_users.each do |user|
210 password = random_password
202 password = random_password
211 user.password = password
203 user.password = password
212 user.password_confirmation = password
204 user.password_confirmation = password
213 user.save
205 user.save
214 end
206 end
215 @changed = true
207 @changed = true
216 end
208 end
217 end
209 end
218
210
219 # contest management
211 # contest management
220
212
221 def contests
213 def contests
222 @contest, @users = find_contest_and_user_from_contest_id(params[:id])
214 @contest, @users = find_contest_and_user_from_contest_id(params[:id])
223 @contests = Contest.enabled
215 @contests = Contest.enabled
224 end
216 end
225
217
226 def assign_from_list
218 def assign_from_list
227 contest_id = params[:users_contest_id]
219 contest_id = params[:users_contest_id]
228 org_contest, users = find_contest_and_user_from_contest_id(contest_id)
220 org_contest, users = find_contest_and_user_from_contest_id(contest_id)
229 contest = Contest.find(params[:new_contest][:id])
221 contest = Contest.find(params[:new_contest][:id])
230 if !contest
222 if !contest
231 flash[:notice] = 'Error: no contest'
223 flash[:notice] = 'Error: no contest'
232 redirect_to :action => 'contests', :id =>contest_id
224 redirect_to :action => 'contests', :id =>contest_id
233 end
225 end
234
226
235 note = []
227 note = []
236 users.each do |u|
228 users.each do |u|
237 u.contests = [contest]
229 u.contests = [contest]
238 note << u.login
230 note << u.login
239 end
231 end
240 flash[:notice] = 'User(s) ' + note.join(', ') +
232 flash[:notice] = 'User(s) ' + note.join(', ') +
241 " were successfully reassigned to #{contest.title}."
233 " were successfully reassigned to #{contest.title}."
242 redirect_to :action => 'contests', :id =>contest.id
234 redirect_to :action => 'contests', :id =>contest.id
243 end
235 end
244
236
245 def add_to_contest
237 def add_to_contest
246 user = User.find(params[:id])
238 user = User.find(params[:id])
247 contest = Contest.find(params[:contest_id])
239 contest = Contest.find(params[:contest_id])
248 if user and contest
240 if user and contest
249 user.contests << contest
241 user.contests << contest
250 end
242 end
251 redirect_to :action => 'list'
243 redirect_to :action => 'list'
252 end
244 end
253
245
254 def remove_from_contest
246 def remove_from_contest
255 user = User.find(params[:id])
247 user = User.find(params[:id])
256 contest = Contest.find(params[:contest_id])
248 contest = Contest.find(params[:contest_id])
@@ -1,195 +1,195
1 require 'net/smtp'
1 require 'net/smtp'
2
2
3 class UsersController < ApplicationController
3 class UsersController < ApplicationController
4
4
5 include MailHelperMethods
5 include MailHelperMethods
6
6
7 before_filter :authenticate, :except => [:new,
7 before_filter :authenticate, :except => [:new,
8 :register,
8 :register,
9 :confirm,
9 :confirm,
10 :forget,
10 :forget,
11 :retrieve_password]
11 :retrieve_password]
12
12
13 before_filter :verify_online_registration, :only => [:new,
13 before_filter :verify_online_registration, :only => [:new,
14 :register,
14 :register,
15 :forget,
15 :forget,
16 :retrieve_password]
16 :retrieve_password]
17 before_filter :authenticate, :profile_authorization, only: [:profile]
17 before_filter :authenticate, :profile_authorization, only: [:profile]
18
18
19 verify :method => :post, :only => [:chg_passwd],
19 verify :method => :post, :only => [:chg_passwd],
20 :redirect_to => { :action => :index }
20 :redirect_to => { :action => :index }
21
21
22 #in_place_edit_for :user, :alias_for_editing
22 #in_place_edit_for :user, :alias_for_editing
23 #in_place_edit_for :user, :email_for_editing
23 #in_place_edit_for :user, :email_for_editing
24
24
25 def index
25 def index
26 if !GraderConfiguration['system.user_setting_enabled']
26 if !GraderConfiguration['system.user_setting_enabled']
27 redirect_to :controller => 'main', :action => 'list'
27 redirect_to :controller => 'main', :action => 'list'
28 else
28 else
29 @user = User.find(session[:user_id])
29 @user = User.find(session[:user_id])
30 end
30 end
31 end
31 end
32
32
33 def chg_passwd
33 def chg_passwd
34 user = User.find(session[:user_id])
34 user = User.find(session[:user_id])
35 user.password = params[:passwd]
35 user.password = params[:passwd]
36 user.password_confirmation = params[:passwd_verify]
36 user.password_confirmation = params[:passwd_verify]
37 if user.save
37 if user.save
38 flash[:notice] = 'password changed'
38 flash[:notice] = 'password changed'
39 else
39 else
40 flash[:notice] = 'Error: password changing failed'
40 flash[:notice] = 'Error: password changing failed'
41 end
41 end
42 redirect_to :action => 'index'
42 redirect_to :action => 'index'
43 end
43 end
44
44
45 def new
45 def new
46 @user = User.new
46 @user = User.new
47 render :action => 'new', :layout => 'empty'
47 render :action => 'new', :layout => 'empty'
48 end
48 end
49
49
50 def register
50 def register
51 if(params[:cancel])
51 if(params[:cancel])
52 redirect_to :controller => 'main', :action => 'login'
52 redirect_to :controller => 'main', :action => 'login'
53 return
53 return
54 end
54 end
55 @user = User.new(params[:user])
55 @user = User.new(params[:user])
56 @user.password_confirmation = @user.password = User.random_password
56 @user.password_confirmation = @user.password = User.random_password
57 @user.activated = false
57 @user.activated = false
58 if (@user.valid?) and (@user.save)
58 if (@user.valid?) and (@user.save)
59 if send_confirmation_email(@user)
59 if send_confirmation_email(@user)
60 render :action => 'new_splash', :layout => 'empty'
60 render :action => 'new_splash', :layout => 'empty'
61 else
61 else
62 @admin_email = GraderConfiguration['system.admin_email']
62 @admin_email = GraderConfiguration['system.admin_email']
63 render :action => 'email_error', :layout => 'empty'
63 render :action => 'email_error', :layout => 'empty'
64 end
64 end
65 else
65 else
66 - @user.errors.add_to_base("Email cannot be blank") if @user.email==''
66 + @user.errors.add(:base,"Email cannot be blank") if @user.email==''
67 render :action => 'new', :layout => 'empty'
67 render :action => 'new', :layout => 'empty'
68 end
68 end
69 end
69 end
70
70
71 def confirm
71 def confirm
72 login = params[:login]
72 login = params[:login]
73 key = params[:activation]
73 key = params[:activation]
74 @user = User.find_by_login(login)
74 @user = User.find_by_login(login)
75 if (@user) and (@user.verify_activation_key(key))
75 if (@user) and (@user.verify_activation_key(key))
76 if @user.valid? # check uniquenss of email
76 if @user.valid? # check uniquenss of email
77 @user.activated = true
77 @user.activated = true
78 @user.save
78 @user.save
79 @result = :successful
79 @result = :successful
80 else
80 else
81 @result = :email_used
81 @result = :email_used
82 end
82 end
83 else
83 else
84 @result = :failed
84 @result = :failed
85 end
85 end
86 render :action => 'confirm', :layout => 'empty'
86 render :action => 'confirm', :layout => 'empty'
87 end
87 end
88
88
89 def forget
89 def forget
90 render :action => 'forget', :layout => 'empty'
90 render :action => 'forget', :layout => 'empty'
91 end
91 end
92
92
93 def retrieve_password
93 def retrieve_password
94 email = params[:email]
94 email = params[:email]
95 user = User.find_by_email(email)
95 user = User.find_by_email(email)
96 if user
96 if user
97 last_updated_time = user.updated_at || user.created_at || (Time.now.gmtime - 1.hour)
97 last_updated_time = user.updated_at || user.created_at || (Time.now.gmtime - 1.hour)
98 if last_updated_time > Time.now.gmtime - 5.minutes
98 if last_updated_time > Time.now.gmtime - 5.minutes
99 flash[:notice] = 'The account has recently created or new password has recently been requested. Please wait for 5 minutes'
99 flash[:notice] = 'The account has recently created or new password has recently been requested. Please wait for 5 minutes'
100 else
100 else
101 user.password = user.password_confirmation = User.random_password
101 user.password = user.password_confirmation = User.random_password
102 user.save
102 user.save
103 send_new_password_email(user)
103 send_new_password_email(user)
104 flash[:notice] = 'New password has been mailed to you.'
104 flash[:notice] = 'New password has been mailed to you.'
105 end
105 end
106 else
106 else
107 flash[:notice] = I18n.t 'registration.password_retrieval.no_email'
107 flash[:notice] = I18n.t 'registration.password_retrieval.no_email'
108 end
108 end
109 redirect_to :action => 'forget'
109 redirect_to :action => 'forget'
110 end
110 end
111
111
112 def profile
112 def profile
113 @user = User.find(params[:id])
113 @user = User.find(params[:id])
114 @submission = Submission.includes(:problem).where(user_id: params[:id])
114 @submission = Submission.includes(:problem).where(user_id: params[:id])
115
115
116 range = 120
116 range = 120
117 @histogram = { data: Array.new(range,0), summary: {} }
117 @histogram = { data: Array.new(range,0), summary: {} }
118 @summary = {count: 0, solve: 0, attempt: 0}
118 @summary = {count: 0, solve: 0, attempt: 0}
119 problem = Hash.new(0)
119 problem = Hash.new(0)
120
120
121 @submission.find_each do |sub|
121 @submission.find_each do |sub|
122 #histogram
122 #histogram
123 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
123 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
124 @histogram[:data][d.to_i] += 1 if d < range
124 @histogram[:data][d.to_i] += 1 if d < range
125
125
126 @summary[:count] += 1
126 @summary[:count] += 1
127 next unless sub.problem
127 next unless sub.problem
128 problem[sub.problem] = [problem[sub.problem], (sub.points >= sub.problem.full_score) ? 1 : 0].max
128 problem[sub.problem] = [problem[sub.problem], (sub.points >= sub.problem.full_score) ? 1 : 0].max
129 end
129 end
130
130
131 @histogram[:summary][:max] = [@histogram[:data].max,1].max
131 @histogram[:summary][:max] = [@histogram[:data].max,1].max
132 @summary[:attempt] = problem.count
132 @summary[:attempt] = problem.count
133 problem.each_value { |v| @summary[:solve] += 1 if v == 1 }
133 problem.each_value { |v| @summary[:solve] += 1 if v == 1 }
134 end
134 end
135
135
136 protected
136 protected
137
137
138 def verify_online_registration
138 def verify_online_registration
139 if !GraderConfiguration['system.online_registration']
139 if !GraderConfiguration['system.online_registration']
140 redirect_to :controller => 'main', :action => 'login'
140 redirect_to :controller => 'main', :action => 'login'
141 end
141 end
142 end
142 end
143
143
144 def send_confirmation_email(user)
144 def send_confirmation_email(user)
145 contest_name = GraderConfiguration['contest.name']
145 contest_name = GraderConfiguration['contest.name']
146 activation_url = url_for(:action => 'confirm',
146 activation_url = url_for(:action => 'confirm',
147 :login => user.login,
147 :login => user.login,
148 :activation => user.activation_key)
148 :activation => user.activation_key)
149 home_url = url_for(:controller => 'main', :action => 'index')
149 home_url = url_for(:controller => 'main', :action => 'index')
150 mail_subject = "[#{contest_name}] Confirmation"
150 mail_subject = "[#{contest_name}] Confirmation"
151 mail_body = t('registration.email_body', {
151 mail_body = t('registration.email_body', {
152 :full_name => user.full_name,
152 :full_name => user.full_name,
153 :contest_name => contest_name,
153 :contest_name => contest_name,
154 :login => user.login,
154 :login => user.login,
155 :password => user.password,
155 :password => user.password,
156 :activation_url => activation_url,
156 :activation_url => activation_url,
157 - :admin_email => admin_email
157 + :admin_email => GraderConfiguration['system.admin_email']
158 })
158 })
159
159
160 logger.info mail_body
160 logger.info mail_body
161
161
162 send_mail(user.email, mail_subject, mail_body)
162 send_mail(user.email, mail_subject, mail_body)
163 end
163 end
164
164
165 def send_new_password_email(user)
165 def send_new_password_email(user)
166 contest_name = GraderConfiguration['contest.name']
166 contest_name = GraderConfiguration['contest.name']
167 mail_subject = "[#{contest_name}] Password recovery"
167 mail_subject = "[#{contest_name}] Password recovery"
168 mail_body = t('registration.password_retrieval.email_body', {
168 mail_body = t('registration.password_retrieval.email_body', {
169 :full_name => user.full_name,
169 :full_name => user.full_name,
170 :contest_name => contest_name,
170 :contest_name => contest_name,
171 :login => user.login,
171 :login => user.login,
172 :password => user.password,
172 :password => user.password,
173 - :admin_email => admin_email
173 + :admin_email => GraderConfiguration['system.admin_email']
174 })
174 })
175
175
176 logger.info mail_body
176 logger.info mail_body
177
177
178 send_mail(user.email, mail_subject, mail_body)
178 send_mail(user.email, mail_subject, mail_body)
179 end
179 end
180
180
181 # allow viewing of regular user profile only when options allow so
181 # allow viewing of regular user profile only when options allow so
182 # only admins can view admins profile
182 # only admins can view admins profile
183 def profile_authorization
183 def profile_authorization
184 #if view admins' profile, allow only admin
184 #if view admins' profile, allow only admin
185 return false unless(params[:id])
185 return false unless(params[:id])
186 user = User.find(params[:id])
186 user = User.find(params[:id])
187 return false unless user
187 return false unless user
188 return admin_authorization if user.admin?
188 return admin_authorization if user.admin?
189 return true if GraderConfiguration["right.user_view_submission"]
189 return true if GraderConfiguration["right.user_view_submission"]
190
190
191 #finally, we allow only admin
191 #finally, we allow only admin
192 admin_authorization
192 admin_authorization
193 end
193 end
194
194
195 end
195 end
@@ -25,114 +25,114
25 append_to menu_items, "[#{I18n.t 'menu.main'}]", 'main', 'list'
25 append_to menu_items, "[#{I18n.t 'menu.main'}]", 'main', 'list'
26 append_to menu_items, "[#{I18n.t 'menu.messages'}]", 'messages', 'list'
26 append_to menu_items, "[#{I18n.t 'menu.messages'}]", 'messages', 'list'
27
27
28 if (user!=nil) and (GraderConfiguration.show_tasks_to?(user))
28 if (user!=nil) and (GraderConfiguration.show_tasks_to?(user))
29 append_to menu_items, "[#{I18n.t 'menu.tasks'}]", 'tasks', 'list'
29 append_to menu_items, "[#{I18n.t 'menu.tasks'}]", 'tasks', 'list'
30 append_to menu_items, "[#{I18n.t 'menu.submissions'}]", 'main', 'submission'
30 append_to menu_items, "[#{I18n.t 'menu.submissions'}]", 'main', 'submission'
31 append_to menu_items, "[#{I18n.t 'menu.test'}]", 'test', 'index'
31 append_to menu_items, "[#{I18n.t 'menu.test'}]", 'test', 'index'
32 end
32 end
33
33
34 if GraderConfiguration['right.user_hall_of_fame']
34 if GraderConfiguration['right.user_hall_of_fame']
35 append_to menu_items, "[#{I18n.t 'menu.hall_of_fame'}]", 'report', 'problem_hof'
35 append_to menu_items, "[#{I18n.t 'menu.hall_of_fame'}]", 'report', 'problem_hof'
36 end
36 end
37 append_to menu_items, "[#{I18n.t 'menu.help'}]", 'main', 'help'
37 append_to menu_items, "[#{I18n.t 'menu.help'}]", 'main', 'help'
38
38
39 if GraderConfiguration['system.user_setting_enabled']
39 if GraderConfiguration['system.user_setting_enabled']
40 append_to menu_items, "[#{I18n.t 'menu.settings'}]", 'users', 'index'
40 append_to menu_items, "[#{I18n.t 'menu.settings'}]", 'users', 'index'
41 end
41 end
42 append_to menu_items, "[#{I18n.t 'menu.log_out'}]", 'main', 'login'
42 append_to menu_items, "[#{I18n.t 'menu.log_out'}]", 'main', 'login'
43
43
44 menu_items.html_safe
44 menu_items.html_safe
45 end
45 end
46
46
47 def append_to(option,label, controller, action)
47 def append_to(option,label, controller, action)
48 option << ' ' if option!=''
48 option << ' ' if option!=''
49 option << link_to_unless_current(label,
49 option << link_to_unless_current(label,
50 :controller => controller,
50 :controller => controller,
51 :action => action)
51 :action => action)
52 end
52 end
53
53
54 def format_short_time(time)
54 def format_short_time(time)
55 now = Time.now.gmtime
55 now = Time.now.gmtime
56 st = ''
56 st = ''
57 if (time.yday != now.yday) or
57 if (time.yday != now.yday) or
58 (time.year != now.year)
58 (time.year != now.year)
59 st = time.strftime("%x ")
59 st = time.strftime("%x ")
60 end
60 end
61 st + time.strftime("%X")
61 st + time.strftime("%X")
62 end
62 end
63
63
64 def format_short_duration(duration)
64 def format_short_duration(duration)
65 return '' if duration==nil
65 return '' if duration==nil
66 d = duration.to_f
66 d = duration.to_f
67 return Time.at(d).gmtime.strftime("%X")
67 return Time.at(d).gmtime.strftime("%X")
68 end
68 end
69
69
70 def read_textfile(fname,max_size=2048)
70 def read_textfile(fname,max_size=2048)
71 begin
71 begin
72 File.open(fname).read(max_size)
72 File.open(fname).read(max_size)
73 rescue
73 rescue
74 nil
74 nil
75 end
75 end
76 end
76 end
77
77
78 def user_title_bar(user)
78 def user_title_bar(user)
79 header = ''
79 header = ''
80 time_left = ''
80 time_left = ''
81
81
82 #
82 #
83 # if the contest is over
83 # if the contest is over
84 if GraderConfiguration.time_limit_mode?
84 if GraderConfiguration.time_limit_mode?
85 if user.contest_finished?
85 if user.contest_finished?
86 header = <<CONTEST_OVER
86 header = <<CONTEST_OVER
87 <tr><td colspan="2" align="center">
87 <tr><td colspan="2" align="center">
88 <span class="contest-over-msg">THE CONTEST IS OVER</span>
88 <span class="contest-over-msg">THE CONTEST IS OVER</span>
89 </td></tr>
89 </td></tr>
90 CONTEST_OVER
90 CONTEST_OVER
91 end
91 end
92 if !user.contest_started?
92 if !user.contest_started?
93 time_left = "&nbsp;&nbsp;" + (t 'title_bar.contest_not_started')
93 time_left = "&nbsp;&nbsp;" + (t 'title_bar.contest_not_started')
94 else
94 else
95 time_left = "&nbsp;&nbsp;" + (t 'title_bar.remaining_time') +
95 time_left = "&nbsp;&nbsp;" + (t 'title_bar.remaining_time') +
96 " #{format_short_duration(user.contest_time_left)}"
96 " #{format_short_duration(user.contest_time_left)}"
97 end
97 end
98 end
98 end
99
99
100 #
100 #
101 # if the contest is in the anaysis mode
101 # if the contest is in the anaysis mode
102 if GraderConfiguration.analysis_mode?
102 if GraderConfiguration.analysis_mode?
103 header = <<ANALYSISMODE
103 header = <<ANALYSISMODE
104 <tr><td colspan="2" align="center">
104 <tr><td colspan="2" align="center">
105 <span class="contest-over-msg">ANALYSIS MODE</span>
105 <span class="contest-over-msg">ANALYSIS MODE</span>
106 </td></tr>
106 </td></tr>
107 ANALYSISMODE
107 ANALYSISMODE
108 end
108 end
109
109
110 contest_name = GraderConfiguration['contest.name']
110 contest_name = GraderConfiguration['contest.name']
111
111
112 #
112 #
113 # build real title bar
113 # build real title bar
114 result = <<TITLEBAR
114 result = <<TITLEBAR
115 <div class="title">
115 <div class="title">
116 <table>
116 <table>
117 #{header}
117 #{header}
118 <tr>
118 <tr>
119 <td class="left-col">
119 <td class="left-col">
120 #{user.full_name}<br/>
120 #{user.full_name}<br/>
121 - #{t 'title_bar.current_time'} #{format_short_time(Time.new)}
121 + #{t 'title_bar.current_time'} #{format_short_time(Time.zone.now)}
122 #{time_left}
122 #{time_left}
123 <br/>
123 <br/>
124 </td>
124 </td>
125 <td class="right-col">#{contest_name}</td>
125 <td class="right-col">#{contest_name}</td>
126 </tr>
126 </tr>
127 </table>
127 </table>
128 </div>
128 </div>
129 TITLEBAR
129 TITLEBAR
130 result.html_safe
130 result.html_safe
131 end
131 end
132
132
133 def markdown(text)
133 def markdown(text)
134 markdown = RDiscount.new(text)
134 markdown = RDiscount.new(text)
135 markdown.to_html.html_safe
135 markdown.to_html.html_safe
136 end
136 end
137
137
138 end
138 end
@@ -1,128 +1,128
1 class Problem < ActiveRecord::Base
1 class Problem < ActiveRecord::Base
2
2
3 belongs_to :description
3 belongs_to :description
4 has_and_belongs_to_many :contests, :uniq => true
4 has_and_belongs_to_many :contests, :uniq => true
5 has_many :test_pairs, :dependent => :delete_all
5 has_many :test_pairs, :dependent => :delete_all
6
6
7 validates_presence_of :name
7 validates_presence_of :name
8 validates_format_of :name, :with => /^\w+$/
8 validates_format_of :name, :with => /^\w+$/
9 validates_presence_of :full_name
9 validates_presence_of :full_name
10
10
11 scope :available, :conditions => {:available => true}
11 scope :available, :conditions => {:available => true}
12
12
13 DEFAULT_TIME_LIMIT = 1
13 DEFAULT_TIME_LIMIT = 1
14 DEFAULT_MEMORY_LIMIT = 32
14 DEFAULT_MEMORY_LIMIT = 32
15
15
16 def self.find_available_problems
16 def self.find_available_problems
17 Problem.available.all(:order => "date_added DESC, name ASC")
17 Problem.available.all(:order => "date_added DESC, name ASC")
18 end
18 end
19
19
20 def self.create_from_import_form_params(params, old_problem=nil)
20 def self.create_from_import_form_params(params, old_problem=nil)
21 org_problem = old_problem || Problem.new
21 org_problem = old_problem || Problem.new
22 import_params, problem = Problem.extract_params_and_check(params,
22 import_params, problem = Problem.extract_params_and_check(params,
23 org_problem)
23 org_problem)
24
24
25 if !problem.errors.empty?
25 if !problem.errors.empty?
26 return problem, 'Error importing'
26 return problem, 'Error importing'
27 end
27 end
28
28
29 problem.full_score = 100
29 problem.full_score = 100
30 problem.date_added = Time.new
30 problem.date_added = Time.new
31 problem.test_allowed = true
31 problem.test_allowed = true
32 problem.output_only = false
32 problem.output_only = false
33 problem.available = false
33 problem.available = false
34
34
35 if not problem.save
35 if not problem.save
36 return problem, 'Error importing'
36 return problem, 'Error importing'
37 end
37 end
38
38
39 import_to_db = params.has_key? :import_to_db
39 import_to_db = params.has_key? :import_to_db
40
40
41 importer = TestdataImporter.new(problem)
41 importer = TestdataImporter.new(problem)
42
42
43 if not importer.import_from_file(import_params[:file],
43 if not importer.import_from_file(import_params[:file],
44 import_params[:time_limit],
44 import_params[:time_limit],
45 import_params[:memory_limit],
45 import_params[:memory_limit],
46 import_params[:checker_name],
46 import_params[:checker_name],
47 import_to_db)
47 import_to_db)
48 - problem.errors.add_to_base('Import error.')
48 + problem.errors.add(:base,'Import error.')
49 end
49 end
50
50
51 return problem, importer.log_msg
51 return problem, importer.log_msg
52 end
52 end
53
53
54 def self.download_file_basedir
54 def self.download_file_basedir
55 return "#{Rails.root}/data/tasks"
55 return "#{Rails.root}/data/tasks"
56 end
56 end
57
57
58 def get_submission_stat
58 def get_submission_stat
59 result = Hash.new
59 result = Hash.new
60 #total number of submission
60 #total number of submission
61 result[:total_sub] = Submission.where(problem_id: self.id).count
61 result[:total_sub] = Submission.where(problem_id: self.id).count
62 result[:attempted_user] = Submission.where(problem_id: self.id).group_by(:user_id)
62 result[:attempted_user] = Submission.where(problem_id: self.id).group_by(:user_id)
63 end
63 end
64
64
65 protected
65 protected
66
66
67 def self.to_i_or_default(st, default)
67 def self.to_i_or_default(st, default)
68 if st!=''
68 if st!=''
69 result = st.to_i
69 result = st.to_i
70 end
70 end
71 result ||= default
71 result ||= default
72 end
72 end
73
73
74 def self.to_f_or_default(st, default)
74 def self.to_f_or_default(st, default)
75 if st!=''
75 if st!=''
76 result = st.to_f
76 result = st.to_f
77 end
77 end
78 result ||= default
78 result ||= default
79 end
79 end
80
80
81 def self.extract_params_and_check(params, problem)
81 def self.extract_params_and_check(params, problem)
82 time_limit = Problem.to_f_or_default(params[:time_limit],
82 time_limit = Problem.to_f_or_default(params[:time_limit],
83 DEFAULT_TIME_LIMIT)
83 DEFAULT_TIME_LIMIT)
84 memory_limit = Problem.to_i_or_default(params[:memory_limit],
84 memory_limit = Problem.to_i_or_default(params[:memory_limit],
85 DEFAULT_MEMORY_LIMIT)
85 DEFAULT_MEMORY_LIMIT)
86
86
87 if time_limit<=0 or time_limit >60
87 if time_limit<=0 or time_limit >60
88 - problem.errors.add_to_base('Time limit out of range.')
88 + problem.errors.add(:base,'Time limit out of range.')
89 end
89 end
90
90
91 if memory_limit==0 and params[:memory_limit]!='0'
91 if memory_limit==0 and params[:memory_limit]!='0'
92 - problem.errors.add_to_base('Memory limit format errors.')
92 + problem.errors.add(:base,'Memory limit format errors.')
93 elsif memory_limit<=0 or memory_limit >512
93 elsif memory_limit<=0 or memory_limit >512
94 - problem.errors.add_to_base('Memory limit out of range.')
94 + problem.errors.add(:base,'Memory limit out of range.')
95 end
95 end
96
96
97 if params[:file]==nil or params[:file]==''
97 if params[:file]==nil or params[:file]==''
98 - problem.errors.add_to_base('No testdata file.')
98 + problem.errors.add(:base,'No testdata file.')
99 end
99 end
100
100
101 checker_name = 'text'
101 checker_name = 'text'
102 if ['text','float'].include? params[:checker]
102 if ['text','float'].include? params[:checker]
103 checker_name = params[:checker]
103 checker_name = params[:checker]
104 end
104 end
105
105
106 file = params[:file]
106 file = params[:file]
107
107
108 if !problem.errors.empty?
108 if !problem.errors.empty?
109 return nil, problem
109 return nil, problem
110 end
110 end
111
111
112 problem.name = params[:name]
112 problem.name = params[:name]
113 if params[:full_name]!=''
113 if params[:full_name]!=''
114 problem.full_name = params[:full_name]
114 problem.full_name = params[:full_name]
115 else
115 else
116 problem.full_name = params[:name]
116 problem.full_name = params[:name]
117 end
117 end
118
118
119 return [{
119 return [{
120 :time_limit => time_limit,
120 :time_limit => time_limit,
121 :memory_limit => memory_limit,
121 :memory_limit => memory_limit,
122 :file => file,
122 :file => file,
123 :checker_name => checker_name
123 :checker_name => checker_name
124 },
124 },
125 problem]
125 problem]
126 end
126 end
127
127
128 end
128 end
@@ -1,157 +1,157
1 #
1 #
2 # A TestRequest is a composition of submission with user's testdata.
2 # A TestRequest is a composition of submission with user's testdata.
3 #
3 #
4 # Note about TestRequest#problem: Usually, A TestRequest has to be
4 # Note about TestRequest#problem: Usually, A TestRequest has to be
5 # associated with a problem, so that execution environment can be
5 # associated with a problem, so that execution environment can be
6 # determined. However, to be more flexible, we have to ensure that
6 # determined. However, to be more flexible, we have to ensure that
7 # it works as well with problem=nil. In this case, we shall provide
7 # it works as well with problem=nil. In this case, we shall provide
8 # a "default" execution environment for it. This can be done
8 # a "default" execution environment for it. This can be done
9 # seamlessly by using TestRequest#problem_name or
9 # seamlessly by using TestRequest#problem_name or
10 # TestRequest#name_of(problem) when retrieving the name of the
10 # TestRequest#name_of(problem) when retrieving the name of the
11 # problem: #name_of would return problem.name when problem!=nil and
11 # problem: #name_of would return problem.name when problem!=nil and
12 # it would return "default" when problem=nil, #problem_name just
12 # it would return "default" when problem=nil, #problem_name just
13 # call #name_of.
13 # call #name_of.
14 #
14 #
15
15
16 require 'fileutils'
16 require 'fileutils'
17
17
18 class TestRequest < Task
18 class TestRequest < Task
19
19
20 set_table_name "test_requests"
20 set_table_name "test_requests"
21
21
22 belongs_to :user
22 belongs_to :user
23 belongs_to :problem
23 belongs_to :problem
24 belongs_to :submission
24 belongs_to :submission
25
25
26 validates_presence_of :submission
26 validates_presence_of :submission
27 validate :must_have_valid_problem
27 validate :must_have_valid_problem
28
28
29 def problem_name
29 def problem_name
30 TestRequest.name_of(self.problem)
30 TestRequest.name_of(self.problem)
31 end
31 end
32
32
33 def language
33 def language
34 self.submission.language
34 self.submission.language
35 end
35 end
36
36
37 def self.get_inqueue_and_change_status(status)
37 def self.get_inqueue_and_change_status(status)
38 # since there will be only one grader grading TestRequest
38 # since there will be only one grader grading TestRequest
39 # we do not need locking (hopefully)
39 # we do not need locking (hopefully)
40
40
41 test_request = TestRequest.find(:first,
41 test_request = TestRequest.find(:first,
42 :order => "created_at",
42 :order => "created_at",
43 :conditions => {:status=> Task::STATUS_INQUEUE})
43 :conditions => {:status=> Task::STATUS_INQUEUE})
44 if test_request!=nil
44 if test_request!=nil
45 test_request.status = status
45 test_request.status = status
46 test_request.save!
46 test_request.save!
47 end
47 end
48
48
49 test_request
49 test_request
50 end
50 end
51
51
52 # interfacing with form
52 # interfacing with form
53 def self.new_from_form_params(user,params)
53 def self.new_from_form_params(user,params)
54 test_request = TestRequest.new
54 test_request = TestRequest.new
55 test_request.user = user
55 test_request.user = user
56 begin
56 begin
57 problem = Problem.find(params[:problem_id])
57 problem = Problem.find(params[:problem_id])
58 rescue ActiveRecord::RecordNotFound
58 rescue ActiveRecord::RecordNotFound
59 problem = nil
59 problem = nil
60 end
60 end
61 test_request.problem = problem
61 test_request.problem = problem
62 if problem!=nil
62 if problem!=nil
63 test_request.submission =
63 test_request.submission =
64 Submission.find_by_user_problem_number(user.id,
64 Submission.find_by_user_problem_number(user.id,
65 problem.id,
65 problem.id,
66 params[:submission_number])
66 params[:submission_number])
67 else
67 else
68 test_request.submission = nil
68 test_request.submission = nil
69 end
69 end
70
70
71 # checks if the user submits any input file
71 # checks if the user submits any input file
72 if params[:input_file]==nil or params[:input_file]==""
72 if params[:input_file]==nil or params[:input_file]==""
73 - test_request.errors.add_to_base("No input submitted.")
73 + test_request.errors.add(:base,"No input submitted.")
74 test_request.input_file_name = nil
74 test_request.input_file_name = nil
75 else
75 else
76 test_request.input_file_name = save_input_file(params[:input_file], user, problem)
76 test_request.input_file_name = save_input_file(params[:input_file], user, problem)
77 if test_request.input_file_name == nil
77 if test_request.input_file_name == nil
78 - test_request.errors.add_to_base("No input submitted.")
78 + test_request.errors.adds(:base,"No input submitted.")
79 end
79 end
80 if params[:additional_file]!=nil and params[:additional_file]!=""
80 if params[:additional_file]!=nil and params[:additional_file]!=""
81 save_additional_file(params[:additional_file],
81 save_additional_file(params[:additional_file],
82 "#{test_request.input_file_name}.files")
82 "#{test_request.input_file_name}.files")
83 end
83 end
84 end
84 end
85 test_request.submitted_at = Time.new.gmtime
85 test_request.submitted_at = Time.new.gmtime
86 test_request.status_inqueue
86 test_request.status_inqueue
87 test_request
87 test_request
88 end
88 end
89
89
90 protected
90 protected
91
91
92 def self.name_of(problem)
92 def self.name_of(problem)
93 if problem!=nil
93 if problem!=nil
94 problem.name
94 problem.name
95 else
95 else
96 "default"
96 "default"
97 end
97 end
98 end
98 end
99
99
100 def self.random_input_file_name(user,problem)
100 def self.random_input_file_name(user,problem)
101 problem_name = TestRequest.name_of(problem)
101 problem_name = TestRequest.name_of(problem)
102 begin
102 begin
103 tmpname = TEST_REQUEST_INPUT_FILE_DIR + "/#{user.login}/#{problem_name}/#{rand(10000)}"
103 tmpname = TEST_REQUEST_INPUT_FILE_DIR + "/#{user.login}/#{problem_name}/#{rand(10000)}"
104 end while File.exists?(tmpname)
104 end while File.exists?(tmpname)
105 tmpname
105 tmpname
106 end
106 end
107
107
108 def self.save_input_file(tempfile, user, problem)
108 def self.save_input_file(tempfile, user, problem)
109 new_file_name = random_input_file_name(user,problem)
109 new_file_name = random_input_file_name(user,problem)
110 dirname = File.dirname(new_file_name)
110 dirname = File.dirname(new_file_name)
111 FileUtils.mkdir_p(File.dirname(new_file_name)) if !File.exists?(dirname)
111 FileUtils.mkdir_p(File.dirname(new_file_name)) if !File.exists?(dirname)
112
112
113 # when the user did not submit any file
113 # when the user did not submit any file
114 return nil if tempfile==""
114 return nil if tempfile==""
115
115
116 if tempfile.instance_of?(Tempfile)
116 if tempfile.instance_of?(Tempfile)
117 tempfile.close
117 tempfile.close
118 FileUtils.move(tempfile.path,new_file_name)
118 FileUtils.move(tempfile.path,new_file_name)
119 else
119 else
120 File.open(new_file_name, "wb") do |f|
120 File.open(new_file_name, "wb") do |f|
121 f.write(tempfile.read)
121 f.write(tempfile.read)
122 end
122 end
123 end
123 end
124 new_file_name
124 new_file_name
125 end
125 end
126
126
127 def self.save_additional_file(tempfile,dir)
127 def self.save_additional_file(tempfile,dir)
128 new_file_name = "#{dir}/#{tempfile.original_filename}"
128 new_file_name = "#{dir}/#{tempfile.original_filename}"
129 dirname = File.dirname(new_file_name)
129 dirname = File.dirname(new_file_name)
130 FileUtils.mkdir_p(File.dirname(new_file_name)) if !File.exists?(dirname)
130 FileUtils.mkdir_p(File.dirname(new_file_name)) if !File.exists?(dirname)
131
131
132 # when the user did not submit any file
132 # when the user did not submit any file
133 return nil if tempfile==""
133 return nil if tempfile==""
134
134
135 if tempfile.instance_of?(Tempfile)
135 if tempfile.instance_of?(Tempfile)
136 tempfile.close
136 tempfile.close
137 FileUtils.move(tempfile.path,new_file_name)
137 FileUtils.move(tempfile.path,new_file_name)
138 else
138 else
139 File.open(new_file_name, "wb") do |f|
139 File.open(new_file_name, "wb") do |f|
140 f.write(tempfile.read)
140 f.write(tempfile.read)
141 end
141 end
142 end
142 end
143 new_file_name
143 new_file_name
144 end
144 end
145
145
146 #
146 #
147 # validations
147 # validations
148 #
148 #
149 def must_have_valid_problem
149 def must_have_valid_problem
150 if problem==nil
150 if problem==nil
151 errors.add('problem',"must be specified.")
151 errors.add('problem',"must be specified.")
152 elsif (!problem.available) and (self.new_record?)
152 elsif (!problem.available) and (self.new_record?)
153 errors.add('problem',"must be valid.")
153 errors.add('problem',"must be valid.")
154 end
154 end
155 end
155 end
156
156
157 end
157 end
@@ -1,223 +1,176
1 require 'digest/sha1'
1 require 'digest/sha1'
2 require 'net/pop'
2 require 'net/pop'
3 require 'net/https'
3 require 'net/https'
4 require 'net/http'
4 require 'net/http'
5 require 'json'
5 require 'json'
6
6
7 class User < ActiveRecord::Base
7 class User < ActiveRecord::Base
8
8
9 has_and_belongs_to_many :roles
9 has_and_belongs_to_many :roles
10
10
11 has_many :test_requests, :order => "submitted_at DESC"
11 has_many :test_requests, :order => "submitted_at DESC"
12
12
13 has_many :messages,
13 has_many :messages,
14 :class_name => "Message",
14 :class_name => "Message",
15 :foreign_key => "sender_id",
15 :foreign_key => "sender_id",
16 :order => 'created_at DESC'
16 :order => 'created_at DESC'
17
17
18 has_many :replied_messages,
18 has_many :replied_messages,
19 :class_name => "Message",
19 :class_name => "Message",
20 :foreign_key => "receiver_id",
20 :foreign_key => "receiver_id",
21 :order => 'created_at DESC'
21 :order => 'created_at DESC'
22
22
23 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
23 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
24
24
25 belongs_to :site
25 belongs_to :site
26 belongs_to :country
26 belongs_to :country
27
27
28 has_and_belongs_to_many :contests, :uniq => true, :order => 'name'
28 has_and_belongs_to_many :contests, :uniq => true, :order => 'name'
29
29
30 scope :activated_users, :conditions => {:activated => true}
30 scope :activated_users, :conditions => {:activated => true}
31
31
32 validates_presence_of :login
32 validates_presence_of :login
33 validates_uniqueness_of :login
33 validates_uniqueness_of :login
34 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
34 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
35 validates_length_of :login, :within => 3..30
35 validates_length_of :login, :within => 3..30
36
36
37 validates_presence_of :full_name
37 validates_presence_of :full_name
38 validates_length_of :full_name, :minimum => 1
38 validates_length_of :full_name, :minimum => 1
39
39
40 validates_presence_of :password, :if => :password_required?
40 validates_presence_of :password, :if => :password_required?
41 validates_length_of :password, :within => 4..20, :if => :password_required?
41 validates_length_of :password, :within => 4..20, :if => :password_required?
42 validates_confirmation_of :password, :if => :password_required?
42 validates_confirmation_of :password, :if => :password_required?
43
43
44 validates_format_of :email,
44 validates_format_of :email,
45 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
45 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
46 :if => :email_validation?
46 :if => :email_validation?
47 validate :uniqueness_of_email_from_activated_users,
47 validate :uniqueness_of_email_from_activated_users,
48 :if => :email_validation?
48 :if => :email_validation?
49 validate :enough_time_interval_between_same_email_registrations,
49 validate :enough_time_interval_between_same_email_registrations,
50 :if => :email_validation?
50 :if => :email_validation?
51
51
52 # these are for ytopc
52 # these are for ytopc
53 # disable for now
53 # disable for now
54 #validates_presence_of :province
54 #validates_presence_of :province
55
55
56 attr_accessor :password
56 attr_accessor :password
57
57
58 before_save :encrypt_new_password
58 before_save :encrypt_new_password
59 before_save :assign_default_site
59 before_save :assign_default_site
60 before_save :assign_default_contest
60 before_save :assign_default_contest
61
61
62 # this is for will_paginate
62 # this is for will_paginate
63 cattr_reader :per_page
63 cattr_reader :per_page
64 @@per_page = 50
64 @@per_page = 50
65
65
66 def self.authenticate(login, password)
66 def self.authenticate(login, password)
67 user = find_by_login(login)
67 user = find_by_login(login)
68 if user
68 if user
69 return user if user.authenticated?(password)
69 return user if user.authenticated?(password)
70 - if user.authenticated_by_cucas?(password) or user.authenticated_by_pop3?(password)
71 - user.password = password
72 - user.save
73 - return user
74 - end
75 end
70 end
76 end
71 end
77
72
78 def authenticated?(password)
73 def authenticated?(password)
79 if self.activated
74 if self.activated
80 hashed_password == User.encrypt(password,self.salt)
75 hashed_password == User.encrypt(password,self.salt)
81 else
76 else
82 false
77 false
83 end
78 end
84 end
79 end
85
80
86 - def authenticated_by_pop3?(password)
87 - Net::POP3.enable_ssl
88 - pop = Net::POP3.new('pops.it.chula.ac.th')
89 - authen = true
90 - begin
91 - pop.start(login, password)
92 - pop.finish
93 - return true
94 - rescue
95 - return false
96 - end
97 - end
98 -
99 - def authenticated_by_cucas?(password)
100 - url = URI.parse('https://www.cas.chula.ac.th/cas/api/?q=studentAuthenticate')
101 - appid = '41508763e340d5858c00f8c1a0f5a2bb'
102 - appsecret ='d9cbb5863091dbe186fded85722a1e31'
103 - post_args = {
104 - 'appid' => appid,
105 - 'appsecret' => appsecret,
106 - 'username' => login,
107 - 'password' => password
108 - }
109 -
110 - #simple call
111 - begin
112 - http = Net::HTTP.new('www.cas.chula.ac.th', 443)
113 - http.use_ssl = true
114 - result = [ ]
115 - http.start do |http|
116 - req = Net::HTTP::Post.new('/cas/api/?q=studentAuthenticate')
117 - param = "appid=#{appid}&appsecret=#{appsecret}&username=#{login}&password=#{password}"
118 - resp = http.request(req,param)
119 - result = JSON.parse resp.body
120 - end
121 - return true if result["type"] == "beanStudent"
122 - rescue
123 - return false
124 - end
125 - return false
126 - end
127 -
128 def admin?
81 def admin?
129 self.roles.detect {|r| r.name == 'admin' }
82 self.roles.detect {|r| r.name == 'admin' }
130 end
83 end
131
84
132 def email_for_editing
85 def email_for_editing
133 if self.email==nil
86 if self.email==nil
134 "(unknown)"
87 "(unknown)"
135 elsif self.email==''
88 elsif self.email==''
136 "(blank)"
89 "(blank)"
137 else
90 else
138 self.email
91 self.email
139 end
92 end
140 end
93 end
141
94
142 def email_for_editing=(e)
95 def email_for_editing=(e)
143 self.email=e
96 self.email=e
144 end
97 end
145
98
146 def alias_for_editing
99 def alias_for_editing
147 if self.alias==nil
100 if self.alias==nil
148 "(unknown)"
101 "(unknown)"
149 elsif self.alias==''
102 elsif self.alias==''
150 "(blank)"
103 "(blank)"
151 else
104 else
152 self.alias
105 self.alias
153 end
106 end
154 end
107 end
155
108
156 def alias_for_editing=(e)
109 def alias_for_editing=(e)
157 self.alias=e
110 self.alias=e
158 end
111 end
159
112
160 def activation_key
113 def activation_key
161 if self.hashed_password==nil
114 if self.hashed_password==nil
162 encrypt_new_password
115 encrypt_new_password
163 end
116 end
164 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
117 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
165 end
118 end
166
119
167 def verify_activation_key(key)
120 def verify_activation_key(key)
168 key == activation_key
121 key == activation_key
169 end
122 end
170
123
171 def self.random_password(length=5)
124 def self.random_password(length=5)
172 chars = 'abcdefghjkmnopqrstuvwxyz'
125 chars = 'abcdefghjkmnopqrstuvwxyz'
173 password = ''
126 password = ''
174 length.times { password << chars[rand(chars.length - 1)] }
127 length.times { password << chars[rand(chars.length - 1)] }
175 password
128 password
176 end
129 end
177
130
178 def self.find_non_admin_with_prefix(prefix='')
131 def self.find_non_admin_with_prefix(prefix='')
179 users = User.find(:all)
132 users = User.find(:all)
180 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
133 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
181 end
134 end
182
135
183 # Contest information
136 # Contest information
184
137
185 def self.find_users_with_no_contest()
138 def self.find_users_with_no_contest()
186 users = User.find(:all)
139 users = User.find(:all)
187 return users.find_all { |u| u.contests.length == 0 }
140 return users.find_all { |u| u.contests.length == 0 }
188 end
141 end
189
142
190
143
191 def contest_time_left
144 def contest_time_left
192 if GraderConfiguration.contest_mode?
145 if GraderConfiguration.contest_mode?
193 return nil if site==nil
146 return nil if site==nil
194 return site.time_left
147 return site.time_left
195 elsif GraderConfiguration.indv_contest_mode?
148 elsif GraderConfiguration.indv_contest_mode?
196 time_limit = GraderConfiguration.contest_time_limit
149 time_limit = GraderConfiguration.contest_time_limit
197 if time_limit == nil
150 if time_limit == nil
198 return nil
151 return nil
199 end
152 end
200 if contest_stat==nil or contest_stat.started_at==nil
153 if contest_stat==nil or contest_stat.started_at==nil
201 return (Time.now.gmtime + time_limit) - Time.now.gmtime
154 return (Time.now.gmtime + time_limit) - Time.now.gmtime
202 else
155 else
203 finish_time = contest_stat.started_at + time_limit
156 finish_time = contest_stat.started_at + time_limit
204 current_time = Time.now.gmtime
157 current_time = Time.now.gmtime
205 if current_time > finish_time
158 if current_time > finish_time
206 return 0
159 return 0
207 else
160 else
208 return finish_time - current_time
161 return finish_time - current_time
209 end
162 end
210 end
163 end
211 else
164 else
212 return nil
165 return nil
213 end
166 end
214 end
167 end
215
168
216 def contest_finished?
169 def contest_finished?
217 if GraderConfiguration.contest_mode?
170 if GraderConfiguration.contest_mode?
218 return false if site==nil
171 return false if site==nil
219 return site.finished?
172 return site.finished?
220 elsif GraderConfiguration.indv_contest_mode?
173 elsif GraderConfiguration.indv_contest_mode?
221 return false if self.contest_stat(true)==nil
174 return false if self.contest_stat(true)==nil
222 return contest_time_left == 0
175 return contest_time_left == 0
223 else
176 else
@@ -258,119 +211,119
258 return true
211 return true
259 end
212 end
260 end
213 end
261 return false
214 return false
262 end
215 end
263
216
264 def available_problems_group_by_contests
217 def available_problems_group_by_contests
265 contest_problems = []
218 contest_problems = []
266 pin = {}
219 pin = {}
267 contests.enabled.each do |contest|
220 contests.enabled.each do |contest|
268 available_problems = contest.problems.available
221 available_problems = contest.problems.available
269 contest_problems << {
222 contest_problems << {
270 :contest => contest,
223 :contest => contest,
271 :problems => available_problems
224 :problems => available_problems
272 }
225 }
273 available_problems.each {|p| pin[p.id] = true}
226 available_problems.each {|p| pin[p.id] = true}
274 end
227 end
275 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
228 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
276 contest_problems << {
229 contest_problems << {
277 :contest => nil,
230 :contest => nil,
278 :problems => other_avaiable_problems
231 :problems => other_avaiable_problems
279 }
232 }
280 return contest_problems
233 return contest_problems
281 end
234 end
282
235
283 def available_problems
236 def available_problems
284 if not GraderConfiguration.multicontests?
237 if not GraderConfiguration.multicontests?
285 return Problem.find_available_problems
238 return Problem.find_available_problems
286 else
239 else
287 contest_problems = []
240 contest_problems = []
288 pin = {}
241 pin = {}
289 contests.enabled.each do |contest|
242 contests.enabled.each do |contest|
290 contest.problems.available.each do |problem|
243 contest.problems.available.each do |problem|
291 if not pin.has_key? problem.id
244 if not pin.has_key? problem.id
292 contest_problems << problem
245 contest_problems << problem
293 end
246 end
294 pin[problem.id] = true
247 pin[problem.id] = true
295 end
248 end
296 end
249 end
297 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
250 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
298 return contest_problems + other_avaiable_problems
251 return contest_problems + other_avaiable_problems
299 end
252 end
300 end
253 end
301
254
302 def can_view_problem?(problem)
255 def can_view_problem?(problem)
303 if not GraderConfiguration.multicontests?
256 if not GraderConfiguration.multicontests?
304 return problem.available
257 return problem.available
305 else
258 else
306 return problem_in_user_contests? problem
259 return problem_in_user_contests? problem
307 end
260 end
308 end
261 end
309
262
310 protected
263 protected
311 def encrypt_new_password
264 def encrypt_new_password
312 return if password.blank?
265 return if password.blank?
313 self.salt = (10+rand(90)).to_s
266 self.salt = (10+rand(90)).to_s
314 self.hashed_password = User.encrypt(self.password,self.salt)
267 self.hashed_password = User.encrypt(self.password,self.salt)
315 end
268 end
316
269
317 def assign_default_site
270 def assign_default_site
318 # have to catch error when migrating (because self.site is not available).
271 # have to catch error when migrating (because self.site is not available).
319 begin
272 begin
320 if self.site==nil
273 if self.site==nil
321 self.site = Site.find_by_name('default')
274 self.site = Site.find_by_name('default')
322 if self.site==nil
275 if self.site==nil
323 self.site = Site.find(1) # when 'default has be renamed'
276 self.site = Site.find(1) # when 'default has be renamed'
324 end
277 end
325 end
278 end
326 rescue
279 rescue
327 end
280 end
328 end
281 end
329
282
330 def assign_default_contest
283 def assign_default_contest
331 # have to catch error when migrating (because self.site is not available).
284 # have to catch error when migrating (because self.site is not available).
332 begin
285 begin
333 if self.contests.length == 0
286 if self.contests.length == 0
334 default_contest = Contest.find_by_name(GraderConfiguration['contest.default_contest_name'])
287 default_contest = Contest.find_by_name(GraderConfiguration['contest.default_contest_name'])
335 if default_contest
288 if default_contest
336 self.contests = [default_contest]
289 self.contests = [default_contest]
337 end
290 end
338 end
291 end
339 rescue
292 rescue
340 end
293 end
341 end
294 end
342
295
343 def password_required?
296 def password_required?
344 self.hashed_password.blank? || !self.password.blank?
297 self.hashed_password.blank? || !self.password.blank?
345 end
298 end
346
299
347 def self.encrypt(string,salt)
300 def self.encrypt(string,salt)
348 Digest::SHA1.hexdigest(salt + string)
301 Digest::SHA1.hexdigest(salt + string)
349 end
302 end
350
303
351 def uniqueness_of_email_from_activated_users
304 def uniqueness_of_email_from_activated_users
352 user = User.activated_users.find_by_email(self.email)
305 user = User.activated_users.find_by_email(self.email)
353 if user and (user.login != self.login)
306 if user and (user.login != self.login)
354 - self.errors.add_to_base("Email has already been taken")
307 + self.errors.add(:base,"Email has already been taken")
355 end
308 end
356 end
309 end
357
310
358 def enough_time_interval_between_same_email_registrations
311 def enough_time_interval_between_same_email_registrations
359 return if !self.new_record?
312 return if !self.new_record?
360 return if self.activated
313 return if self.activated
361 open_user = User.find_by_email(self.email,
314 open_user = User.find_by_email(self.email,
362 :order => 'created_at DESC')
315 :order => 'created_at DESC')
363 if open_user and open_user.created_at and
316 if open_user and open_user.created_at and
364 (open_user.created_at > Time.now.gmtime - 5.minutes)
317 (open_user.created_at > Time.now.gmtime - 5.minutes)
365 - self.errors.add_to_base("There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
318 + self.errors.add(:base,"There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
366 end
319 end
367 end
320 end
368
321
369 def email_validation?
322 def email_validation?
370 begin
323 begin
371 return VALIDATE_USER_EMAILS
324 return VALIDATE_USER_EMAILS
372 rescue
325 rescue
373 return false
326 return false
374 end
327 end
375 end
328 end
376 end
329 end
@@ -1,31 +1,34
1 %h1 Contest management
1 %h1 Contest management
2
2
3 .infobox
3 .infobox
4
4
5 - if @num_contests>1
5 - if @num_contests>1
6 %b Multiple contests:
6 %b Multiple contests:
7 = "There are #{@num_contests} contests running."
7 = "There are #{@num_contests} contests running."
8 - else
8 - else
9 %b Single contest:
9 %b Single contest:
10 =raw "[#{link_to 'Add/remove contests', :controller => 'contests', :action => 'index'}]"
10 =raw "[#{link_to 'Add/remove contests', :controller => 'contests', :action => 'index'}]"
11
11
12 .infobox
12 .infobox
13 %b Web interface mode:
13 %b Web interface mode:
14 - - if (not GraderConfiguration.contest_mode?) and (not GraderConfiguration.indv_contest_mode?)
14 + - if GraderConfiguration.analysis_mode?
15 - standard mode
15 + Analysis Mode
16 + - elsif (not GraderConfiguration.contest_mode?) and (not GraderConfiguration.indv_contest_mode?)
17 + Standard Mode
16 - elsif GraderConfiguration.contest_mode?
18 - elsif GraderConfiguration.contest_mode?
17 - normal contest mode.
19 + Normal Contest Mode
18 - else
20 - else
19 - individual contest mode.
21 + Individual Contest Mode
20
22
21 %br/
23 %br/
22 Change mode to:
24 Change mode to:
23 - =raw "[#{link_to 'standard', :action => 'change_contest_mode', :id => 'standard'}]"
25 + =raw "[#{link_to 'Standard', :action => 'change_contest_mode', :id => 'standard'}]"
24 - =raw "[#{link_to 'contest', :action => 'change_contest_mode', :id => 'contest'}]"
26 + =raw "[#{link_to 'Contest', :action => 'change_contest_mode', :id => 'contest'}]"
25 - =raw "[#{link_to 'individual contest', :action => 'change_contest_mode', :id => 'indv-contest'}]"
27 + =raw "[#{link_to 'Individual Contest', :action => 'change_contest_mode', :id => 'indv-contest'}]"
28 + =raw "[#{link_to 'Analysis', :action => 'change_contest_mode', :id => 'analysis'}]"
26
29
27 - if GraderConfiguration.indv_contest_mode?
30 - if GraderConfiguration.indv_contest_mode?
28 = render :partial => 'indv_contest_mode_index'
31 = render :partial => 'indv_contest_mode_index'
29
32
30 %br/
33 %br/
31
34
@@ -1,40 +1,40
1 %h1= "Test Request: #{@test_request.id}"
1 %h1= "Test Request: #{@test_request.id}"
2
2
3 %p
3 %p
4 User:
4 User:
5 = "#{@test_request.user.login}"
5 = "#{@test_request.user.login}"
6 %br/
6 %br/
7 Problem:
7 Problem:
8 - if @test_request.problem!=nil
8 - if @test_request.problem!=nil
9 = "#{@test_request.problem.full_name}"
9 = "#{@test_request.problem.full_name}"
10 - else
10 - else
11 = "(n/a)"
11 = "(n/a)"
12 %br/
12 %br/
13 = "Submission: #{@test_request.submission.number}"
13 = "Submission: #{@test_request.submission.number}"
14 = link_to '[view submission]', :action => 'submission', :id => @test_request.submission.id
14 = link_to '[view submission]', :action => 'submission', :id => @test_request.submission.id
15 %br/
15 %br/
16 = "Test submitted at: #{format_short_time(@test_request.submitted_at)}"
16 = "Test submitted at: #{format_short_time(@test_request.submitted_at)}"
17 %br/
17 %br/
18 = "Execution time: #{@test_request.running_time} s."
18 = "Execution time: #{@test_request.running_time} s."
19 %br/
19 %br/
20 = "Memory usage: #{@test_request.memory_usage}kb"
20 = "Memory usage: #{@test_request.memory_usage}kb"
21 %br/
21 %br/
22 %b= @test_request.exit_status
22 %b= @test_request.exit_status
23 %br/
23 %br/
24
24
25 - if @test_request.compiler_message!=nil and @test_request.compiler_message!=''
25 - if @test_request.compiler_message!=nil and @test_request.compiler_message!=''
26 %b Compiler Message
26 %b Compiler Message
27 %div{:style => "border: 1px solid black; background: lightgrey"}
27 %div{:style => "border: 1px solid black; background: lightgrey"}
28 - = simple_format(truncate((@test_request.compiler_message or ''),200))
28 + = simple_format(truncate((@test_request.compiler_message or ''), :length => 200))
29
29
30 %b Input (first 2kb)
30 %b Input (first 2kb)
31 %div{:style => "border: 1px solid black; background: lightgrey"}
31 %div{:style => "border: 1px solid black; background: lightgrey"}
32 - if @test_request.input_file_name!=nil
32 - if @test_request.input_file_name!=nil
33 = simple_format(read_textfile(@test_request.input_file_name,2048))
33 = simple_format(read_textfile(@test_request.input_file_name,2048))
34
34
35 %b Output (first 2kb)
35 %b Output (first 2kb)
36 %div{:style => "border: 1px solid black; background: lightgrey"}
36 %div{:style => "border: 1px solid black; background: lightgrey"}
37 - if @test_request.output_file_name!=nil
37 - if @test_request.output_file_name!=nil
38 = simple_format(read_textfile(@test_request.output_file_name,2048))
38 = simple_format(read_textfile(@test_request.output_file_name,2048))
39 - else
39 - else
40 (no output)
40 (no output)
@@ -1,15 +1,15
1
1
2 - <% if compiler_message==nil or compiler_message=='' %>
2 + <% if compiler_message == nil or compiler_message.chomp == '' %>
3 No message
3 No message
4 <% else %>
4 <% else %>
5 <div><div><a href="#" onClick="n = this.parentNode.parentNode.lastChild;
5 <div><div><a href="#" onClick="n = this.parentNode.parentNode.lastChild;
6 if(n.style.display == 'none') { n.style.display = 'block'; }
6 if(n.style.display == 'none') { n.style.display = 'block'; }
7 else {n.style.display ='none'; } return false;">
7 else {n.style.display ='none'; } return false;">
8 (click to see)</a>
8 (click to see)</a>
9 </div>
9 </div>
10 <div style="display: none">
10 <div style="display: none">
11 <div class="compilermsgbody" style="border: thin solid grey; margin: 2px">
11 <div class="compilermsgbody" style="border: thin solid grey; margin: 2px">
12 <%=simple_format(compiler_message) %>
12 <%=simple_format(compiler_message) %>
13 </div>
13 </div>
14 </div></div>
14 </div></div>
15 <% end %>
15 <% end %>
@@ -1,6 +1,6
1 %h2= "Compiler message for submission \##{@submission.number}, task: #{@submission.problem.name}"
1 %h2= "Compiler message for submission \##{@submission.number}, task: #{@submission.problem.name}"
2 %p
2 %p
3 - - if @submission.compiler_message.chomp == ''
3 + - if @submission.compiler_message == nil or @submission.compiler_message.chomp == ''
4 - no message
4 + No message
5 - else
5 - else
6 = simple_format(@submission.compiler_message)
6 = simple_format(@submission.compiler_message)
@@ -1,16 +1,16
1 = user_title_bar(@user)
1 = user_title_bar(@user)
2
2
3 .announcementbox
3 .announcementbox
4 %span{:class => 'title'}
4 %span{:class => 'title'}
5 =t 'main.confirm_contest_start.box_title'
5 =t 'main.confirm_contest_start.box_title'
6 .announcement
6 .announcement
7 %center
7 %center
8 =t 'main.confirm_contest_start.contest_list'
8 =t 'main.confirm_contest_start.contest_list'
9 - @contests.each do |contest|
9 - @contests.each do |contest|
10 = contest.title
10 = contest.title
11 %br
11 %br
12
12
13 =t 'main.confirm_contest_start.timer_starts_after_click'
13 =t 'main.confirm_contest_start.timer_starts_after_click'
14
14
15 - = form_tag :action => 'confirm_contest_start', :method => 'post' do
15 + = form_tag :action => 'confirm_contest_start' do
16 = submit_tag t('main.confirm_contest_start.start_button'), :confirm => t('main.confirm_contest_start.start_button_confirm')
16 = submit_tag t('main.confirm_contest_start.start_button'), :confirm => t('main.confirm_contest_start.start_button_confirm')
@@ -1,25 +1,25
1 <%= error_messages_for 'user' %>
1 <%= error_messages_for 'user' %>
2
2
3 <!--[form:user]-->
3 <!--[form:user]-->
4 <p><label for="user_name">Login</label><br/>
4 <p><label for="user_name">Login</label><br/>
5 <%= text_field 'user', 'login' %></p>
5 <%= text_field 'user', 'login' %></p>
6
6
7 <p><label for="user_name">Full name</label><br/>
7 <p><label for="user_name">Full name</label><br/>
8 <%= text_field 'user', 'full_name' %></p>
8 <%= text_field 'user', 'full_name' %></p>
9
9
10 <p><label for="password">Password</label><br/>
10 <p><label for="password">Password</label><br/>
11 <%= password_field 'user', 'password' %></p>
11 <%= password_field 'user', 'password' %></p>
12
12
13 <p><label for="password_confirmation">Password (confirm)</label><br/>
13 <p><label for="password_confirmation">Password (confirm)</label><br/>
14 <%= password_field 'user', 'password_confirmation' %></p>
14 <%= password_field 'user', 'password_confirmation' %></p>
15
15
16 <p><label for="user_email">E-mail</label><br/>
16 <p><label for="user_email">E-mail</label><br/>
17 - <%= text_field 'user', 'email' %></p>
17 + <%= email_field 'user', 'email' %></p>
18
18
19 <p><label for="user_alias">Alias</label><br/>
19 <p><label for="user_alias">Alias</label><br/>
20 <%= text_field 'user', 'alias' %></p>
20 <%= text_field 'user', 'alias' %></p>
21
21
22 <p><label for="user_remark">Remark</label><br/>
22 <p><label for="user_remark">Remark</label><br/>
23 <%= text_field 'user', 'remark' %></p>
23 <%= text_field 'user', 'remark' %></p>
24 <!--[eoform:user]-->
24 <!--[eoform:user]-->
25
25
@@ -1,87 +1,87
1 <h1>Listing users</h1>
1 <h1>Listing users</h1>
2
2
3 <div class="submitbox">
3 <div class="submitbox">
4 <b>Quick add</b>
4 <b>Quick add</b>
5 <%= form_tag :action => 'create' do %>
5 <%= form_tag :action => 'create' do %>
6 <table border="0">
6 <table border="0">
7 <tr>
7 <tr>
8 <td><label for="user_login">Login</label></td>
8 <td><label for="user_login">Login</label></td>
9 <td><label for="user_full_name">Full name</label></td>
9 <td><label for="user_full_name">Full name</label></td>
10 <td><label for="user_password">Password</label></td>
10 <td><label for="user_password">Password</label></td>
11 <td><label for="user_password_confirmation">Confirm</label></td>
11 <td><label for="user_password_confirmation">Confirm</label></td>
12 <td><label for="user_email">Email</label></td>
12 <td><label for="user_email">Email</label></td>
13 </tr>
13 </tr>
14 <tr>
14 <tr>
15 <td><%= text_field 'user', 'login', :size => 10 %></td>
15 <td><%= text_field 'user', 'login', :size => 10 %></td>
16 <td><%= text_field 'user', 'full_name', :size => 30 %></td>
16 <td><%= text_field 'user', 'full_name', :size => 30 %></td>
17 <td><%= password_field 'user', 'password', :size => 10 %></td>
17 <td><%= password_field 'user', 'password', :size => 10 %></td>
18 <td><%= password_field 'user', 'password_confirmation', :size => 10 %></td>
18 <td><%= password_field 'user', 'password_confirmation', :size => 10 %></td>
19 - <td><%= text_field 'user', 'email', :size => 15 %></td>
19 + <td><%= email_field 'user', 'email', :size => 15 %></td>
20 <td><%= submit_tag "Create" %></td>
20 <td><%= submit_tag "Create" %></td>
21 </tr>
21 </tr>
22 </table>
22 </table>
23 <% end %>
23 <% end %>
24 <br/>
24 <br/>
25 <b>Import from site management</b>
25 <b>Import from site management</b>
26 <%= form_tag({:action => 'import'}, :multipart => true) do %>
26 <%= form_tag({:action => 'import'}, :multipart => true) do %>
27 File: <%= file_field_tag 'file' %> <%= submit_tag 'Import' %>
27 File: <%= file_field_tag 'file' %> <%= submit_tag 'Import' %>
28 <% end %>
28 <% end %>
29 <br/>
29 <br/>
30 <b>What else: </b>
30 <b>What else: </b>
31 <%= link_to '[New user]', :action => 'new' %>
31 <%= link_to '[New user]', :action => 'new' %>
32 <%= link_to '[New list of users]', :action => 'new_list' %>
32 <%= link_to '[New list of users]', :action => 'new_list' %>
33 <%= link_to '[View administrators]', :action => 'admin' %>
33 <%= link_to '[View administrators]', :action => 'admin' %>
34 <%= link_to '[Random passwords]', :action => 'random_all_passwords' %>
34 <%= link_to '[Random passwords]', :action => 'random_all_passwords' %>
35 <%= link_to '[View active users]', :action => 'active' %>
35 <%= link_to '[View active users]', :action => 'active' %>
36 <%= link_to '[Mass mailing]', :action => 'mass_mailing' %>
36 <%= link_to '[Mass mailing]', :action => 'mass_mailing' %>
37 <% if GraderConfiguration.multicontests? %>
37 <% if GraderConfiguration.multicontests? %>
38 <br/><b>Multi-contest:</b>
38 <br/><b>Multi-contest:</b>
39 <%= link_to '[Manage bulk users in contests]', :action => 'contest_management' %>
39 <%= link_to '[Manage bulk users in contests]', :action => 'contest_management' %>
40 View users in:
40 View users in:
41 <% @contests.each do |contest| %>
41 <% @contests.each do |contest| %>
42 <%= link_to "[#{contest.name}]", :action => 'contests', :id => contest.id %>
42 <%= link_to "[#{contest.name}]", :action => 'contests', :id => contest.id %>
43 <% end %>
43 <% end %>
44 <%= link_to "[no contest]", :action => 'contests', :id => 'none' %>
44 <%= link_to "[no contest]", :action => 'contests', :id => 'none' %>
45 <% end %>
45 <% end %>
46 </div>
46 </div>
47
47
48 Total <%= @user_count %> users |
48 Total <%= @user_count %> users |
49 <% if !@paginated %>
49 <% if !@paginated %>
50 Display all users.
50 Display all users.
51 <%= link_to '[show in pages]', :action => 'list', :page => '1' %>
51 <%= link_to '[show in pages]', :action => 'list', :page => '1' %>
52 <% else %>
52 <% else %>
53 Display in pages.
53 Display in pages.
54 <%= link_to '[display all]', :action => 'list', :page => 'all' %> |
54 <%= link_to '[display all]', :action => 'list', :page => 'all' %> |
55 <%= will_paginate @users, :container => false %>
55 <%= will_paginate @users, :container => false %>
56 <% end %>
56 <% end %>
57 <table class="info">
57 <table class="info">
58 <tr class="info-head">
58 <tr class="info-head">
59 <% for column in User.content_columns %>
59 <% for column in User.content_columns %>
60 <% if !@hidden_columns.index(column.name) %>
60 <% if !@hidden_columns.index(column.name) %>
61 <th><%= column.human_name %></th>
61 <th><%= column.human_name %></th>
62 <% end %>
62 <% end %>
63 <% end %>
63 <% end %>
64 <th></th>
64 <th></th>
65 <th></th>
65 <th></th>
66 <th></th>
66 <th></th>
67 </tr>
67 </tr>
68
68
69 <% for user in @users %>
69 <% for user in @users %>
70 <tr class="info-<%= cycle("odd","even") %>">
70 <tr class="info-<%= cycle("odd","even") %>">
71 <td><%= link_to user.login, controller: :users, :action => 'profile', :id => user %></td>
71 <td><%= link_to user.login, controller: :users, :action => 'profile', :id => user %></td>
72 <% for column in User.content_columns %>
72 <% for column in User.content_columns %>
73 <% if !@hidden_columns.index(column.name) and column.name != 'login' %>
73 <% if !@hidden_columns.index(column.name) and column.name != 'login' %>
74 <td><%=h user.send(column.name) %></td>
74 <td><%=h user.send(column.name) %></td>
75 <% end %>
75 <% end %>
76 <% end %>
76 <% end %>
77 <td><%= link_to 'Show', :action => 'show', :id => user %></td>
77 <td><%= link_to 'Show', :action => 'show', :id => user %></td>
78 <td><%= link_to 'Edit', :action => 'edit', :id => user %></td>
78 <td><%= link_to 'Edit', :action => 'edit', :id => user %></td>
79 <td><%= link_to 'Destroy', { :action => 'destroy', :id => user }, :confirm => 'Are you sure?', :method => :post %></td>
79 <td><%= link_to 'Destroy', { :action => 'destroy', :id => user }, :confirm => 'Are you sure?', :method => :post %></td>
80 </tr>
80 </tr>
81 <% end %>
81 <% end %>
82 </table>
82 </table>
83
83
84 <br />
84 <br />
85
85
86 <%= link_to '[New user]', :action => 'new' %>
86 <%= link_to '[New user]', :action => 'new' %>
87 <%= link_to '[New list of users]', :action => 'new_list' %>
87 <%= link_to '[New list of users]', :action => 'new_list' %>
@@ -1,18 +1,19
1 .contest-title
1 .contest-title
2 %h1
2 %h1
3 = "#{GraderConfiguration['contest.name']}: #{t 'registration.password_retrieval.header'}"
3 = "#{GraderConfiguration['contest.name']}: #{t 'registration.password_retrieval.header'}"
4
4
5 - if flash[:notice]
5 - if flash[:notice]
6 %hr/
6 %hr/
7 %b= flash[:notice]
7 %b= flash[:notice]
8 %hr/
8 %hr/
9
9
10 %br/
10 %br/
11
11
12 = form_tag :action => 'retrieve_password' do
12 = form_tag :action => 'retrieve_password' do
13 =t 'registration.password_retrieval.instructions'
13 =t 'registration.password_retrieval.instructions'
14 - = text_field 'email', nil, :size => 20
14 + %br/
15 + = email_field 'email', nil, :size => 20
15 %br/
16 %br/
16 = submit_tag(t 'registration.password_retrieval.button_label')
17 = submit_tag(t 'registration.password_retrieval.button_label')
17
18
18 = link_to "#{t 'go_back_to'}#{t 'home_page'}", :controller => 'main', :action => 'index'
19 = link_to "#{t 'go_back_to'}#{t 'home_page'}", :controller => 'main', :action => 'index'
@@ -1,39 +1,39
1 .contest-title
1 .contest-title
2 %h1
2 %h1
3 = "#{GraderConfiguration['contest.name']}: #{t 'registration.title'}"
3 = "#{GraderConfiguration['contest.name']}: #{t 'registration.title'}"
4
4
5 .registration-desc
5 .registration-desc
6 =t 'registration.description'
6 =t 'registration.description'
7
7
8 = error_messages_for :user, :header_message => (t 'registration.errors.header')
8 = error_messages_for :user, :header_message => (t 'registration.errors.header')
9
9
10 %table
10 %table
11 = form_for @user, :url => { :action => 'register' } do |f|
11 = form_for @user, :url => { :action => 'register' } do |f|
12 %tr
12 %tr
13 %td{:align => "right"}
13 %td{:align => "right"}
14 = "#{t 'login_label'}:"
14 = "#{t 'login_label'}:"
15 %td= f.text_field :login
15 %td= f.text_field :login
16 %tr
16 %tr
17 %td
17 %td
18 %td
18 %td
19 %small
19 %small
20 =t 'registration.login_guide'
20 =t 'registration.login_guide'
21 %tr
21 %tr
22 %td{:align => "right"}
22 %td{:align => "right"}
23 = "#{t 'full_name_label'}:"
23 = "#{t 'full_name_label'}:"
24 %td= f.text_field :full_name
24 %td= f.text_field :full_name
25 %tr
25 %tr
26 %td{:align => "right"}
26 %td{:align => "right"}
27 = "#{t 'email_label'}:"
27 = "#{t 'email_label'}:"
28 - %td= f.text_field :email
28 + %td= f.email_field :email
29 %tr
29 %tr
30 %td
30 %td
31 %td
31 %td
32 %small
32 %small
33 - =t 'registration.email_guide'
33 + =t('registration.email_guide').html_safe
34 %tr
34 %tr
35 %td/
35 %td/
36 %td
36 %td
37 = submit_tag((t 'registration.register'), :name => 'commit')
37 = submit_tag((t 'registration.register'), :name => 'commit')
38 = submit_tag((t 'cancel'), :name => 'cancel')
38 = submit_tag((t 'cancel'), :name => 'cancel')
39
39
@@ -1,37 +1,40
1 CafeGrader::Application.configure do
1 CafeGrader::Application.configure do
2 # Settings specified here will take precedence over those in config/application.rb
2 # Settings specified here will take precedence over those in config/application.rb
3
3
4 # In the development environment your application's code is reloaded on
4 # In the development environment your application's code is reloaded on
5 # every request. This slows down response time but is perfect for development
5 # every request. This slows down response time but is perfect for development
6 # since you don't have to restart the web server when you make code changes.
6 # since you don't have to restart the web server when you make code changes.
7 config.cache_classes = false
7 config.cache_classes = false
8
8
9 # Log error messages when you accidentally call methods on nil.
9 # Log error messages when you accidentally call methods on nil.
10 config.whiny_nils = true
10 config.whiny_nils = true
11
11
12 # Show full error reports and disable caching
12 # Show full error reports and disable caching
13 config.consider_all_requests_local = true
13 config.consider_all_requests_local = true
14 config.action_controller.perform_caching = false
14 config.action_controller.perform_caching = false
15
15
16 # Don't care if the mailer can't send
16 # Don't care if the mailer can't send
17 config.action_mailer.raise_delivery_errors = false
17 config.action_mailer.raise_delivery_errors = false
18
18
19 # Print deprecation notices to the Rails logger
19 # Print deprecation notices to the Rails logger
20 config.active_support.deprecation = :log
20 config.active_support.deprecation = :log
21
21
22 # Only use best-standards-support built into browsers
22 # Only use best-standards-support built into browsers
23 config.action_dispatch.best_standards_support = :builtin
23 config.action_dispatch.best_standards_support = :builtin
24
24
25 # Raise exception on mass assignment protection for Active Record models
25 # Raise exception on mass assignment protection for Active Record models
26 config.active_record.mass_assignment_sanitizer = :strict
26 config.active_record.mass_assignment_sanitizer = :strict
27
27
28 # Log the query plan for queries taking more than this (works
28 # Log the query plan for queries taking more than this (works
29 # with SQLite, MySQL, and PostgreSQL)
29 # with SQLite, MySQL, and PostgreSQL)
30 config.active_record.auto_explain_threshold_in_seconds = 0.5
30 config.active_record.auto_explain_threshold_in_seconds = 0.5
31
31
32 # Do not compress assets
32 # Do not compress assets
33 config.assets.compress = false
33 config.assets.compress = false
34
34
35 # Expands the lines which load the assets
35 # Expands the lines which load the assets
36 config.assets.debug = true
36 config.assets.debug = true
37 +
38 + # Prevents assets from rendering twice
39 + config.serve_static_assets = false
37 end
40 end
@@ -1,30 +1,41
1 module MailHelperMethods
1 module MailHelperMethods
2
2
3 def send_mail(mail_to, mail_subject, mail_body)
3 def send_mail(mail_to, mail_subject, mail_body)
4 mail_from = GraderConfiguration['system.online_registration.from']
4 mail_from = GraderConfiguration['system.online_registration.from']
5 smtp_server = GraderConfiguration['system.online_registration.smtp']
5 smtp_server = GraderConfiguration['system.online_registration.smtp']
6
6
7 if ['fake', 'debug'].include? smtp_server
7 if ['fake', 'debug'].include? smtp_server
8 puts "-------------------------
8 puts "-------------------------
9 To: #{mail_to}
9 To: #{mail_to}
10 From: #{mail_from}
10 From: #{mail_from}
11 Subject: #{mail_subject}
11 Subject: #{mail_subject}
12 #{mail_body}
12 #{mail_body}
13 --------------------------
13 --------------------------
14 "
14 "
15 return true
15 return true
16 end
16 end
17
17
18 mail = Mail.new do
18 mail = Mail.new do
19 from mail_from
19 from mail_from
20 to mail_to
20 to mail_to
21 subject mail_subject
21 subject mail_subject
22 body mail_body
22 body mail_body
23 end
23 end
24
24
25 - mail.delivery_settings = { :address => smtp_server }
25 + mail_option = {
26 + :address => smtp_server,
27 + # :domain => nil,
28 + # :port => 25,
29 + # :user_name => nil,
30 + # :password => nil,
31 + # :authentication=>'plain',
32 + # :enable_starttls_auto => true
33 + }
34 +
35 + mail.delivery_method :smtp, mail_option
36 +
26 mail.deliver
37 mail.deliver
27 end
38 end
28
39
29 end
40 end
30
41
You need to be logged in to leave comments. Login now