Description:
fix cucas authen, the old code work on 2.1.2 but not 1.9.2
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r407:b11b67ad58fb - - 1 file changed: 8 inserted, 1 deleted

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