Description:
fix pop3 authen
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r395:52cd3037bb5e - - 1 file changed: 2 inserted, 1 deleted

@@ -1,341 +1,342
1 require 'digest/sha1'
1 require 'digest/sha1'
2 require 'net/pop'
2 require 'net/pop'
3
3
4 class User < ActiveRecord::Base
4 class User < ActiveRecord::Base
5
5
6 has_and_belongs_to_many :roles
6 has_and_belongs_to_many :roles
7
7
8 has_many :test_requests, :order => "submitted_at DESC"
8 has_many :test_requests, :order => "submitted_at DESC"
9
9
10 has_many :messages,
10 has_many :messages,
11 :class_name => "Message",
11 :class_name => "Message",
12 :foreign_key => "sender_id",
12 :foreign_key => "sender_id",
13 :order => 'created_at DESC'
13 :order => 'created_at DESC'
14
14
15 has_many :replied_messages,
15 has_many :replied_messages,
16 :class_name => "Message",
16 :class_name => "Message",
17 :foreign_key => "receiver_id",
17 :foreign_key => "receiver_id",
18 :order => 'created_at DESC'
18 :order => 'created_at DESC'
19
19
20 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
20 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
21
21
22 belongs_to :site
22 belongs_to :site
23 belongs_to :country
23 belongs_to :country
24
24
25 has_and_belongs_to_many :contests, :uniq => true, :order => 'name'
25 has_and_belongs_to_many :contests, :uniq => true, :order => 'name'
26
26
27 scope :activated_users, :conditions => {:activated => true}
27 scope :activated_users, :conditions => {:activated => true}
28
28
29 validates_presence_of :login
29 validates_presence_of :login
30 validates_uniqueness_of :login
30 validates_uniqueness_of :login
31 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
31 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
32 validates_length_of :login, :within => 3..30
32 validates_length_of :login, :within => 3..30
33
33
34 validates_presence_of :full_name
34 validates_presence_of :full_name
35 validates_length_of :full_name, :minimum => 1
35 validates_length_of :full_name, :minimum => 1
36
36
37 validates_presence_of :password, :if => :password_required?
37 validates_presence_of :password, :if => :password_required?
38 validates_length_of :password, :within => 4..20, :if => :password_required?
38 validates_length_of :password, :within => 4..20, :if => :password_required?
39 validates_confirmation_of :password, :if => :password_required?
39 validates_confirmation_of :password, :if => :password_required?
40
40
41 validates_format_of :email,
41 validates_format_of :email,
42 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
42 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
43 :if => :email_validation?
43 :if => :email_validation?
44 validate :uniqueness_of_email_from_activated_users,
44 validate :uniqueness_of_email_from_activated_users,
45 :if => :email_validation?
45 :if => :email_validation?
46 validate :enough_time_interval_between_same_email_registrations,
46 validate :enough_time_interval_between_same_email_registrations,
47 :if => :email_validation?
47 :if => :email_validation?
48
48
49 # these are for ytopc
49 # these are for ytopc
50 # disable for now
50 # disable for now
51 #validates_presence_of :province
51 #validates_presence_of :province
52
52
53 attr_accessor :password
53 attr_accessor :password
54
54
55 before_save :encrypt_new_password
55 before_save :encrypt_new_password
56 before_save :assign_default_site
56 before_save :assign_default_site
57 before_save :assign_default_contest
57 before_save :assign_default_contest
58
58
59 # this is for will_paginate
59 # this is for will_paginate
60 cattr_reader :per_page
60 cattr_reader :per_page
61 @@per_page = 50
61 @@per_page = 50
62
62
63 def self.authenticate(login, password)
63 def self.authenticate(login, password)
64 user = find_by_login(login)
64 user = find_by_login(login)
65 return user if user && user.authenticated?(password)
65 return user if user && user.authenticated?(password)
66 - if user.authenticated_by_pop3?(password)
66 + if user && user.authenticated_by_pop3?(password)
67 user.password = password
67 user.password = password
68 + user.save
68 return user
69 return user
69 end
70 end
70 end
71 end
71
72
72 def authenticated?(password)
73 def authenticated?(password)
73 if self.activated
74 if self.activated
74 hashed_password == User.encrypt(password,self.salt)
75 hashed_password == User.encrypt(password,self.salt)
75 else
76 else
76 false
77 false
77 end
78 end
78 end
79 end
79
80
80 def authenticated_by_pop3?(password)
81 def authenticated_by_pop3?(password)
81 Net::POP3.enable_ssl
82 Net::POP3.enable_ssl
82 pop = Net::POP3.new('pops.it.chula.ac.th')
83 pop = Net::POP3.new('pops.it.chula.ac.th')
83 authen = true
84 authen = true
84 begin
85 begin
85 pop.start(login, password) # (1)
86 pop.start(login, password) # (1)
86 pop.finish
87 pop.finish
87 return true
88 return true
88 rescue
89 rescue
89 return false
90 return false
90 end
91 end
91 end
92 end
92
93
93 def admin?
94 def admin?
94 self.roles.detect {|r| r.name == 'admin' }
95 self.roles.detect {|r| r.name == 'admin' }
95 end
96 end
96
97
97 def email_for_editing
98 def email_for_editing
98 if self.email==nil
99 if self.email==nil
99 "(unknown)"
100 "(unknown)"
100 elsif self.email==''
101 elsif self.email==''
101 "(blank)"
102 "(blank)"
102 else
103 else
103 self.email
104 self.email
104 end
105 end
105 end
106 end
106
107
107 def email_for_editing=(e)
108 def email_for_editing=(e)
108 self.email=e
109 self.email=e
109 end
110 end
110
111
111 def alias_for_editing
112 def alias_for_editing
112 if self.alias==nil
113 if self.alias==nil
113 "(unknown)"
114 "(unknown)"
114 elsif self.alias==''
115 elsif self.alias==''
115 "(blank)"
116 "(blank)"
116 else
117 else
117 self.alias
118 self.alias
118 end
119 end
119 end
120 end
120
121
121 def alias_for_editing=(e)
122 def alias_for_editing=(e)
122 self.alias=e
123 self.alias=e
123 end
124 end
124
125
125 def activation_key
126 def activation_key
126 if self.hashed_password==nil
127 if self.hashed_password==nil
127 encrypt_new_password
128 encrypt_new_password
128 end
129 end
129 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
130 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
130 end
131 end
131
132
132 def verify_activation_key(key)
133 def verify_activation_key(key)
133 key == activation_key
134 key == activation_key
134 end
135 end
135
136
136 def self.random_password(length=5)
137 def self.random_password(length=5)
137 chars = 'abcdefghjkmnopqrstuvwxyz'
138 chars = 'abcdefghjkmnopqrstuvwxyz'
138 password = ''
139 password = ''
139 length.times { password << chars[rand(chars.length - 1)] }
140 length.times { password << chars[rand(chars.length - 1)] }
140 password
141 password
141 end
142 end
142
143
143 def self.find_non_admin_with_prefix(prefix='')
144 def self.find_non_admin_with_prefix(prefix='')
144 users = User.find(:all)
145 users = User.find(:all)
145 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
146 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
146 end
147 end
147
148
148 # Contest information
149 # Contest information
149
150
150 def self.find_users_with_no_contest()
151 def self.find_users_with_no_contest()
151 users = User.find(:all)
152 users = User.find(:all)
152 return users.find_all { |u| u.contests.length == 0 }
153 return users.find_all { |u| u.contests.length == 0 }
153 end
154 end
154
155
155
156
156 def contest_time_left
157 def contest_time_left
157 if GraderConfiguration.contest_mode?
158 if GraderConfiguration.contest_mode?
158 return nil if site==nil
159 return nil if site==nil
159 return site.time_left
160 return site.time_left
160 elsif GraderConfiguration.indv_contest_mode?
161 elsif GraderConfiguration.indv_contest_mode?
161 time_limit = GraderConfiguration.contest_time_limit
162 time_limit = GraderConfiguration.contest_time_limit
162 if time_limit == nil
163 if time_limit == nil
163 return nil
164 return nil
164 end
165 end
165 if contest_stat==nil or contest_stat.started_at==nil
166 if contest_stat==nil or contest_stat.started_at==nil
166 return (Time.now.gmtime + time_limit) - Time.now.gmtime
167 return (Time.now.gmtime + time_limit) - Time.now.gmtime
167 else
168 else
168 finish_time = contest_stat.started_at + time_limit
169 finish_time = contest_stat.started_at + time_limit
169 current_time = Time.now.gmtime
170 current_time = Time.now.gmtime
170 if current_time > finish_time
171 if current_time > finish_time
171 return 0
172 return 0
172 else
173 else
173 return finish_time - current_time
174 return finish_time - current_time
174 end
175 end
175 end
176 end
176 else
177 else
177 return nil
178 return nil
178 end
179 end
179 end
180 end
180
181
181 def contest_finished?
182 def contest_finished?
182 if GraderConfiguration.contest_mode?
183 if GraderConfiguration.contest_mode?
183 return false if site==nil
184 return false if site==nil
184 return site.finished?
185 return site.finished?
185 elsif GraderConfiguration.indv_contest_mode?
186 elsif GraderConfiguration.indv_contest_mode?
186 return false if self.contest_stat(true)==nil
187 return false if self.contest_stat(true)==nil
187 return contest_time_left == 0
188 return contest_time_left == 0
188 else
189 else
189 return false
190 return false
190 end
191 end
191 end
192 end
192
193
193 def contest_started?
194 def contest_started?
194 if GraderConfiguration.indv_contest_mode?
195 if GraderConfiguration.indv_contest_mode?
195 stat = self.contest_stat
196 stat = self.contest_stat
196 return ((stat != nil) and (stat.started_at != nil))
197 return ((stat != nil) and (stat.started_at != nil))
197 elsif GraderConfiguration.contest_mode?
198 elsif GraderConfiguration.contest_mode?
198 return true if site==nil
199 return true if site==nil
199 return site.started
200 return site.started
200 else
201 else
201 return true
202 return true
202 end
203 end
203 end
204 end
204
205
205 def update_start_time
206 def update_start_time
206 stat = self.contest_stat
207 stat = self.contest_stat
207 if stat == nil or stat.started_at == nil
208 if stat == nil or stat.started_at == nil
208 stat ||= UserContestStat.new(:user => self)
209 stat ||= UserContestStat.new(:user => self)
209 stat.started_at = Time.now.gmtime
210 stat.started_at = Time.now.gmtime
210 stat.save
211 stat.save
211 end
212 end
212 end
213 end
213
214
214 def problem_in_user_contests?(problem)
215 def problem_in_user_contests?(problem)
215 problem_contests = problem.contests.all
216 problem_contests = problem.contests.all
216
217
217 if problem_contests.length == 0 # this is public contest
218 if problem_contests.length == 0 # this is public contest
218 return true
219 return true
219 end
220 end
220
221
221 contests.each do |contest|
222 contests.each do |contest|
222 if problem_contests.find {|c| c.id == contest.id }
223 if problem_contests.find {|c| c.id == contest.id }
223 return true
224 return true
224 end
225 end
225 end
226 end
226 return false
227 return false
227 end
228 end
228
229
229 def available_problems_group_by_contests
230 def available_problems_group_by_contests
230 contest_problems = []
231 contest_problems = []
231 pin = {}
232 pin = {}
232 contests.enabled.each do |contest|
233 contests.enabled.each do |contest|
233 available_problems = contest.problems.available
234 available_problems = contest.problems.available
234 contest_problems << {
235 contest_problems << {
235 :contest => contest,
236 :contest => contest,
236 :problems => available_problems
237 :problems => available_problems
237 }
238 }
238 available_problems.each {|p| pin[p.id] = true}
239 available_problems.each {|p| pin[p.id] = true}
239 end
240 end
240 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
241 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
241 contest_problems << {
242 contest_problems << {
242 :contest => nil,
243 :contest => nil,
243 :problems => other_avaiable_problems
244 :problems => other_avaiable_problems
244 }
245 }
245 return contest_problems
246 return contest_problems
246 end
247 end
247
248
248 def available_problems
249 def available_problems
249 if not GraderConfiguration.multicontests?
250 if not GraderConfiguration.multicontests?
250 return Problem.find_available_problems
251 return Problem.find_available_problems
251 else
252 else
252 contest_problems = []
253 contest_problems = []
253 pin = {}
254 pin = {}
254 contests.enabled.each do |contest|
255 contests.enabled.each do |contest|
255 contest.problems.available.each do |problem|
256 contest.problems.available.each do |problem|
256 if not pin.has_key? problem.id
257 if not pin.has_key? problem.id
257 contest_problems << problem
258 contest_problems << problem
258 end
259 end
259 pin[problem.id] = true
260 pin[problem.id] = true
260 end
261 end
261 end
262 end
262 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
263 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
263 return contest_problems + other_avaiable_problems
264 return contest_problems + other_avaiable_problems
264 end
265 end
265 end
266 end
266
267
267 def can_view_problem?(problem)
268 def can_view_problem?(problem)
268 if not GraderConfiguration.multicontests?
269 if not GraderConfiguration.multicontests?
269 return problem.available
270 return problem.available
270 else
271 else
271 return problem_in_user_contests? problem
272 return problem_in_user_contests? problem
272 end
273 end
273 end
274 end
274
275
275 protected
276 protected
276 def encrypt_new_password
277 def encrypt_new_password
277 return if password.blank?
278 return if password.blank?
278 self.salt = (10+rand(90)).to_s
279 self.salt = (10+rand(90)).to_s
279 self.hashed_password = User.encrypt(self.password,self.salt)
280 self.hashed_password = User.encrypt(self.password,self.salt)
280 end
281 end
281
282
282 def assign_default_site
283 def assign_default_site
283 # 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).
284 begin
285 begin
285 if self.site==nil
286 if self.site==nil
286 self.site = Site.find_by_name('default')
287 self.site = Site.find_by_name('default')
287 if self.site==nil
288 if self.site==nil
288 self.site = Site.find(1) # when 'default has be renamed'
289 self.site = Site.find(1) # when 'default has be renamed'
289 end
290 end
290 end
291 end
291 rescue
292 rescue
292 end
293 end
293 end
294 end
294
295
295 def assign_default_contest
296 def assign_default_contest
296 # have to catch error when migrating (because self.site is not available).
297 # have to catch error when migrating (because self.site is not available).
297 begin
298 begin
298 if self.contests.length == 0
299 if self.contests.length == 0
299 default_contest = Contest.find_by_name(GraderConfiguration['contest.default_contest_name'])
300 default_contest = Contest.find_by_name(GraderConfiguration['contest.default_contest_name'])
300 if default_contest
301 if default_contest
301 self.contests = [default_contest]
302 self.contests = [default_contest]
302 end
303 end
303 end
304 end
304 rescue
305 rescue
305 end
306 end
306 end
307 end
307
308
308 def password_required?
309 def password_required?
309 self.hashed_password.blank? || !self.password.blank?
310 self.hashed_password.blank? || !self.password.blank?
310 end
311 end
311
312
312 def self.encrypt(string,salt)
313 def self.encrypt(string,salt)
313 Digest::SHA1.hexdigest(salt + string)
314 Digest::SHA1.hexdigest(salt + string)
314 end
315 end
315
316
316 def uniqueness_of_email_from_activated_users
317 def uniqueness_of_email_from_activated_users
317 user = User.activated_users.find_by_email(self.email)
318 user = User.activated_users.find_by_email(self.email)
318 if user and (user.login != self.login)
319 if user and (user.login != self.login)
319 self.errors.add_to_base("Email has already been taken")
320 self.errors.add_to_base("Email has already been taken")
320 end
321 end
321 end
322 end
322
323
323 def enough_time_interval_between_same_email_registrations
324 def enough_time_interval_between_same_email_registrations
324 return if !self.new_record?
325 return if !self.new_record?
325 return if self.activated
326 return if self.activated
326 open_user = User.find_by_email(self.email,
327 open_user = User.find_by_email(self.email,
327 :order => 'created_at DESC')
328 :order => 'created_at DESC')
328 if open_user and open_user.created_at and
329 if open_user and open_user.created_at and
329 (open_user.created_at > Time.now.gmtime - 5.minutes)
330 (open_user.created_at > Time.now.gmtime - 5.minutes)
330 self.errors.add_to_base("There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
331 self.errors.add_to_base("There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
331 end
332 end
332 end
333 end
333
334
334 def email_validation?
335 def email_validation?
335 begin
336 begin
336 return VALIDATE_USER_EMAILS
337 return VALIDATE_USER_EMAILS
337 rescue
338 rescue
338 return false
339 return false
339 end
340 end
340 end
341 end
341 end
342 end
You need to be logged in to leave comments. Login now