class GxG::Storage::Volume
Public Class Methods
new(options={})
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 1498 def initialize(options={}) # options: :directory => "/path/to/dir", :credential => <UUID>.to_s, :act_as => :owner? || :database => <GxG::Database::Database>, :credential => <UUID>.to_s, :root_uuid => <UUID>.to_s @thread_safety = ::Mutex.new @credential = GxG::DB[:administrator].to_s @database = nil @root_uuid = nil # Acts As: :owner, :group, :other for File System Volumes if [:owner, :group, :other].include?(options[:act_as]) @act_as = options[:act_as] else @act_as = nil end @directory = options[:directory] if @directory.to_s.size > 0 if ::GxG::valid_uuid?(options[:credential].to_s.to_sym) unless @act_as # set @act_as according to credential Group/Role membership: Administrators=:owner, Developers/Designers=:group, all others=:other if GxG::DB[:authority].role_member?(GxG::DB[:authority][:system_credentials][:administrators], options[:credential].to_s.to_sym) @act_as = :owner else if GxG::DB[:authority].role_member?(GxG::DB[:authority][:system_credentials][:developers].to_s.to_sym, options[:credential].to_s.to_sym) || GxG::DB[:authority].role_member?(GxG::DB[:authority][:system_credentials][:designers].to_s.to_sym, options[:credential].to_s.to_sym) @act_as = :group else @act_as = :other end end end end if ::Dir.exist?(@directory.to_s) if ::File.readable_real?(@directory.to_s) @directory = ::Dir.new(@directory.to_s) else raise Exception, "You do not have read permissions to directory #{@directory.inspect}." end else raise Exception, "Directory #{@directory.inspect} does not exist in the filesystem." end # else @credential = (options[:credential] || GxG::DB[:administrator]).to_s if options[:database].is_a?(::GxG::Database::Database) and @credential.size > 0 @database = options[:database] if @database.setting_keys.include?(:volume_information) vol_info = @database[:volume_information] else if @database.db_permissions()[:write] new_root = @database.try_persist([], @credential) if new_root new_root.wait_for_reservation() new_root.set_title("Volume Root") vol_info = {:volume_root => new_root.uuid()} new_root.deactivate @database[:volume_information] = vol_info else raise Exception, "Unable to initialize volume root" end else raise Exception, "Cannot initialize Volume Information on read-only database." end end # One can specify a sub-array to the volume as this volume's root array. if GxG::valid_uuid?(options[:root_uuid].to_s) # verify array's existence the_persisted_array = @database.retrieve_by_uuid(options[:root_uuid], @credential) if the_persisted_array.is_a?(::GxG::Database::PersistedArray) the_persisted_array.deactivate @root_uuid = options[:root_uuid].to_s.to_sym else raise Exception, "The root_uuid points to a non-existent or invalid object, or you do not have permissions to read it." end # else @root_uuid = vol_info[:volume_root].to_sym end else raise ArgumentError, "You MUST supply a valid credential and a database object. :credential => #{@credential.inspect}, :database => #{options[:database].inspect}" end end # end
Public Instance Methods
credential()
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 1069 def credential() @credential end
database()
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 1073 def database() @database end
db_path(subpath="")
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 1089 def db_path(subpath="") result = nil unless subpath.to_s[0] == "/" subpath = ("/" << subpath.to_s) end subpath_array = subpath.to_s.split("/") if subpath_array.size == 0 subpath_array << "Volume Root" else subpath_array[0] = "Volume Root" end path_array = [{:uuid => @root_uuid, :title => "Volume Root"}] subpath_array.each_with_index do |the_entry, indexer| parent_uuid = path_array.last[:uuid] # @database.connector()[:array_elements].filter({:parent_uuid => parent_uuid.to_s}).order(:ordinal).each do |item| if [:element_array, :element_hash].include?(item[:element].to_s.to_sym) if item[:element].to_s.to_sym == :element_array record = @database.connector()[:element_array].filter({:uuid => item[:element_array_uuid].to_s}).first else record = @database.connector()[:element_hash].filter({:uuid => item[:element_hash_uuid].to_s}).first end if record if record[:title] == subpath_array[(indexer + 1)].to_s path_array << {:uuid => record[:uuid].to_sym, :title => record[:title]} break end end end end # end if path_array.size == subpath_array.size result = path_array end result end
directory()
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 1077 def directory() @directory end
entries(subpath="", as_credential=nil, options={:follow_symlinks => true})
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 1579 def entries(subpath="", as_credential=nil, options={:follow_symlinks => true}) results = [] if @directory # FS if subpath.to_s == "" or subpath.to_s == "/" the_path = (@directory.path) else unless subpath.to_s[0] == "/" subpath = ("/" << subpath.to_s) end the_path = (@directory.path + subpath.to_s).gsub("//", "/") end ::Dir::entries(the_path).each do |item| unless [".", ".."].include?(item) if as_credential the_profile = self.profile((subpath + "/" + item), options.merge({:with_credential => as_credential})) else the_profile = self.profile((subpath + "/" + item), options) end if the_profile the_profile[:title] = item results << the_profile end end end # else # DB unless subpath.to_s[0] == "/" subpath = ("/" << subpath.to_s) end path_array = self.db_path(subpath.to_s) if path_array base_profile = self.profile(subpath.to_s, {:with_credential => as_credential}) if base_profile if base_profile[:permissions][:effective][:read] if base_profile[:type] == :persisted_array object_details = {:uuid => path_array.last[:uuid], :table => :unspecified, :dbid => 0} header = @database.connector()[:element_array].filter({:uuid => object_details[:uuid].to_s}).first if header object_details[:table] = :element_array object_details[:dbid] = header[:dbid] end contained_titles = [] @database.connector()[:array_elements].select(:element_hash_uuid, :element_array_uuid).where({:parent_uuid => path_array.last[:uuid].to_s}).each do |link_record| if link_record[:element_hash_uuid].to_s.size > 0 header = @database.connector()[:element_hash].filter({:uuid => link_record[:element_hash_uuid].to_s}).first if header contained_titles << header[:title].to_s end else if link_record[:element_array_uuid].to_s.size > 0 header = @database.connector()[:element_array].filter({:uuid => link_record[:element_array_uuid].to_s}).first if header contained_titles << header[:title].to_s end end end end contained_titles.sort.each do |the_title| if the_title.size > 0 results << self.profile((subpath.to_s + "/" + the_title).gsub("//","/"), {:with_credential => as_credential}) end end end end end end end results end
exist?(subpath="")
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 1127 def exist?(subpath="") result = false if @directory if subpath.to_s == "" or subpath.to_s == "/" the_path = (@directory.path) else unless subpath.to_s[0] == "/" subpath = ("/" << subpath.to_s) end the_path = (@directory.path + subpath.to_s).gsub("//", "/") end result = ::File::exist?(the_path) else # DB object exist? if self.db_path(subpath) result = true end end result end
file_system?()
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 1081 def file_system?() if self.directory() true else false end end
get_permissions(subpath="", the_credential=nil)
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 2359 def get_permissions(subpath="", the_credential=nil) result = [] if @directory if self.exist?(subpath) the_profile = self.profile(subpath) if the_profile[:file_id] result = GxG::DB[:roles][:vfs].vfs_permission_manifest(the_profile[:file_id], the_credential) end # ???? # xxx # group_roles = GxG::DB[:authority][:system_credentials] # the_record = {:credential => group_roles[:administrators], :permissions => the_profile[:permissions][:owner], :details => {}} # role = GxG::DB[:authority].role_fetch({:uuid => the_record[:credential].to_s}) # group = GxG::DB[:authority].group_fetch({:uuid => role[:group_uuid].to_s}) # the_record[:details][:role_title] = role[:title] # the_record[:details][:group] = group[:uuid].to_s.to_sym # the_record[:details][:group_title] = group[:title] # result << the_record # the_record = {:credential => group_roles[:developers], :permissions => the_profile[:permissions][:group], :details => {}} # role = GxG::DB[:authority].role_fetch({:uuid => the_record[:credential].to_s}) # group = GxG::DB[:authority].group_fetch({:uuid => role[:group_uuid].to_s}) # the_record[:details][:role_title] = role[:title] # the_record[:details][:group] = group[:uuid].to_s.to_sym # the_record[:details][:group_title] = group[:title] # result << the_record # the_record = {:credential => group_roles[:designers], :permissions => the_profile[:permissions][:group], :details => {}} # role = GxG::DB[:authority].role_fetch({:uuid => the_record[:credential].to_s}) # group = GxG::DB[:authority].group_fetch({:uuid => role[:group_uuid].to_s}) # the_record[:details][:role_title] = role[:title] # the_record[:details][:group] = group[:uuid].to_s.to_sym # the_record[:details][:group_title] = group[:title] # result << the_record # the_record = {:credential => :"00000000-0000-4000-0000-000000000000", :permissions => the_profile[:permissions][:other], :details => {}} # user = GxG::DB[:authority].user_fetch({:uuid => the_record[:credential].to_s}) # the_record[:details][:user_title] = user[:user_id] # result << the_record end else if self.exist?(subpath) the_profile = self.profile(subpath) result = @database.element_permissions_by_uuid(the_profile[:uuid]) end end result end
inspect()
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 1065 def inspect() "<Volume: #{(@database || @directory).inspect}>" end
mkdir(subpath="", permissions=nil)
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 2233 def mkdir(subpath="", permissions=nil) result = false if @directory if subpath.to_s == "" or subpath.to_s == "/" the_path = (@directory.path) else unless subpath.to_s[0] == "/" subpath = ("/" << subpath.to_s) end the_path = (@directory.path + subpath.to_s).gsub("//", "/") end perm = 16384 if permissions.is_a?(::Hash) # Best if you pass the entire :permissions hash from a profile query "040000".each_char_with_index do |digit, indexer| case indexer when 0 when 1 # TODO: process other flags when 2 when 3 if permissions[:owner].is_a?(::Hash) if permissions[:owner][:execute] perm += 256 end if permissions[:owner][:write] perm += 128 end if permissions[:owner][:read] perm += 64 end end when 4 if permissions[:group].is_a?(::Hash) if permissions[:group][:execute] perm += 32 end if permissions[:group][:write] perm += 16 end if permissions[:group][:read] perm += 8 end end when 5 if permissions[:other].is_a?(::Hash) if permissions[:other][:execute] perm += 4 end if permissions[:other][:write] perm += 2 end if permissions[:other][:read] perm += 1 end end end end # else base_profile = self.profile("/") if base_profile.is_a?(::Hash) if base_profile[:mode].is_a?(::String) perm = base_profile[:mode].to_i(base=8) else perm = 16877 end else perm = 16877 end end # FS mkdir begin parent_profile = self.profile(::File::dirname(subpath.to_s)) if parent_profile if parent_profile[:permissions][:effective][:create] if ::File::exist?(the_path) result = true else if ::Dir::mkdir(the_path, perm) == 0 # Generate VFS-DB permissions, return result self.profile(subpath) result = true end end else raise Exception, "You do not have create permissions here" end else raise Exception, "Invalid path" end rescue Exception => the_error log_error({:error => the_error, :parameters => {:path => the_path, :permissions => permissions}}) # end else # DB dir create begin parent_profile = self.profile(::File::dirname(subpath.to_s)) if parent_profile if parent_profile[:permissions][:effective][:create] == true new_object = @database.try_persist([], @credential) new_object.wait_for_reservation new_object.set_title(::File::basename(subpath.to_s)) # ### Fashion a link under the parent uuid. new_ordinal = @database.connector()[:array_elements].filter({:parent_uuid => parent_profile[:uuid].to_s}).count @database.connector()[:array_elements].insert({:parent_uuid => parent_profile[:uuid].to_s, :version => new_object.version(), :ordinal => new_ordinal, :element => "element_array", :element_array_uuid => new_object.uuid.to_s}) # ### Wrap up and return new object new_object.release_reservation result = true else raise Exception, "You do not have create permissions here" end else raise Exception, "Invalid path" end # rescue Exception => the_error log_error({:error => the_error, :parameters => {:path => subpath, :permissions => permissions}}) # end # end result end
open(subpath="", options={})
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 1974 def open(subpath="", options={}) result = nil if @directory if subpath.to_s == "" or subpath.to_s == "/" the_path = (@directory.path) else unless subpath.to_s[0] == "/" subpath = ("/" << subpath.to_s) end the_path = (@directory.path + subpath.to_s).gsub("//", "/") end flags = 0 flag_array = (options[:flags] || [:readwrite]) flag_array.each do |the_flag| case the_flag when :append flags += ::File::APPEND when :binary flags += ::File::BINARY when :create flags += ::File::CREAT when :direct flags += ::File::DIRECT when :dsync flags += ::File::DSYNC when :duplex flags += ::File::DUPLEX when :exclusive flags += ::File::EXCL when :casefold flags += ::File::FNM_CASEFOLD when :dotmatch flags += ::File::FNM_DOTMATCH when :no_escape flags += ::File::FNM_NOESCAPE when :pathname flags += ::File::FNM_PATHNAME when :system_case flags += ::File::FNM_SYSCASE when :lock_ex flags += ::File::LOCK_EX when :lock_nb flags += ::File::LOCK_NB when :lock_sh flags += ::File::LOCK_SH when :lock_un flags += ::File::LOCK_UN when :no_atime flags += ::File::NOATIME when :no_ctty flags += ::File::NOCTTY when :no_follow flags += ::File::NOFOLLOW when :nonblock flags += ::File::NONBLOCK when :read flags += ::File::RDONLY when :rsync flags += ::File::RSYNC when :seek_cur flags += ::File::SEEK_CUR when :seek_end flags += ::File::SEEK_END when :seek_set flags += ::File::SEEK_SET when :setenc_by_bom flags += ::File::SETENC_BY_BOM when :sync flags += ::File::SYNC when :text flags += ::File::TEXT when :truncate flags += ::File::TRUNC when :tty flags += ::File::TTY when :write flags += ::File::WRONLY when :readwrite flags += ::File::RDWR when :wsplit flags += ::File::WSPLIT when :wsplit_initialized flags += ::File::WSPLIT_INITIALIZED end end perm = 16384 permissions = options[:permissions] if permissions.is_a?(::Hash) # Best if you pass the entire :permissions hash from a profile query "040000".each_char_with_index do |digit, indexer| case indexer when 0 when 1 # TODO: process other flags when 2 when 3 if permissions[:owner].is_a?(::Hash) if permissions[:owner][:execute] perm += 256 end if permissions[:owner][:write] perm += 128 end if permissions[:owner][:read] perm += 64 end end when 4 if permissions[:group].is_a?(::Hash) if permissions[:group][:execute] perm += 32 end if permissions[:group][:write] perm += 16 end if permissions[:group][:read] perm += 8 end end when 5 if permissions[:other].is_a?(::Hash) if permissions[:other][:execute] perm += 4 end if permissions[:other][:write] perm += 2 end if permissions[:other][:read] perm += 1 end end end end # else base_profile = self.profile("/") if base_profile.is_a?(::Hash) if base_profile[:mode].is_a?(::String) perm = (base_profile[:mode][0..2].to_s + "644").to_i(base=8) else perm = 16804 end else perm = 16804 end end # FS begin parent_profile = self.profile(::File::dirname(subpath.to_s)) if parent_profile if ::File::exist?(the_path) if ::File::directory?(the_path) result = ::Dir::new(the_path) else if flag_array.include?(:read) unless parent_profile[:permissions][:effective][:read] raise Exception, "You do not have read permissions here." end end if flag_array.include?(:write) unless parent_profile[:permissions][:effective][:write] raise Exception, "You do not have write permissions here." end end if flag_array.include?(:readwrite) unless parent_profile[:permissions][:effective][:read] raise Exception, "You do not have read permissions here." end unless parent_profile[:permissions][:effective][:write] raise Exception, "You do not have write permissions here." end end if ::GxG::Engine::available_file_descriptors() > 0 result = ::File::open(the_path, flags) else raise Exception, "Maximum File Descriptor count exceeded. Aborting" end end else if parent_profile[:permissions][:effective][:create] if ::GxG::Engine::available_file_descriptors() > 0 ::File::new(the_path, "w", perm).close result = ::File::open(the_path, flags) # Generate VFS-DB permissions, return result self.profile(subpath) else raise Exception, "Maximum File Descriptor count exceeded. Aborting" end else raise Exception, "You do not have create permissions here" end end else raise Exception, "Invalid path" end rescue Exception => the_error log_error({:error => the_error, :parameters => {:path => the_path, :options => options}}) # end else # DB open/create :persisted_hash begin path_array = self.db_path(subpath.to_s) if path_array profile = self.profile(subpath.to_s) if profile[:permissions][:effective][:read] result = @database.retrieve_by_uuid(path_array.last[:uuid], @credential) else # Review : keep? this breaks the 'if you don't have privs you can't see it - no errors, security through obscurity' idea. raise Exception, "You do not have read permissions on this object" end else parent_profile = self.profile(::File::dirname(subpath.to_s)) if parent_profile if parent_profile[:permissions][:effective][:create] == true if options[:format] if GxG::valid_uuid?(options[:format]) new_object = @database.new_structure_from_format(@credential,{:uuid => options[:format]}) else new_object = @database.new_structure_from_format(@credential,{:ufs => options[:format]}) end else if options[:ufs] new_object = @database.new_structure_from_format(@credential,{:ufs => options[:ufs]}) else new_object = @database.try_persist({}, @credential) end end # ### allow to create the object with a specific UUID. if ::GxG::valid_uuid?(options[:with_uuid]) address = new_object.db_address() new_object.deactivate @database.connector()[(address[:table])].filter({:dbid => address[:dbid]}).first.update({:uuid => options[:with_uuid].to_s}) new_object = @database.retrieve_by_uuid(options[:with_uuid].to_s.to_sym, @credential) end # new_object.wait_for_reservation new_object.set_title(::File::basename(subpath.to_s)) # ### Fashion a link under the parent uuid. new_ordinal = @database.connector()[:array_elements].filter({:parent_uuid => parent_profile[:uuid].to_s}).count @database.connector()[:array_elements].insert({:parent_uuid => parent_profile[:uuid].to_s, :version => new_object.version(), :ordinal => new_ordinal, :element => "element_hash", :element_hash_uuid => new_object.uuid.to_s}) # ### Wrap up and return new object new_object.release_reservation result = new_object else raise Exception, "You do not have create permissions here" end # else raise Exception, "Invalid path" end end rescue Exception => the_error log_error({:error => the_error, :parameters => {:path => the_path, :options => options}}) end end result end
profile(subpath="",params={:follow_symlinks => true})
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 1148 def profile(subpath="",params={:follow_symlinks => true}) unless params.is_a?(::Hash) params = {:follow_symlinks => true} end unless params[:follow_symlinks] unless params.keys.include?(:follow_symlinks) params[:follow_symlinks] = true end end platform_details = GxG::SYSTEM.platform() result = {:title => "", :type => :unspecified, :owner_type => :unspecified, :uuid => nil, :version => 0.0, :on_device => nil, :on_device_major => nil, :on_device_minor => nil, :is_device => nil, :is_device_major => nil, :is_device_minor => nil, :inode => nil, :flags => [:read], :hardlinks_to => 0, :user_id => nil, :group_id => nil, :size => 0, :block_size => 0, :blocks => 0, :accessed => nil, :modified => nil, :status_modified => nil, :permissions => {:effective => {:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read=>false}}, :mode=>nil, :mime => nil} if @directory # return FS object profile result[:title] = (subpath.split("/").last.to_s) if subpath.to_s == "" or subpath.to_s == "/" the_path = (@directory.path) else unless subpath.to_s[0] == "/" subpath = ("/" << subpath.to_s) end the_path = (@directory.path + subpath.to_s).gsub("//", "/") end if params[:follow_symlinks] raw_stat = ::File::stat(the_path.to_s) else raw_stat = ::File::lstat(the_path.to_s) end raw_mode = raw_stat.mode.to_s(base=8) # puts "Got: #{raw_mode}" if raw_mode.size < 6 raw_mode = ("0" << raw_mode) end # puts "Then Got: #{raw_mode}" set_user_id = false set_group_id = false set_sticky_bit = false if (raw_mode[2].to_i & 4) == 4 set_user_id = true end if (raw_mode[2].to_i & 2) == 2 set_group_id = true end if (raw_mode[2].to_i & 1) == 1 set_sticky_bit = true end raw_permission = { :execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false } case raw_stat.ftype.to_s.downcase.to_sym when :link # are .lnk files handled properly on win32 for this? result[:type] = :symlink when :file the_extension = ::File::basename(the_path.to_s).split(".")[-1].to_s.downcase if the_extension == "lnk" result[:type] = :symlink else if ["so","la","a","dylib","dll","class"].include?(the_extension) result[:type] = :library else if (["out","exe","misc","java","jar", "sh", "rb", "py", "pyc"].include?(the_extension) || raw_stat.executable_real?) result[:type] = :application else # TODO: find a way to externally sense if a tty result[:type] = :file end end end when :fifo result[:type] = :fifo when :characterspecial result[:type] = :character_device when :blockspecial result[:type] = :block_device when :socket result[:type] = :socket when :directory result[:type] = :directory when :unknown result[:type] = :unknown if raw_stat.pipe? result[:type] = :pipe end else if raw_stat.pipe? result[:type] = :pipe end end # result[:owner_type] = result[:type] result[:on_device] = raw_stat.dev.to_s(base=10).to_i if result[:on_device] result[:on_device_major] = raw_stat.dev_major result[:on_device_minor] = raw_stat.dev_minor end result[:is_device] = raw_stat.rdev if result[:is_device] result[:is_device_major] = raw_stat.rdev_major result[:is_device_minor] = raw_stat.rdev_minor end result[:inode] = raw_stat.ino.to_i # ### :file_id result[:file_id] = "#{(result[:on_device] || 0).to_s}-#{(result[:on_device_major] || 0).to_s}-#{(result[:on_device_minor] || 0).to_s}-#{(result[:inode] || 0).to_s}" result[:flags] = [] if ::File::writable_real?(the_path.to_s) result[:flags] << :write end if ::File::readable_real?(the_path.to_s) result[:flags] << :read end # result[:hardlinks_to] = raw_stat.nlink.to_i result[:user_id] = raw_stat.uid.to_i result[:group_id] = raw_stat.gid.to_i result[:size] = raw_stat.size result[:block_size] = raw_stat.blksize result[:blocks] = raw_stat.blocks result[:version] = raw_stat.mtime.to_f result[:accessed] = DateTime::parse(raw_stat.atime.to_s) result[:modified] = DateTime::parse(raw_stat.mtime.to_s) result[:status_modified] = DateTime::parse(raw_stat.ctime.to_s) # File permissions work in an ACL style, even if based only upon Unix-style permissions. # result[:permissions] = {:effective => raw_permission.clone, :owner => raw_permission.clone, :group => raw_permission.clone, :other => raw_permission.clone} if set_user_id result[:flags] << :user_id_on_execute end if set_group_id result[:flags] << :group_id_on_execute end if set_sticky_bit result[:flags] << :sticky_bit end # # owner permissions if (raw_mode[3].to_i & 4) == 4 result[:permissions][:owner][:read] = true end if (raw_mode[3].to_i & 2) == 2 result[:permissions][:owner][:write] = true if platform_details[:platform] == :windows # :windows way of reading :rename, :move, and :destroy permission for file/directory. else result[:permissions][:owner][:rename] = true result[:permissions][:owner][:move] = true result[:permissions][:owner][:destroy] = true result[:permissions][:owner][:create] = true end end if (raw_mode[3].to_i & 1) == 1 result[:permissions][:owner][:execute] = true end # group permissions if (raw_mode[4].to_i & 4) == 4 result[:permissions][:group][:read] = true end if (raw_mode[4].to_i & 2) == 2 result[:permissions][:group][:write] = true if platform_details[:platform] == :windows # :windows way of reading :rename, :move, and :destroy permission for file/directory. else result[:permissions][:group][:rename] = true result[:permissions][:group][:move] = true result[:permissions][:group][:destroy] = true result[:permissions][:group][:create] = true end end if (raw_mode[4].to_i & 1) == 1 result[:permissions][:group][:execute] = true end # other permissions if (raw_mode[5].to_i & 4) == 4 result[:permissions][:other][:read] = true end if (raw_mode[5].to_i & 2) == 2 result[:permissions][:other][:write] = true if platform_details[:platform] == :windows # :windows way of reading :rename, :move, and :destroy permission for file/directory. else result[:permissions][:other][:rename] = true result[:permissions][:other][:move] = true result[:permissions][:other][:destroy] = true result[:permissions][:other][:create] = true end end if (raw_mode[5].to_i & 1) == 1 result[:permissions][:other][:execute] = true end # effective (this user) permissions (while opened, supercedes normal effective file system permissions) if result[:flags].index(:read) result[:permissions][:effective][:read] = true # end # ### db-based virtualized permission system keyed by :file_id # ### on non-linux systems - make sure to support the :file_id format subsystem, and map to local-arch-platform equivilents. # search_database(credential, {:ufs => "the.ufs.code", :properties => [{:the_property => {:equals => value}}]}) if ::GxG::valid_uuid?(params[:with_credential] || @credential) acts_as = :group current_roles = GxG::DB[:authority].user_roles(params[:with_credential] || @credential) current_roles.each do |role_record| unless GxG::DB[:roles][:vfs].vfs_permission_exist?(result[:file_id], role_record[:credential]) if role_record[:credential] == GxG::DB[:authority][:system_credentials][:designers] || role_record[:credential] == GxG::DB[:authority][:system_credentials][:developers] || role_record[:credential] == GxG::DB[:authority][:system_credentials][:administrators] GxG::DB[:roles][:vfs].create_vfs_permission(result[:file_id], role_record[:credential], result[:permissions][:owner]) acts_as = :owner else GxG::DB[:roles][:vfs].create_vfs_permission(result[:file_id], role_record[:credential], result[:permissions][:group]) end # end end # unless GxG::DB[:roles][:vfs].vfs_permission_exist?(result[:file_id], :"00000000-0000-4000-0000-000000000000") GxG::DB[:roles][:vfs].create_vfs_permission(result[:file_id], :"00000000-0000-4000-0000-000000000000", result[:permissions][:other]) end # ### Review : should I support individual permissions at all, or rather confine it to roles and the public id? # unless GxG::DB[:roles][:vfs].vfs_permission_exist?(result[:file_id], (params[:with_credential] || @credential)) # if acts_as == :owner # GxG::DB[:roles][:vfs].create_vfs_permission(result[:file_id], (params[:with_credential] || @credential), result[:permissions][:owner]) # else # GxG::DB[:roles][:vfs].create_vfs_permission(result[:file_id], (params[:with_credential] || @credential), result[:permissions][:group]) # end # end # result[:permissions][:effective] = GxG::DB[:roles][:vfs].effective_vfs_permission(result[:file_id], (params[:with_credential] || @credential)) # else log_error({:error => Exception.new("Invalid credential: #{params[:with_credential] || @credential}")}) end result[:permissions].delete(:owner) result[:permissions].delete(:group) result[:permissions].delete(:other) # # # if @act_as.is_a?(::Symbol) || params[:with_credential] # if ::GxG::valid_uuid?(params[:with_credential]) # if GxG::DB[:authority].role_member?(GxG::DB[:authority][:system_credentials][:administrators], params[:with_credential].to_s.to_sym) # now_act_as = :owner # else # if GxG::DB[:authority].role_member?(GxG::DB[:authority][:system_credentials][:developers].to_s.to_sym, params[:with_credential].to_s.to_sym) || GxG::DB[:authority].role_member?(GxG::DB[:authority][:system_credentials][:designers].to_s.to_sym, params[:with_credential].to_s.to_sym) # now_act_as = :group # else # now_act_as = :other # end # end # result[:permissions][:effective] = result[:permissions][(now_act_as)].clone # else # result[:permissions][:effective] = result[:permissions][(@act_as)].clone # end # else # if result[:flags].index(:write) # result[:permissions][:effective][:write] = true # if platform_details[:platform] == :windows # # :windows way of reading :rename, :move, and :destroy permission for file/directory. # else # result[:permissions][:effective][:rename] = true # result[:permissions][:effective][:move] = true # result[:permissions][:effective][:destroy] = true # result[:permissions][:effective][:create] = true # end # end # if raw_stat.executable? # result[:permissions][:effective][:execute] = true # end # end # result[:mode] = raw_mode # Mime type identification: if File.directory?(the_path) mime_type = "inode/directory" else mime_type = MimeMagic.by_extension(File.extname(result[:title])) unless mime_type mime_type = MimeMagic.by_path(the_path) end unless mime_type handle = ::File.open(the_path,"rb") handle.rewind mime_type = ::MimeMagic.by_magic(handle) handle.close end if mime_type mime_type = mime_type.type() else mime_type = "application/octet-stream" end end result[:mime] = mime_type # # else # return DB object profile unless subpath.to_s[0] == "/" subpath = ("/" << subpath.to_s) end # path_array = self.db_path(subpath.to_s) if path_array object_details = {:uuid => path_array.last[:uuid], :table => :unspecified, :dbid => 0} header = @database.connector()[:element_hash].filter({:uuid => object_details[:uuid].to_s}).first if header object_details[:table] = :element_hash object_details[:dbid] = header[:dbid] else header = @database.connector()[:element_array].filter({:uuid => object_details[:uuid].to_s}).first if header object_details[:table] = :element_array object_details[:dbid] = header[:dbid] end end # result = {:title => path_array.last[:title], :type => :virtual_directory, :owner_type => :virtual_directory, :uuid => path_array.last[:uuid], :version => header[:version], :on_device => nil, :on_device_major => nil, :on_device_minor => nil, :is_device => nil, :is_device_major => nil, :is_device_minor => nil, :inode => nil, :file_id => nil, :flags => [:read], :hardlinks_to => 0, :user_id => nil, :group_id => nil, :size => 0, :block_size => 0, :blocks => 0, :accessed => nil, :modified => nil, :status_modified => nil, :permissions => {:effective => {:execute => true, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read=>true}}, :mode=>nil, :mime => nil} if object_details[:table] == :element_array result[:type] = :persisted_array result[:owner_type] = :persisted_array else result[:type] = :persisted_hash result[:owner_type] = :persisted_hash end if ::GxG::valid_uuid?(params[:with_credential]) result[:permissions][:effective] = @database.effective_uuid_permission(object_details[:uuid], params[:with_credential]) else result[:permissions][:effective] = @database.effective_uuid_permission(object_details[:uuid], @credential) end # Object Size in DB: if result[:type] == :persisted_hash # Review : DB overhaul - ensure @database.byte_size_by_uuid supports new arch. # result[:size] = @database.byte_size_by_uuid(object_details[:uuid]) else # result[:size] = 0 end # Pseudo-mime for objects: mime_type = nil if header[:format].to_s.size > 0 the_format = @database.format_list({:uuid => header[:format]})[0] if the_format mime_type = "vnd.gxg/#{the_format[:ufs].to_s.gsub('_','-')}" else mime_type = "vnd.gxg/org.gxg.hash.persisted" end else if object_details[:table] == :element_array mime_type = "vnd.gxg/org.gxg.array.persisted" end end result[:mime] = mime_type else # raise Exception, "Invalid path" end end result end
rename(subpath="", new_name="", options={})
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 1905 def rename(subpath="", new_name="", options={}) result = false if @directory if subpath.to_s == "" or subpath.to_s == "/" the_path = (@directory.path) else unless subpath.to_s[0] == "/" subpath = ("/" << subpath.to_s) end the_path = (@directory.path + subpath.to_s).gsub("//", "/") end # FS begin if options[:with_credential] item_profile = self.profile(subpath.to_s,options.merge({:follow_symlinks => true})) else item_profile = self.profile(subpath.to_s) end if item_profile.is_a?(::Hash) if item_profile[:permissions][:effective][:rename] == true ::File.rename(the_path,(File.dirname(the_path) + "/" + new_name)) # Review : check for file_id changes and update the VFS-DB permission records. result = true else raise Exception, "You do not have rename permissions here" end else raise Exception, "Invalid path" end rescue Exception => the_error log_error({:error => the_error, :parameters => {:path => the_path, :options => options}}) # end else # DB open/create :persisted_hash or open :persisted_array begin path_array = self.db_path(subpath.to_s) if path_array if options[:with_credential] profile = self.profile(subpath.to_s, options) else profile = self.profile(subpath.to_s) end profile = self.profile(subpath.to_s) if profile[:permissions][:effective][:rename] == true if profile[:type] == :persisted_hash @database.connector()[:element_hash].filter({:uuid => profile[:uuid].to_s}).update({:title => new_name}) result = true else if profile[:type] == :persisted_array @database.connector()[:element_array].filter({:uuid => profile[:uuid].to_s}).update({:title => new_name}) result = true end end # else raise Exception, "You do not have rename permissions here" end # else raise Exception, "Invalid path" end rescue Exception => the_error log_error({:error => the_error, :parameters => {:path => the_path, :options => options}}) end end result end
revoke_permissions(subpath="", the_credential=nil)
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 2405 def revoke_permissions(subpath="", the_credential=nil) # revoke_element_permissions(table=:unspecified, dbid=0, credential=nil) result = false if @directory # Review - all I need is the :file_id : make more efficient profile = self.profile(subpath) if profile[:file_id] result = GxG::DB[:roles][:vfs].destroy_vfs_permission(profile[:file_id], the_credential) end else if self.exist?(subpath) the_profile = self.profile(subpath) result = @database.revoke_permissions_by_uuid(the_profile[:uuid], the_credential) end end result end
rmdir(subpath="")
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 1651 def rmdir(subpath="") result = false if @directory # FS rmdir if subpath.to_s == "" or subpath.to_s == "/" the_path = (@directory.path) else unless subpath.to_s[0] == "/" subpath = ("/" << subpath.to_s) end the_path = (@directory.path + subpath.to_s).gsub("//", "/") end # if ::File::exist?(the_path) begin the_profile = self.profile(subpath.to_s) if the_profile if the_profile[:permissions][:effective][:destroy] # Recursively delete any content files and subdirs first file_list = [] dir_list = [] vfs_list = [ (the_profile[:file_id]) ] # Gather up all VFS-DB :file_id entries: search_queue = [(subpath)] while search_queue.size > 0 do entry = search_queue.shift self.entries(entry).each do |the_subitem_profile| if the_subitem_profile[:file_id].to_s.size > 0 vfs_list << the_subitem_profile[:file_id] end if [:virtual_directory, :persisted_array, :directory].include?(the_subitem_profile[:type]) search_queue << (entry + "/" + the_subitem_profile[:title]) end end end # Do the FS work: search_queue = [(the_path)] while search_queue.size > 0 do entry = search_queue.shift if entry Dir.entries(entry).each do |the_item_name| unless [".",".."].include?(the_item_name) if File.directory?(entry + "/" + the_item_name) dir_list << (entry + "/" + the_item_name) search_queue << (entry + "/" + the_item_name) else file_list << (entry + "/" + the_item_name) end end end end end file_list.each do |the_file_path| File.delete(the_file_path) end dir_list.each do |the_dir_path| ::Dir::rmdir(the_dir_path) end if ::Dir::rmdir(the_path) == 0 vfs_list.each do |the_file_id| GxG::DB[:roles][:vfs].destroy_vfs_permission(the_file_id) end result = true end else raise Exception, "You do not have destroy permissions to do this" end else raise Exception, "Inavalid path" end rescue Exception => the_error log_error({:error => the_error, :parameters => {:path => the_path}}) end else begin raise Exception, "Invaid path" rescue Exception => the_error log_error({:error => the_error, :parameters => {:path => the_path}}) end end # else # DB rmdir unless subpath.to_s[0] == "/" subpath = ("/" << subpath.to_s) end path_array = self.db_path(subpath.to_s) if path_array if path_array.size > 1 the_profile = self.profile(subpath.to_s) if the_profile if the_profile[:permissions][:effective][:destroy] parent_uuid = (path_array[-2] || {})[:uuid] link_uuids = [] found_link = nil if parent_uuid @database.connector()[:array_elements].filter({:parent_uuid => parent_uuid.to_s}).order(:ordinal).each do |link_record| header = nil if link_record[:element_array_uuid].to_s.size > 0 header = @database.connector()[:element_array].filter({:uuid => link_record[:element_array_uuid].to_s}).first end if header if header[:uuid] == path_array.last[:uuid] && header[:title] == path_array.last[:title] found_link = {:uuid => header[:uuid], :linkid => link_record[:dbid]} else link_uuids << {:uuid => header[:uuid], :linkid => link_record[:dbid]} end end end if found_link # Review : how to deal with lots of users deleting objects at once?? if @database.destroy_by_uuid(@credential, found_link[:uuid].to_sym) == true # ### Delete array_elements link of id ... @database.connector()[:array_elements].filter({:dbid => found_link[:linkid]}).delete # ### Reset ordinals of array_elements links. (Even though VFS.entries sorts results) link_uuids.each_with_index do |link_record, ordinal| @database.connector()[:array_elements].filter({:dbid => found_link[:linkid]}).update({:ordinal => ordinal}) end end end end else begin raise Exception, "You do not have permissions to destroy this object" rescue Exception => the_error log_error({:error => the_error, :parameters => {:path => subpath}}) end end else begin raise Exception, "Invalid path" rescue Exception => the_error log_error({:error => the_error, :parameters => {:path => subpath}}) end end else begin raise Exception, "You do not have permissions to destroy this object" rescue Exception => the_error log_error({:error => the_error, :parameters => {:path => subpath}}) end end else begin raise Exception, "Invalid path" rescue Exception => the_error log_error({:error => the_error, :parameters => {:path => subpath}}) end end end result end
rmfile(subpath="")
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 1804 def rmfile(subpath="") result = false if @directory # FS rmfile if subpath.to_s == "" or subpath.to_s == "/" the_path = (@directory.path) else unless subpath.to_s[0] == "/" subpath = ("/" << subpath.to_s) end the_path = (@directory.path + subpath.to_s).gsub("//", "/") end # if ::File::exist?(the_path) begin the_profile = self.profile(subpath.to_s) if the_profile if the_profile[:permissions][:effective][:destroy] if ::File::delete(the_path) GxG::DB[:roles][:vfs].destroy_vfs_permission(the_profile[:file_id]) result = true end else raise Exception, "You do not have destroy permissions to do this" end else raise Exception, "Inavalid path" end rescue Exception => the_error log_error({:error => the_error, :parameters => {:path => the_path}}) end else begin raise Exception, "Invaid path" rescue Exception => the_error log_error({:error => the_error, :parameters => {:path => the_path}}) end end # else # DB rmfile path_array = self.db_path(subpath.to_s) if path_array the_profile = self.profile(subpath.to_s) if the_profile if the_profile[:permissions][:effective][:destroy] parent_uuid = (path_array[-2] || {})[:uuid] link_uuids = [] found_link = nil if parent_uuid @database.connector()[:array_elements].filter({:parent_uuid => parent_uuid.to_s}).order(:ordinal).each do |link_record| header = nil if link_record[:element_hash_uuid].to_s.size > 0 header = @database.connector()[:element_hash].filter({:uuid => link_record[:element_hash_uuid].to_s}).first end if header if header[:uuid] == path_array.last[:uuid] && header[:title] == path_array.last[:title] found_link = {:uuid => header[:uuid], :linkid => link_record[:dbid]} else link_uuids << {:uuid => header[:uuid], :linkid => link_record[:dbid]} end end end if found_link # Review : how to deal with lots of users deleting objects at once?? if @database.destroy_by_uuid(@credential, found_link[:uuid].to_sym) == true # ### Delete array_elements link of id ... @database.connector()[:array_elements].filter({:dbid => found_link[:linkid]}).delete # ### Reset ordinals of array_elements links. (Even though VFS.entries sorts results) link_uuids.each_with_index do |link_record, ordinal| @database.connector()[:array_elements].filter({:dbid => found_link[:linkid]}).update({:ordinal => ordinal}) end end end end # else begin raise Exception, "You do not have destroy permissions to do this" rescue Exception => the_error log_error({:error => the_error, :parameters => {:path => subpath.to_s}}) end end else begin raise Exception, "Invaid path" rescue Exception => the_error log_error({:error => the_error, :parameters => {:path => subpath.to_s}}) end end else begin raise Exception, "Invaid path" rescue Exception => the_error log_error({:error => the_error, :parameters => {:path => subpath.to_s}}) end end end result end
set_permissions(subpath="", the_credential=nil, the_permissions={})
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 2423 def set_permissions(subpath="", the_credential=nil, the_permissions={}) result = false if @directory if subpath.to_s == "" or subpath.to_s == "/" the_path = (@directory.path) else unless subpath.to_s[0] == "/" subpath = ("/" << subpath.to_s) end the_path = (@directory.path + subpath.to_s).gsub("//", "/") end if ::File::exist?(the_path) # Review - all I need is the :file_id : make more efficient profile = self.profile(subpath, the_credential) the_credentials = [] owner_roles = [(GxG::DB[:authority][:system_credentials][:administrators]), (GxG::DB[:authority][:system_credentials][:developers]), (GxG::DB[:authority][:system_credentials][:designers])].flatten! user_roles = GxG::DB[:authority].user_roles(the_credential).collect {|record| record[:credential]} the_role = :other user_roles.each do |the_role_credential| if owner_roles.include?(the_role_credential) the_role = :owner the_credentials = owner_roles break end end unless the_role == :owner if the_credential.to_s == "00000000-0000-4000-0000-000000000000" the_role = :other the_credentials = [ :"00000000-0000-4000-0000-000000000000" ] else the_role = :group the_credentials = user_roles end end # translate to unix permissions old_permission = ::File.stat(the_path).mode.to_s(base=2) x = nil if ::File.directory?(the_path) x = 1 else if the_permissions.keys.include?(:execute) if the_permissions[:execute] == true x = 1 else x = 0 end end end w = nil if the_permissions.keys.include?(:write) if the_permissions[:write] == true w = 1 else w = 0 end else [:rename, :move, :destroy, :create].each do |the_action| if the_permissions.keys.include?(the_action) if the_permissions[(the_action)] == true w = 1 break end end end end if the_permissions.keys.include?(:read) if the_permissions[:read] == true r = 1 else r = 0 end else r = nil end case the_role when :owner if x old_permission[-7] = x.to_s end if w old_permission[-8] = w.to_s end if r old_permission[-9] = r.to_s end when :group if x old_permission[-4] = x.to_s end if w old_permission[-5] = w.to_s end if r old_permission[-6] = r.to_s end when :other if x old_permission[-1] = x.to_s end if w old_permission[-2] = w.to_s end if r old_permission[-3] = r.to_s end end ::File.chmod(old_permission.to_i(2), the_path) if profile[:file_id] the_credentials.each do |credential_uuid| GxG::DB[:roles][:vfs].update_vfs_permission(profile[:file_id], credential_uuid, the_permissions) end end result = true end else # DB object exist? path_array = self.db_path(subpath.to_s) if path_array object_details = {:uuid => path_array.last[:uuid], :table => :unspecified, :dbid => 0} header = @database.connector()[:element_hash].filter({:uuid => object_details[:uuid].to_s}).first if header object_details[:table] = :element_hash object_details[:dbid] = header[:dbid] else header = @database.connector()[:element_array].filter({:uuid => object_details[:uuid].to_s}).first if header object_details[:table] = :element_array object_details[:dbid] = header[:dbid] end end if object_details[:uuid].to_s.size > 0 if object_details[:table] = :element_array manifest = [{:table => object_details[:table], :dbid => object_details[:dbid]}] else # Note: for an element_hash - ensure all sub-objects are extended this permission. manifest = [] structures = [{:table => object_details[:table], :dbid => object_details[:dbid]}] while structures.size > 0 do entry = structures[0] @database.element_manifest(entry[:table],entry[:dbid]).each do |record| if [:element_hash, :element_array].include?(record[:table]) unless structures.include?(record) structures << record end end end manifest << structures.shift end end # manifest.each do |record| @database.assign_element_permission(record[:table], record[:dbid], credential, the_permissions) end result = true end end end result end
set_permissions_recursive(subpath="", the_credential=nil, the_permissions={})
click to toggle source
# File lib/gxg/gxg_dbfs.rb, line 2583 def set_permissions_recursive(subpath="", the_credential=nil, the_permissions={}) the_profile = self.profile((File.expand_path(subpath)).to_s) if the_profile if [:virtual_directory, :directory, :persisted_array].include?(the_profile[:type]) paths = [(File.expand_path(subpath))] while paths.size > 0 do the_path = paths.shift the_path_profile = self.profile(the_path.to_s) if [:virtual_directory, :directory, :persisted_array].include?(the_path_profile[:type]) self.entries(the_path, the_credential).each do |a_profile| paths << File.expand_path(the_path + "/" + a_profile[:title].to_s) end self.set_permissions(the_path, the_credential, the_permissions) else self.set_permissions(the_path, the_credential, the_permissions) end end else self.set_permissions(subpath, the_credential, the_permissions) end end true end