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

r746:1323b43e275a - - 1 file changed: 0 inserted, 48 deleted

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