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