Description:
logs out users after contests changed
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r294:069c049fbc3a - - 22 files changed: 191 inserted, 192 deleted

@@ -0,0 +1,87
1 + require 'spec_helper'
2 + require 'config_spec_helper'
3 + require 'delorean'
4 +
5 + describe "ContestManagements" do
6 + include ConfigSpecHelperMethods
7 +
8 + fixtures :users
9 + fixtures :problems
10 + fixtures :contests
11 + fixtures :roles
12 +
13 + before(:each) do
14 + @admin_user = users(:mary)
15 + @contest_b = contests(:contest_b)
16 + @james = users(:james)
17 + @jack = users(:jack)
18 +
19 + set_contest_time_limit('3:00')
20 + set_indv_contest_mode
21 + end
22 +
23 + it "should reset users' timer when their contests change" do
24 + james_session = open_session
25 + james_session.extend(MainSessionMethods)
26 +
27 + james_login_and_get_main_list(james_session)
28 + james_session.response.should_not have_text(/OVER/)
29 +
30 + Delorean.time_travel_to(190.minutes.since) do
31 + james_session.get_main_list
32 + james_session.response.should have_text(/OVER/)
33 +
34 + james_session.get '/' # logout
35 + james_session.get '/main/list' # clearly log out
36 + james_session.response.should_not render_template 'main/list'
37 +
38 + admin_change_users_contest_to("james", @contest_b, true)
39 +
40 + james_login_and_get_main_list(james_session)
41 + james_session.response.should_not have_text(/OVER/)
42 + end
43 + end
44 +
45 + private
46 +
47 + module MainSessionMethods
48 + def login(login_name, password)
49 + post '/login/login', :login => login_name, :password => password
50 + assert_redirected_to '/main/list'
51 + end
52 +
53 + def get_main_list
54 + get '/main/list'
55 + assert_template 'main/list'
56 + end
57 + end
58 +
59 + module ContestManagementSessionMethods
60 + def change_users_contest_to(user_login_list, contest, reset_timer=false)
61 + post_data = {
62 + :contest => {:id => contest.id},
63 + :operation => 'assign',
64 + :login_list => user_login_list
65 + }
66 + post_data[:reset_timer] = true if reset_timer
67 + post '/user_admin/manage_contest', post_data
68 + end
69 + end
70 +
71 + def admin_change_users_contest_to(user_list, contest, reset_timer)
72 + admin_session = open_session
73 + admin_session.extend(MainSessionMethods)
74 + admin_session.extend(ContestManagementSessionMethods)
75 +
76 + admin_session.login('mary','goodbye')
77 + admin_session.get '/main/list'
78 + admin_session.change_users_contest_to(user_list, contest, reset_timer)
79 + end
80 +
81 + def james_login_and_get_main_list(session)
82 + session.login('james', 'morning')
83 + session.get_main_list
84 + end
85 +
86 + end
87 +
@@ -103,225 +103,241
103 render :action => 'edit'
103 render :action => 'edit'
104 end
104 end
105 end
105 end
106
106
107 def destroy
107 def destroy
108 User.find(params[:id]).destroy
108 User.find(params[:id]).destroy
109 redirect_to :action => 'list'
109 redirect_to :action => 'list'
110 end
110 end
111
111
112 def user_stat
112 def user_stat
113 @problems = Problem.find_available_problems
113 @problems = Problem.find_available_problems
114 @users = User.find(:all)
114 @users = User.find(:all)
115 @scorearray = Array.new
115 @scorearray = Array.new
116 @users.each do |u|
116 @users.each do |u|
117 ustat = Array.new
117 ustat = Array.new
118 ustat[0] = u
118 ustat[0] = u
119 @problems.each do |p|
119 @problems.each do |p|
120 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
120 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
121 if (sub!=nil) and (sub.points!=nil)
121 if (sub!=nil) and (sub.points!=nil)
122 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
122 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
123 else
123 else
124 ustat << [0,false]
124 ustat << [0,false]
125 end
125 end
126 end
126 end
127 @scorearray << ustat
127 @scorearray << ustat
128 end
128 end
129 end
129 end
130
130
131 def import
131 def import
132 if params[:file]==''
132 if params[:file]==''
133 flash[:notice] = 'Error importing no file'
133 flash[:notice] = 'Error importing no file'
134 redirect_to :action => 'list' and return
134 redirect_to :action => 'list' and return
135 end
135 end
136 import_from_file(params[:file])
136 import_from_file(params[:file])
137 end
137 end
138
138
139 def random_all_passwords
139 def random_all_passwords
140 users = User.find(:all)
140 users = User.find(:all)
141 @prefix = params[:prefix] || ''
141 @prefix = params[:prefix] || ''
142 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
142 @non_admin_users = User.find_non_admin_with_prefix(@prefix)
143 @changed = false
143 @changed = false
144 if request.request_method == :post
144 if request.request_method == :post
145 @non_admin_users.each do |user|
145 @non_admin_users.each do |user|
146 password = random_password
146 password = random_password
147 user.password = password
147 user.password = password
148 user.password_confirmation = password
148 user.password_confirmation = password
149 user.save
149 user.save
150 end
150 end
151 @changed = true
151 @changed = true
152 end
152 end
153 end
153 end
154
154
155 # contest management
155 # contest management
156
156
157 def add_to_contest
157 def add_to_contest
158 user = User.find(params[:id])
158 user = User.find(params[:id])
159 contest = Contest.find(params[:contest_id])
159 contest = Contest.find(params[:contest_id])
160 if user and contest
160 if user and contest
161 user.contests << contest
161 user.contests << contest
162 end
162 end
163 redirect_to :action => 'list'
163 redirect_to :action => 'list'
164 end
164 end
165
165
166 def remove_from_contest
166 def remove_from_contest
167 user = User.find(params[:id])
167 user = User.find(params[:id])
168 contest = Contest.find(params[:contest_id])
168 contest = Contest.find(params[:contest_id])
169 if user and contest
169 if user and contest
170 user.contests.delete(contest)
170 user.contests.delete(contest)
171 end
171 end
172 redirect_to :action => 'list'
172 redirect_to :action => 'list'
173 end
173 end
174
174
175 def contest_management
175 def contest_management
176 end
176 end
177
177
178 def manage_contest
178 def manage_contest
179 contest = Contest.find(params[:contest][:id])
179 contest = Contest.find(params[:contest][:id])
180 if !contest
180 if !contest
181 flash[:notice] = 'You did not choose the contest.'
181 flash[:notice] = 'You did not choose the contest.'
182 redirect_to :action => 'contest_management' and return
182 redirect_to :action => 'contest_management' and return
183 end
183 end
184
184
185 operation = params[:operation]
185 operation = params[:operation]
186
186
187 if not ['add','remove','assign'].include? operation
187 if not ['add','remove','assign'].include? operation
188 flash[:notice] = 'You did not choose the operation to perform.'
188 flash[:notice] = 'You did not choose the operation to perform.'
189 redirect_to :action => 'contest_management' and return
189 redirect_to :action => 'contest_management' and return
190 end
190 end
191
191
192 lines = params[:login_list]
192 lines = params[:login_list]
193 if !lines or lines.blank?
193 if !lines or lines.blank?
194 flash[:notice] = 'You entered an empty list.'
194 flash[:notice] = 'You entered an empty list.'
195 redirect_to :action => 'contest_management' and return
195 redirect_to :action => 'contest_management' and return
196 end
196 end
197
197
198 note = []
198 note = []
199 + user_ids = {}
199 lines.split("\n").each do |line|
200 lines.split("\n").each do |line|
200 - puts line
201 user = User.find_by_login(line.chomp)
201 user = User.find_by_login(line.chomp)
202 - puts user
203 if user
202 if user
204 if operation=='add'
203 if operation=='add'
205 - user.contests << contest
204 + if ! user.contests.include? contest
205 + user.contests << contest
206 + end
206 elsif operation=='remove'
207 elsif operation=='remove'
207 user.contests.delete(contest)
208 user.contests.delete(contest)
208 else
209 else
209 user.contests = [contest]
210 user.contests = [contest]
210 end
211 end
211 -
212 +
212 user.contest_stat.destroy if params[:reset_timer]
213 user.contest_stat.destroy if params[:reset_timer]
213
214
214 note << user.login
215 note << user.login
216 + user_ids[user.id] = true
215 end
217 end
216 end
218 end
219 +
220 + if params[:reset_timer]
221 + logout_users(user_ids)
222 + end
223 +
217 flash[:notice] = 'User(s) ' + note.join(', ') +
224 flash[:notice] = 'User(s) ' + note.join(', ') +
218 ' were successfully modified. '
225 ' were successfully modified. '
219 redirect_to :action => 'contest_management'
226 redirect_to :action => 'contest_management'
220 end
227 end
221
228
222 # admin management
229 # admin management
223
230
224 def admin
231 def admin
225 @admins = User.find(:all).find_all {|user| user.admin? }
232 @admins = User.find(:all).find_all {|user| user.admin? }
226 end
233 end
227
234
228 def grant_admin
235 def grant_admin
229 login = params[:login]
236 login = params[:login]
230 user = User.find_by_login(login)
237 user = User.find_by_login(login)
231 if user!=nil
238 if user!=nil
232 admin_role = Role.find_by_name('admin')
239 admin_role = Role.find_by_name('admin')
233 user.roles << admin_role
240 user.roles << admin_role
234 else
241 else
235 flash[:notice] = 'Unknown user'
242 flash[:notice] = 'Unknown user'
236 end
243 end
237 flash[:notice] = 'User added as admins'
244 flash[:notice] = 'User added as admins'
238 redirect_to :action => 'admin'
245 redirect_to :action => 'admin'
239 end
246 end
240
247
241 def revoke_admin
248 def revoke_admin
242 user = User.find(params[:id])
249 user = User.find(params[:id])
243 if user==nil
250 if user==nil
244 flash[:notice] = 'Unknown user'
251 flash[:notice] = 'Unknown user'
245 redirect_to :action => 'admin' and return
252 redirect_to :action => 'admin' and return
246 elsif user.login == 'root'
253 elsif user.login == 'root'
247 flash[:notice] = 'You cannot revoke admisnistrator permission from root.'
254 flash[:notice] = 'You cannot revoke admisnistrator permission from root.'
248 redirect_to :action => 'admin' and return
255 redirect_to :action => 'admin' and return
249 end
256 end
250
257
251 admin_role = Role.find_by_name('admin')
258 admin_role = Role.find_by_name('admin')
252 user.roles.delete(admin_role)
259 user.roles.delete(admin_role)
253 flash[:notice] = 'User permission revoked'
260 flash[:notice] = 'User permission revoked'
254 redirect_to :action => 'admin'
261 redirect_to :action => 'admin'
255 end
262 end
256
263
257 protected
264 protected
258
265
259 def random_password(length=5)
266 def random_password(length=5)
260 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
267 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
261 newpass = ""
268 newpass = ""
262 length.times { newpass << chars[rand(chars.size-1)] }
269 length.times { newpass << chars[rand(chars.size-1)] }
263 return newpass
270 return newpass
264 end
271 end
265
272
266 def import_from_file(f)
273 def import_from_file(f)
267 data_hash = YAML.load(f)
274 data_hash = YAML.load(f)
268 @import_log = ""
275 @import_log = ""
269
276
270 country_data = data_hash[:countries]
277 country_data = data_hash[:countries]
271 site_data = data_hash[:sites]
278 site_data = data_hash[:sites]
272 user_data = data_hash[:users]
279 user_data = data_hash[:users]
273
280
274 # import country
281 # import country
275 countries = {}
282 countries = {}
276 country_data.each_pair do |id,country|
283 country_data.each_pair do |id,country|
277 c = Country.find_by_name(country[:name])
284 c = Country.find_by_name(country[:name])
278 if c!=nil
285 if c!=nil
279 countries[id] = c
286 countries[id] = c
280 @import_log << "Found #{country[:name]}\n"
287 @import_log << "Found #{country[:name]}\n"
281 else
288 else
282 countries[id] = Country.new(:name => country[:name])
289 countries[id] = Country.new(:name => country[:name])
283 countries[id].save
290 countries[id].save
284 @import_log << "Created #{country[:name]}\n"
291 @import_log << "Created #{country[:name]}\n"
285 end
292 end
286 end
293 end
287
294
288 # import sites
295 # import sites
289 sites = {}
296 sites = {}
290 site_data.each_pair do |id,site|
297 site_data.each_pair do |id,site|
291 s = Site.find_by_name(site[:name])
298 s = Site.find_by_name(site[:name])
292 if s!=nil
299 if s!=nil
293 @import_log << "Found #{site[:name]}\n"
300 @import_log << "Found #{site[:name]}\n"
294 else
301 else
295 s = Site.new(:name => site[:name])
302 s = Site.new(:name => site[:name])
296 @import_log << "Created #{site[:name]}\n"
303 @import_log << "Created #{site[:name]}\n"
297 end
304 end
298 s.password = site[:password]
305 s.password = site[:password]
299 s.country = countries[site[:country_id]]
306 s.country = countries[site[:country_id]]
300 s.save
307 s.save
301 sites[id] = s
308 sites[id] = s
302 end
309 end
303
310
304 # import users
311 # import users
305 user_data.each_pair do |id,user|
312 user_data.each_pair do |id,user|
306 u = User.find_by_login(user[:login])
313 u = User.find_by_login(user[:login])
307 if u!=nil
314 if u!=nil
308 @import_log << "Found #{user[:login]}\n"
315 @import_log << "Found #{user[:login]}\n"
309 else
316 else
310 u = User.new(:login => user[:login])
317 u = User.new(:login => user[:login])
311 @import_log << "Created #{user[:login]}\n"
318 @import_log << "Created #{user[:login]}\n"
312 end
319 end
313 u.full_name = user[:name]
320 u.full_name = user[:name]
314 u.password = user[:password]
321 u.password = user[:password]
315 u.country = countries[user[:country_id]]
322 u.country = countries[user[:country_id]]
316 u.site = sites[user[:site_id]]
323 u.site = sites[user[:site_id]]
317 u.activated = true
324 u.activated = true
318 u.email = "empty-#{u.login}@none.com"
325 u.email = "empty-#{u.login}@none.com"
319 if not u.save
326 if not u.save
320 @import_log << "Errors\n"
327 @import_log << "Errors\n"
321 u.errors.each { |attr,msg| @import_log << "#{attr} - #{msg}\n" }
328 u.errors.each { |attr,msg| @import_log << "#{attr} - #{msg}\n" }
322 end
329 end
323 end
330 end
324
331
325 end
332 end
326
333
334 + def logout_users(user_ids)
335 + sessions = ActiveRecord::SessionStore::Session.find(:all, :conditions => ["updated_at >= ?", 60.minutes.ago])
336 + sessions.each do |session|
337 + if user_ids.has_key? session.data[:user_id]
338 + session.destroy
339 + end
340 + end
341 + end
342 +
327 end
343 end
@@ -1,183 +1,184
1 require 'yaml'
1 require 'yaml'
2
2
3 #
3 #
4 # This class also contains various login of the system.
4 # This class also contains various login of the system.
5 #
5 #
6 class Configuration < ActiveRecord::Base
6 class Configuration < ActiveRecord::Base
7
7
8 SYSTEM_MODE_CONF_KEY = 'system.mode'
8 SYSTEM_MODE_CONF_KEY = 'system.mode'
9 TEST_REQUEST_EARLY_TIMEOUT_KEY = 'contest.test_request.early_timeout'
9 TEST_REQUEST_EARLY_TIMEOUT_KEY = 'contest.test_request.early_timeout'
10 + MULTICONTESTS_KEY = 'system.multicontests'
11 + CONTEST_TIME_LIMIT_KEY = 'contest.time_limit'
10
12
11 cattr_accessor :cache
13 cattr_accessor :cache
12 cattr_accessor :config_cache
14 cattr_accessor :config_cache
13 cattr_accessor :task_grading_info_cache
15 cattr_accessor :task_grading_info_cache
14 cattr_accessor :contest_time_str
16 cattr_accessor :contest_time_str
15 cattr_accessor :contest_time
17 cattr_accessor :contest_time
16
18
17 # set @@cache = true to only reload once.
19 # set @@cache = true to only reload once.
18 Configuration.cache = false
20 Configuration.cache = false
19
21
20 Configuration.config_cache = nil
22 Configuration.config_cache = nil
21 Configuration.task_grading_info_cache = nil
23 Configuration.task_grading_info_cache = nil
22
24
23 def self.get(key)
25 def self.get(key)
24 if Configuration.cache
26 if Configuration.cache
25 if Configuration.config_cache == nil
27 if Configuration.config_cache == nil
26 self.read_config
28 self.read_config
27 end
29 end
28 return Configuration.config_cache[key]
30 return Configuration.config_cache[key]
29 else
31 else
30 return Configuration.read_one_key(key)
32 return Configuration.read_one_key(key)
31 end
33 end
32 end
34 end
33
35
34 def self.[](key)
36 def self.[](key)
35 self.get(key)
37 self.get(key)
36 end
38 end
37
39
38 def self.reload
40 def self.reload
39 self.read_config
41 self.read_config
40 end
42 end
41
43
42 def self.clear
44 def self.clear
43 Configuration.config_cache = nil
45 Configuration.config_cache = nil
44 end
46 end
45
47
46 def self.cache?
48 def self.cache?
47 Configuration.cache
49 Configuration.cache
48 end
50 end
49
51
50 def self.enable_caching
52 def self.enable_caching
51 Configuration.cache = true
53 Configuration.cache = true
52 end
54 end
53
55
54 #
56 #
55 # View decision
57 # View decision
56 #
58 #
57 def self.show_submitbox_to?(user)
59 def self.show_submitbox_to?(user)
58 mode = get(SYSTEM_MODE_CONF_KEY)
60 mode = get(SYSTEM_MODE_CONF_KEY)
59 return false if mode=='analysis'
61 return false if mode=='analysis'
60 if (mode=='contest')
62 if (mode=='contest')
61 return false if (user.site!=nil) and
63 return false if (user.site!=nil) and
62 ((user.site.started!=true) or (user.site.finished?))
64 ((user.site.started!=true) or (user.site.finished?))
63 end
65 end
64 return true
66 return true
65 end
67 end
66
68
67 def self.show_tasks_to?(user)
69 def self.show_tasks_to?(user)
68 if time_limit_mode?
70 if time_limit_mode?
69 return false if not user.contest_started?
71 return false if not user.contest_started?
70 end
72 end
71 return true
73 return true
72 end
74 end
73
75
74 def self.show_grading_result
76 def self.show_grading_result
75 return (get(SYSTEM_MODE_CONF_KEY)=='analysis')
77 return (get(SYSTEM_MODE_CONF_KEY)=='analysis')
76 end
78 end
77
79
78 def self.allow_test_request(user)
80 def self.allow_test_request(user)
79 mode = get(SYSTEM_MODE_CONF_KEY)
81 mode = get(SYSTEM_MODE_CONF_KEY)
80 early_timeout = get(TEST_REQUEST_EARLY_TIMEOUT_KEY)
82 early_timeout = get(TEST_REQUEST_EARLY_TIMEOUT_KEY)
81 if (mode=='contest')
83 if (mode=='contest')
82 return false if ((user.site!=nil) and
84 return false if ((user.site!=nil) and
83 ((user.site.started!=true) or
85 ((user.site.started!=true) or
84 (early_timeout and (user.site.time_left < 30.minutes))))
86 (early_timeout and (user.site.time_left < 30.minutes))))
85 end
87 end
86 return false if mode=='analysis'
88 return false if mode=='analysis'
87 return true
89 return true
88 end
90 end
89
91
90 def self.task_grading_info
92 def self.task_grading_info
91 if Configuration.task_grading_info_cache==nil
93 if Configuration.task_grading_info_cache==nil
92 read_grading_info
94 read_grading_info
93 end
95 end
94 return Configuration.task_grading_info_cache
96 return Configuration.task_grading_info_cache
95 end
97 end
96
98
97 def self.standard_mode?
99 def self.standard_mode?
98 return get(SYSTEM_MODE_CONF_KEY) == 'standard'
100 return get(SYSTEM_MODE_CONF_KEY) == 'standard'
99 end
101 end
100
102
101 def self.contest_mode?
103 def self.contest_mode?
102 return get(SYSTEM_MODE_CONF_KEY) == 'contest'
104 return get(SYSTEM_MODE_CONF_KEY) == 'contest'
103 end
105 end
104
106
105 def self.indv_contest_mode?
107 def self.indv_contest_mode?
106 return get(SYSTEM_MODE_CONF_KEY) == 'indv-contest'
108 return get(SYSTEM_MODE_CONF_KEY) == 'indv-contest'
107 end
109 end
108
110
109 def self.multicontests?
111 def self.multicontests?
110 - g = get('system.multicontests')
112 + return get(MULTICONTESTS_KEY) == true
111 - return get('system.multicontests') == true
112 end
113 end
113
114
114 def self.time_limit_mode?
115 def self.time_limit_mode?
115 mode = get(SYSTEM_MODE_CONF_KEY)
116 mode = get(SYSTEM_MODE_CONF_KEY)
116 return ((mode == 'contest') or (mode == 'indv-contest'))
117 return ((mode == 'contest') or (mode == 'indv-contest'))
117 end
118 end
118
119
119 def self.analysis_mode?
120 def self.analysis_mode?
120 return get(SYSTEM_MODE_CONF_KEY) == 'analysis'
121 return get(SYSTEM_MODE_CONF_KEY) == 'analysis'
121 end
122 end
122
123
123 def self.contest_time_limit
124 def self.contest_time_limit
124 - contest_time_str = Configuration['contest.time_limit']
125 + contest_time_str = Configuration[CONTEST_TIME_LIMIT_KEY]
125
126
126 if not defined? Configuration.contest_time_str
127 if not defined? Configuration.contest_time_str
127 Configuration.contest_time_str = nil
128 Configuration.contest_time_str = nil
128 end
129 end
129
130
130 if Configuration.contest_time_str != contest_time_str
131 if Configuration.contest_time_str != contest_time_str
131 Configuration.contest_time_str = contest_time_str
132 Configuration.contest_time_str = contest_time_str
132 if tmatch = /(\d+):(\d+)/.match(contest_time_str)
133 if tmatch = /(\d+):(\d+)/.match(contest_time_str)
133 h = tmatch[1].to_i
134 h = tmatch[1].to_i
134 m = tmatch[2].to_i
135 m = tmatch[2].to_i
135
136
136 Configuration.contest_time = h.hour + m.minute
137 Configuration.contest_time = h.hour + m.minute
137 else
138 else
138 Configuration.contest_time = nil
139 Configuration.contest_time = nil
139 end
140 end
140 end
141 end
141 return Configuration.contest_time
142 return Configuration.contest_time
142 end
143 end
143
144
144 protected
145 protected
145
146
146 def self.convert_type(val,type)
147 def self.convert_type(val,type)
147 case type
148 case type
148 when 'string'
149 when 'string'
149 return val
150 return val
150
151
151 when 'integer'
152 when 'integer'
152 return val.to_i
153 return val.to_i
153
154
154 when 'boolean'
155 when 'boolean'
155 return (val=='true')
156 return (val=='true')
156 end
157 end
157 end
158 end
158
159
159 def self.read_config
160 def self.read_config
160 Configuration.config_cache = {}
161 Configuration.config_cache = {}
161 Configuration.find(:all).each do |conf|
162 Configuration.find(:all).each do |conf|
162 key = conf.key
163 key = conf.key
163 val = conf.value
164 val = conf.value
164 Configuration.config_cache[key] = Configuration.convert_type(val,conf.value_type)
165 Configuration.config_cache[key] = Configuration.convert_type(val,conf.value_type)
165 end
166 end
166 end
167 end
167
168
168 def self.read_one_key(key)
169 def self.read_one_key(key)
169 conf = Configuration.find_by_key(key)
170 conf = Configuration.find_by_key(key)
170 if conf
171 if conf
171 return Configuration.convert_type(conf.value,conf.value_type)
172 return Configuration.convert_type(conf.value,conf.value_type)
172 else
173 else
173 return nil
174 return nil
174 end
175 end
175 end
176 end
176
177
177 def self.read_grading_info
178 def self.read_grading_info
178 f = File.open(TASK_GRADING_INFO_FILENAME)
179 f = File.open(TASK_GRADING_INFO_FILENAME)
179 Configuration.task_grading_info_cache = YAML.load(f)
180 Configuration.task_grading_info_cache = YAML.load(f)
180 f.close
181 f.close
181 end
182 end
182
183
183 end
184 end
@@ -61,196 +61,193
61
61
62 def authenticated?(password)
62 def authenticated?(password)
63 if self.activated
63 if self.activated
64 hashed_password == User.encrypt(password,self.salt)
64 hashed_password == User.encrypt(password,self.salt)
65 else
65 else
66 false
66 false
67 end
67 end
68 end
68 end
69
69
70 def admin?
70 def admin?
71 self.roles.detect {|r| r.name == 'admin' }
71 self.roles.detect {|r| r.name == 'admin' }
72 end
72 end
73
73
74 def email_for_editing
74 def email_for_editing
75 if self.email==nil
75 if self.email==nil
76 "(unknown)"
76 "(unknown)"
77 elsif self.email==''
77 elsif self.email==''
78 "(blank)"
78 "(blank)"
79 else
79 else
80 self.email
80 self.email
81 end
81 end
82 end
82 end
83
83
84 def email_for_editing=(e)
84 def email_for_editing=(e)
85 self.email=e
85 self.email=e
86 end
86 end
87
87
88 def alias_for_editing
88 def alias_for_editing
89 if self.alias==nil
89 if self.alias==nil
90 "(unknown)"
90 "(unknown)"
91 elsif self.alias==''
91 elsif self.alias==''
92 "(blank)"
92 "(blank)"
93 else
93 else
94 self.alias
94 self.alias
95 end
95 end
96 end
96 end
97
97
98 def alias_for_editing=(e)
98 def alias_for_editing=(e)
99 self.alias=e
99 self.alias=e
100 end
100 end
101
101
102 def activation_key
102 def activation_key
103 if self.hashed_password==nil
103 if self.hashed_password==nil
104 encrypt_new_password
104 encrypt_new_password
105 end
105 end
106 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
106 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
107 end
107 end
108
108
109 def verify_activation_key(key)
109 def verify_activation_key(key)
110 key == activation_key
110 key == activation_key
111 end
111 end
112
112
113 def self.random_password(length=5)
113 def self.random_password(length=5)
114 chars = 'abcdefghjkmnopqrstuvwxyz'
114 chars = 'abcdefghjkmnopqrstuvwxyz'
115 password = ''
115 password = ''
116 length.times { password << chars[rand(chars.length - 1)] }
116 length.times { password << chars[rand(chars.length - 1)] }
117 password
117 password
118 end
118 end
119
119
120 def self.find_non_admin_with_prefix(prefix='')
120 def self.find_non_admin_with_prefix(prefix='')
121 users = User.find(:all)
121 users = User.find(:all)
122 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
122 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
123 end
123 end
124
124
125 # Contest information
125 # Contest information
126
126
127 def contest_time_left
127 def contest_time_left
128 if Configuration.contest_mode?
128 if Configuration.contest_mode?
129 return nil if site==nil
129 return nil if site==nil
130 return site.time_left
130 return site.time_left
131 elsif Configuration.indv_contest_mode?
131 elsif Configuration.indv_contest_mode?
132 time_limit = Configuration.contest_time_limit
132 time_limit = Configuration.contest_time_limit
133 if time_limit == nil
133 if time_limit == nil
134 return nil
134 return nil
135 end
135 end
136 if contest_stat==nil
136 if contest_stat==nil
137 return (Time.now.gmtime + time_limit) - Time.now.gmtime
137 return (Time.now.gmtime + time_limit) - Time.now.gmtime
138 else
138 else
139 finish_time = contest_stat.started_at + time_limit
139 finish_time = contest_stat.started_at + time_limit
140 current_time = Time.now.gmtime
140 current_time = Time.now.gmtime
141 if current_time > finish_time
141 if current_time > finish_time
142 return 0
142 return 0
143 else
143 else
144 return finish_time - current_time
144 return finish_time - current_time
145 end
145 end
146 end
146 end
147 else
147 else
148 return nil
148 return nil
149 end
149 end
150 end
150 end
151
151
152 def contest_finished?
152 def contest_finished?
153 if Configuration.contest_mode?
153 if Configuration.contest_mode?
154 return false if site==nil
154 return false if site==nil
155 return site.finished?
155 return site.finished?
156 elsif Configuration.indv_contest_mode?
156 elsif Configuration.indv_contest_mode?
157 - time_limit = Configuration.contest_time_limit
157 + return false if self.contest_stat(true)==nil
158 -
159 - return false if contest_stat==nil
160 -
161 return contest_time_left == 0
158 return contest_time_left == 0
162 else
159 else
163 return false
160 return false
164 end
161 end
165 end
162 end
166
163
167 def contest_started?
164 def contest_started?
168 if Configuration.contest_mode?
165 if Configuration.contest_mode?
169 return true if site==nil
166 return true if site==nil
170 return site.started
167 return site.started
171 else
168 else
172 return true
169 return true
173 end
170 end
174 end
171 end
175
172
176 def update_start_time
173 def update_start_time
177 stat = self.contest_stat
174 stat = self.contest_stat
178 if stat == nil
175 if stat == nil
179 stat = UserContestStat.new(:user => self,
176 stat = UserContestStat.new(:user => self,
180 :started_at => Time.now.gmtime)
177 :started_at => Time.now.gmtime)
181 stat.save
178 stat.save
182 end
179 end
183 end
180 end
184
181
185 def problem_in_user_contests?(problem)
182 def problem_in_user_contests?(problem)
186 problem_contests = problem.contests.all
183 problem_contests = problem.contests.all
187
184
188 if problem_contests.length == 0 # this is public contest
185 if problem_contests.length == 0 # this is public contest
189 return true
186 return true
190 end
187 end
191
188
192 contests.each do |contest|
189 contests.each do |contest|
193 if problem_contests.find {|c| c.id == contest.id }
190 if problem_contests.find {|c| c.id == contest.id }
194 return true
191 return true
195 end
192 end
196 end
193 end
197 return false
194 return false
198 end
195 end
199
196
200 def available_problems_group_by_contests
197 def available_problems_group_by_contests
201 contest_problems = []
198 contest_problems = []
202 pin = {}
199 pin = {}
203 contests.enabled.each do |contest|
200 contests.enabled.each do |contest|
204 available_problems = contest.problems.available
201 available_problems = contest.problems.available
205 contest_problems << {
202 contest_problems << {
206 :contest => contest,
203 :contest => contest,
207 :problems => available_problems
204 :problems => available_problems
208 }
205 }
209 available_problems.each {|p| pin[p.id] = true}
206 available_problems.each {|p| pin[p.id] = true}
210 end
207 end
211 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
208 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
212 contest_problems << {
209 contest_problems << {
213 :contest => nil,
210 :contest => nil,
214 :problems => other_avaiable_problems
211 :problems => other_avaiable_problems
215 }
212 }
216 return contest_problems
213 return contest_problems
217 end
214 end
218
215
219 def available_problems
216 def available_problems
220 if not Configuration.multicontests?
217 if not Configuration.multicontests?
221 return Problem.find_available_problems
218 return Problem.find_available_problems
222 else
219 else
223 contest_problems = []
220 contest_problems = []
224 pin = {}
221 pin = {}
225 contests.enabled.each do |contest|
222 contests.enabled.each do |contest|
226 contest.problems.available.each do |problem|
223 contest.problems.available.each do |problem|
227 if not pin.has_key? problem.id
224 if not pin.has_key? problem.id
228 contest_problems << problem
225 contest_problems << problem
229 end
226 end
230 pin[problem.id] = true
227 pin[problem.id] = true
231 end
228 end
232 end
229 end
233 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
230 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
234 return contest_problems + other_avaiable_problems
231 return contest_problems + other_avaiable_problems
235 end
232 end
236 end
233 end
237
234
238 def can_view_problem?(problem)
235 def can_view_problem?(problem)
239 if not Configuration.multicontests?
236 if not Configuration.multicontests?
240 return problem.available
237 return problem.available
241 else
238 else
242 return problem_in_user_contests? problem
239 return problem_in_user_contests? problem
243 end
240 end
244 end
241 end
245
242
246 protected
243 protected
247 def encrypt_new_password
244 def encrypt_new_password
248 return if password.blank?
245 return if password.blank?
249 self.salt = (10+rand(90)).to_s
246 self.salt = (10+rand(90)).to_s
250 self.hashed_password = User.encrypt(self.password,self.salt)
247 self.hashed_password = User.encrypt(self.password,self.salt)
251 end
248 end
252
249
253 def assign_default_site
250 def assign_default_site
254 # have to catch error when migrating (because self.site is not available).
251 # have to catch error when migrating (because self.site is not available).
255 begin
252 begin
256 if self.site==nil
253 if self.site==nil
@@ -1,128 +1,128
1 CONFIGURATIONS =
1 CONFIGURATIONS =
2 [
2 [
3 {
3 {
4 :key => 'system.single_user_mode',
4 :key => 'system.single_user_mode',
5 :value_type => 'boolean',
5 :value_type => 'boolean',
6 :default_value => 'false',
6 :default_value => 'false',
7 :description => 'Only admins can log in to the system when running under single user mode.'
7 :description => 'Only admins can log in to the system when running under single user mode.'
8 },
8 },
9
9
10 {
10 {
11 :key => 'ui.front.title',
11 :key => 'ui.front.title',
12 :value_type => 'string',
12 :value_type => 'string',
13 :default_value => 'Grader'
13 :default_value => 'Grader'
14 },
14 },
15
15
16 {
16 {
17 :key => 'ui.front.welcome_message',
17 :key => 'ui.front.welcome_message',
18 :value_type => 'string',
18 :value_type => 'string',
19 :default_value => 'Welcome!'
19 :default_value => 'Welcome!'
20 },
20 },
21
21
22 {
22 {
23 :key => 'ui.show_score',
23 :key => 'ui.show_score',
24 :value_type => 'boolean',
24 :value_type => 'boolean',
25 :default_value => 'true'
25 :default_value => 'true'
26 },
26 },
27
27
28 {
28 {
29 :key => 'contest.time_limit',
29 :key => 'contest.time_limit',
30 :value_type => 'string',
30 :value_type => 'string',
31 :default_value => 'unlimited',
31 :default_value => 'unlimited',
32 - :description => 'Time limit in format hh:mm, or "unlimited" for contests with no time limits.'
32 + :description => 'Time limit in format hh:mm, or "unlimited" for contests with no time limits. This config is CACHED. Restart the server before the change can take effect.'
33 },
33 },
34
34
35 {
35 {
36 :key => 'system.mode',
36 :key => 'system.mode',
37 :value_type => 'string',
37 :value_type => 'string',
38 :default_value => 'standard',
38 :default_value => 'standard',
39 :description => 'Current modes are "standard", "contest", "indv-contest", and "analysis".'
39 :description => 'Current modes are "standard", "contest", "indv-contest", and "analysis".'
40 },
40 },
41
41
42 {
42 {
43 :key => 'contest.name',
43 :key => 'contest.name',
44 :value_type => 'string',
44 :value_type => 'string',
45 :default_value => 'Grader',
45 :default_value => 'Grader',
46 :description => 'This name will be shown on the user header bar.'
46 :description => 'This name will be shown on the user header bar.'
47 },
47 },
48
48
49 {
49 {
50 :key => 'contest.multisites',
50 :key => 'contest.multisites',
51 :value_type => 'boolean',
51 :value_type => 'boolean',
52 :default_value => 'false',
52 :default_value => 'false',
53 :description => 'If the server is in contest mode and this option is true, on the log in of the admin a menu for site selections is shown.'
53 :description => 'If the server is in contest mode and this option is true, on the log in of the admin a menu for site selections is shown.'
54 },
54 },
55
55
56 {
56 {
57 :key => 'system.online_registration',
57 :key => 'system.online_registration',
58 :value_type => 'boolean',
58 :value_type => 'boolean',
59 :default_value => 'false',
59 :default_value => 'false',
60 :description => 'This option enables online registration.'
60 :description => 'This option enables online registration.'
61 },
61 },
62
62
63 # If Configuration['system.online_registration'] is true, the
63 # If Configuration['system.online_registration'] is true, the
64 # system allows online registration, and will use these
64 # system allows online registration, and will use these
65 # information for sending confirmation emails.
65 # information for sending confirmation emails.
66 {
66 {
67 :key => 'system.online_registration.smtp',
67 :key => 'system.online_registration.smtp',
68 :value_type => 'string',
68 :value_type => 'string',
69 :default_value => 'smtp.somehost.com'
69 :default_value => 'smtp.somehost.com'
70 },
70 },
71
71
72 {
72 {
73 :key => 'system.online_registration.from',
73 :key => 'system.online_registration.from',
74 :value_type => 'string',
74 :value_type => 'string',
75 :default_value => 'your.email@address'
75 :default_value => 'your.email@address'
76 },
76 },
77
77
78 {
78 {
79 :key => 'system.admin_email',
79 :key => 'system.admin_email',
80 :value_type => 'string',
80 :value_type => 'string',
81 :default_value => 'admin@admin.email'
81 :default_value => 'admin@admin.email'
82 },
82 },
83
83
84 {
84 {
85 :key => 'system.user_setting_enabled',
85 :key => 'system.user_setting_enabled',
86 :value_type => 'boolean',
86 :value_type => 'boolean',
87 :default_value => 'true',
87 :default_value => 'true',
88 :description => 'If this option is true, users can change their settings'
88 :description => 'If this option is true, users can change their settings'
89 },
89 },
90
90
91 # If Configuration['contest.test_request.early_timeout'] is true
91 # If Configuration['contest.test_request.early_timeout'] is true
92 # the user will not be able to use test request at 30 minutes
92 # the user will not be able to use test request at 30 minutes
93 # before the contest ends.
93 # before the contest ends.
94 {
94 {
95 :key => 'contest.test_request.early_timeout',
95 :key => 'contest.test_request.early_timeout',
96 :value_type => 'boolean',
96 :value_type => 'boolean',
97 :default_value => 'false'
97 :default_value => 'false'
98 },
98 },
99
99
100 {
100 {
101 :key => 'system.multicontests',
101 :key => 'system.multicontests',
102 :value_type => 'boolean',
102 :value_type => 'boolean',
103 :default_value => 'false'
103 :default_value => 'false'
104 }
104 }
105 ]
105 ]
106
106
107
107
108 def create_configuration_key(key,
108 def create_configuration_key(key,
109 value_type,
109 value_type,
110 default_value,
110 default_value,
111 description='')
111 description='')
112 conf = (Configuration.find_by_key(key) ||
112 conf = (Configuration.find_by_key(key) ||
113 Configuration.new(:key => key,
113 Configuration.new(:key => key,
114 :value_type => value_type,
114 :value_type => value_type,
115 :value => default_value))
115 :value => default_value))
116 conf.description = description
116 conf.description = description
117 conf.save
117 conf.save
118 end
118 end
119
119
120 def seed_config
120 def seed_config
121 CONFIGURATIONS.each do |conf|
121 CONFIGURATIONS.each do |conf|
122 if conf.has_key? :description
122 if conf.has_key? :description
123 desc = conf[:description]
123 desc = conf[:description]
124 else
124 else
125 desc = ''
125 desc = ''
126 end
126 end
127 create_configuration_key(conf[:key],
127 create_configuration_key(conf[:key],
128 conf[:value_type],
128 conf[:value_type],
@@ -1,20 +1,38
1
1
2 module ConfigSpecHelperMethods
2 module ConfigSpecHelperMethods
3
3
4 def find_or_create_and_set_config(key, type, value)
4 def find_or_create_and_set_config(key, type, value)
5 c = Configuration.find_by_key(key)
5 c = Configuration.find_by_key(key)
6 c ||= Configuration.new(:key => key,
6 c ||= Configuration.new(:key => key,
7 :value_type => type)
7 :value_type => type)
8 c.value = value
8 c.value = value
9 c.save!
9 c.save!
10 end
10 end
11
11
12 def enable_multicontest
12 def enable_multicontest
13 - find_or_create_and_set_config('system.multicontests','boolean','true')
13 + find_or_create_and_set_config(Configuration::MULTICONTESTS_KEY,
14 + 'boolean','true')
14 end
15 end
15
16
16 def disable_multicontest
17 def disable_multicontest
17 - find_or_create_and_set_config('system.multicontests','boolean','false')
18 + find_or_create_and_set_config(Configuration::MULTICONTESTS_KEY,
19 + 'boolean','false')
20 + end
21 +
22 + def set_indv_contest_mode
23 + find_or_create_and_set_config(Configuration::SYSTEM_MODE_CONF_KEY,
24 + 'string','indv-contest')
18 end
25 end
19
26
27 + def set_standard_mode
28 + find_or_create_and_set_config(Configuration::SYSTEM_MODE_CONF_KEY,
29 + 'string','standard')
30 + end
31 +
32 + def set_contest_time_limit(limit)
33 + find_or_create_and_set_config(Configuration::CONTEST_TIME_LIMIT_KEY,
34 + 'string',limit)
35 + # clear old value
36 + Configuration.contest_time_str = nil
37 + end
20 end
38 end
@@ -1,144 +1,193
1 + require 'delorean'
2 +
1 require File.dirname(__FILE__) + '/../spec_helper'
3 require File.dirname(__FILE__) + '/../spec_helper'
2 require File.dirname(__FILE__) + '/../config_spec_helper'
4 require File.dirname(__FILE__) + '/../config_spec_helper'
3
5
4 describe MainController, "when a user comes to list page" do
6 describe MainController, "when a user comes to list page" do
5
7
6 it "should redirect user to login page when unlogged-in user try to access main/list" do
8 it "should redirect user to login page when unlogged-in user try to access main/list" do
7 get 'list'
9 get 'list'
8 response.should redirect_to(:action => 'login')
10 response.should redirect_to(:action => 'login')
9 end
11 end
10
12
11 end
13 end
12
14
13 describe MainController, "when a logged in user comes to list page, with multicontests off" do
15 describe MainController, "when a logged in user comes to list page, with multicontests off" do
14 integrate_views
16 integrate_views
15
17
16 include ConfigSpecHelperMethods
18 include ConfigSpecHelperMethods
17
19
18 fixtures :users
20 fixtures :users
19 fixtures :problems
21 fixtures :problems
20 fixtures :contests
22 fixtures :contests
21
23
22 before(:each) do
24 before(:each) do
23 disable_multicontest
25 disable_multicontest
24 end
26 end
25
27
26 it "should list available problems" do
28 it "should list available problems" do
27 john = users(:john)
29 john = users(:john)
28 get "list", {}, {:user_id => john.id}
30 get "list", {}, {:user_id => john.id}
29
31
30 response.should render_template 'main/list'
32 response.should render_template 'main/list'
31 response.should have_text(/add/)
33 response.should have_text(/add/)
32 response.should have_text(/easy_problem/)
34 response.should have_text(/easy_problem/)
33 response.should have_text(/hard_problem/)
35 response.should have_text(/hard_problem/)
34 end
36 end
35
37
36 end
38 end
37
39
38 describe MainController, "when a logged in user comes to list page, with multicontests on" do
40 describe MainController, "when a logged in user comes to list page, with multicontests on" do
39 integrate_views
41 integrate_views
40
42
41 include ConfigSpecHelperMethods
43 include ConfigSpecHelperMethods
42
44
43 fixtures :users
45 fixtures :users
44 fixtures :problems
46 fixtures :problems
45 fixtures :contests
47 fixtures :contests
46
48
47 before(:each) do
49 before(:each) do
48 enable_multicontest
50 enable_multicontest
49 end
51 end
50
52
51 it "should list only available public problems to users with no contest assigned" do
53 it "should list only available public problems to users with no contest assigned" do
52 john = users(:john)
54 john = users(:john)
53 get "list", {}, {:user_id => john.id}
55 get "list", {}, {:user_id => john.id}
54
56
55 response.should render_template('main/list')
57 response.should render_template('main/list')
56 response.should have_text(/add/)
58 response.should have_text(/add/)
57 response.should_not have_text(/easy_problem/)
59 response.should_not have_text(/easy_problem/)
58 response.should_not have_text(/hard_problem/)
60 response.should_not have_text(/hard_problem/)
59 end
61 end
60
62
61 it "should list available problems on a specific contest" do
63 it "should list available problems on a specific contest" do
62 james = users(:james)
64 james = users(:james)
63 get "list", {}, {:user_id => james.id}
65 get "list", {}, {:user_id => james.id}
64
66
65 response.should render_template('main/list')
67 response.should render_template('main/list')
66 response.should have_text(/add/)
68 response.should have_text(/add/)
67 response.should have_text(/easy_problem/)
69 response.should have_text(/easy_problem/)
68 response.should_not have_text(/hard_problem/)
70 response.should_not have_text(/hard_problem/)
69 end
71 end
70
72
71 it "should shows available problems by contests" do
73 it "should shows available problems by contests" do
72 james = users(:james)
74 james = users(:james)
73 get "list", {}, {:user_id => james.id}
75 get "list", {}, {:user_id => james.id}
74
76
75 response.should render_template('main/list')
77 response.should render_template('main/list')
76 response.should have_text(Regexp.new('Contest A.*easy_problem', Regexp::MULTILINE))
78 response.should have_text(Regexp.new('Contest A.*easy_problem', Regexp::MULTILINE))
77 end
79 end
78
80
79 it "should shows available problems by contests; problems belonging to more the one contest should appear many times" do
81 it "should shows available problems by contests; problems belonging to more the one contest should appear many times" do
80 jack = users(:jack)
82 jack = users(:jack)
81 get "list", {}, {:user_id => jack.id}
83 get "list", {}, {:user_id => jack.id}
82
84
83 response.should render_template('main/list')
85 response.should render_template('main/list')
84 response.should have_text(Regexp.new('Contest A.*easy_problem.*Contest B.*easy_problem', Regexp::MULTILINE))
86 response.should have_text(Regexp.new('Contest A.*easy_problem.*Contest B.*easy_problem', Regexp::MULTILINE))
85 response.should have_text(Regexp.new('Contest B.*hard_problem', Regexp::MULTILINE))
87 response.should have_text(Regexp.new('Contest B.*hard_problem', Regexp::MULTILINE))
86 end
88 end
87 end
89 end
88
90
89 describe MainController, "when a user loads sources and compiler messages" do
91 describe MainController, "when a user loads sources and compiler messages" do
90
92
91 before(:each) do
93 before(:each) do
92 @problem = mock(Problem, :name => 'test', :output_only => false)
94 @problem = mock(Problem, :name => 'test', :output_only => false)
93 @language = mock(Language, :name => 'cpp', :ext => 'cpp')
95 @language = mock(Language, :name => 'cpp', :ext => 'cpp')
94 @submission = mock(Submission,
96 @submission = mock(Submission,
95 :id => 1,
97 :id => 1,
96 :user_id => 1,
98 :user_id => 1,
97 :problem => @problem,
99 :problem => @problem,
98 :language => @language,
100 :language => @language,
99 :source => 'sample source',
101 :source => 'sample source',
100 :compiler_message => 'none')
102 :compiler_message => 'none')
101
103
102 @user = mock(User, :id => 1, :login => 'john')
104 @user = mock(User, :id => 1, :login => 'john')
103 @user.should_receive(:update_start_time).at_most(:once)
105 @user.should_receive(:update_start_time).at_most(:once)
104
106
105 @another_user = mock(User, :id => 2, :login => 'mary')
107 @another_user = mock(User, :id => 2, :login => 'mary')
106 @another_user.should_receive(:update_start_time).at_most(:once)
108 @another_user.should_receive(:update_start_time).at_most(:once)
107
109
108 User.should_receive(:find).
110 User.should_receive(:find).
109 with(1).any_number_of_times.
111 with(1).any_number_of_times.
110 and_return(@user)
112 and_return(@user)
111 User.should_receive(:find).
113 User.should_receive(:find).
112 with(2).any_number_of_times.
114 with(2).any_number_of_times.
113 and_return(@another_user)
115 and_return(@another_user)
114 Submission.should_receive(:find).
116 Submission.should_receive(:find).
115 any_number_of_times.with(@submission.id.to_s).
117 any_number_of_times.with(@submission.id.to_s).
116 and_return(@submission)
118 and_return(@submission)
117 end
119 end
118
120
119 it "should let user sees her own source" do
121 it "should let user sees her own source" do
120 @submission.should_receive(:download_filename).and_return("foo.c")
122 @submission.should_receive(:download_filename).and_return("foo.c")
121 get 'source', {:id => @submission.id}, {:user_id => 1}
123 get 'source', {:id => @submission.id}, {:user_id => 1}
122 response.should be_success
124 response.should be_success
123 end
125 end
124
126
125 it "should let user sees her own compiler message" do
127 it "should let user sees her own compiler message" do
126 get 'compiler_msg', {:id => @submission.id}, {:user_id => 1}
128 get 'compiler_msg', {:id => @submission.id}, {:user_id => 1}
127 response.should be_success
129 response.should be_success
128 end
130 end
129
131
130 it "should not let user sees other user's source" do
132 it "should not let user sees other user's source" do
131 get 'source', {:id => @submission.id}, {:user_id => 2}
133 get 'source', {:id => @submission.id}, {:user_id => 2}
132 flash[:notice].should =~ /[Ee]rror/
134 flash[:notice].should =~ /[Ee]rror/
133 response.should redirect_to(:action => 'list')
135 response.should redirect_to(:action => 'list')
134 end
136 end
135
137
136 it "should not let user sees other user's compiler message" do
138 it "should not let user sees other user's compiler message" do
137 get 'compiler_msg', {:id => @submission.id}, {:user_id => 2}
139 get 'compiler_msg', {:id => @submission.id}, {:user_id => 2}
138 flash[:notice].should =~ /[Ee]rror/
140 flash[:notice].should =~ /[Ee]rror/
139 response.should redirect_to(:action => 'list')
141 response.should redirect_to(:action => 'list')
140 end
142 end
141
143
142 end
144 end
143
145
144
146
147 + describe MainController, "during individual contest mode" do
148 +
149 + integrate_views
150 +
151 + include ConfigSpecHelperMethods
152 +
153 + fixtures :users
154 + fixtures :problems
155 + fixtures :contests
156 +
157 + before(:each) do
158 + set_contest_time_limit('3:00') # 3 hours
159 + set_indv_contest_mode
160 + end
161 +
162 + it "should allow newly login user to see problem list" do
163 + john = users(:john)
164 + get "list", {}, {:user_id => john.id}
165 +
166 + response.should render_template 'main/list'
167 + response.should have_text(/add/)
168 + response.should have_text(/easy_problem/)
169 + response.should have_text(/hard_problem/)
170 + end
171 +
172 + it "should not show 'contest over' sign before the contest ends" do
173 + john = users(:john)
174 + get "list", {}, {:user_id => john.id}
175 +
176 + Delorean.time_travel_to(179.minutes.since) do
177 + get "list", {}, {:user_id => john.id}
178 + response.should_not have_text(/OVER/)
179 + end
180 + end
181 +
182 + it "should show 'contest over' sign after the contest ends" do
183 + john = users(:john)
184 + get "list", {}, {:user_id => john.id}
185 +
186 + Delorean.time_travel_to(181.minutes.since) do
187 + get "list", {}, {:user_id => john.id}
188 + response.should have_text(/OVER/)
189 + end
190 + end
191 +
192 + end
193 +
@@ -1,3 +1,4
1 # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
1 # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2 admin:
2 admin:
3 + name: admin
3 rights: graders_right, user_admin_right, problems_right No newline at end of file
4 rights: graders_right, user_admin_right, problems_right
@@ -1,11 +1,11
1 # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
1 # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2
2
3 - one:
3 + first_site:
4 - name: MyString
4 + name: First site
5 started: false
5 started: false
6 start_time: 2008-04-09 14:08:28
6 start_time: 2008-04-09 14:08:28
7
7
8 - two:
8 + second_site:
9 - name: MyString
9 + name: Second site
10 started: false
10 started: false
11 start_time: 2008-04-09 14:08:28
11 start_time: 2008-04-09 14:08:28
@@ -1,34 +1,38
1 # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
1 # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2
2
3 <%
3 <%
4 User.public_class_method :encrypt
4 User.public_class_method :encrypt
5
5
6 salt = "abc"
6 salt = "abc"
7 %>
7 %>
8
8
9 john:
9 john:
10 login: john
10 login: john
11 full_name: john
11 full_name: john
12 hashed_password: <%= User.encrypt("hello",salt) %>
12 hashed_password: <%= User.encrypt("hello",salt) %>
13 salt: <%= salt %>
13 salt: <%= salt %>
14 + activated: true
14
15
15 mary:
16 mary:
16 login: mary
17 login: mary
17 full_name: mary
18 full_name: mary
18 hashed_password: <%= User.encrypt("goodbye",salt) %>
19 hashed_password: <%= User.encrypt("goodbye",salt) %>
19 salt: <%= salt %>
20 salt: <%= salt %>
20 roles: admin
21 roles: admin
22 + activated: true
21
23
22 james:
24 james:
23 login: james
25 login: james
24 full_name: James
26 full_name: James
25 hashed_password: <%= User.encrypt("morning",salt) %>
27 hashed_password: <%= User.encrypt("morning",salt) %>
26 salt: <%= salt %>
28 salt: <%= salt %>
27 contests: contest_a
29 contests: contest_a
30 + activated: true
28
31
29 jack:
32 jack:
30 login: jack
33 login: jack
31 full_name: Jack
34 full_name: Jack
32 hashed_password: <%= User.encrypt("morning",salt) %>
35 hashed_password: <%= User.encrypt("morning",salt) %>
33 salt: <%= salt %>
36 salt: <%= salt %>
34 contests: contest_a, contest_b
37 contests: contest_a, contest_b
38 + activated: true
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
You need to be logged in to leave comments. Login now