Description:
added contest problem access control
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r282:6dab27215603 - - 5 files changed: 76 inserted, 17 deleted

@@ -1,60 +1,75
1 1 class TasksController < ApplicationController
2 2
3 3 before_filter :authenticate, :check_viewability
4 4
5 5 def index
6 6 redirect_to :action => 'list'
7 7 end
8 8
9 9 def list
10 10 @problems = Problem.find_available_problems
11 - @user = User.find(session[:user_id])
12 11 end
13 12
13 + # this has contest-wide access control
14 14 def view
15 15 base_name = params[:file]
16 - if !check_user_viewability(base_name)
16 + base_filename = File.basename("#{base_name}.#{params[:ext]}")
17 + filename = "#{Problem.download_file_basedir}/#{base_filename}"
18 +
19 + if !FileTest.exists?(filename)
17 20 redirect_to :action => 'index' and return
18 21 end
19 22
20 - base_filename = File.basename("#{base_name}.#{params[:ext]}")
21 - filename = "#{Problem.download_file_basedir}/#{base_filename}"
23 + send_file_to_user(filename, base_filename)
24 + end
22 25
23 - if !check_user_viewability(base_name) or !FileTest.exists?(filename)
26 + # this has problem-level access control
27 + def download
28 + problem = Problem.find(params[:id])
29 + if !problem or !problem.available or !@user.can_view_problem? problem
24 30 redirect_to :action => 'index' and return
25 31 end
26 32
33 + base_name = params[:file]
34 + base_filename = File.basename("#{base_name}.#{params[:ext]}")
35 + filename = "#{Problem.download_file_basedir}/#{params[:id]}/#{base_filename}"
36 + puts "SENDING: #{filename}"
37 +
38 + if !FileTest.exists?(filename)
39 + redirect_to :action => 'index' and return
40 + end
41 +
42 + puts "SENDING: #{filename}"
43 +
44 + send_file_to_user(filename, base_filename)
45 + end
46 +
47 + protected
48 +
49 + def send_file_to_user(filename, base_filename)
27 50 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
28 51 response.headers['Content-Type'] = "application/force-download"
29 52 response.headers['Content-Disposition'] = "attachment; filename=\"#{File.basename(filename)}\""
30 53 response.headers["X-Sendfile"] = filename
31 54 response.headers['Content-length'] = File.size(filename)
32 55 render :nothing => true
33 56 else
34 57 if params[:ext]=='pdf'
35 58 content_type = 'application/pdf'
36 59 else
37 60 content_type = 'application/octet-stream'
38 61 end
39 62
40 63 send_file filename, :stream => false, :filename => base_filename, :type => content_type
41 64 end
42 65 end
43 66
44 - protected
45 -
46 67 def check_viewability
47 68 @user = User.find(session[:user_id])
48 69 if @user==nil or !Configuration.show_tasks_to?(@user)
49 70 redirect_to :controller => 'main', :action => 'list'
50 71 return false
51 72 end
52 73 end
53 74
54 - def check_user_viewability(filename)
55 - # individual file access control shall be added here
56 - return false if not @user
57 - return Configuration.show_tasks_to?(@user)
58 75 end
59 -
60 - end
@@ -1,18 +1,19
1 1 module MainHelper
2 2
3 3 def link_to_description_if_any(name, problem, options={})
4 4 if !problem.url.blank?
5 5 return link_to name, problem.url, options
6 6 elsif !problem.description_filename.blank?
7 7 basename, ext = problem.description_filename.split('.')
8 8 options[:controller] = 'tasks'
9 - options[:action] = 'view'
9 + options[:action] = 'download'
10 + options[:id] = problem.id
10 11 options[:file] = basename
11 12 options[:ext] = ext
12 13 return link_to name, options
13 14 else
14 15 return ''
15 16 end
16 17 end
17 18
18 19 end
@@ -173,24 +173,47
173 173 end
174 174 end
175 175
176 176 def update_start_time
177 177 stat = self.contest_stat
178 178 if stat == nil
179 179 stat = UserContestStat.new(:user => self,
180 180 :started_at => Time.now.gmtime)
181 181 stat.save
182 182 end
183 183 end
184 184
185 + def problem_in_user_contests?(problem)
186 + problem_contests = problem.contests.all
187 +
188 + if problem_contests.length == 0 # this is public contest
189 + return true
190 + end
191 +
192 + contests.each do |contest|
193 + if problem_contests.find {|c| c.id == contest.id }
194 + return true
195 + end
196 + end
197 + return false
198 + end
199 +
200 + def can_view_problem?(problem)
201 + if not Configuration.multicontests?
202 + return problem.available
203 + else
204 + return problem_in_user_contests? problem
205 + end
206 + end
207 +
185 208 protected
186 209 def encrypt_new_password
187 210 return if password.blank?
188 211 self.salt = (10+rand(90)).to_s
189 212 self.hashed_password = User.encrypt(self.password,self.salt)
190 213 end
191 214
192 215 def assign_default_site
193 216 # have to catch error when migrating (because self.site is not available).
194 217 begin
195 218 if self.site==nil
196 219 self.site = Site.find_by_name('default')
@@ -14,17 +14,18
14 14 # map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase'
15 15 # This route can be invoked with purchase_url(:id => product.id)
16 16
17 17 # You can have the root of your site routed by hooking up ''
18 18 # -- just remember to delete public/index.html.
19 19 map.connect '', :controller => 'main', :action => 'login'
20 20
21 21 # Allow downloading Web Service WSDL as a file with an extension
22 22 # instead of a file named 'wsdl'
23 23 map.connect ':controller/service.wsdl', :action => 'wsdl'
24 24
25 25 map.connect 'tasks/view/:file.:ext', :controller => 'tasks', :action => 'view'
26 + map.connect 'tasks/download/:id/:file.:ext', :controller => 'tasks', :action => 'download'
26 27
27 28 # Install the default route as the lowest priority.
28 29 map.connect ':controller/:action/:id.:format'
29 30 map.connect ':controller/:action/:id'
30 31 end
@@ -42,28 +42,33
42 42
43 43 def self.long_ext(filename)
44 44 i = filename.index('.')
45 45 len = filename.length
46 46 return filename.slice(i..len)
47 47 end
48 48
49 49 def extract(tempfile)
50 50 testdata_filename = save_testdata_file(tempfile)
51 51 ext = TestdataImporter.long_ext(tempfile.original_filename)
52 52
53 53 extract_dir = File.join(GraderScript.raw_dir, @problem.name)
54 + if File.exists? extract_dir
55 + backup_count = 0
54 56 begin
57 + backup_count += 1
58 + backup_dirname = "#{extract_dir}.backup.#{backup_count}"
59 + end while File.exists? backup_dirname
60 + File.rename(extract_dir, backup_dirname)
61 + end
55 62 Dir.mkdir extract_dir
56 - rescue Errno::EEXIST
57 - end
58 63
59 64 if ext=='.tar.gz' or ext=='.tgz'
60 65 cmd = "tar -zxvf #{testdata_filename} -C #{extract_dir}"
61 66 elsif ext=='.tar'
62 67 cmd = "tar -xvf #{testdata_filename} -C #{extract_dir}"
63 68 elsif ext=='.zip'
64 69 cmd = "unzip -o #{testdata_filename} -d #{extract_dir}"
65 70 else
66 71 return nil
67 72 end
68 73
69 74 system(cmd)
@@ -129,25 +134,39
129 134 description.body = open(filename).read
130 135 description.save
131 136 @problem.description = description
132 137 @problem.save
133 138 return "\nProblem description imported from #{filename}."
134 139 else
135 140 return ''
136 141 end
137 142 end
138 143
139 144 def import_problem_pdf(dirname)
140 145 pdf_files = Dir["#{dirname}/*.pdf"]
146 + puts "CHECKING... #{dirname}"
141 147 if pdf_files.length != 0
148 + puts "HAS PDF FILE"
142 149 filename = pdf_files[0]
143 - out_filename = "#{Problem.download_file_basedir}/#{@problem.name}.pdf"
150 +
151 + @problem.save if not @problem.id
152 + out_dirname = "#{Problem.download_file_basedir}/#{@problem.id}"
153 + if not FileTest.exists? out_dirname
154 + Dir.mkdir out_dirname
155 + end
156 +
157 + out_filename = "#{out_dirname}/#{@problem.name}.pdf"
158 +
159 + if FileTest.exists? out_filename
160 + File.delete out_filename
161 + end
162 +
144 163 File.rename(filename, out_filename)
145 164 @problem.description_filename = "#{@problem.name}.pdf"
146 165 @problem.save
147 166 return "\nProblem pdf imported from #{filename}."
148 167 else
149 168 return ""
150 169 end
151 170 end
152 171
153 172 end
You need to be logged in to leave comments. Login now