Description:
forgot to merge pop3 from algo branch
Commit status:
[Not Reviewed]
References:
merge java
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r403:845ea78912ad - - 1 file changed: 18 inserted, 0 deleted

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