Description:
finalize multiple_login, change default menu of report to multiple login
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r521:5a22064770a9 - - 7 files changed: 59 inserted, 12 deleted

@@ -70,193 +70,193
70 70
71 71 def edit
72 72 @problem = Problem.find(params[:id])
73 73 @description = @problem.description
74 74 end
75 75
76 76 def update
77 77 @problem = Problem.find(params[:id])
78 78 @description = @problem.description
79 79 if @description == nil and params[:description][:body]!=''
80 80 @description = Description.new(params[:description])
81 81 if !@description.save
82 82 flash[:notice] = 'Error saving description'
83 83 render :action => 'edit' and return
84 84 end
85 85 @problem.description = @description
86 86 elsif @description!=nil
87 87 if !@description.update_attributes(params[:description])
88 88 flash[:notice] = 'Error saving description'
89 89 render :action => 'edit' and return
90 90 end
91 91 end
92 92 if params[:file] and params[:file].content_type != 'application/pdf'
93 93 flash[:notice] = 'Error: Uploaded file is not PDF'
94 94 render :action => 'edit' and return
95 95 end
96 96 if @problem.update_attributes(params[:problem])
97 97 flash[:notice] = 'Problem was successfully updated.'
98 98 unless params[:file] == nil or params[:file] == ''
99 99 flash[:notice] = 'Problem was successfully updated and a new PDF file is uploaded.'
100 100 out_dirname = "#{Problem.download_file_basedir}/#{@problem.id}"
101 101 if not FileTest.exists? out_dirname
102 102 Dir.mkdir out_dirname
103 103 end
104 104
105 105 out_filename = "#{out_dirname}/#{@problem.name}.pdf"
106 106 if FileTest.exists? out_filename
107 107 File.delete out_filename
108 108 end
109 109
110 110 File.open(out_filename,"wb") do |file|
111 111 file.write(params[:file].read)
112 112 end
113 113 @problem.description_filename = "#{@problem.name}.pdf"
114 114 @problem.save
115 115 end
116 116 redirect_to :action => 'show', :id => @problem
117 117 else
118 118 render :action => 'edit'
119 119 end
120 120 end
121 121
122 122 def destroy
123 123 Problem.find(params[:id]).destroy
124 124 redirect_to :action => 'list'
125 125 end
126 126
127 127 def toggle
128 128 @problem = Problem.find(params[:id])
129 129 @problem.available = !(@problem.available)
130 130 @problem.save
131 131 end
132 132
133 133 def turn_all_off
134 134 Problem.find(:all,
135 135 :conditions => "available = 1").each do |problem|
136 136 problem.available = false
137 137 problem.save
138 138 end
139 139 redirect_to :action => 'list'
140 140 end
141 141
142 142 def turn_all_on
143 143 Problem.find(:all,
144 144 :conditions => "available = 0").each do |problem|
145 145 problem.available = true
146 146 problem.save
147 147 end
148 148 redirect_to :action => 'list'
149 149 end
150 150
151 151 def stat
152 152 @problem = Problem.find(params[:id])
153 153 unless @problem.available or session[:admin]
154 154 redirect_to :controller => 'main', :action => 'list'
155 155 return
156 156 end
157 157 @submissions = Submission.includes(:user).where(problem_id: params[:id]).order(:user_id,:id)
158 158
159 159 #stat summary
160 160 range =65
161 161 @histogram = { data: Array.new(range,0), summary: {} }
162 162 user = Hash.new(0)
163 163 @submissions.find_each do |sub|
164 164 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
165 165 @histogram[:data][d.to_i] += 1 if d < range
166 - user[sub.user_id] = [user[sub.user_id], (sub.points >= @problem.full_score) ? 1 : 0].max
166 + user[sub.user_id] = [user[sub.user_id], (sub.try(:points) >= @problem.full_score) ? 1 : 0].max
167 167 end
168 168 @histogram[:summary][:max] = [@histogram[:data].max,1].max
169 169
170 170 @summary = { attempt: user.count, solve: 0 }
171 171 user.each_value { |v| @summary[:solve] += 1 if v == 1 }
172 172 end
173 173
174 174 def manage
175 175 @problems = Problem.find(:all, :order => 'date_added DESC')
176 176 end
177 177
178 178 def do_manage
179 179 if params.has_key? 'change_date_added'
180 180 change_date_added
181 181 elsif params.has_key? 'add_to_contest'
182 182 add_to_contest
183 183 elsif params.has_key? 'enable_problem'
184 184 set_available(true)
185 185 elsif params.has_key? 'disable_problem'
186 186 set_available(false)
187 187 end
188 188 redirect_to :action => 'manage'
189 189 end
190 190
191 191 def import
192 192 @allow_test_pair_import = allow_test_pair_import?
193 193 end
194 194
195 195 def do_import
196 196 old_problem = Problem.find_by_name(params[:name])
197 197 if !allow_test_pair_import? and params.has_key? :import_to_db
198 198 params.delete :import_to_db
199 199 end
200 200 @problem, import_log = Problem.create_from_import_form_params(params,
201 201 old_problem)
202 202
203 203 if !@problem.errors.empty?
204 204 render :action => 'import' and return
205 205 end
206 206
207 207 if old_problem!=nil
208 208 flash[:notice] = "The test data has been replaced for problem #{@problem.name}"
209 209 end
210 210 @log = import_log
211 211 end
212 212
213 213 def remove_contest
214 214 problem = Problem.find(params[:id])
215 215 contest = Contest.find(params[:contest_id])
216 216 if problem!=nil and contest!=nil
217 217 problem.contests.delete(contest)
218 218 end
219 219 redirect_to :action => 'manage'
220 220 end
221 221
222 222 ##################################
223 223 protected
224 224
225 225 def allow_test_pair_import?
226 226 if defined? ALLOW_TEST_PAIR_IMPORT
227 227 return ALLOW_TEST_PAIR_IMPORT
228 228 else
229 229 return false
230 230 end
231 231 end
232 232
233 233 def change_date_added
234 234 problems = get_problems_from_params
235 235 year = params[:date_added][:year].to_i
236 236 month = params[:date_added][:month].to_i
237 237 day = params[:date_added][:day].to_i
238 238 date = Date.new(year,month,day)
239 239 problems.each do |p|
240 240 p.date_added = date
241 241 p.save
242 242 end
243 243 end
244 244
245 245 def add_to_contest
246 246 problems = get_problems_from_params
247 247 contest = Contest.find(params[:contest][:id])
248 248 if contest!=nil and contest.enabled
249 249 problems.each do |p|
250 250 p.contests << contest
251 251 end
252 252 end
253 253 end
254 254
255 255 def set_available(avail)
256 256 problems = get_problems_from_params
257 257 problems.each do |p|
258 258 p.available = avail
259 259 p.save
260 260 end
261 261 end
262 262
@@ -123,109 +123,132
123 123
124 124 lang = Language.find_by_id(sub.language_id)
125 125 next unless lang
126 126 next unless sub.points >= @problem.full_score
127 127
128 128 #initialize
129 129 unless @by_lang.has_key?(lang.pretty_name)
130 130 @by_lang[lang.pretty_name] = {
131 131 runtime: { avail: false, value: 2**30-1 },
132 132 memory: { avail: false, value: 2**30-1 },
133 133 length: { avail: false, value: 2**30-1 },
134 134 first: { avail: false, value: DateTime.new(3000,1,1) }
135 135 }
136 136 end
137 137
138 138 if sub.max_runtime and sub.max_runtime < @by_lang[lang.pretty_name][:runtime][:value]
139 139 @by_lang[lang.pretty_name][:runtime] = { avail: true, user_id: sub.user_id, value: sub.max_runtime, sub_id: sub.id }
140 140 end
141 141
142 142 if sub.peak_memory and sub.peak_memory < @by_lang[lang.pretty_name][:memory][:value]
143 143 @by_lang[lang.pretty_name][:memory] = { avail: true, user_id: sub.user_id, value: sub.peak_memory, sub_id: sub.id }
144 144 end
145 145
146 146 if sub.submitted_at and sub.submitted_at < @by_lang[lang.pretty_name][:first][:value] and
147 147 !sub.user.admin?
148 148 @by_lang[lang.pretty_name][:first] = { avail: true, user_id: sub.user_id, value: sub.submitted_at, sub_id: sub.id }
149 149 end
150 150
151 151 if @by_lang[lang.pretty_name][:length][:value] > sub.effective_code_length
152 152 @by_lang[lang.pretty_name][:length] = { avail: true, user_id: sub.user_id, value: sub.effective_code_length, sub_id: sub.id }
153 153 end
154 154 end
155 155
156 156 #process user_id
157 157 @by_lang.each do |lang,prop|
158 158 prop.each do |k,v|
159 159 v[:user] = User.exists?(v[:user_id]) ? User.find(v[:user_id]).full_name : "(NULL)"
160 160 end
161 161 end
162 162
163 163 #sum into best
164 164 if @by_lang and @by_lang.first
165 165 @best = @by_lang.first[1].clone
166 166 @by_lang.each do |lang,prop|
167 167 if @best[:runtime][:value] >= prop[:runtime][:value]
168 168 @best[:runtime] = prop[:runtime]
169 169 @best[:runtime][:lang] = lang
170 170 end
171 171 if @best[:memory][:value] >= prop[:memory][:value]
172 172 @best[:memory] = prop[:memory]
173 173 @best[:memory][:lang] = lang
174 174 end
175 175 if @best[:length][:value] >= prop[:length][:value]
176 176 @best[:length] = prop[:length]
177 177 @best[:length][:lang] = lang
178 178 end
179 179 if @best[:first][:value] >= prop[:first][:value]
180 180 @best[:first] = prop[:first]
181 181 @best[:first][:lang] = lang
182 182 end
183 183 end
184 184 end
185 185
186 186 @histogram[:summary][:max] = [@histogram[:data].max,1].max
187 187 @summary[:attempt] = user.count
188 188 user.each_value { |v| @summary[:solve] += 1 if v == 1 }
189 189 end
190 190
191 191 def stuck #report struggling user,problem
192 192 # init
193 193 user,problem = nil
194 194 solve = true
195 195 tries = 0
196 196 @struggle = Array.new
197 197 record = {}
198 198 Submission.includes(:problem,:user).order(:problem_id,:user_id).find_each do |sub|
199 199 next unless sub.user and sub.problem
200 200 if user != sub.user_id or problem != sub.problem_id
201 201 @struggle << { user: record[:user], problem: record[:problem], tries: tries } unless solve
202 202 record = {user: sub.user, problem: sub.problem}
203 203 user,problem = sub.user_id, sub.problem_id
204 204 solve = false
205 205 tries = 0
206 206 end
207 207 if sub.points >= sub.problem.full_score
208 208 solve = true
209 209 else
210 210 tries += 1
211 211 end
212 212 end
213 213 @struggle.sort!{|a,b| b[:tries] <=> a[:tries] }
214 214 @struggle = @struggle[0..50]
215 215 end
216 216
217 217
218 218 def multiple_login
219 + #user with multiple IP
219 220 raw = Submission.joins(:user).joins(:problem).where("problems.available != 0").group("login,ip_address").order(:login)
220 221 last,count = 0,0
221 - @multiple = []
222 + first = 0
223 + @users = []
222 224 raw.each do |r|
223 225 if last != r.user.login
224 226 count = 1
227 + last = r.user.login
228 + first = r
225 229 else
226 - @multiple << r
230 + @users << first if count == 1
231 + @users << r
232 + count += 1
233 + end
234 + end
235 +
236 + #IP with multiple user
237 + raw = Submission.joins(:user).joins(:problem).where("problems.available != 0").group("login,ip_address").order(:ip_address)
238 + last,count = 0,0
239 + first = 0
240 + @ip = []
241 + raw.each do |r|
242 + if last != r.ip_address
243 + count = 1
244 + last = r.ip_address
245 + first = r
246 + else
247 + @ip << first if count == 1
248 + @ip << r
249 + count += 1
227 250 end
228 251 end
229 252 end
230 253
231 254 end
@@ -1,187 +1,192
1 1 require 'csv'
2 2
3 3 class UserAdminController < ApplicationController
4 4
5 5
6 6 include MailHelperMethods
7 7
8 8 before_filter :admin_authorization
9 9
10 10 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
11 11 verify :method => :post, :only => [ :destroy,
12 12 :create, :create_from_list,
13 13 :update,
14 14 :manage_contest,
15 15 :bulk_mail
16 16 ],
17 17 :redirect_to => { :action => :list }
18 18
19 19 def index
20 20 list
21 21 render :action => 'list'
22 22 end
23 23
24 24 def list
25 25 @user_count = User.count
26 26 if params[:page] == 'all'
27 27 @users = User.all
28 28 @paginated = false
29 29 else
30 30 @users = User.paginate :page => params[:page]
31 31 @paginated = true
32 32 end
33 33 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
34 34 @contests = Contest.enabled
35 35 end
36 36
37 37 def active
38 38 sessions = ActiveRecord::SessionStore::Session.find(:all, :conditions => ["updated_at >= ?", 60.minutes.ago])
39 39 @users = []
40 40 sessions.each do |session|
41 41 if session.data[:user_id]
42 42 @users << User.find(session.data[:user_id])
43 43 end
44 44 end
45 45 end
46 46
47 47 def show
48 48 @user = User.find(params[:id])
49 49 end
50 50
51 51 def new
52 52 @user = User.new
53 53 end
54 54
55 55 def create
56 56 @user = User.new(params[:user])
57 57 @user.activated = true
58 58 if @user.save
59 59 flash[:notice] = 'User was successfully created.'
60 60 redirect_to :action => 'list'
61 61 else
62 62 render :action => 'new'
63 63 end
64 64 end
65 65
66 66 def create_from_list
67 67 lines = params[:user_list]
68 68
69 69 note = []
70 70
71 71 lines.split("\n").each do |line|
72 72 items = line.chomp.split(',')
73 73 if items.length>=2
74 74 login = items[0]
75 75 full_name = items[1]
76 76
77 77 added_random_password = false
78 78 if items.length>=3
79 79 password = items[2].chomp(" ")
80 80 user_alias = (items.length>=4) ? items[3] : login
81 81 else
82 82 password = random_password
83 83 user_alias = (items.length>=4) ? items[3] : login
84 84 added_random_password = true
85 85 end
86 86
87 + user = User.find_by_login(login)
88 + if user
89 + user.password = password
90 + else
87 91 user = User.new({:login => login,
88 92 :full_name => full_name,
89 93 :password => password,
90 94 :password_confirmation => password,
91 95 :alias => user_alias})
96 + end
92 97 user.activated = true
93 98 user.save
94 99
95 100 if added_random_password
96 101 note << "'#{login}' (+)"
97 102 else
98 103 note << login
99 104 end
100 105 end
101 106 end
102 107 flash[:notice] = 'User(s) ' + note.join(', ') +
103 108 ' were successfully created. ' +
104 109 '( (+) - created with random passwords.)'
105 110 redirect_to :action => 'list'
106 111 end
107 112
108 113 def edit
109 114 @user = User.find(params[:id])
110 115 end
111 116
112 117 def update
113 118 @user = User.find(params[:id])
114 119 if @user.update_attributes(params[:user])
115 120 flash[:notice] = 'User was successfully updated.'
116 121 redirect_to :action => 'show', :id => @user
117 122 else
118 123 render :action => 'edit'
119 124 end
120 125 end
121 126
122 127 def destroy
123 128 User.find(params[:id]).destroy
124 129 redirect_to :action => 'list'
125 130 end
126 131
127 132 def user_stat
128 133 if params[:commit] == 'download csv'
129 134 @problems = Problem.all
130 135 else
131 136 @problems = Problem.find_available_problems
132 137 end
133 138 @users = User.find(:all, :include => [:contests, :contest_stat])
134 139 @scorearray = Array.new
135 140 @users.each do |u|
136 141 ustat = Array.new
137 142 ustat[0] = u
138 143 @problems.each do |p|
139 144 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
140 145 if (sub!=nil) and (sub.points!=nil)
141 146 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
142 147 else
143 148 ustat << [0,false]
144 149 end
145 150 end
146 151 @scorearray << ustat
147 152 end
148 153
149 154 if params[:commit] == 'download csv' then
150 155 csv = gen_csv_from_scorearray(@scorearray,@problems)
151 156 send_data csv, filename: 'last_score.csv'
152 157 else
153 158 render template: 'user_admin/user_stat'
154 159 end
155 160 end
156 161
157 162 def user_stat_max
158 163 if params[:commit] == 'download csv'
159 164 @problems = Problem.all
160 165 else
161 166 @problems = Problem.find_available_problems
162 167 end
163 168 @users = User.find(:all, :include => [:contests, :contest_stat])
164 169 @scorearray = Array.new
165 170 #set up range from param
166 171 since_id = params.fetch(:since_id, 0).to_i
167 172 until_id = params.fetch(:until_id, 0).to_i
168 173 @users.each do |u|
169 174 ustat = Array.new
170 175 ustat[0] = u
171 176 @problems.each do |p|
172 177 max_points = 0
173 178 Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub|
174 179 max_points = sub.points if sub and sub.points and (sub.points > max_points)
175 180 end
176 181 ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)]
177 182 end
178 183 @scorearray << ustat
179 184 end
180 185
181 186 if params[:commit] == 'download csv' then
182 187 csv = gen_csv_from_scorearray(@scorearray,@problems)
183 188 send_data csv, filename: 'max_score.csv'
184 189 else
185 190 render template: 'user_admin/user_stat'
186 191 end
187 192 end
@@ -1,112 +1,112
1 1 # Methods added to this helper will be available to all templates in the application.
2 2 module ApplicationHelper
3 3
4 4 def user_header
5 5 menu_items = ''
6 6 user = User.find(session[:user_id])
7 7
8 8 if (user!=nil) and (session[:admin])
9 9 # admin menu
10 10 menu_items << "<b>Administrative task:</b> "
11 11 append_to menu_items, '[Announcements]', 'announcements', 'index'
12 12 append_to menu_items, '[Msg console]', 'messages', 'console'
13 13 append_to menu_items, '[Problems]', 'problems', 'index'
14 14 append_to menu_items, '[Users]', 'user_admin', 'index'
15 15 append_to menu_items, '[Results]', 'user_admin', 'user_stat'
16 - append_to menu_items, '[Report]', 'report', 'login_stat'
16 + append_to menu_items, '[Report]', 'report', 'multiple_login'
17 17 append_to menu_items, '[Graders]', 'graders', 'list'
18 18 append_to menu_items, '[Contests]', 'contest_management', 'index'
19 19 append_to menu_items, '[Sites]', 'sites', 'index'
20 20 append_to menu_items, '[System config]', 'configurations', 'index'
21 21 menu_items << "<br/>"
22 22 end
23 23
24 24 # main page
25 25 append_to menu_items, "[#{I18n.t 'menu.main'}]", 'main', 'list'
26 26 append_to menu_items, "[#{I18n.t 'menu.messages'}]", 'messages', 'list'
27 27
28 28 if (user!=nil) and (GraderConfiguration.show_tasks_to?(user))
29 29 append_to menu_items, "[#{I18n.t 'menu.tasks'}]", 'tasks', 'list'
30 30 append_to menu_items, "[#{I18n.t 'menu.submissions'}]", 'main', 'submission'
31 31 append_to menu_items, "[#{I18n.t 'menu.test'}]", 'test', 'index'
32 32 end
33 33
34 34 if GraderConfiguration['right.user_hall_of_fame']
35 35 append_to menu_items, "[#{I18n.t 'menu.hall_of_fame'}]", 'report', 'problem_hof'
36 36 end
37 37 append_to menu_items, "[#{I18n.t 'menu.help'}]", 'main', 'help'
38 38
39 39 if GraderConfiguration['system.user_setting_enabled']
40 40 append_to menu_items, "[#{I18n.t 'menu.settings'}]", 'users', 'index'
41 41 end
42 42 append_to menu_items, "[#{I18n.t 'menu.log_out'}]", 'main', 'login'
43 43
44 44 menu_items.html_safe
45 45 end
46 46
47 47 def append_to(option,label, controller, action)
48 48 option << ' ' if option!=''
49 49 option << link_to_unless_current(label,
50 50 :controller => controller,
51 51 :action => action)
52 52 end
53 53
54 54 def format_short_time(time)
55 55 now = Time.now.gmtime
56 56 st = ''
57 57 if (time.yday != now.yday) or
58 58 (time.year != now.year)
59 59 st = time.strftime("%x ")
60 60 end
61 61 st + time.strftime("%X")
62 62 end
63 63
64 64 def format_short_duration(duration)
65 65 return '' if duration==nil
66 66 d = duration.to_f
67 67 return Time.at(d).gmtime.strftime("%X")
68 68 end
69 69
70 70 def read_textfile(fname,max_size=2048)
71 71 begin
72 72 File.open(fname).read(max_size)
73 73 rescue
74 74 nil
75 75 end
76 76 end
77 77
78 78 def user_title_bar(user)
79 79 header = ''
80 80 time_left = ''
81 81
82 82 #
83 83 # if the contest is over
84 84 if GraderConfiguration.time_limit_mode?
85 85 if user.contest_finished?
86 86 header = <<CONTEST_OVER
87 87 <tr><td colspan="2" align="center">
88 88 <span class="contest-over-msg">THE CONTEST IS OVER</span>
89 89 </td></tr>
90 90 CONTEST_OVER
91 91 end
92 92 if !user.contest_started?
93 93 time_left = "&nbsp;&nbsp;" + (t 'title_bar.contest_not_started')
94 94 else
95 95 time_left = "&nbsp;&nbsp;" + (t 'title_bar.remaining_time') +
96 96 " #{format_short_duration(user.contest_time_left)}"
97 97 end
98 98 end
99 99
100 100 #
101 101 # if the contest is in the anaysis mode
102 102 if GraderConfiguration.analysis_mode?
103 103 header = <<ANALYSISMODE
104 104 <tr><td colspan="2" align="center">
105 105 <span class="contest-over-msg">ANALYSIS MODE</span>
106 106 </td></tr>
107 107 ANALYSISMODE
108 108 end
109 109
110 110 contest_name = GraderConfiguration['contest.name']
111 111
112 112 #
@@ -1,170 +1,170
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_many :test_requests, :order => "submitted_at DESC"
12 12
13 13 has_many :messages,
14 14 :class_name => "Message",
15 15 :foreign_key => "sender_id",
16 16 :order => 'created_at DESC'
17 17
18 18 has_many :replied_messages,
19 19 :class_name => "Message",
20 20 :foreign_key => "receiver_id",
21 21 :order => 'created_at DESC'
22 22
23 23 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
24 24
25 25 belongs_to :site
26 26 belongs_to :country
27 27
28 28 has_and_belongs_to_many :contests, :uniq => true, :order => 'name'
29 29
30 30 scope :activated_users, :conditions => {:activated => true}
31 31
32 32 validates_presence_of :login
33 33 validates_uniqueness_of :login
34 34 validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/
35 35 validates_length_of :login, :within => 3..30
36 36
37 37 validates_presence_of :full_name
38 38 validates_length_of :full_name, :minimum => 1
39 39
40 40 validates_presence_of :password, :if => :password_required?
41 41 validates_length_of :password, :within => 4..20, :if => :password_required?
42 42 validates_confirmation_of :password, :if => :password_required?
43 43
44 44 validates_format_of :email,
45 45 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
46 46 :if => :email_validation?
47 47 validate :uniqueness_of_email_from_activated_users,
48 48 :if => :email_validation?
49 49 validate :enough_time_interval_between_same_email_registrations,
50 50 :if => :email_validation?
51 51
52 52 # these are for ytopc
53 53 # disable for now
54 54 #validates_presence_of :province
55 55
56 56 attr_accessor :password
57 57
58 58 before_save :encrypt_new_password
59 59 before_save :assign_default_site
60 60 before_save :assign_default_contest
61 61
62 62 # this is for will_paginate
63 63 cattr_reader :per_page
64 64 @@per_page = 50
65 65
66 66 def self.authenticate(login, password)
67 67 user = find_by_login(login)
68 68 if user
69 69 return user if user.authenticated?(password)
70 - if user.authenticated_by_cucas?(password) or user.authenticated_by_pop3?(password)
71 - user.password = password
72 - user.save
73 - return user
74 - end
70 + # if user.authenticated_by_cucas?(password) or user.authenticated_by_pop3?(password)
71 + # user.password = password
72 + # user.save
73 + # return user
74 + # end
75 75 end
76 76 end
77 77
78 78 def authenticated?(password)
79 79 if self.activated
80 80 hashed_password == User.encrypt(password,self.salt)
81 81 else
82 82 false
83 83 end
84 84 end
85 85
86 86 def authenticated_by_pop3?(password)
87 87 Net::POP3.enable_ssl
88 88 pop = Net::POP3.new('pops.it.chula.ac.th')
89 89 authen = true
90 90 begin
91 91 pop.start(login, password)
92 92 pop.finish
93 93 return true
94 94 rescue
95 95 return false
96 96 end
97 97 end
98 98
99 99 def authenticated_by_cucas?(password)
100 100 url = URI.parse('https://www.cas.chula.ac.th/cas/api/?q=studentAuthenticate')
101 101 appid = '41508763e340d5858c00f8c1a0f5a2bb'
102 102 appsecret ='d9cbb5863091dbe186fded85722a1e31'
103 103 post_args = {
104 104 'appid' => appid,
105 105 'appsecret' => appsecret,
106 106 'username' => login,
107 107 'password' => password
108 108 }
109 109
110 110 #simple call
111 111 begin
112 112 http = Net::HTTP.new('www.cas.chula.ac.th', 443)
113 113 http.use_ssl = true
114 114 result = [ ]
115 115 http.start do |http|
116 116 req = Net::HTTP::Post.new('/cas/api/?q=studentAuthenticate')
117 117 param = "appid=#{appid}&appsecret=#{appsecret}&username=#{login}&password=#{password}"
118 118 resp = http.request(req,param)
119 119 result = JSON.parse resp.body
120 120 end
121 121 return true if result["type"] == "beanStudent"
122 122 rescue
123 123 return false
124 124 end
125 125 return false
126 126 end
127 127
128 128 def admin?
129 129 self.roles.detect {|r| r.name == 'admin' }
130 130 end
131 131
132 132 def email_for_editing
133 133 if self.email==nil
134 134 "(unknown)"
135 135 elsif self.email==''
136 136 "(blank)"
137 137 else
138 138 self.email
139 139 end
140 140 end
141 141
142 142 def email_for_editing=(e)
143 143 self.email=e
144 144 end
145 145
146 146 def alias_for_editing
147 147 if self.alias==nil
148 148 "(unknown)"
149 149 elsif self.alias==''
150 150 "(blank)"
151 151 else
152 152 self.alias
153 153 end
154 154 end
155 155
156 156 def alias_for_editing=(e)
157 157 self.alias=e
158 158 end
159 159
160 160 def activation_key
161 161 if self.hashed_password==nil
162 162 encrypt_new_password
163 163 end
164 164 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
165 165 end
166 166
167 167 def verify_activation_key(key)
168 168 key == activation_key
169 169 end
170 170
@@ -1,51 +1,53
1 1 :css
2 2 .fix-width {
3 3 font-family: "Consolas, Monaco, Droid Sans Mono,Mono, Monospace,Courier"
4 4 }
5 5
6 6 %h1 Problem stat: #{@problem.name}
7 7 %h2 Overview
8 8
9 9
10 10 %table.info
11 11 %thead
12 12 %tr.info-head
13 13 %th Stat
14 14 %th Value
15 15 %tbody
16 16 %tr{class: cycle('info-even','info-odd')}
17 17 %td Submissions
18 18 %td= @submissions.count
19 19 %tr{class: cycle('info-even','info-odd')}
20 20 %td Solved/Attempted User
21 21 %td #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
22 22
23 23 %h2 Submissions Count
24 24 = render partial: 'application/bar_graph', locals: { histogram: @histogram }
25 25
26 26 %h2 Submissions
27 27 - if @submissions and @submissions.count > 0
28 28 %table.info#main_table
29 29 %thead
30 30 %tr.info-head
31 31 %th ID
32 32 %th Login
33 33 %th Name
34 34 %th Submitted_at
35 35 %th Points
36 36 %th comment
37 + %th IP
37 38 %tbody
38 39 - row_odd,curr = true,''
39 40 - @submissions.each do |sub|
40 41 - next unless sub.user
41 42 - row_odd,curr = !row_odd, sub.user if curr != sub.user
42 43 %tr{class: row_odd ? "info-odd" : "info-even"}
43 44 %td= link_to sub.id, controller: 'graders', action: 'submission', id: sub.id
44 45 %td= link_to sub.user.login, controller: :users, action: :profile, id: sub.user.id
45 46 %td= sub.user.full_name
46 47 %td= time_ago_in_words(sub.submitted_at) + " ago"
47 48 %td= sub.points
48 49 %td.fix-width= sub.grader_comment
50 + %td= sub.ip_address
49 51 - else
50 52 No submission
51 53
@@ -1,20 +1,37
1 1 - content_for :header do
2 2 = stylesheet_link_tag 'tablesorter-theme.cafe'
3 3 = javascript_include_tag 'local_jquery'
4 4
5 5 %h1 Login status
6 6
7 7 =render partial: 'report_menu'
8 8
9 + Checking for all submissions with the currently available problem
10 +
11 + %h2 Users with Multiple IP
9 12 %table.tablesorter-cafe#my_table
10 13 %thead
11 14 %tr
12 15 %th login
13 16 %th full name
14 17 %th IP
15 18 %tbody
16 - - @multiple.each do |l|
19 + - @users.each do |l|
17 20 %tr{class: cycle('info-even','info-odd')}
18 - %td= link_to l[:login], controller: 'users', action: 'profile', id: l[:id]
19 - %td= l[:full_name]
21 + %td= link_to l.user.login, controller: 'users', action: 'profile', id: l[:id]
22 + %td= l.user.full_name
20 23 %td= l[:ip_address]
24 +
25 + %h2 IP with multiple users
26 + %table.tablesorter-cafe#my_table
27 + %thead
28 + %tr
29 + %th IP
30 + %th login
31 + %th full name
32 + %tbody
33 + - @ip.each do |l|
34 + %tr{class: cycle('info-even','info-odd')}
35 + %td= l[:ip_address]
36 + %td= link_to l.user.login, controller: 'users', action: 'profile', id: l[:id]
37 + %td= l.user.full_name
You need to be logged in to leave comments. Login now