Description:
a cleaner, testable way to log out user after contest changed
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r295:4f81b9ab5d77 - - 11 files changed: 170 inserted, 18 deleted

@@ -0,0 +1,9
1 + class AddForcedLogoutToUserContestStat < ActiveRecord::Migration
2 + def self.up
3 + add_column :user_contest_stats, :forced_logout, :boolean
4 + end
5 +
6 + def self.down
7 + remove_column :user_contest_stats, :forced_logout, :boolean
8 + end
9 + end
@@ -0,0 +1,73
1 + require 'delorean'
2 +
3 + require File.dirname(__FILE__) + '/../spec_helper'
4 + require File.dirname(__FILE__) + '/../config_spec_helper'
5 +
6 + describe UserAdminController, "when manage contest" do
7 +
8 + include ConfigSpecHelperMethods
9 +
10 + fixtures :users
11 + fixtures :problems
12 + fixtures :contests
13 + fixtures :roles
14 +
15 + def change_users_contest_to(user_login_list, contest, reset_timer=false)
16 + post_data = {
17 + :contest => {:id => contest.id},
18 + :operation => 'assign',
19 + :login_list => user_login_list
20 + }
21 + post_data[:reset_timer] = true if reset_timer
22 + post 'manage_contest', post_data, {:user_id => @admin_user.id}
23 + end
24 +
25 + before(:each) do
26 + @admin_user = users(:mary)
27 + @contest_b = contests(:contest_b)
28 + @james = users(:james)
29 + @jack = users(:jack)
30 +
31 + set_contest_time_limit('3:00')
32 + set_indv_contest_mode
33 + end
34 +
35 + it "should allow admin to see contest management page" do
36 + get 'contest_management', {}, {:user_id => @admin_user.id}
37 +
38 + response.should render_template 'user_admin/contest_management'
39 + end
40 +
41 + it "should change users' contest" do
42 + change_users_contest_to("james\njack", @contest_b)
43 + response.should redirect_to :action => 'contest_management'
44 +
45 + @james.contests(true).should include @contest_b
46 + @jack.contests(true).should_not include @contest_a
47 + end
48 +
49 + it "should reset users' timer when their contests change" do
50 + @james.update_start_time
51 +
52 + Delorean.time_travel_to(190.minutes.since) do
53 + @james.contest_finished?.should be_true
54 +
55 + change_users_contest_to("james", @contest_b, true)
56 +
57 + @james.contest_finished?.should be_false
58 + end
59 + end
60 +
61 + it "should set forced_logout flag for users when their contests change" do
62 + @james.update_start_time
63 +
64 + Delorean.time_travel_to(190.minutes.since) do
65 + @james.contest_finished?.should be_true
66 +
67 + change_users_contest_to("james", @contest_b, true)
68 +
69 + @james.contest_stat(true).forced_logout.should be_true
70 + end
71 + end
72 +
73 + end
@@ -1,74 +1,84
1 1 # Filters added to this controller apply to all controllers in the application.
2 2 # Likewise, all the methods added will be available for all controllers.
3 3
4 4 class ApplicationController < ActionController::Base
5 5
6 6 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
7 7
8 8 def admin_authorization
9 9 return false unless authenticate
10 10 user = User.find(session[:user_id], :include => ['roles'])
11 11 redirect_to :controller => 'main', :action => 'login' unless user.admin?
12 12 end
13 13
14 14 def authorization_by_roles(allowed_roles)
15 15 return false unless authenticate
16 16 user = User.find(session[:user_id])
17 17 unless user.roles.detect { |role| allowed_roles.member?(role.name) }
18 18 flash[:notice] = 'You are not authorized to view the page you requested'
19 19 redirect_to :controller => 'main', :action => 'login'
20 20 return false
21 21 end
22 22 end
23 23
24 24 protected
25 25
26 26 def authenticate
27 27 unless session[:user_id]
28 28 redirect_to :controller => 'main', :action => 'login'
29 29 return false
30 30 end
31 31
32 - #Configuration.reload
33 32 # check if run in single user mode
34 - if (Configuration[SINGLE_USER_MODE_CONF_KEY])
33 + if Configuration[SINGLE_USER_MODE_CONF_KEY]
35 34 user = User.find(session[:user_id])
36 35 if user==nil or (not user.admin?)
37 36 redirect_to :controller => 'main', :action => 'login'
38 37 return false
39 38 end
39 + return true
40 40 end
41 41
42 + if Configuration.multicontests?
43 + user = User.find(session[:user_id])
44 + begin
45 + if user.contest_stat(true).forced_logout
46 + flash[:notice] = 'You have been automatically logged out.'
47 + redirect_to :controller => 'main', :action => 'index'
48 + end
49 + rescue
50 + end
51 + end
42 52 return true
43 53 end
44 54
45 55 def authorization
46 56 return false unless authenticate
47 57 user = User.find(session[:user_id])
48 58 unless user.roles.detect { |role|
49 59 role.rights.detect{ |right|
50 60 right.controller == self.class.controller_name and
51 61 (right.action == 'all' or right.action == action_name)
52 62 }
53 63 }
54 64 flash[:notice] = 'You are not authorized to view the page you requested'
55 65 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
56 66 redirect_to :controller => 'main', :action => 'login'
57 67 return false
58 68 end
59 69 end
60 70
61 71 def verify_time_limit
62 72 return true if session[:user_id]==nil
63 73 user = User.find(session[:user_id], :include => :site)
64 74 return true if user==nil or user.site == nil
65 75 if user.contest_finished?
66 76 flash[:notice] = 'Error: the contest you are participating is over.'
67 77 redirect_to :back
68 78 return false
69 79 end
70 80 return true
71 81 end
72 82
73 83 end
74 84
@@ -1,39 +1,51
1 1 class LoginController < ApplicationController
2 2
3 3 def index
4 4 # show login screen
5 5 reset_session
6 6 redirect_to :controller => 'main', :action => 'login'
7 7 end
8 8
9 9 def login
10 10 if user = User.authenticate(params[:login], params[:password])
11 11 session[:user_id] = user.id
12 12 session[:admin] = user.admin?
13 +
14 + # clear forced logout flag for multicontests contest change
15 + if Configuration.multicontests?
16 + contest_stat = user.contest_stat
17 + if contest_stat.respond_to? :forced_logout
18 + if contest_stat.forced_logout
19 + contest_stat.forced_logout = false
20 + contest_stat.save
21 + end
22 + end
23 + end
24 +
13 25 redirect_to :controller => 'main', :action => 'list'
14 26 else
15 27 flash[:notice] = 'Wrong password'
16 28 redirect_to :controller => 'main', :action => 'login'
17 29 end
18 30 end
19 31
20 32 def site_login
21 33 begin
22 34 site = Site.find(params[:login][:site_id])
23 35 rescue ActiveRecord::RecordNotFound
24 36 site = nil
25 37 end
26 38 if site==nil
27 39 flash[:notice] = 'Wrong site'
28 40 redirect_to :controller => 'main', :action => 'login' and return
29 41 end
30 42 if (site.password) and (site.password == params[:login][:password])
31 43 session[:site_id] = site.id
32 44 redirect_to :controller => 'site', :action => 'index'
33 45 else
34 46 flash[:notice] = 'Wrong site password'
35 47 redirect_to :controller => 'site', :action => 'login'
36 48 end
37 49 end
38 50
39 51 end
@@ -298,52 +298,59
298 298
299 299 # copied from grader/script/lib/test_request_helper.rb
300 300 def extract_running_stat(results)
301 301 running_stat_line = results[-1]
302 302
303 303 # extract exit status line
304 304 run_stat = ""
305 305 if !(/[Cc]orrect/.match(results[0]))
306 306 run_stat = results[0].chomp
307 307 else
308 308 run_stat = 'Program exited normally'
309 309 end
310 310
311 311 logger.info "Stat line: #{running_stat_line}"
312 312
313 313 # extract running time
314 314 if res = /r(.*)u(.*)s/.match(running_stat_line)
315 315 seconds = (res[1].to_f + res[2].to_f)
316 316 time_stat = "Time used: #{seconds} sec."
317 317 else
318 318 seconds = nil
319 319 time_stat = "Time used: n/a sec."
320 320 end
321 321
322 322 # extract memory usage
323 323 if res = /s(.*)m/.match(running_stat_line)
324 324 memory_used = res[1].to_i
325 325 else
326 326 memory_used = -1
327 327 end
328 328
329 329 return {
330 330 :msg => "#{run_stat}\n#{time_stat}",
331 331 :running_time => seconds,
332 332 :exit_status => run_stat,
333 333 :memory_usage => memory_used
334 334 }
335 335 end
336 336
337 337 def update_user_start_time
338 338 user = User.find(session[:user_id])
339 339 user.update_start_time
340 340 end
341 341
342 342 def reject_announcement_refresh_when_logged_out
343 343 if not session[:user_id]
344 344 render :text => 'Access forbidden', :status => 403
345 345 end
346 +
347 + if Configuration.multicontests?
348 + user = User.find(session[:user_id])
349 + if user.contest_stat.forced_logout
350 + render :text => 'Access forbidden', :status => 403
351 + end
352 + end
346 353 end
347 354
348 355 end
349 356
@@ -151,119 +151,122
151 151 @changed = true
152 152 end
153 153 end
154 154
155 155 # contest management
156 156
157 157 def add_to_contest
158 158 user = User.find(params[:id])
159 159 contest = Contest.find(params[:contest_id])
160 160 if user and contest
161 161 user.contests << contest
162 162 end
163 163 redirect_to :action => 'list'
164 164 end
165 165
166 166 def remove_from_contest
167 167 user = User.find(params[:id])
168 168 contest = Contest.find(params[:contest_id])
169 169 if user and contest
170 170 user.contests.delete(contest)
171 171 end
172 172 redirect_to :action => 'list'
173 173 end
174 174
175 175 def contest_management
176 176 end
177 177
178 178 def manage_contest
179 179 contest = Contest.find(params[:contest][:id])
180 180 if !contest
181 181 flash[:notice] = 'You did not choose the contest.'
182 182 redirect_to :action => 'contest_management' and return
183 183 end
184 184
185 185 operation = params[:operation]
186 186
187 187 if not ['add','remove','assign'].include? operation
188 188 flash[:notice] = 'You did not choose the operation to perform.'
189 189 redirect_to :action => 'contest_management' and return
190 190 end
191 191
192 192 lines = params[:login_list]
193 193 if !lines or lines.blank?
194 194 flash[:notice] = 'You entered an empty list.'
195 195 redirect_to :action => 'contest_management' and return
196 196 end
197 197
198 198 note = []
199 - user_ids = {}
199 + users = []
200 200 lines.split("\n").each do |line|
201 201 user = User.find_by_login(line.chomp)
202 202 if user
203 203 if operation=='add'
204 204 if ! user.contests.include? contest
205 205 user.contests << contest
206 206 end
207 207 elsif operation=='remove'
208 208 user.contests.delete(contest)
209 209 else
210 210 user.contests = [contest]
211 211 end
212 212
213 - user.contest_stat.destroy if params[:reset_timer]
213 + if params[:reset_timer]
214 + user.contest_stat.forced_logout = true
215 + user.contest_stat.reset_timer_and_save
216 + end
214 217
215 218 note << user.login
216 - user_ids[user.id] = true
219 + users << user
217 220 end
218 221 end
219 222
220 223 if params[:reset_timer]
221 - logout_users(user_ids)
224 + logout_users(users)
222 225 end
223 226
224 227 flash[:notice] = 'User(s) ' + note.join(', ') +
225 228 ' were successfully modified. '
226 229 redirect_to :action => 'contest_management'
227 230 end
228 231
229 232 # admin management
230 233
231 234 def admin
232 235 @admins = User.find(:all).find_all {|user| user.admin? }
233 236 end
234 237
235 238 def grant_admin
236 239 login = params[:login]
237 240 user = User.find_by_login(login)
238 241 if user!=nil
239 242 admin_role = Role.find_by_name('admin')
240 243 user.roles << admin_role
241 244 else
242 245 flash[:notice] = 'Unknown user'
243 246 end
244 247 flash[:notice] = 'User added as admins'
245 248 redirect_to :action => 'admin'
246 249 end
247 250
248 251 def revoke_admin
249 252 user = User.find(params[:id])
250 253 if user==nil
251 254 flash[:notice] = 'Unknown user'
252 255 redirect_to :action => 'admin' and return
253 256 elsif user.login == 'root'
254 257 flash[:notice] = 'You cannot revoke admisnistrator permission from root.'
255 258 redirect_to :action => 'admin' and return
256 259 end
257 260
258 261 admin_role = Role.find_by_name('admin')
259 262 user.roles.delete(admin_role)
260 263 flash[:notice] = 'User permission revoked'
261 264 redirect_to :action => 'admin'
262 265 end
263 266
264 267 protected
265 268
266 269 def random_password(length=5)
267 270 chars = 'abcdefghijkmnopqrstuvwxyz23456789'
268 271 newpass = ""
269 272 length.times { newpass << chars[rand(chars.size-1)] }
@@ -286,58 +289,59
286 289 countries[id] = c
287 290 @import_log << "Found #{country[:name]}\n"
288 291 else
289 292 countries[id] = Country.new(:name => country[:name])
290 293 countries[id].save
291 294 @import_log << "Created #{country[:name]}\n"
292 295 end
293 296 end
294 297
295 298 # import sites
296 299 sites = {}
297 300 site_data.each_pair do |id,site|
298 301 s = Site.find_by_name(site[:name])
299 302 if s!=nil
300 303 @import_log << "Found #{site[:name]}\n"
301 304 else
302 305 s = Site.new(:name => site[:name])
303 306 @import_log << "Created #{site[:name]}\n"
304 307 end
305 308 s.password = site[:password]
306 309 s.country = countries[site[:country_id]]
307 310 s.save
308 311 sites[id] = s
309 312 end
310 313
311 314 # import users
312 315 user_data.each_pair do |id,user|
313 316 u = User.find_by_login(user[:login])
314 317 if u!=nil
315 318 @import_log << "Found #{user[:login]}\n"
316 319 else
317 320 u = User.new(:login => user[:login])
318 321 @import_log << "Created #{user[:login]}\n"
319 322 end
320 323 u.full_name = user[:name]
321 324 u.password = user[:password]
322 325 u.country = countries[user[:country_id]]
323 326 u.site = sites[user[:site_id]]
324 327 u.activated = true
325 328 u.email = "empty-#{u.login}@none.com"
326 329 if not u.save
327 330 @import_log << "Errors\n"
328 331 u.errors.each { |attr,msg| @import_log << "#{attr} - #{msg}\n" }
329 332 end
330 333 end
331 334
332 335 end
333 336
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
337 + def logout_users(users)
338 + users.each do |user|
339 + contest_stat = user.contest_stat(true)
340 + if contest_stat and !contest_stat.forced_logout
341 + contest_stat.forced_logout = true
342 + contest_stat.save
339 343 end
340 344 end
341 345 end
342 346
343 347 end
@@ -88,138 +88,138
88 88 def alias_for_editing
89 89 if self.alias==nil
90 90 "(unknown)"
91 91 elsif self.alias==''
92 92 "(blank)"
93 93 else
94 94 self.alias
95 95 end
96 96 end
97 97
98 98 def alias_for_editing=(e)
99 99 self.alias=e
100 100 end
101 101
102 102 def activation_key
103 103 if self.hashed_password==nil
104 104 encrypt_new_password
105 105 end
106 106 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
107 107 end
108 108
109 109 def verify_activation_key(key)
110 110 key == activation_key
111 111 end
112 112
113 113 def self.random_password(length=5)
114 114 chars = 'abcdefghjkmnopqrstuvwxyz'
115 115 password = ''
116 116 length.times { password << chars[rand(chars.length - 1)] }
117 117 password
118 118 end
119 119
120 120 def self.find_non_admin_with_prefix(prefix='')
121 121 users = User.find(:all)
122 122 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
123 123 end
124 124
125 125 # Contest information
126 126
127 127 def contest_time_left
128 128 if Configuration.contest_mode?
129 129 return nil if site==nil
130 130 return site.time_left
131 131 elsif Configuration.indv_contest_mode?
132 132 time_limit = Configuration.contest_time_limit
133 133 if time_limit == nil
134 134 return nil
135 135 end
136 - if contest_stat==nil
136 + if contest_stat==nil or contest_stat.started_at==nil
137 137 return (Time.now.gmtime + time_limit) - Time.now.gmtime
138 138 else
139 139 finish_time = contest_stat.started_at + time_limit
140 140 current_time = Time.now.gmtime
141 141 if current_time > finish_time
142 142 return 0
143 143 else
144 144 return finish_time - current_time
145 145 end
146 146 end
147 147 else
148 148 return nil
149 149 end
150 150 end
151 151
152 152 def contest_finished?
153 153 if Configuration.contest_mode?
154 154 return false if site==nil
155 155 return site.finished?
156 156 elsif Configuration.indv_contest_mode?
157 157 return false if self.contest_stat(true)==nil
158 158 return contest_time_left == 0
159 159 else
160 160 return false
161 161 end
162 162 end
163 163
164 164 def contest_started?
165 165 if Configuration.contest_mode?
166 166 return true if site==nil
167 167 return site.started
168 168 else
169 169 return true
170 170 end
171 171 end
172 172
173 173 def update_start_time
174 174 stat = self.contest_stat
175 - if stat == nil
176 - stat = UserContestStat.new(:user => self,
177 - :started_at => Time.now.gmtime)
175 + if stat == nil or stat.started_at == nil
176 + stat ||= UserContestStat.new(:user => self)
177 + stat.started_at = Time.now.gmtime
178 178 stat.save
179 179 end
180 180 end
181 181
182 182 def problem_in_user_contests?(problem)
183 183 problem_contests = problem.contests.all
184 184
185 185 if problem_contests.length == 0 # this is public contest
186 186 return true
187 187 end
188 188
189 189 contests.each do |contest|
190 190 if problem_contests.find {|c| c.id == contest.id }
191 191 return true
192 192 end
193 193 end
194 194 return false
195 195 end
196 196
197 197 def available_problems_group_by_contests
198 198 contest_problems = []
199 199 pin = {}
200 200 contests.enabled.each do |contest|
201 201 available_problems = contest.problems.available
202 202 contest_problems << {
203 203 :contest => contest,
204 204 :problems => available_problems
205 205 }
206 206 available_problems.each {|p| pin[p.id] = true}
207 207 end
208 208 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
209 209 contest_problems << {
210 210 :contest => nil,
211 211 :problems => other_avaiable_problems
212 212 }
213 213 return contest_problems
214 214 end
215 215
216 216 def available_problems
217 217 if not Configuration.multicontests?
218 218 return Problem.find_available_problems
219 219 else
220 220 contest_problems = []
221 221 pin = {}
222 222 contests.enabled.each do |contest|
223 223 contest.problems.available.each do |problem|
224 224 if not pin.has_key? problem.id
225 225 contest_problems << problem
@@ -1,5 +1,10
1 1 class UserContestStat < ActiveRecord::Base
2 2
3 3 belongs_to :user
4 4
5 + def reset_timer_and_save
6 + self.started_at = nil
7 + save
8 + end
9 +
5 10 end
@@ -1,60 +1,60
1 1 # This file is auto-generated from the current state of the database. Instead of editing this file,
2 2 # please use the migrations feature of Active Record to incrementally modify your database, and
3 3 # then regenerate this schema definition.
4 4 #
5 5 # Note that this schema.rb definition is the authoritative source for your database schema. If you need
6 6 # to create the application database on another system, you should be using db:schema:load, not running
7 7 # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
8 8 # you'll amass, the slower it'll run and the greater likelihood for issues).
9 9 #
10 10 # It's strongly recommended to check this file into your version control system.
11 11
12 - ActiveRecord::Schema.define(:version => 20100303095700) do
12 + ActiveRecord::Schema.define(:version => 20100328123325) do
13 13
14 14 create_table "announcements", :force => true do |t|
15 15 t.string "author"
16 16 t.text "body"
17 17 t.boolean "published"
18 18 t.datetime "created_at"
19 19 t.datetime "updated_at"
20 20 t.boolean "frontpage", :default => false
21 21 t.boolean "contest_only", :default => false
22 22 t.string "title"
23 23 end
24 24
25 25 create_table "configurations", :force => true do |t|
26 26 t.string "key"
27 27 t.string "value_type"
28 28 t.string "value"
29 29 t.datetime "created_at"
30 30 t.datetime "updated_at"
31 31 t.text "description"
32 32 end
33 33
34 34 create_table "contests", :force => true do |t|
35 35 t.string "title"
36 36 t.boolean "enabled"
37 37 t.datetime "created_at"
38 38 t.datetime "updated_at"
39 39 t.string "name"
40 40 end
41 41
42 42 create_table "contests_problems", :id => false, :force => true do |t|
43 43 t.integer "contest_id"
44 44 t.integer "problem_id"
45 45 end
46 46
47 47 create_table "contests_users", :id => false, :force => true do |t|
48 48 t.integer "contest_id"
49 49 t.integer "user_id"
50 50 end
51 51
52 52 create_table "countries", :force => true do |t|
53 53 t.string "name"
54 54 t.datetime "created_at"
55 55 t.datetime "updated_at"
56 56 end
57 57
58 58 create_table "descriptions", :force => true do |t|
59 59 t.text "body"
60 60 t.boolean "markdowned"
@@ -165,67 +165,68
165 165 t.string "source_filename"
166 166 end
167 167
168 168 add_index "submissions", ["user_id", "problem_id", "number"], :name => "index_submissions_on_user_id_and_problem_id_and_number", :unique => true
169 169 add_index "submissions", ["user_id", "problem_id"], :name => "index_submissions_on_user_id_and_problem_id"
170 170
171 171 create_table "tasks", :force => true do |t|
172 172 t.integer "submission_id"
173 173 t.datetime "created_at"
174 174 t.integer "status"
175 175 t.datetime "updated_at"
176 176 end
177 177
178 178 create_table "test_pairs", :force => true do |t|
179 179 t.integer "problem_id"
180 180 t.text "input", :limit => 16777215
181 181 t.text "solution", :limit => 16777215
182 182 t.datetime "created_at"
183 183 t.datetime "updated_at"
184 184 end
185 185
186 186 create_table "test_requests", :force => true do |t|
187 187 t.integer "user_id"
188 188 t.integer "problem_id"
189 189 t.integer "submission_id"
190 190 t.string "input_file_name"
191 191 t.string "output_file_name"
192 192 t.string "running_stat"
193 193 t.integer "status"
194 194 t.datetime "updated_at"
195 195 t.datetime "submitted_at"
196 196 t.datetime "compiled_at"
197 197 t.text "compiler_message"
198 198 t.datetime "graded_at"
199 199 t.string "grader_comment"
200 200 t.datetime "created_at"
201 201 t.float "running_time"
202 202 t.string "exit_status"
203 203 t.integer "memory_usage"
204 204 end
205 205
206 206 add_index "test_requests", ["user_id", "problem_id"], :name => "index_test_requests_on_user_id_and_problem_id"
207 207
208 208 create_table "user_contest_stats", :force => true do |t|
209 209 t.integer "user_id"
210 210 t.datetime "started_at"
211 211 t.datetime "created_at"
212 212 t.datetime "updated_at"
213 + t.boolean "forced_logout"
213 214 end
214 215
215 216 create_table "users", :force => true do |t|
216 217 t.string "login", :limit => 50
217 218 t.string "full_name"
218 219 t.string "hashed_password"
219 220 t.string "salt", :limit => 5
220 221 t.string "alias"
221 222 t.string "email"
222 223 t.integer "site_id"
223 224 t.integer "country_id"
224 225 t.boolean "activated", :default => false
225 226 t.datetime "created_at"
226 227 t.datetime "updated_at"
227 228 end
228 229
229 230 add_index "users", ["login"], :name => "index_users_on_login", :unique => true
230 231
231 232 end
@@ -1,40 +1,41
1 1
2 2 var Announcement = {
3 3
4 4 mostRecentId: 0,
5 5
6 6 refreshUrl: '/main/announcements',
7 7
8 8 setMostRecentId: function(id) {
9 9 Announcement.mostRecentId = id;
10 10 },
11 11
12 12 updateRecentId: function(id) {
13 13 if(Announcement.mostRecentId < id)
14 14 Announcement.mostRecentId = id;
15 15 },
16 16
17 17 refreshAnnouncement: function() {
18 18 var url = Announcement.refreshUrl;
19 19 new Ajax.Request(url, {
20 20 method: 'get',
21 21 parameters: { recent: Announcement.mostRecentId },
22 22 onSuccess: function(transport) {
23 - if(transport.responseText.match(/\S/)!=null) {
23 + if((transport.status == 200) &&
24 + (transport.responseText.match(/\S/)!=null)) {
24 25 var announcementBody = $("announcementbox-body");
25 26 announcementBody.insert({ top: transport.responseText });
26 27 var announcementBoxes = $$(".announcementbox");
27 28 if(announcementBoxes.length!=0)
28 29 announcementBoxes[0].show();
30 + Announcement.registerRefreshEventTimer();
29 31 }
30 32 }
31 33 });
32 - Announcement.registerRefreshEventTimer();
33 34 },
34 35
35 36 registerRefreshEventTimer: function() {
36 37 setTimeout(function () {
37 38 Announcement.refreshAnnouncement();
38 39 }, 30000);
39 40 }
40 41 };
@@ -1,87 +1,117
1 1 require 'spec_helper'
2 2 require 'config_spec_helper'
3 3 require 'delorean'
4 4
5 5 describe "ContestManagements" do
6 6 include ConfigSpecHelperMethods
7 7
8 8 fixtures :users
9 9 fixtures :problems
10 10 fixtures :contests
11 11 fixtures :roles
12 12
13 13 before(:each) do
14 14 @admin_user = users(:mary)
15 15 @contest_b = contests(:contest_b)
16 16 @james = users(:james)
17 17 @jack = users(:jack)
18 18
19 19 set_contest_time_limit('3:00')
20 20 set_indv_contest_mode
21 + enable_multicontest
21 22 end
22 23
23 24 it "should reset users' timer when their contests change" do
24 25 james_session = open_session
25 26 james_session.extend(MainSessionMethods)
26 27
27 28 james_login_and_get_main_list(james_session)
28 29 james_session.response.should_not have_text(/OVER/)
29 30
30 31 Delorean.time_travel_to(190.minutes.since) do
31 32 james_session.get_main_list
32 33 james_session.response.should have_text(/OVER/)
33 34
34 35 james_session.get '/' # logout
35 36 james_session.get '/main/list' # clearly log out
36 37 james_session.response.should_not render_template 'main/list'
37 38
38 39 admin_change_users_contest_to("james", @contest_b, true)
39 40
40 41 james_login_and_get_main_list(james_session)
41 42 james_session.response.should_not have_text(/OVER/)
42 43 end
43 44 end
44 45
46 + it "should force users to log out when their contests change" do
47 + james_session = open_session
48 + james_session.extend(MainSessionMethods)
49 +
50 + james_login_and_get_main_list(james_session)
51 + james_session.response.should_not have_text(/OVER/)
52 +
53 + Delorean.time_travel_to(190.minutes.since) do
54 + james_session.get_main_list
55 + james_session.response.should have_text(/OVER/)
56 +
57 + admin_change_users_contest_to("james", @contest_b, true)
58 +
59 + james_session.get '/main/list'
60 + james_session.response.should_not render_template 'main/list'
61 + james_session.should be_redirect
62 +
63 + Delorean.time_travel_to(200.minutes.since) do
64 + james_login_and_get_main_list(james_session)
65 + james_session.response.should_not have_text(/OVER/)
66 + end
67 + end
68 + end
69 +
45 70 private
46 71
47 72 module MainSessionMethods
48 73 def login(login_name, password)
49 74 post '/login/login', :login => login_name, :password => password
50 75 assert_redirected_to '/main/list'
51 76 end
52 77
53 78 def get_main_list
54 79 get '/main/list'
55 80 assert_template 'main/list'
56 81 end
82 +
83 + def get_main_list_and_assert_logout
84 + get '/main/list'
85 + assert_redirected_to '/main'
86 + end
57 87 end
58 88
59 89 module ContestManagementSessionMethods
60 90 def change_users_contest_to(user_login_list, contest, reset_timer=false)
61 91 post_data = {
62 92 :contest => {:id => contest.id},
63 93 :operation => 'assign',
64 94 :login_list => user_login_list
65 95 }
66 96 post_data[:reset_timer] = true if reset_timer
67 97 post '/user_admin/manage_contest', post_data
68 98 end
69 99 end
70 100
71 101 def admin_change_users_contest_to(user_list, contest, reset_timer)
72 102 admin_session = open_session
73 103 admin_session.extend(MainSessionMethods)
74 104 admin_session.extend(ContestManagementSessionMethods)
75 105
76 106 admin_session.login('mary','goodbye')
77 107 admin_session.get '/main/list'
78 108 admin_session.change_users_contest_to(user_list, contest, reset_timer)
79 109 end
80 110
81 111 def james_login_and_get_main_list(session)
82 112 session.login('james', 'morning')
83 113 session.get_main_list
84 114 end
85 115
86 116 end
87 117
You need to be logged in to leave comments. Login now