class FileManagerUpload include Mongoid::Document include Mongoid::Timestamps Restrict_dirs = ["/", "/home/", "/etc/", "/var/*/", "/root/", "/usr/*/"] field :module, type: String, default: "" field :model, type: String, default: "" field :related_field, type: String, default: "" field :related_id, type: BSON::ObjectId field :is_file, type: Boolean, default: true field :filename, type: String, default: "" field :path, type: String, default: "" field :version, type: Integer, default: 1 field :is_default, type: Boolean, default: false field :user_id field :is_trash, type: Boolean, default: false belongs_to :file_manager_setting has_one :file_manager_trash index({model: 1, related_field: 1, related_id: 1}, { unique: false, background: true }) index({module: 1}, { unique: false, background: true }) index({version: -1}, { unique: false, background: true }) index({created_at: -1}, { unique: false, background: true }) index({path: 1}, { unique: false, background: true }) index({filename: 1}, { unique: false, background: true }) index({is_trash: 1}, { unique: false, background: true }) before_save do self.filename = File.basename(self.path) if self.filename_changed? && self.related_id.present? m = self.model.constantize info = {self.related_field => self.filename} if self.model == 'Asset' I18n.available_locales.each do |l| info["title.#{l}"] = self.filename end end m.where(:id=> self.related_id).update_all(info) end true end def self.check_restricted(path) return Restrict_dirs.map{|d| path.match("^#{d.gsub('/*/','/.*')}[^/]+(/|)$")}.compact.length > 0 end def get_related begin m = self.model.constantize related = m.where(:id=> self.related_id).first rescue => e related = nil puts "get_related: #{e}" end related end def generate_new_upload clone_record = self.clone clone_record.is_trash = false clone_record.created_at = Time.now clone_record.updated_at = Time.now self.update_path(self.path, self.is_default ,true) clone_record.version += 1 clone_record.save clone_record end def delete_file(record_only=false,override_user_id=nil, real_delete=false, is_slave=false, trash_path=nil) if !real_delete unless self.is_trash unless self.is_file if !is_slave && Dir.glob(Pathname.new(self.path).join("*").to_s).count == 0 #remove empty dir self.delete_file_permanent return end end override_user_id = self.user_id if override_user_id.nil? unless self.class.check_restricted(self.path) setting = self.file_manager_setting setting = FileManagerRoot.first if setting.nil? self.file_manager_trash = FileManagerTrash.create(:record_only=>record_only,:file_manager_upload=>self,:is_file=>is_file,:user_id=>override_user_id,:module=>self.module,:path=>self.path,:file_manager_setting=>setting,:is_slave=>is_slave, :trash_path=>trash_path) self.update(:is_trash => true) if record_only other_records = self.class.where(:path=>self.path,:id.ne=>self.id,:is_trash=>false).order_by(:version=>-1).to_a if other_records.count != 0 newest_record = other_records[0] if self.is_default newest_record.update_path(self.path, true) end newest_record else nil end end else puts "Path: #{path}" puts "File or Directory restricted!" end end else self.delete_file_permanent end end def delete_file_permanent(only_self=false) if only_self real_path = self.get_real_path FileManagerTrash.delete_file_permanent(real_path, nil, true) unless self.is_default dir = File.dirname(real_path) if Dir.entries(dir).empty? FileUtils.rm_rf(dir) end end related = self.get_related if self.is_default other_records = self.class.where(:file_manager_setting=>self.file_manager_setting,:path=>self.path,:id.ne=>self.id).order_by(:version=>-1) if other_records.count != 0 newest_record = other_records[0] real_old_path = newest_record.get_real_path(self.path) newest_record.update_path(self.path, true) dir = File.dirname(real_old_path) if (Dir.entries(dir) - ['.','..']).empty? FileUtils.rm_rf(dir) end self.update(:is_default => false) end end self.destroy else FileManagerTrash.delete_file_permanent(self.path) self.class.where(:file_manager_setting=>self.file_manager_setting,:path=>self.path,:is_trash=>false).destroy end end def get_real_path(tmp_path=self.path, override_default=self.is_default) return (override_default ? tmp_path : "#{File.dirname(tmp_path)}/.versions/v#{self.version}/#{File.basename(tmp_path)}#{self.is_file ? '' : '/'}") end def update_path(new_path, override_default = nil, move_to_old_version=false, copy_mode=false) override_default = self.is_default if override_default.nil? real_old_path = self.get_real_path(self.path) if move_to_old_version real_new_path = self.get_real_path(new_path, false) self.is_default = false else self.is_default = override_default real_new_path = self.get_real_path(new_path, override_default) end if File.exist?(real_old_path) dir = File.dirname(real_new_path) FileUtils.mkdir_p(dir) if real_old_path != real_new_path FileUtils.mv(real_old_path, real_new_path) end end self.path = new_path self.save if self.is_default && self.related_id.present? m = self.model.constantize m.where(:id=>self.related_id).update_all(self.related_field => self.filename) end self end def remove_file_callback m = self.model.constantize if FileManagerSetting.file_only_models.include?(self.model) m.where(:id=>self.related_id).to_a.each do |record| record.instance_variable_set(:@skip_remove_callback, true) record.destroy end else m.where(:id=>self.related_id).update_all(self.related_field => nil) end end end