applied my changes - initial import
[boxroom-stian.git] / app / controllers / folder_controller.rb
blob2379cc5c255669aebea8875679a3d1c880a6a9fe
1 # The folder controller contains the following actions:\r
2 # [#index]              the default action, redirects to list\r
3 # [#list]               list files and sub folders in a folder\r
4 # [#feed]               authorizes, sets appropriate variables and header for RSS feed\r
5 # [#feed_warning]       renders page with explanations/warnings about RSS feed\r
6 # [#new]                shows the form for creating a new folder\r
7 # [#create]             create a new folder\r
8 # [#rename]             show the form for adjusting the folder's name\r
9 # [#update]             updates the attributes of a folder\r
10 # [#destroy]            delete a folder\r
11 # [#update_permissions] save the new rights given by the user\r
13 class FolderController < ApplicationController\r
14   skip_before_filter :authorize, :only => :feed\r
16   before_filter :does_folder_exist, :except => [:list, :feed, :feed_warning]\r
17   before_filter :authorize_creating, :only => [:new, :create, :multimove]\r
18   before_filter :authorize_reading, :only => :list\r
19   before_filter :authorize_updating, :only => [:rename, :update, :update_rights]\r
20   before_filter :authorize_deleting, :only => :destroy\r
22   # Sessions are not needed for feeds\r
23   session :off, :only => 'feed'\r
24   layout 'folder', :except => 'feed'\r
25                                    \r
26   # do something to selected files in folder list\r
27   def multichange\r
28     @folder = Folder.find(folder_id)\r
29     unless @logged_in_user.can_delete(folder_id)\r
30       flash[:folder_error] = "You don't have delete permissions for this folder."\r
31       redirect_to :action => 'list', :id => folder_id and return false\r
32     end\r
34     checked_files, checked_folders = [], []\r
35     params['checked_file'].each {|k,v| checked_files << Myfile.find(k.to_i) if v == 'yes' } if params['checked_file']\r
36     params['checked_folder'].each {|k,v| checked_folders << Folder.find(k.to_i) if v == 'yes' } if params['checked_folder']\r
37     unless (checked_files.size + checked_folders.size) > 0\r
38       flash[:folder_error] = "You didn't select any files or folders."\r
39       redirect_to :action => 'list', :id => folder_id and return false\r
40     end\r
42     case params['checked']['action']\r
43       when 'delete'\r
44         checked_files.each {|x| x.destroy }\r
45         checked_folders.each {|x| x.delete }\r
47       when 'add to clipboard'\r
48         flash[:folder_info] = "The files and/or folders you marked have been put on the clipboard. They will not disappear from this folder, until you choose moving them to a new folder."\r
49         temp = @logged_in_user.clipboards\r
50         already_files, already_folders = temp.collect(&:myfile), temp.collect(&:folder)\r
51         checked_files.each do |x| \r
52           unless already_files.index(x)\r
53             Clipboard.new(:user => @logged_in_user, :myfile => x).save \r
54           end\r
55         end\r
56         \r
57         checked_folders.each do |x| \r
58           unless already_folders.index(x) \r
59             Clipboard.new(:user => @logged_in_user, :folder => x).save \r
60           end\r
61         end\r
63       when 'download all'\r
64         tmpfile = TEMP_PATH + "/zip" + Time.now.to_f.to_s + ".tmp"\r
65         folders, files = "", "" \r
66         checked_folders.collect(&:name).each {|x| folders << "\"#{x}\" " }\r
67         checked_files.collect(&:filename).each {|x| files << "\"#{x}\" " }\r
69         # tricky because we don't want absolute paths in the zip file, but the temp \r
70         # dir is a relative path \r
71         slashes = @folder.path_on_disk.scan('/').size\r
72         slashes += 1 unless @folder.id == 1\r
73         tmppath = '../' * slashes\r
74         cmd = "cd \"#{@folder.path_on_disk}\"; zip -r #{tmppath}#{tmpfile} #{folders} #{files}"\r
75         `#{cmd}`   \r
76         puts cmd\r
77         p files\r
78         @folder.log_usage("zipped", cmd)\r
79         p @folder.path_on_disk\r
81         if File.exists?(tmpfile)\r
82           send_file tmpfile, :filename => "DownloadAllFiles.zip"\r
83           return false\r
84         else\r
85           flash[:folder_error] = "Could not zip selected files."\r
86           @folder.log_usage("error","could not zip " + checked_folders.join(":") + " " + checked_files.join(":") )\r
87         end\r
88           \r
89     end\r
90     redirect_to :action => 'list', :id => folder_id\r
91   end\r
93   # move files and folders in clipboard to the current folder\r
94   def multimove\r
95     @logged_in_user.clipboards.each do |x|\r
96       if x.folder\r
97         File.mv(x.folder.path_on_disk, @folder.path_on_disk)\r
98         x.folder.log_usage("moved", "from #{x.folder.name} to #{@folder.name}")\r
99         x.folder.parent = @folder\r
100         x.folder.save\r
101       else\r
102         File.mv(File.join(x.myfile.folder.path_on_disk, x.myfile.filename), @folder.path_on_disk)\r
103         x.myfile.log_usage("moved", "from #{x.myfile.folder.name} to #{@folder.name}")\r
104         x.myfile.folder = @folder\r
105         x.myfile.save\r
106       end\r
107       x.destroy\r
108     end\r
109     redirect_to :action => 'list', :id => folder_id\r
110   end\r
112   # deletes all clipboard entries for a given user\r
113   def cancel_moving\r
114     @logged_in_user.clipboards.collect(&:destroy)\r
115     redirect_to :action => 'list', :id => params[:folder_id]\r
116   end\r
118   # The default action, redirects to list.\r
119   def index\r
120     list\r
121     render_action 'list'\r
122   end\r
124   # List the files and sub-folders in a folder.\r
125   def list\r
126     # Get the folder\r
127     @folder = Folder.find_by_id(folder_id)\r
128     \r
129     # Set if the user is allowed to update or delete in this folder;\r
130     # these instance variables are used in the view.\r
131     @can_update = @logged_in_user.can_update(@folder.id)\r
132     @can_delete = @logged_in_user.can_delete(@folder.id)\r
134     # determine the order in which files are shown\r
135     file_order = 'filename '\r
136     file_order = params[:order_by].sub('name', 'filename') + ' ' if params[:order_by]\r
137     file_order += params[:order] if params[:order]\r
139     # determine the order in which folders are shown\r
140     folder_order = 'name '\r
141     if params[:order_by] and params[:order_by] != 'filesize'    \r
142       folder_order = params[:order_by] + ' '\r
143       folder_order += params[:order] if params[:order]\r
144     end\r
146     # List of subfolders\r
147     @folders = @folder.list_subfolders(@logged_in_user, folder_order.rstrip)\r
149     # List of files in the folder\r
150     @myfiles = @folder.list_files(@logged_in_user, file_order.rstrip)\r
152     #get the correct URL\r
153     url = url_for(:controller => 'folder', :action => 'list', :id => nil)\r
155     # it's nice to have the possibility to go up one level\r
156     @folder_up = @folder.parent.id.to_s if @folder.parent\r
157   end\r
159   # Authorizes, sets the appropriate variables and headers.\r
160   # The feed is actually implemented in: app/views/folder/feed.rxml.\r
161   def feed\r
162     # check for valid access key:\r
163     user = User.find_by_rss_access_key(params[:access_key])\r
164     @authorized = !user.blank?\r
166     # get the folder\r
167     @folder = Folder.find_by_id(folder_id)\r
169     # set appriopriate instance variables,\r
170     # so the feed can be created in folder.rxml\r
171     if @authorized and not @folder.blank?\r
172       if @folder.is_root or user.can_read(@folder.id)\r
173         @folders = @folder.list_subfolders(user, 'name')\r
174         @myfiles = @folder.list_files(user, 'filename')\r
175       else\r
176         @authorized = false\r
177       end\r
178     end\r
180     # finally, set correct header\r
181     if @authorized\r
182       headers['Content-Type'] = 'text/xml'\r
183     else\r
184       headers['Content-Type'] = 'text/html'\r
185     end\r
186   end\r
188   # Page that shows warning about RSS\r
189   # and the feed's authorization.\r
190   def feed_warning\r
191     render\r
192   end\r
194   # Shows the form where a user can enter the name for the a folder.\r
195   # The new folder will be stored in the 'current' folder.\r
196   def new\r
197     @folder = Folder.new\r
198   end\r
200   # Create a new folder with the posted variables from the 'new' view.\r
201   def create\r
202     if request.post?\r
203       params[:folder][:name] = Myfile.base_part_of(params[:folder][:name])\r
204       @folder = Folder.new(params[:folder])\r
205       @folder.parent = Folder.find(folder_id)\r
206       @folder.date_modified = Time.now\r
207       @folder.user = @logged_in_user\r
208       if @folder.save\r
209         # copy groups rights on parent folder to new folder\r
210         copy_permissions_to_new_folder(@folder)\r
211         # back to the list\r
212         redirect_to :action => 'list', :id => params[:id]\r
213       else\r
214         render_action 'new'\r
215       end\r
216     end\r
217   end\r
219   # Show a form with the current name of the folder in a text field.\r
220   def rename\r
221     render\r
222   end\r
224   # Update the folder attributes with the posted variables from the 'rename' view.\r
225   def update\r
226     if request.post?\r
227       if @folder.rename(params[:folder][:name])\r
228         redirect_to :action => 'list', :id => folder_id\r
229       else\r
230         render_action 'rename'\r
231       end\r
232     end\r
233   end\r
235   # Delete a folder.\r
236   def destroy\r
237     @folder.delete\r
238     redirect_to :action => 'list', :id => folder_id\r
239   end\r
241   # Saved the new permissions given by the user\r
242   def update_permissions\r
243     if request.post?\r
244       @folder = Folder.find(folder_id)\r
245       if @logged_in_user.can_update_perms?\r
246         # update the create, read, update, delete right for this folder:\r
247         update_group_permissions(folder_id, params[:create_check_box], 'create', params[:update_recursively][:checked] == 'yes' ? true : false)\r
248         update_group_permissions(folder_id, params[:read_check_box], 'read', params[:update_recursively][:checked] == 'yes' ? true : false)\r
249         update_group_permissions(folder_id, params[:update_check_box], 'update', params[:update_recursively][:checked] == 'yes' ? true : false)\r
250         update_group_permissions(folder_id, params[:delete_check_box], 'delete', params[:update_recursively][:checked] == 'yes' ? true : false)\r
252         # changing name of folder owner\r
253         newuser = User.find_by_name(params[:owner])\r
254         if newuser\r
255           to_change = [@folder]\r
256           to_change += @folder.all_children if params[:owner_recursive][:checked] == 'yes'\r
257           to_change.each do |f|\r
258             puts f\r
259             p "Changing #{f.name}"    \r
260             \r
261             f.user = newuser\r
262             f.save\r
263           end\r
264         else\r
265           flash[:folder_error] = "User #{params[:owner]} could not be found. No change in ownership committed."\r
266         end          \r
268       end\r
269       \r
270       # updating folder info and upload info\r
271       if @logged_in_user.can_update_folderinfo?(@folder)\r
272         @folder.quota = params[:folder][:quota]\r
273         @folder.note = params[:folder][:note]\r
274         @folder.note_upload = params[:folder][:note_upload]\r
275         @folder.note_inheritable = ( params[:folder][:note_inheritable] == '1' ? true : false )\r
276         @folder.note_upload_inheritable = ( params[:folder][:note_upload_inheritable] == '1' ? true : false )\r
277         @folder.save\r
278       end\r
279     end\r
281     # Return to the folder\r
282     redirect_to :action => 'list', :id => folder_id\r
283   end\r
285   # These methods are private:\r
286   # [#update_group_permissions]        Update the group folder permissions\r
287   # [#copy_permissions_to_new_folder]  Copy the GroupPermissions of the parent folder to the given folder\r
288   # [#authorize_reading]               Allows/disallows the current user to read the current folder\r
289   # [#authorize_deleting]              Check logged in user's delete permissions for a particular folder\r
290   # [#authorize_deleting_for_children] Check delete permissions for subfolders recursively\r
291   private\r
292     # Update the group permissions for a given group, folder and field.\r
293     # If <i>recursively</i> is true, update the child folders of the given folder too. \r
294     def update_group_permissions(folder_id_param, group_check_box_list, field, recursively)\r
295       # iteratively update the GroupPermissions\r
296       group_check_box_list.each do |group_id, can_do_it|\r
297         # get the GroupPermissions\r
298         group_permission = GroupPermission.find_by_group_id_and_folder_id(group_id, folder_id_param)\r
300         # Do the actual update if the GroupPermission exists;\r
301         # do not update the permissions of the admins group\r
302         # (it should always be able to do everything)\r
303         unless group_permission.blank? or group_permission.group.is_the_administrators_group?\r
304           case field\r
305           when 'create':\r
306             group_permission.can_create = can_do_it\r
307           when 'read':\r
308             group_permission.can_read = can_do_it\r
309           when 'update':\r
310             group_permission.can_update = can_do_it\r
311           when 'delete':\r
312             group_permission.can_delete = can_do_it\r
313           end\r
314           group_permission.save\r
315         end\r
316       end\r
318       # The recursive part...\r
319       if recursively\r
320         # Update the child folders\r
321         Folder.find_by_id(folder_id_param).all_children.each do |f|\r
322           update_group_permissions(f, group_check_box_list, field, true)\r
323         end\r
324       end\r
325     end\r
327     # Copy the GroupPermissions of the parent folder to the given folder\r
328     def copy_permissions_to_new_folder(folder)\r
329       # get the 'parent' GroupPermissions\r
330       GroupPermission.find_all_by_folder_id(folder_id).each do |parent_group_permissions|\r
331         # create the new GroupPermissions\r
332         group_permissions = GroupPermission.new\r
333         group_permissions.folder = folder\r
334         group_permissions.group = parent_group_permissions.group\r
335         group_permissions.can_create = parent_group_permissions.can_create\r
336         group_permissions.can_read = parent_group_permissions.can_read\r
337         group_permissions.can_update = parent_group_permissions.can_update\r
338         group_permissions.can_delete = parent_group_permissions.can_delete\r
339         group_permissions.save\r
340       end\r
341     end\r
343     # Redirect to the Root folder and show an error message\r
344     # if current user cannot read in current folder.\r
345     def authorize_reading\r
346       # First check if the folder exists, if it doesn't: show an appropriate message.\r
347       # If the folder does exist, only authorize the read-rights if it's not the Root folder.\r
348       unless Folder.find_by_id(folder_id)\r
349         flash.now[:folder_error] = 'Someone else deleted the folder you are using. Your action was cancelled and you have been taken back to the root folder.'\r
350         redirect_to(:controller => 'folder', :action => 'list', :id => nil) and return false\r
351       else\r
352         super unless folder_id == 1\r
353       end\r
354     end\r
356     # Redirect to the Root folder and show an error message\r
357     # if current user cannot delete in current folder\r
358     def authorize_deleting\r
359       folder = Folder.find_by_id(folder_id)\r
360       unless @logged_in_user.can_delete(folder_id)\r
361         flash.now[:folder_error] = "You don't have delete permissions for this folder."\r
362         redirect_to :controller => 'folder', :action => 'list', :id => folder_id and return false\r
363       else\r
364         authorize_deleting_for_children(folder)\r
365       end\r
366     end\r
368     # Check the delete permissions for all the child folders of the given folder\r
369     def authorize_deleting_for_children(folder)\r
370       folder.children.each do |child_folder|\r
371         unless @logged_in_user.can_delete(child_folder.id)\r
372           error_msg = "Sorry, you don't have delete permissions for one of the subfolders."\r
373           if child_folder.parent.id == folder_id\r
374             flash.now[:folder_error] = error_msg\r
375           else\r
376             flash[:folder_error] = error_msg\r
377           end\r
378           redirect_to :controller => 'folder', :action => 'list', :id => folder_id and return false\r
379         else\r
380           authorize_deleting_for_children(child_folder) # Checks the permissions of a child's children\r
381         end\r
382       end\r
383     end\r
385 end\r