file-manager/app/models/file_manager_upload.rb

172 lines
6.2 KiB
Ruby

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