Description:
add pop3 authentication for chula create both bookmark and branch so that github will work too
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r390:edc9bac52078 - - 1 file changed: 17 inserted, 0 deleted

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