trabajo-afectivo/app/models/store.rb

301 lines
6.8 KiB
Ruby
Raw Normal View History

2014-02-03 19:23:00 +00:00
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
2012-04-10 14:06:46 +00:00
require 'digest/md5'
2013-01-24 08:18:29 +00:00
class Store < ApplicationModel
store :preferences
belongs_to :store_object, :class_name => 'Store::Object'
belongs_to :store_file, :class_name => 'Store::File'
validates :filename, :presence => true
2014-04-28 07:44:36 +00:00
=begin
add an attachment to storage
result = Store.add(
:object => 'Ticket::Article',
:o_id => 4711,
:data => binary_string,
:preferences => {
:content_type => 'image/png',
:content_id => 234,
}
)
returns
result = true
=end
2012-04-10 14:06:46 +00:00
def self.add(data)
data = data.stringify_keys
# lookup store_object.id
2013-01-24 08:18:29 +00:00
store_object = Store::Object.create_if_not_exists( :name => data['object'] )
2012-04-10 14:06:46 +00:00
data['store_object_id'] = store_object.id
2012-12-02 10:18:55 +00:00
2012-04-10 14:06:46 +00:00
# check if record already exists
# store = Store.where( :store_object_id => store_object.id, :o_id => data['o_id'], ).first
# if store != nil
# return store
# end
2012-12-02 10:18:55 +00:00
2012-04-10 14:06:46 +00:00
# check real store
md5 = Digest::MD5.hexdigest( data['data'] )
2013-01-24 08:18:29 +00:00
data['size'] = data['data'].to_s.bytesize
2012-04-10 14:06:46 +00:00
2014-05-02 09:03:06 +00:00
# file = Store::Provider::DB.create( data['data'], md5 )
2012-04-10 14:06:46 +00:00
file = Store::File.where( :md5 => md5 ).first
2012-12-02 10:18:55 +00:00
2012-04-10 14:06:46 +00:00
# store attachment
if file == nil
file = Store::File.create(
:data => data['data'],
2014-04-28 07:44:36 +00:00
:md5 => md5,
2012-04-10 14:06:46 +00:00
)
end
2012-12-02 10:18:55 +00:00
2012-04-10 14:06:46 +00:00
data['store_file_id'] = file.id
# not needed attributes
data.delete('data')
data.delete('object')
# store meta data
store = Store.create(data)
2014-04-28 07:44:36 +00:00
true
2012-04-10 14:06:46 +00:00
end
2012-12-02 10:18:55 +00:00
2014-04-28 07:44:36 +00:00
=begin
get attachment of object
list = Store.list(
:object => 'Ticket::Article',
:o_id => 4711,
)
returns
result = [store1, store2]
store1 = {
:size => 94123,
:filename => 'image.png',
:preferences => {
:content_type => 'image/png',
:content_id => 234,
}
}
store1.content # binary_string
=end
2012-04-10 14:06:46 +00:00
def self.list(data)
# search
2013-05-10 21:48:29 +00:00
store_object_id = Store::Object.lookup( :name => data[:object] )
stores = Store.where( :store_object_id => store_object_id, :o_id => data[:o_id].to_i ).
order('created_at ASC, id ASC')
2012-04-10 14:06:46 +00:00
return stores
end
2014-04-28 07:44:36 +00:00
=begin
remove an attachment to storage
result = Store.remove(
:object => 'Ticket::Article',
:o_id => 4711,
)
returns
result = true
=end
2012-04-10 14:06:46 +00:00
def self.remove(data)
# search
2013-05-10 21:48:29 +00:00
store_object_id = Store::Object.lookup( :name => data[:object] )
stores = Store.where( :store_object_id => store_object_id ).
where( :o_id => data[:o_id] ).
order('created_at ASC, id ASC')
2012-04-10 14:06:46 +00:00
stores.each do |store|
2014-04-28 07:44:36 +00:00
# check backend for references
files = Store.where( :store_file_id => store.store_file_id )
if files.count == 1 && files.first.id == store.id
2014-05-02 09:03:06 +00:00
# file = Store::Provider::DB.delete( store.store_file_id )
2014-04-28 07:44:36 +00:00
Store::File.find( store.store_file_id ).destroy
end
2012-04-10 14:06:46 +00:00
store.destroy
end
2012-12-02 10:18:55 +00:00
return true
2012-04-10 14:06:46 +00:00
end
2014-04-28 07:44:36 +00:00
# get attachment
def content
2014-05-02 09:03:06 +00:00
# Store::Provider::DB.content( store.store_file_id )
2014-04-28 07:44:36 +00:00
file = Store::File.where( :id => self.store_file_id ).first
return if !file
if file.file_system
return file.read_from_fs
end
file.data
2012-04-10 14:06:46 +00:00
end
2014-04-28 07:44:36 +00:00
end
2012-04-10 14:06:46 +00:00
2014-04-28 07:44:36 +00:00
class Store::Object < ApplicationModel
validates :name, :presence => true
end
2012-04-10 14:06:46 +00:00
2014-04-28 07:44:36 +00:00
class Store::File < ApplicationModel
before_validation :add_md5
before_create :check_location
2014-04-28 17:24:47 +00:00
after_destroy :unlink_location
2014-04-28 07:44:36 +00:00
# generate file location
def get_locaton
# generate directory
2014-04-28 19:20:09 +00:00
base = Rails.root.to_s + '/storage/fs/'
parts = self.md5.scan(/.{1,3}/)
path = parts[ 1 .. 7 ].join('/') + '/'
file = parts[ 8 .. parts.count ].join('')
location = "#{base}/#{path}"
2014-04-28 07:44:36 +00:00
# create directory if not exists
if !File.exist?( location )
FileUtils.mkdir_p( location )
end
2014-04-28 19:20:09 +00:00
location += file
2012-04-10 14:06:46 +00:00
end
2014-04-28 17:24:47 +00:00
# read file from fs
def unlink_location
if File.exist?( self.get_locaton )
puts "NOTICE: storge remove '#{self.get_locaton}'"
File.delete( self.get_locaton )
end
end
2014-04-28 07:44:36 +00:00
# read file from fs
def read_from_fs
puts "read from fs #{self.get_locaton}"
return if !File.exist?( self.get_locaton )
data = File.open( self.get_locaton, 'rb' )
content = data.read
# check md5
md5 = Digest::MD5.hexdigest( content )
if md5 != self.md5
raise "ERROR: Corrupt file in fs #{self.get_locaton}, md5 should be #{self.md5} but is #{md5}"
end
content
end
# write file to fs
def write_to_fs
# install file
permission = '600'
if !File.exist?( self.get_locaton )
puts "NOTICE: storge write '#{self.get_locaton}' (#{permission})"
file = File.new( self.get_locaton, 'wb' )
file.write( self.data )
file.close
end
File.chmod( permission.to_i(8), self.get_locaton )
# check md5
md5 = Digest::MD5.hexdigest( self.read_from_fs )
if md5 != self.md5
raise "ERROR: Corrupt file in fs #{self.get_locaton}, md5 should be #{self.md5} but is #{md5}"
end
true
end
# write file to db
def write_to_db
# read and check md5
content = self.read_from_fs
# store in database
self.data = content
self.save
# check md5 against db content
md5 = Digest::MD5.hexdigest( self.data )
if md5 != self.md5
raise "ERROR: Corrupt file in db #{self.get_locaton}, md5 should be #{self.md5} but is #{md5}"
end
true
end
2014-04-28 19:20:09 +00:00
# check database data and md5, in case fix it
def self.db_check_md5(fix_it = nil)
Store::File.where( :file_system => false ).each {|item|
md5 = Digest::MD5.hexdigest( item.data )
if md5 != item.md5
puts "DIFF: md5 diff of Store::File.find(#{item.id}) "
if fix_it
item.update_attribute( :md5, md5 )
end
end
}
true
end
2014-05-02 09:03:06 +00:00
def self.fs_check_md5(fix_it = nil)
Store::File.where( :file_system => true ).each {|item|
md5 = Digest::MD5.hexdigest( item.read_from_fs )
if md5 != item.md5
puts "DIFF: md5 diff of Store::File.find(#{item.id}) "
if fix_it
item.update_attribute( :md5, md5 )
end
end
}
true
end
2014-04-28 07:44:36 +00:00
def self.move_to_fs
Store::File.where( :file_system => false ).each {|item|
item.write_to_fs
item.update_attribute( :file_system, true )
item.update_attribute( :data, nil )
}
end
def self.move_to_db
Store::File.where( :file_system => true ).each {|item|
item.write_to_db
item.update_attribute( :file_system, false )
2014-04-28 17:24:47 +00:00
item.unlink_location
2014-04-28 07:44:36 +00:00
}
end
private
def check_location
# write initial to fs if needed
if self.file_system && self.data
self.write_to_fs
self.data = nil
end
end
def add_md5
if self.data && !self.md5
self.md5 = Digest::MD5.hexdigest( self.data )
end
end
end