class GxG::Database::Database

Database class proper

Public Class Methods

element_table_by_index(the_index=0) click to toggle source
# File lib/gxg/gxg_database.rb, line 97
def self.element_table_by_index(the_index=0)
  (::GxG::Database::Database::element_tables().keys[(the_index)] || :unspecified)
end
element_table_for_instance(the_instance=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 101
def self.element_table_for_instance(the_instance=nil)
  # Review : rewrite - in use
  result = :unspecified
  #
  table = ::GxG::Database::Database::element_tables()
  table.keys.each do |the_key| 
    unless the_key == :unspecified
      if the_instance.is_any?(table[(the_key)])
        result = the_key
        break
      end
    end
  end
  #
  result
end
element_table_index(the_key=:unspecified) click to toggle source
# File lib/gxg/gxg_database.rb, line 93
def self.element_table_index(the_key=:unspecified)
  (::GxG::Database::Database::element_tables().keys.index(the_key.to_sym) || 0)
end
element_tables() click to toggle source
# File lib/gxg/gxg_database.rb, line 74
def self.element_tables()
  {
    :unspecified => nil,
    :element_boolean => [::TrueClass, ::FalseClass, ::NilClass],
    :element_integer => [::Integer],
    :element_float => [::Float],
    :element_bigdecimal => [::BigDecimal],
    :element_datetime => [::DateTime],
    :element_text => [::String],
    :element_binary => [::GxG::ByteArray],
    :element_array => [::Array],
    :element_hash => [::Hash]
  }
end
new(connection = nil, options={}) click to toggle source
Calls superclass method
# File lib/gxg/gxg_database.rb, line 5111
def initialize(connection = nil, options={})
  # TODO: require :credential (access privs)
  super()
  @credential = nil
  @url = options[:url]
  @base_permissions = {:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false}
  #
  if connection.is_a?(::Sequel::Database)
    @connector = connection
    #
    @active = false
    unless open?()
      raise Exception, "Unable to connect with the database"
    end
    #
    @scheme = @url.scheme.to_s.to_sym
    case @scheme
    when :sqlite, :sqlite3
      @connector.run("PRAGMA page_size=65536")
      @connector.run("PRAGMA max_page_count=281474976710656")
      @connector.run("PRAGMA encoding='UTF-8'")
    when :mysql, :mysql2
      @connector.run("SET GLOBAL max_allowed_packet=17825792;")
      @connector.run("SET NAMES 'utf8' COLLATE 'utf8_general_ci';")
      @connector.run("SET collation_connection = 'utf8_general_ci';")
    when :postgres
      # place holder
    end
  else
    raise Exception, "Invalid db connection"
  end
  # characterize basic effective permissions
  begin
    formatted = db_formatted?()
    @base_permissions[:read] = true
    @base_permissions[:execute] = true
  rescue Exception => the_error
    formatted = false
    raise Exception, "Lack read permissions to the database"
  end
  #
  unless options[:read_only]
    if formatted
      begin
        dbid = @connector[:text_page].insert()
      rescue Exception => the_error
        dbid = nil
      end
      if dbid.is_a?(::Integer)
        @connector[:text_page].filter({:dbid => (dbid)}).delete
        @base_permissions[:write] = true
        @base_permissions[:create] = true
        @base_permissions[:destroy] = true
        @base_permissions[:rename] = true
        @base_permissions[:move] = true
      end
    else
      begin
        test_table_name = ::GxG::uuid_generate().gsub("-","")
        while (@connector.table_exists?(test_table_name.to_sym)) do
          test_table_name = ::GxG::uuid_generate().gsub("-","")
        end
        @connector.create_table(test_table_name.to_sym) do
          primary_key :dbid
        end
        @connector.drop_table(test_table_name.to_sym)
        @base_permissions[:write] = true
        @base_permissions[:create] = true
        @base_permissions[:destroy] = true
        @base_permissions[:rename] = true
        @base_permissions[:move] = true
      rescue Exception => the_error
        # Read-only Database
      end
    end
  end
  #
  @base_permissions.freeze
  #
  unless formatted
    if @base_permissions[:write]
      db_format
      unless db_formatted?()
        @active = false
        raise Exception, "Unable to format the database for use"
      end
    else
      raise Exception, "Unable to format a read-only database"
    end
  end
  #
  @authority = nil
  @db_list = []
  if options[:authority].is_a?(::GxG::Database::Database)
    @authority = options[:authority]
    @authority.db_register(self)
  end
  #
  unless @authority
    unless self.group_exist?("Administrators")
      if @base_permissions[:write]
        if self.user_id_available?("root")
          self.user_create("root","password")
          temp_cred = self.user_credential("root","password")
          temp_group = self.group_create({:title => "Administrators", :default_role => {:title => "Members"}})
          self.role_add_user(temp_group[:default_role],temp_cred)
          #
          dev_group = self.group_create({:title => "Developers", :default_role => {:title => "Members"}})
          dsn_group = self.group_create({:title => "Designers", :default_role => {:title => "Members"}})
          #
          self[:system_credentials] = {:administrator => temp_cred, :administrators => temp_group[:default_role], :developers => dev_group[:default_role], :designers => dsn_group[:default_role]}
          self[:permission_policy] = [{:event => :extend, :credential => :any, :action => {:extend_permissions => temp_group[:default_role]}}]
          #
        end
        if self.user_id_available?("public")
          self.user_create("public","password", "00000000-0000-4000-0000-000000000000")
        end
      end
    end
  end
  #
  permission_policy_load
  self
end
valid_field_classes() click to toggle source
# File lib/gxg/gxg_database.rb, line 89
def self.valid_field_classes()
  [::TrueClass, ::FalseClass, ::NilClass, ::Integer, ::Float, ::BigDecimal, ::DateTime, ::String, ::GxG::ByteArray]
end

Public Instance Methods

[](setting_key=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 3500
def [](setting_key=nil)
  result = nil
  begin
    if self.alive?()
      if self.open?()
        record = @connector[:settings].filter({:title => setting_key.to_s}).first
        if record
          content = ""
          @connector[:text_page].select(:content).where({:parent_uuid => record[:uuid].to_s}).order(:ordinal).each do |entry|
            content << entry[:content]
          end
          if content.size > 0
            result = content.unserialize()
          end
        end
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Attempted to access a defunct Database"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:setting_key => setting_key}})
  end
  result
end
[]=(setting_key=nil, object=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 3527
def []=(setting_key=nil, object=nil)
  result = object
  begin
    if self.alive?()
      if self.open?()
        unless self.db_permissions()[:write]
          raise Exception, "Unable to write to database"
        end
        unless setting_key.is_a?(::Symbol)
          raise ArgumentError, "You must supply a setting key as a Symbol"
        end
        unless setting_key.to_s.size > 0
          raise ArgumentError, "You must supply a setting key whose length is greater than zero"
        end
        record = @connector[:settings].filter({:title => setting_key.to_s}).first
        unless record
          new_uuid = ::GxG::uuid_generate().to_s
          while (@connector[:settings].filter({:uuid => (new_uuid)}).count > 0 or @connector[:formats].filter({:uuid => (new_uuid)}).count > 0 or @connector[:element_text].filter({:uuid => (new_uuid)}).count > 0)
            new_uuid = ::GxG::uuid_generate().to_s
          end
          @connector[:settings].insert({:title => setting_key.to_s, :uuid => new_uuid.to_s})
          record = @connector[:settings].filter({:uuid => (new_uuid)}).first
        end
        if record
          @connector[:settings].filter({:dbid => (record[:dbid])}).update({:version => (record[:version] + 0.0001)})
          content = object.serialize()
          old_segments = []
          @connector[:text_page].select(:dbid).where({:parent_uuid => record[:uuid].to_s}).order(:ordinal).each do |entry|
            old_segments << entry[:dbid]
          end
          if content.size == 0
            if old_segments.size > 0
              @connector[:text_page].filter({:parent_uuid => record[:uuid].to_s}).delete
            end
          else
            new_segments = ::GxG::apportioned_ranges(content.size, 4096)
            if old_segments.size > new_segments.size
              the_count = old_segments.size
            else
              the_count = new_segments.size
            end
            manifest = []
            (0..(the_count - 1)).each do |the_ordinal|
              if new_segments[(the_ordinal)] and old_segments[(the_ordinal)]
                #overwrite with new segment range
                manifest << {:operation => :overwrite, :dbid => (old_segments[(the_ordinal)]), :ordinal => (the_ordinal), :portion => (new_segments[(the_ordinal)])}
              else
                if new_segments[(the_ordinal)]
                  # create new segment at this ordinal
                  manifest << {:operation => :create, :ordinal => (the_ordinal), :portion => (new_segments[(the_ordinal)])}
                else
                  # delete old segment
                  manifest << {:operation => :delete, :dbid => (old_segments[(the_ordinal)])}
                end
              end
            end
            manifest.each do |action|
              case action[:operation]
              when :overwrite
                @connector[:text_page].filter({:dbid => (action[:dbid])}).update({:ordinal => (action[:ordinal]), :length => (content[(action[:portion])].size), :content => (content[(action[:portion])])})
              when :create
                @connector[:text_page].insert({:parent_uuid => (record[:uuid]), :ordinal => (action[:ordinal]), :length => (content[(action[:portion])].size), :content => (content[(action[:portion])])})
              when :delete
                @connector[:text_page].filter({:dbid => (action[:dbid])}).delete
              end
            end
            #
          end
        else
          raise Exception, "Internal Error - could not retrieve setting record: #{setting_key.inspect}"
        end
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Attempted to access a defunct Database"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:setting => setting_key, :object => object}})
  end
  result
end
assign_element_permission(table=:unspecified, dbid=0, credential=nil, permissions={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 1502
def assign_element_permission(table=:unspecified, dbid=0, credential=nil, permissions={})
  result = false
  begin
    unless self.alive?
      raise Exception, "Database inactive"
    end
    unless self.open?
      raise Exception, "Database not available"
    end
    unless dbid.is_a?(::Integer)
      raise ArgumentError, "dbid must be specified with a Integer"
    end
    unless permissions.is_a?(::Hash)
      raise ArgumentError, "permissions must be specified with a Hash"
    end
    unless ::GxG::valid_uuid?(credential)
      raise ArgumentError, "You must specify a valid credential UUID (as a String or Symbol)"
    end
    if table.is_a?(::Integer)
      table = ::GxG::Database::Database::element_table_by_index(table)
    end
    # Review : change in permission policy
    # if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :element_binary, :element_array, :element_hash].include?(table)
    if [:element_array, :element_hash].include?(table)
      record = @connector[:permissions].filter({:element_table => (table.to_s), :elementid => (dbid), :credential => (credential.to_s)}).first
      if record
        # update
        the_update = {:execute => 0, :rename => 0, :move => 0, :destroy => 0, :create => 0, :write => 0, :read => 0}
        [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
          if record[(the_permission)] == 1
            the_update[(the_permission)] = 1
          end
        end
        [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
          if permissions[(the_permission)].is_a?(::TrueClass)
            the_update[(the_permission)] = 1
          end
          if permissions[(the_permission)].is_a?(::FalseClass)
            the_update[(the_permission)] = 0
          end
        end
        the_update[:version] = record[:version] + 0.0001
        @connector[:permissions].filter({:dbid => (record[:dbid])}).update(the_update)
      else
        # create
        new_record = {:credential => (credential.to_s), :element_table => (table.to_s), :elementid => (dbid), :execute => 0, :rename => 0, :move => 0, :destroy => 0, :create => 0, :write => 0, :read => 0}
        [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
          if permissions[(the_permission)]
            new_record[(the_permission)] = 1
          end
        end
        @connector[:permissions].insert(new_record)
      end
      result = true
    else
      raise ArgumentError, "Invalid table specified"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:table => (table), :dbid => (dbid), :credential => (credential), :permissions => (permissions)}})
  end
  result
end
byte_size_by_uuid(the_uuid=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 2514
def byte_size_by_uuid(the_uuid=nil)
  result = 0
  begin
    if self.alive?
      if self.open?
        found = @connector[:element_hash].select(:dbid, :uuid).filter({:uuid => the_uuid.to_s}).first
        if found
          result += self.element_byte_size(:element_hash,(found[:dbid]))
        else
          found = @connector[:element_array].select(:dbid, :uuid).filter({:uuid => the_uuid.to_s}).first
          if found
            result += self.element_byte_size(:element_array,(found[:dbid]))
          end
        end
      end
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:uuid => (the_uuid)}})
  end
  result
end
clear_all_element_locks() click to toggle source

Utility methods

# File lib/gxg/gxg_database.rb, line 5086
def clear_all_element_locks()
  # for when boo-boos happen
  if self.open?()
    if self.db_permissions()[:write]
      @connector[:element_locks].filter({}).delete
    end
  end
end
clone() click to toggle source
# File lib/gxg/gxg_database.rb, line 5107
def clone()
  initialize_clone
end
close() click to toggle source
# File lib/gxg/gxg_database.rb, line 415
def close()
  # place holder for now.
  if @authority
    @authority.db_unregister(self)
  end
end
connector() click to toggle source
# File lib/gxg/gxg_database.rb, line 422
def connector()
  @connector
end
create_vfs_permission(file_id=nil, credential=nil, permission={:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false}) click to toggle source
# File lib/gxg/gxg_database.rb, line 1767
def create_vfs_permission(file_id=nil, credential=nil, permission={:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false})
  result = false
  begin
    unless self.alive?
      raise Exception, "Database inactive"
    end
    unless self.open?
      raise Exception, "Database not available"
    end
    unless file_id.is_a?(::String)
      raise ArgumentError, "file_id must be specified with a String"
    end
    unless permission.is_a?(::Hash)
      raise ArgumentError, "permission must be specified with a Hash"
    end
    unless ::GxG::valid_uuid?(credential)
      raise ArgumentError, "You must specify a valid credential UUID (as a String or Symbol)"
    end
    #
    record = @connector[:file_permissions].filter({:file_id => file_id.to_s, :credential => credential.to_s}).first
    if record
      update = true
      dbid = record.delete(:dbid)
    else
      update = false
      dbid = nil
      record = {:file_id => file_id.to_s, :credential => credential.to_s, :execute => 0, :rename => 0, :move => 0, :destroy => 0, :create => 0, :write => 0, :read => 0}
    end
    permission.keys.each do |the_permission_key|
      if permission[(the_permission_key)] == true
        record[(the_permission_key)] = 1
      else
        record[(the_permission_key)] = 0
      end
    end
    if update == true
      @connector[:file_permissions].filter({:dbid => dbid}).update(record)
    else
      @connector[:file_permissions].insert(record)
    end
    result = true
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:file_id => (file_id), :credential => (credential)}})
  end
  result
end
db_format(format_options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 297
def db_format(format_options={})
  # MySql stuff:
  # ALTER TABLE tbl_name MAX_ROWS=1000000000 AVG_ROW_LENGTH=nnn;
  # See: https://dev.mysql.com/doc/refman/5.0/en/table-size-limit.html
  result = true
  #
  begin
    if @connector.is_a?(::Sequel::Database)
      case @scheme
      when :sqlite
        @connector.run("PRAGMA page_size=65536")
        @connector.run("PRAGMA max_page_count=281474976710656")
        @connector.run("PRAGMA encoding='UTF-8'")
      when :mysql, :mysql2
        @connector.run("SET GLOBAL max_allowed_packet = 17825792;")
        @connector.run("SET NAMES 'utf8' COLLATE 'utf8_general_ci';")
        @connector.run("SET collation_connection = 'utf8_general_ci';")
      when :postgres
        # place holder
      end
      migration = db_migration()
      migration.keys.each do |the_table|
        unless @connector.table_exists?(the_table)
            @connector.create_table(the_table) do
            primary_key :dbid
          end
        end
        used_bytes = 0
        #
        existing_columns = @connector[(the_table)].columns
        migration[(the_table)].keys.each do |the_column|
          used_bytes += (migration[(the_table)][(the_column)][:bytes]).to_i
          if existing_columns.include?(the_column)
            # TODO: figure out a way to inspect columns for attributes -> detailed verification
          else
            # collation for mysql
            if @scheme == :mysql
              # Note: might have to specify :collate first, use -> {:collate => ""}.merge(migration[(the_table)][(the_column)][:options])
              if migration[(the_table)][(the_column)][:type] == :varchar
                # migration[(the_table)][(the_column)][:options] = {:collate => "utf8_general_ci"}.merge(migration[(the_table)][(the_column)][:options])
                migration[(the_table)][(the_column)][:options][:collate] = "utf8_general_ci"
              end
              if migration[(the_table)][(the_column)][:type] == :blob
                # migration[(the_table)][(the_column)][:options] = {:collate => "binary"}.merge(migration[(the_table)][(the_column)][:options])
                # Note: MySQL 5 doesn't like putting collation on blobs! (blows up)
                # migration[(the_table)][(the_column)][:options][:collate] = "binary"
              end
            else
            end
            # do the deed
            @connector.add_column((the_table), (the_column), (migration[(the_table)][(the_column)][:type]), (migration[(the_table)][(the_column)][:options]))
            #
          end
        end
        #
        if @scheme == :mysql
          @connector.run("ALTER TABLE #{the_table.to_s} MAX_ROWS=18446744073709551616 AVG_ROW_LENGTH=#{used_bytes.to_s};")
        end
        #
      end
    else
      raise Exception, "Invalid db connection"
    end
  rescue Exception => the_error
    result = false
    log_error({:error => the_error, :parameters => format_options})
  end
  #
  result
end
db_formatted?() click to toggle source
# File lib/gxg/gxg_database.rb, line 368
def db_formatted?()
  result = true
  #
  begin
    if @connector.is_a?(::Sequel::Database)
      migration = db_migration()
      migration.keys.each do |the_table|
        unless @connector.table_exists?(the_table)
          result = false
          break
        end
        #columns
        existing_columns = @connector[(the_table)].columns
        migration[(the_table)].keys.each do |the_column|
          unless existing_columns.include?(the_column)
            result = false
            break
          end
        end
        #
        unless (result)
          break
        end
      end
    else
      raise Exception, "Invalid db connection"
    end
  rescue Exception => the_error
    result = false
    log_error({:error => the_error, :parameters => nil})
  end
  #
  result
end
db_list() click to toggle source
# File lib/gxg/gxg_database.rb, line 455
def db_list()
  result = []
  @db_list.each do |the_db|
    result << the_db
  end
  result
end
db_migration() click to toggle source
# File lib/gxg/gxg_database.rb, line 118
def db_migration()
  # Review : Consider adding support for a ::Symbol class as well. (ease-of-use implications later)
  # Internal mapping of the database format
  # Datatypes - See: http://sequel.jeremyevans.net/rdoc/files/doc/schema_modification_rdoc.html
  # Column Options - See: http://sequel.jeremyevans.net/rdoc/classes/Sequel/Database.html#method-i-add_column
  # See also : http://ruby-doc.org/core-2.2.0/Array.html#method-i-pack
  {
    :element_text => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
      :length => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)}
      },
    :text_page => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :parent_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :ordinal => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :length => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :content => {:type => :varchar, :options => {:size => 4099, :default => "", :null => false}, :bytes => 4099}
      },
    :element_binary => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
      :format => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :length => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)}
      },
    :binary_page => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :parent_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :ordinal => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :length => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :content => {:type => :blob, :options => {:size => 65536}, :bytes => 65536}
      },
    :element_array => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :constraint => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :title => {:type => :varchar, :options => {:size => 259, :null => false, :default => "Untitled"}, :bytes => 259},
      :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
      },
    :array_elements => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :parent_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :ordinal => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
      :element => {:type => :varchar, :options => {:size => 259, :default => "element_boolean", :null => false}, :bytes => 259},
      :element_boolean => {:type => :integer, :options => {:size => 1, :default => -1}, :bytes => ([ -1 ].pack('l!').length)},
      :element_integer => {:type => :integer, :options => {}, :bytes => ([ -1 ].pack('l!').length)},
      :element_float => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
      :element_bigdecimal => {:type => :numeric, :options => {:default => ::BigDecimal.new("0.0")}, :bytes => 256},
      :element_datetime => {:type => :datetime, :options => {}, :bytes => 16},
      :time_offset => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
      :time_prior => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
      :time_after => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
      :length => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :element_text => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
      :element_text_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :element_binary_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :element_array_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :element_hash_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40}
    },
    :element_hash => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :format => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :title => {:type => :varchar, :options => {:size => 259, :null => false, :default => "Untitled"}, :bytes => 259},
      :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
      },
    :hash_properties => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :parent_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :property => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
      :ordinal => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
      :element => {:type => :varchar, :options => {:size => 259, :default => "element_boolean", :null => false}, :bytes => 259},
      :element_boolean => {:type => :integer, :options => {:size => 1, :default => -1}, :bytes => ([ -1 ].pack('l!').length)},
      :element_integer => {:type => :integer, :options => {}, :bytes => ([ -1 ].pack('l!').length)},
      :element_float => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
      :element_bigdecimal => {:type => :numeric, :options => {:default => ::BigDecimal.new("0.0")}, :bytes => 256},
      :element_datetime => {:type => :datetime, :options => {}, :bytes => 16},
      :time_offset => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
      :time_prior => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
      :time_after => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
      :length => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :element_text => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
      :element_text_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :element_binary_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :element_array_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :element_hash_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40}
    },
    :element_locks => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :type => {:type => :varchar, :options => {:size => 40,:default => "", :null => false}, :bytes => 40},
      :reservation => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :credential => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :element_table => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
      :elementid => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)}
    },
    :trash => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :element_table => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
      :elementid => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)}
    },
    :users => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :user_id => {:type => :varchar, :options => {:size => 259, :null => false, :default => ""}, :bytes => 259},
      :password_hash => {:type => :varchar, :options => {:size => 259, :null => false, :default => ""}, :bytes => 259},
      :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
    },
    :roles => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :group_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :seo => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
      :title => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
      :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
    },
    :user_roles => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :user_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :role_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
    },
    :groups => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :parent_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :default_role => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :seo => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
      :title => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
      :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
    },
    :permissions => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :credential => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :execute => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :rename => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :move => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :destroy => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :create => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :write => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :read => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :element_table => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
      :elementid => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
    },
    :file_permissions => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :file_id => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :credential => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :execute => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :rename => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :move => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :destroy => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :create => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :write => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :read => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
      :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
    },
    :formats => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :type => {:type => :varchar, :options => {:size => 40, :null => false, :default => "structure"}, :bytes => 40},
      :ufs => {:type => :varchar, :options => {:size => 4099, :default => "", :null => false}, :bytes => 4099},
      :title => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
      :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
      :mime_types => {:type => :varchar, :options => {:size => 4099, :default => "", :null => false}, :bytes => 4099}
    },
    :settings => {
      :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
      :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
      :title => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
      :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
    }
  }
end
db_permissions() click to toggle source

Permission Handling methods

# File lib/gxg/gxg_database.rb, line 435
def db_permissions
  @base_permissions.clone
end
db_register(the_db) click to toggle source

Authority support

# File lib/gxg/gxg_database.rb, line 439
def db_register(the_db)
  if the_db.is_a?(::GxG::Database::Database)
    unless @db_list.find_index(the_db)
      @db_list << the_db
    end
  end
end
db_unregister(the_db) click to toggle source
# File lib/gxg/gxg_database.rb, line 447
def db_unregister(the_db)
  if the_db.is_a?(::GxG::Database::Database)
    if @db_list.find_index(the_db)
      @db_list.delete_at(@db_list.find_index(the_db))
    end
  end
end
destroy_by_uuid(credential=nil, the_uuid=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 2457
def destroy_by_uuid(credential=nil, the_uuid=nil)
  # Review : rewrite - in use
  # element_destroy(credential=nil,table=:unspecified,dbid=0, options={})
  # .effective_uuid_permission(data["location"].to_s.to_sym,@credential)
  result = false
  begin
    if self.alive?
      if self.open?
        if self.db_permissions()[:destroy] == true
          if ::GxG::valid_uuid?(credential)
            found = @connector[:element_hash].select(:dbid, :uuid).filter({:uuid => the_uuid.to_s}).first
            if found
              self.element_destroy(credential, :element_hash,(found[:dbid]))
              result = true
            else
              found = @connector[:element_array].select(:dbid, :uuid).filter({:uuid => the_uuid.to_s}).first
              if found
                self.element_destroy(credential, :element_array,(found[:dbid]))
                result = true
              end
            end
          else
            raise ArgumentError, "You must supply a valid credential UUID (as a String or Symbol)"
          end
        end
      end
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:credential => (credential), :uuid => (the_uuid)}})
  end
  result
end
destroy_vfs_permission(file_id=nil, credential=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 1861
def destroy_vfs_permission(file_id=nil, credential=nil)
  result = false
  begin
    unless self.alive?
      raise Exception, "Database inactive"
    end
    unless self.open?
      raise Exception, "Database not available"
    end
    unless file_id.is_a?(::String)
      raise ArgumentError, "file_id must be specified with a String"
    end
    # ### Review : make more efficient
    if credential
      unless ::GxG::valid_uuid?(credential)
        raise ArgumentError, "You must specify a valid credential UUID (as a String or Symbol)"
      end
      record = @connector[:file_permissions].filter({:file_id => file_id.to_s, :credential => credential.to_s}).first
      if record
        @connector[:file_permissions].filter({:file_id => file_id.to_s, :credential => credential.to_s}).delete
      end
    else
      record = @connector[:file_permissions].filter({:file_id => file_id.to_s}).first
      if record
        @connector[:file_permissions].filter({:file_id => file_id.to_s}).delete
      end
    end
    result = true
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:file_id => (file_id), :credential => (credential)}})
  end
  result
end
dup()
Alias for: initialize_clone
effective_element_permission(table=:unspecified, dbid=0, credential=nil) click to toggle source

DB Objects

# File lib/gxg/gxg_database.rb, line 1895
def effective_element_permission(table=:unspecified, dbid=0, credential=nil)
  result = {:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false}
  begin
    unless self.alive?
      raise Exception, "Database inactive"
    end
    unless self.open?
      raise Exception, "Database not available"
    end
    unless dbid.is_a?(::Integer)
      raise ArgumentError, "dbid must be specified with a Integer"
    end
    unless ::GxG::valid_uuid?(credential)
      raise ArgumentError, "You must specify a valid credential UUID (as a String or Symbol)"
    end
    if table.is_a?(::Integer)
      table = ::GxG::Database::Database::element_table_by_index(table)
    end
    # Review : change in permission policy
    # if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :element_binary, :element_array, :element_hash].include?(table)
    if [:element_array, :element_hash].include?(table)
      # is credential a user or role?
      raw_permissions = []
      # Include PUBLIC credential
      credentials = ["00000000-0000-4000-0000-000000000000"]
      #
      if self.user_exist?(credential)
        credentials << credential
        role_list = self.user_roles(credential)
        role_list.each do |entry|
          credentials << entry[:credential]
        end
        #
      else
        if self.role_exist?(credential)
          credentials << credential
        else
          raise ArgumentError, "Invalid credential.  It is neither a user nor a role UUID"
        end
      end
      credentials.each do |entry|
        manifest = @connector[:permissions].filter({:credential => (entry.to_s), :element_table => (table.to_s), :elementid => (dbid)})
        manifest.each do |record|
          new_permission = {:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false}
          [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
            if record[(the_permission)] == 1
              new_permission[(the_permission)] = true
            end
          end
          raw_permissions << new_permission
        end
      end
      permission = {:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false}
      raw_permissions.each do |entry|
        [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
          if entry[(the_permission)]
            permission[(the_permission)] = true
          end
        end
      end
      db_limits = self.db_permissions()
      [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
        if db_limits[(the_permission)] and permission[(the_permission)]
          result[(the_permission)] = true
        end
      end
      #
    else
      raise ArgumentError, "Invalid table specified"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:table => (table), :dbid => (dbid), :credential => (credential)}})
  end
  result
end
effective_uuid_permission(uuid=nil, credential=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 1971
def  effective_uuid_permission(uuid=nil, credential=nil)
  result = nil
  begin
    if self.alive?
      if self.open?
        address = nil
        record = @connector[:element_hash].filter({:uuid => (uuid.to_s)}).first
        if record
          address = {:database => self, :table => :element_hash, :dbid => (record[:dbid])}
        else
          record = @connector[:element_array].filter({:uuid => (uuid.to_s)}).first
          if record
            address = {:database => self, :table => :element_array, :dbid => (record[:dbid])}
          end
        end
        if address
          result = self.effective_element_permission(address[:table], address[:dbid], credential)
        else
          # ### Review : Experimental Code - attempt to seemlessly integrate dbs of different roles into in-memory structures.
          already_checked = [(self)]
          ::GxG::DB[:roles].each_pair do |the_db_role, the_database|
            unless already_checked.include?(the_database)
              record = the_database.connector[:element_hash].filter({:uuid => (uuid.to_s)}).first
              if record
                address = {:database => the_database, :table => :element_hash, :dbid => (record[:dbid])}
                result = the_database.effective_element_permission(address[:table], address[:dbid], credential)
                break
              else
                record = the_database.connector[:element_array].filter({:uuid => (uuid.to_s)}).first
                if record
                  address = {:database => the_database, :table => :element_array, :dbid => (record[:dbid])}
                  result = the_database.effective_element_permission(address[:table], address[:dbid], credential)
                  break
                end
              end
              already_checked << the_database
            end
          end
          #
        end
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Database not available (defunct)"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:uuid => (uuid), :credential => (credential)}})
  end
  result
end
effective_vfs_permission(file_id=nil, credential=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 1710
def effective_vfs_permission(file_id=nil, credential=nil)
  result = {:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false}
  begin
    unless self.alive?
      raise Exception, "Database inactive"
    end
    unless self.open?
      raise Exception, "Database not available"
    end
    unless file_id.is_a?(::String)
      raise ArgumentError, "file_id must be specified with a String"
    end
    unless ::GxG::valid_uuid?(credential)
      raise ArgumentError, "You must specify a valid credential UUID (as a String or Symbol)"
    end
    # ### VFS Permissions
    raw_permissions = []
    credentials = ["00000000-0000-4000-0000-000000000000"]
    if self.user_exist?(credential)
      credentials << credential
      role_list = self.user_roles(credential)
      role_list.each do |entry|
        credentials << entry[:credential]
      end
      #
    else
      if self.role_exist?(credential)
        credentials << credential
      else
        raise ArgumentError, "Invalid credential.  It is neither a user nor a role UUID"
      end
    end
    credentials.each do |entry|
      manifest = @connector[:file_permissions].filter({:file_id => file_id.to_s, :credential => (entry.to_s)})
      manifest.each do |record|
        new_permission = {:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false}
        [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
          if record[(the_permission)] == 1
            new_permission[(the_permission)] = true
          end
        end
        raw_permissions << new_permission
      end
    end
    raw_permissions.each do |entry|
      [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
        if entry[(the_permission)]
          result[(the_permission)] = true
        end
      end
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:file_id => (file_id), :credential => (credential)}})
  end
  result
end
element_byte_size(table=:unspecified, dbid=0) click to toggle source
# File lib/gxg/gxg_database.rb, line 2490
def element_byte_size(table=:unspecified, dbid=0)
  #
  result = 0
  begin
    if self.alive?
      if self.open?
        migration = self.db_migration()
        elements = self.element_manifest(table, dbid, true)
        elements.each do |entry|
          table_definition = migration[(entry[:table])]
          if table_definition
            table_definition.keys.each do |the_field|
              result += table_definition[(the_field)][:bytes].to_i
            end
          end
        end
      end
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:table => (table), :dbid => (dbid)}})
  end
  result
end
element_create(the_table=:unspecified, the_record=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 2090
def element_create(the_table=:unspecified, the_record=nil)
  # Review : rewrite - in use
  result = nil
  begin
    unless the_table.is_a?(::Symbol)
      raise ArgumentError, "You MUST provide the table specifier as a Symbol."
    end
    unless the_record.is_a?(::Hash)
      raise ArgumentError, "You MUST provide a record in the form of a Hash."
    end
    if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :text_page, :element_binary, :binary_page, :element_array, :element_hash].include?(the_table)
      # Review : UTF8 fix
      begin
        result = @connector[(the_table)].insert(the_record)
      rescue Exception
        if the_table == :text_page
          the_record[:content] = the_record[:content].encode64
        end
        result = @connector[(the_table)].insert(the_record)
      end
    else
      raise ArgumentError, "The table specified is unknown - Check your code."
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:table => (the_table), :record => (the_record)}})
  end
  result
end
element_destroy(credential=nil,table=:unspecified,dbid=0, options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 2401
def element_destroy(credential=nil,table=:unspecified,dbid=0, options={})
  # Review : rewrite for new arch.
  # Review : rewrite - in use
  result = false
  begin
    if self.alive?
      if self.open?
        if self.db_permissions()[:write]
          # if credential has :destroy permission on this element?
          if ::GxG::valid_uuid?(credential)
            if [:persisted_array, :persisted_hash].include?(table.to_s.to_sym)
              go_ahead = self.effective_element_permission(table, dbid, credential)[:destroy]
            else
              go_ahead = true
            end
            # xxx Quick fix : BETA: clean all this up!
            if go_ahead
              # Review : DB overhaul / rewrite - allow delete if object has write lock in place? I think not. (return false)
              # Note: BETA - bring back read-locks? it was 9x slower with them ... not sure.
              elements = self.element_manifest(table, dbid, false)
              elements.each do |entry|
                #
                unless self.element_in_trash?(entry[:table], entry[:dbid])
                  @connector[:trash].insert({:element_table => entry[:table].to_s, :elementid => entry[:dbid]})
                end
                #
                #if @connector[:element_locks].filter({:type => "read", :element_table => entry[:table].to_s, :elementid => entry[:dbid]}).count > 0
                  # put in trash
                  #unless self.element_in_trash?(entry[:table], entry[:dbid])
                    #@connector[:trash].insert({:element_table => entry[:table].to_s, :elementid => entry[:dbid]})
                  #end
                #else
                  # delete now
                  #manifest = self.element_manifest(entry[:table], entry[:dbid], true)
                  #manifest.each do |item|
                    #@connector[:permissions].filter({:element_table => (item[:table].to_s), :elementid => (item[:dbid])}).delete
                    #@connector[(item[:table])].filter({:dbid => item[:dbid]}).delete
                  #end
                #end
              end
              result = true
            else
              raise Exception, "You do not have permission to destory this element"
            end
          else
            raise ArgumentError, "You must supply a valid credential UUID (as a String or Symbol)"
          end
        end
      end
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:credential => (credential), :table => (table), :dbid => (dbid)}})
  end
  result
end
element_exists?(the_table=:unspecified, the_dbid=0) click to toggle source

Data Handling methods

# File lib/gxg/gxg_database.rb, line 2024
def element_exists?(the_table=:unspecified, the_dbid=0)
  result = false
  if the_table.is_a?(::Integer)
    the_table = ::GxG::Database::Database::element_table_by_index(the_table)
  end
  if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :element_binary, :element_array, :element_hash].include?(the_table)
    begin
      record = @connector[(the_table)].select(:dbid).where({:dbid => (the_dbid)}).first
      if record
        result = true
      end
    rescue Exception => the_error
      log_error({:error => the_error, :parameters => {:table => (the_table), :dbid => (the_dbid)}})
    end
  end
  result
end
element_in_trash?(table=:unspecified, dbid=0) click to toggle source
# File lib/gxg/gxg_database.rb, line 3021
def element_in_trash?(table=:unspecified, dbid=0)
  result = false
  begin
    if self.alive?
      if self.open?
        if @connector[:trash].filter({:element_table => table.to_s, :elementid => dbid}).count > 0
          result = true
        end
      end
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:table => (table), :dbid => (dbid)}})
  end
  result
end
element_in_use?(db_table=:unspecified, dbid = 0) click to toggle source
# File lib/gxg/gxg_database.rb, line 2211
def element_in_use?(db_table=:unspecified, dbid = 0)
  # Review : rewrite - in use for now.
  # Review : rewrite - todo (alter to reflect the new architecture : perhaps limit to structures only)
  unless db_table.is_any?(::Integer, ::Symbol)
    raise ArgumentError, "Table needs to be specified as a Symbol, or a table code Integer"
  end
  unless dbid.is_a?(::Integer)
    raise ArgumentError, "Record ID needs to be specified with an Integer"
  end
  result = false
  begin
    if db_table == :element_hash || db_table == :element_array
      # Review : make more efficient in later revs of this.
      the_record = @connector[(db_table)].filter({:dbid => (dbid)}).select(:uuid).first
      if the_record
        if @connector[:hash_properties].filter({:element_hash_uuid => the_record[:uuid]}).count > 0 || @connector[:array_elements].filter({:element_array_uuid => the_record[:uuid]}).count > 0
          result = true
        end
      end
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:table_code => (db_table), :dbid => (dbid)}})
  end
  result
end
element_manifest(the_table=:unspecified, the_dbid=0, everything=false) click to toggle source
# File lib/gxg/gxg_database.rb, line 2263
def element_manifest(the_table=:unspecified, the_dbid=0, everything=false)
  # Review : rewrite - in use
  # returns an Array of tables and dbid pairs and sub-item pairs if they exist
  result = []
  #
  begin
    unless the_dbid > 0
      raise ArgumentError, "dbid specified must be greater than zero"
    end
    case the_table
    when :element_text
      the_record = @connector[:element_text].select(:uuid, :dbid).where({:dbid => (the_dbid)}).first
      if the_record
        result << {:table => :element_text, :dbid => the_record[:dbid]}
        if everything
          the_pages = @connector[:text_page].select(:dbid, :ordinal).where({:parent_uuid => (the_record[:uuid])}).order(:ordinal)
          the_pages.each do |entry|
            result << {:table => :text_page, :dbid => entry[:dbid]}
          end
        end
      end
    when :element_binary
      the_record = @connector[:element_binary].select(:uuid, :dbid).where({:dbid => (the_dbid)}).first
      if the_record
        result << {:table => :element_binary, :dbid => the_record[:dbid]}
        if everything
          the_pages = @connector[:binary_page].select(:dbid, :ordinal).where({:parent_uuid => (the_record[:uuid])}).order(:ordinal)
          the_pages.each do |entry|
            result << {:table => :binary_page, :dbid => entry[:dbid]}
          end
        end
      end
    when :element_array, :element_hash
      record_db = [{:table => the_table, :dbid => the_dbid}]
      while record_db.size > 0 do
        item = record_db.shift
        case item[:table]
        when :element_text
          the_record = @connector[:element_text].select(:uuid, :dbid).where({:dbid => item[:dbid]}).first
          if the_record
            result << {:table => :element_text, :dbid => the_record[:dbid]}
            if everything
              the_pages = @connector[:text_page].select(:dbid, :ordinal).where({:parent_uuid => (the_record[:uuid])}).order(:ordinal)
              the_pages.each do |entry|
                result << {:table => :text_page, :dbid => entry[:dbid]}
              end
            end
          end
        when :element_binary
          the_record = @connector[:element_binary].select(:uuid, :dbid).where({:dbid => item[:dbid]}).first
          if the_record
            result << {:table => :element_binary, :dbid => the_record[:dbid]}
            if everything
              the_pages = @connector[:binary_page].select(:dbid, :ordinal).where({:parent_uuid => (the_record[:uuid])}).order(:ordinal)
              the_pages.each do |entry|
                result << {:table => :binary_page, :dbid => entry[:dbid]}
              end
            end
          end
        when :element_array
          result << {:table => item[:table], :dbid => item[:dbid]}
          array_record = @connector[:element_array].select(:uuid).where({:dbid => item[:dbid]}).first
          if array_record
            @connector[:array_elements].filter({:parent_uuid => (array_record[:uuid])}).order(:ordinal).each do |entry|
              if entry[:element_text_uuid].size > 0
                the_temp_record = @connector[:element_text].select(:dbid).where({:uuid => entry[:element_text_uuid]}).first
                if the_temp_record
                  record_db << {:table => :element_text, :dbid => the_temp_record[:dbid]}
                end
              end
              if entry[:element_binary_uuid].size > 0
                the_temp_record = @connector[:element_binary].select(:dbid).where({:uuid => entry[:element_binary_uuid]}).first
                if the_temp_record
                  record_db << {:table => :element_binary, :dbid => the_temp_record[:dbid]}
                end
              end
              if entry[:element_array_uuid].size > 0
                the_temp_record = @connector[:element_array].select(:dbid).where({:uuid => entry[:element_array_uuid]}).first
                if the_temp_record
                  record_db << {:table => :element_array, :dbid => the_temp_record[:dbid]}
                end
              end
              if entry[:element_hash_uuid].size > 0
                the_temp_record = @connector[:element_hash].select(:dbid).where({:uuid => entry[:element_hash_uuid]}).first
                if the_temp_record
                  record_db << {:table => :element_hash, :dbid => the_temp_record[:dbid]}
                end
              end
              result << {:table => :array_elements, :dbid => entry[:dbid]}
            end
          end
        when :element_hash
          result << {:table => item[:table], :dbid => item[:dbid]}
          hash_record = @connector[:element_hash].select(:uuid).where({:dbid => item[:dbid]}).first
          if hash_record
            @connector[:hash_properties].filter({:parent_uuid => (hash_record[:uuid])}).order(:ordinal).each do |entry|
              if entry[:element_text_uuid].size > 0
                the_temp_record = @connector[:element_text].select(:dbid).where({:uuid => entry[:element_text_uuid]}).first
                if the_temp_record
                  record_db << {:table => :element_text, :dbid => the_temp_record[:dbid]}
                end
              end
              if entry[:element_binary_uuid].size > 0
                the_temp_record = @connector[:element_binary].select(:dbid).where({:uuid => entry[:element_binary_uuid]}).first
                if the_temp_record
                  record_db << {:table => :element_binary, :dbid => the_temp_record[:dbid]}
                end
              end
              if entry[:element_array_uuid].size > 0
                the_temp_record = @connector[:element_array].select(:dbid).where({:uuid => entry[:element_array_uuid]}).first
                if the_temp_record
                  record_db << {:table => :element_array, :dbid => the_temp_record[:dbid]}
                end
              end
              if entry[:element_hash_uuid].size > 0
                the_temp_record = @connector[:element_hash].select(:dbid).where({:uuid => entry[:element_hash_uuid]}).first
                if the_temp_record
                  record_db << {:table => :element_hash, :dbid => the_temp_record[:dbid]}
                end
              end
              result << {:table => :hash_properties, :dbid => entry[:dbid]}
            end
          end
        else
          the_record = @connector[(item[:table])].select(:dbid).where({:dbid => (item[:dbid])}).first
          if the_record
            result << {:table => item[:table], :dbid => item[:dbid]}
          end
        end
      end
      #
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:table => (the_table), :dbid => (the_dbid)}})
  end
  result
end
element_parent_address(the_table=:unspecified, the_dbid=0) click to toggle source
# File lib/gxg/gxg_database.rb, line 2237
def element_parent_address(the_table=:unspecified, the_dbid=0)
  result = nil
  if self.element_in_use?(the_table,the_dbid)
    begin
      link = @connector[:hash_links].select(:parent_uuid).where({:element => (::GxG::Database::Database::element_table_index(the_table)), :elementid => (the_dbid)}).first
      if link
        record = @connector[:element_hash].select(:dbid).where({:uuid => link[:parent_uuid]}).first
        if record
          result = {:table => :element_hash, :dbid => (record[:dbid])}
        end
      else
        link = @connector[:array_links].select(:parent_uuid).where({:element => (::GxG::Database::Database::element_table_index(the_table)), :elementid => (the_dbid)}).first
        if link
          record = @connector[:element_array].select(:dbid).where({:uuid => link[:parent_uuid]}).first
          if record
            result = {:table => :element_array, :dbid => (record[:dbid])}
          end
        end
      end
    rescue Exception => the_error
      log_error({:error => the_error, :parameters => {:table => (the_table), :dbid => (the_dbid)}})
    end
  end
  result
end
element_permissions(table=:unspecified, dbid=0, options={}) click to toggle source

Raw Permission Handling methods

# File lib/gxg/gxg_database.rb, line 1345
def element_permissions(table=:unspecified, dbid=0, options={})
  result = []
  begin
    unless self.alive?
      raise Exception, "Database inactive"
    end
    unless self.open?
      raise Exception, "Database not available"
    end
    unless dbid.is_a?(::Integer)
      raise ArgumentError, "dbid must be specified with a Integer"
    end
    unless options.is_a?(::Hash)
      raise ArgumentError, "options must be specified with a Hash"
    end
    credential = options[:credential]
    if credential
      unless ::GxG::valid_uuid?(credential)
        raise ArgumentError, "This option requires a valid credential UUID (as a String or Symbol)"
      end
    end
    if table.is_a?(::Integer)
      table = ::GxG::Database::Database::element_table_by_index(table)
    end
    # Review : change in permission policy
    # if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :element_binary, :element_array, :element_hash].include?(table)
    if [:element_array, :element_hash].include?(table)
      if credential
        list = @connector[:permissions].filter({:element_table => (table.to_s), :elementid => (dbid), :credential => (credential.to_s)})
      else
        list = @connector[:permissions].filter({:element_table => (table.to_s), :elementid => (dbid)})
      end
      list.each do |record|
        # [:execute, :rename, :move, :destroy, :create, :write, :read]
        entry = {:credential => (record[:credential].to_sym), :table => (record[:element_table].to_sym), :dbid => (record[:elementid]), :permissions => {}}
        [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
          if record[(the_permission)] == 1
            entry[:permissions][(the_permission)] = true
          else
            entry[:permissions][(the_permission)] = false
          end
        end
        result << entry
      end
    else
      raise ArgumentError, "Invalid table specified"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:table => (table), :dbid => (dbid), :options => (options)}})
  end
  result
end
element_permissions_by_uuid(the_uuid=nil,options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 1458
def element_permissions_by_uuid(the_uuid=nil,options={})
  result = []
  begin
    if self.alive?
      if self.open?
        found = @connector[:element_hash].select(:dbid, :uuid).filter({:uuid => the_uuid.to_s}).first
        if found
          result = self.element_permissions_manifest(:element_hash,(found[:dbid]),options)
        else
          found = @connector[:element_array].select(:dbid, :uuid).filter({:uuid => the_uuid.to_s}).first
          if found
            result = self.element_permissions_manifest(:element_array,(found[:dbid]),options)
          end
        end
      end
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:uuid => (the_uuid)}})
  end
  result
end
element_permissions_manifest(table=:unspecified, dbid=0, options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 1431
def element_permissions_manifest(table=:unspecified, dbid=0, options={})
  result = []
  self.element_permissions(table,dbid,options).each do |entry|
    the_record = {:credential => nil, :permissions => {}, :details => {}}
    #
    the_record[:credential] = entry[:credential]
    the_record[:permissions] = entry[:permissions]
    if self.role_exist?(entry[:credential])
      role = self.role_fetch({:uuid => entry[:credential].to_s})
      group = self.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]
    else
      if self.user_exist?(entry[:credential])
        user = self.user_fetch({:uuid => entry[:credential].to_s})
        the_record[:details][:user_title] = user[:user_id]
      else
        log_warn("Invalid User Credential Detected: #{entry[:credential].to_s.to_sym.inspect}")
        the_record[:details][:user_title] = "Invalid User Credential #{entry[:credential].to_s.to_sym.inspect} !"
      end
    end
    result << the_record
  end
  result
end
element_recover(table=:unspecified, dbid=0) click to toggle source
# File lib/gxg/gxg_database.rb, line 3037
def element_recover(table=:unspecified, dbid=0)
  # recover an element from the trash
  result = false
  begin
    if self.alive?
      if self.open?
        if self.db_permissions()[:write]
          unless [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :element_binary, :element_array, :element_hash].include?(table)
            raise ArgumentError, "Invalid table specified"
          end
          unless dbid > 0
            raise ArgumentError, "dbid must be greater than zero"
          end
          if self.element_in_trash?(table, dbid)
            scrub_list = []
            manifest = self.element_manifest(table, dbid)
            manifest.each do |entry|
              if @connector[:trash].filter({:element_table => (entry[:table].to_s), :elementid => (entry[:dbid])}).count > 0
                record = @connector[:trash].select(:dbid).where({:element_table => (entry[:table].to_s), :elementid => (entry[:dbid])}).first
                if record
                  scrub_list << record[:dbid]
                end
              end
            end
            scrub_list.each do |entry|
              @connector[:trash].filter({:dbid => entry}).delete
            end
            result = true
          else
            # it was never in the trash, so mission accomplished
            result = true
          end
        end
      end
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:table => (table), :dbid => (dbid)}})
  end
  result
end
element_retrieve(the_table=:unspecified, the_filter={}, options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 2042
def element_retrieve(the_table=:unspecified, the_filter={}, options={})
  result = []
  begin
    if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :text_page, :element_binary,:binary_page, :element_array, :element_hash].include?(the_table)
      #
      if the_filter.is_a?(::Hash)
        if options[:order]
          raw_result = @connector[(the_table)].filter(the_filter).order(options[:order])
        else
          raw_result = @connector[(the_table)].filter(the_filter)
        end
        # Review : UTF-8 Encoding Error Fix
        if options[:single_record] == true
          result = raw_result.first
          # utf8 fix
          if the_table == :text_page
            if result[:content].is_a?(::String)
              if result[:content].base64?
                result[:content] = result[:content].decode64
              end
            end
          end
          #
        else
          # utf8 fix
          raw_result.each do |the_record|
            if the_record[:content].is_a?(::String)
              if the_record[:content].base64?
                the_record[:content] = the_record[:content].decode64
              end
            end
            result << the_record
          end
          # result = raw_result
        end
        #
      else
        raise ArguementError, "You MUST provide a record selection filter as a Hash. "
      end
    else
      raise ArgumentError, "The table specified is unknown - Check your code."
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:table => the_table, :filter => the_filter, :options => options}})
  end
  result
end
element_update(the_table=:unspecified, the_filter={}, the_record=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 2119
def element_update(the_table=:unspecified, the_filter={}, the_record=nil)
  result = false
  begin
    unless the_table.is_a?(::Symbol)
      raise ArgumentError, "You MUST provide the table specifier as a Symbol."
    end
    unless the_filter.is_a?(::Hash)
      raise ArgumentError, "You MUST provide a selection filter in the form of a Hash."
    end
    unless the_record.is_a?(::Hash)
      raise ArgumentError, "You MUST provide a record in the form of a Hash."
    end
    if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :text_page, :element_binary, :binary_page, :element_array, :element_hash].include?(the_table)
      # Review : shim to eliminate UTF-8 encoding errors
      begin
        @connector[(the_table)].filter(the_filter).update(the_record)
      rescue Exception
        if the_table == :text_page
          the_record[:content] = the_record[:content].encode64
        end
        @connector[(the_table)].filter(the_filter).update(the_record)
      end
      result = true
    else
      raise ArgumentError, "The table specified is unknown - Check your code."
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:table => the_table, :filter => the_filter, :record => the_record}})
  end
  result
end
empty_trash() click to toggle source
# File lib/gxg/gxg_database.rb, line 2986
def empty_trash()
  result = false
  begin
    if self.alive?
      if self.open?
        if self.db_permissions()[:write]
          scrub_list = []
          @connector[:trash].filter({}).each do |entry|
            the_table = entry[:element_table].to_sym
            the_dbid = entry[:elementid]
            if @connector[:element_locks].filter({:type => "write", :element_table => the_table.to_s, :elementid => the_dbid}).count == 0
              # delete full manifest
              manifest = self.element_manifest(the_table, the_dbid, true)
              manifest.each do |item|
                @connector[:permissions].filter({:element_table => (item[:table].to_s), :elementid => (item[:dbid])}).delete
                @connector[(item[:table])].filter({:dbid => item[:dbid]}).delete
              end
              scrub_list << entry[:dbid]
            end
          end
          scrub_list.each do |entry|
            @connector[:trash].filter({:dbid => entry}).delete
          end
          if @connector[:trash].filter({}).count == 0
            result = true
          end
        end
      end
    end
  rescue Exception => the_error
    log_error({:error => the_error})
  end
  result
end
enforce_permission_policy(event={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 3679
def enforce_permission_policy(event={})
  # Event format: enforce_permission_policy({:action => :extend, :credential => nil, :source => nil, :destination => nil})
  # Rule format: {:event => :create, :credential => :any, :action => {:extend_permissions => nil}}
  the_policy = self.permission_policy()
  result = false
  begin
    if self.alive?()
      if self.open?()
        actions = []
        the_policy.each do |rule|
          if event[:action] == rule[:event]
            if rule[:credential] == event[:credential] || rule[:credential] == :any
              actions << rule[:action]
            end
          end
        end
        actions.each do |action|
          case action.keys[0]
          when :extend_permissions
            if action[:use_permission].is_a?(::Hash)
              use_permission = action[:use_permission]
            else
              use_permission = nil
            end
            credential = event[:credential]
            unless ::GxG::valid_uuid?(credential)
              raise ArgumentError, "You MUST provide a valid UUID as :credential."
            end
            new_credential = action[:extend_permissions]
            source = event[:source]
            unless source.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
              raise ArgumentError, "You MUST provide a persisted object as :source."
            end
            unless source.db_address
              raise Exception, "You provided a Deactivated object as :source."
            end
            destination = event[:destination]
            unless destination.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
              raise ArgumentError, "You MUST provide a persisted object as :source."
            end
            unless destination.db_address
              raise Exception, "You provided a Deactivated object as :destination."
            end
            #
            permissions = self.element_permissions(source.db_address()[:table],source.db_address()[:dbid])
            permission_db = []
            if [:persisted_array, :persisted_hash].include?(destination.db_address()[:table])
              search_db = [{:table => destination.db_address()[:table], :dbid => destination.db_address()[:dbid]}]
              permission_db << {:table => destination.db_address()[:table], :dbid => destination.db_address()[:dbid]}
              while search_db.size > 0 do
                entry = search_db.shift
                self.element_manifest(entry[:table],entry[:dbid],false).each do |item|
                  if [:persisted_array, :persisted_hash].include?(item[:table])
                    search_db << item
                    permission_db << item
                  end
                end
              end
              permission_db.each do |the_reference|
                permissions.each do |record|
                  self.assign_element_permission(the_reference[:table],the_reference[:dbid], credential, record[:permissions])
                  if use_permission
                    self.assign_element_permission(the_reference[:table],the_reference[:dbid], new_credential, use_permission)
                  else
                    self.assign_element_permission(the_reference[:table],the_reference[:dbid], new_credential, record[:permissions])
                  end
                end
              end
              # destination.search do |the_value, the_selector, the_container|
              #   if [:persisted_array, :persisted_hash].include?(the_value.db_address()[:table])
              #     permission_db << {:table => the_value.db_address()[:table], :dbid => the_value.db_address()[:dbid]}
              #   end
              # end
              #
            end
            # permission_db << {:table => destination.db_address()[:table], :dbid => destination.db_address()[:dbid]}
            # if destination.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
            #   destination.search do |the_value, the_selector, the_container|
            #     permission_db << {:table => the_value.db_address()[:table], :dbid => the_value.db_address()[:dbid]}
            #   end
            # end
            # permission_db.each do |item|
            #   self.element_manifest(item[:table],item[:dbid],false).each do |entry|
            #     permissions.each do |record|
            #       self.assign_element_permission(entry[:table],entry[:dbid], credential, record[:permissions])
            #       if use_permission
            #         self.assign_element_permission(entry[:table],entry[:dbid], new_credential, use_permission)
            #       else
            #         self.assign_element_permission(entry[:table],entry[:dbid], new_credential, record[:permissions])
            #       end
            #     end
            #   end
            # end
            #
          end
        end
        result = true
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Attempted to access a defunct Database"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:event => event}})
  end
  result
end
extend_element_permissions(source_table=:unspecified, source_dbid=0, dest_table=:unspecified, dest_dbid=0) click to toggle source
# File lib/gxg/gxg_database.rb, line 1565
def extend_element_permissions(source_table=:unspecified, source_dbid=0, dest_table=:unspecified, dest_dbid=0)
  permissions = self.element_permissions(source_table, source_dbid)
  permissions.each do |entry|
    if [:persisted_array, :persisted_hash].include?(dest_table)
      self.assign_element_permission(dest_table, dest_dbid, entry[:credential], entry[:permissions])
    end
  end
end
format_create(format_record=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 3244
def format_create(format_record=nil)
  result = false
  begin
    if self.alive?()
      if self.open?
        unless self.db_permissions()[:write]
          raise Exception, "Unable to write to database"
        end
        if format_record.is_a?(::Hash)
          unless ::GxG::valid_uuid?(format_record[:uuid])
            raise Exception, "Invalid UUID passed for the format"
          end
          unless format_record[:type].is_any?([::String, ::Symbol])
            raise Exception, "You must pass the format_record[:type] as a String or Symbol"
          end
          unless format_record[:ufs].is_any?([::String, ::Symbol])
            raise Exception, "You must pass the format_record[:ufs] as a String or Symbol"
          end
          unless format_record[:title].is_a?(::String)
            raise Exception, "You must pass the format_record[:title] as a String"
          end
          unless format_record[:version].is_a?(::Float)
            raise Exception, "You must pass the format_record[:version] as a Float"
          end
          unless format_record[:mime_types].is_any?(::String, ::Array)
            raise Exception, "You must pass the format_record[:mime_types] as a String"
          end
          unless format_record[:content].is_a?(::Hash)
            raise Exception, "You must pass the format_record[:content] as a Hash"
          end
          unless self.persistable?(format_record[:content])
            raise Exception, "You must pass the format_record[:content] as a Hash of persistable elements"
          end
          if (@connector[:settings].filter({:uuid => format_record[:uuid].to_s}).count == 0 and @connector[:formats].filter({:uuid => format_record[:uuid].to_s}).count == 0 and @connector[:element_text].filter({:uuid => format_record[:uuid].to_s}).count == 0)
            new_record = {:uuid => (format_record[:uuid].to_s)}
            new_record[:type] = format_record[:type].to_s
            new_record[:ufs] = format_record[:ufs].to_s
            new_record[:title] = format_record[:title].to_s[0..256]
            new_record[:version] = format_record[:version]
            if format_record[:mime_types].is_a?(::Array)
              the_mimes = format_record[:mime_types].join(",").to_s[0..4096]
            else
              the_mimes = format_record[:mime_types].to_s[0..4096]
            end
            new_record[:mime_types] = the_mimes
            content = format_record[:content].gxg_export.to_json.encode64
            new_dbid = @connector[:formats].insert(new_record)
            if content.size > 0
              ::GxG::apportioned_ranges(content.size, 4096).each_with_index do |portion, ordinal|
                @connector[:text_page].insert({:parent_uuid => (new_record[:uuid].to_s), :ordinal => (ordinal), :length => (content[(portion)].size), :content => (content[(portion)])})
              end
            end
            if new_dbid
              result = true
            end
          else
            raise Exception, "That format UUID is already in use, please generate another"
          end
          #
        else
          raise ArgumentError, "You must supply a valid format record as a Hash"
        end
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Attempted to access a defunct Database"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:format_record => (format_record)}})
  end
  result
end
format_destroy(search_options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 3452
def format_destroy(search_options={})
  result = false
  begin
    if self.alive?()
      if self.open?
        unless self.db_permissions()[:write]
          raise Exception, "Unable to write to database"
        end
        format_stub = self.format_list(search_options).first
        if format_stub
          @connector[:formats].filter({:uuid => (format_stub[:uuid].to_s)}).delete
          if @connector[:text_page].filter({:parent_uuid => (format_stub[:uuid].to_s)}).count > 0
            @connector[:text_page].filter({:parent_uuid => (format_stub[:uuid].to_s)}).delete
          end
          result = true
        end
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Attempted to access a defunct Database"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:search_options => (search_options)}})
  end
  result
end
format_list(search_options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 3112
def format_list(search_options={})
  result = []
  begin
    if self.alive?
      if self.open?
        unless search_options.is_a?(::Hash)
          raise ArgumentError, "You must specify search options as a Hash"
        end
        the_filter = {}
        if search_options[:uuid]
          the_filter[:uuid] = search_options[:uuid].to_s
        end
        if search_options[:type]
          the_filter[:type] = search_options[:type].to_s
        end
        if search_options[:ufs]
          the_filter[:ufs] = search_options[:ufs].to_s[0..4096]
        end
        if search_options[:title]
          the_filter[:title] = search_options[:title].to_s[0..256]
        end
        if search_options[:version].is_a?(::Float)
          the_filter[:version] = search_options[:version]
        end
        mime_type = search_options[:mime_type].to_s
        if mime_type.size > 0
          @connector[:formats].filter(the_filter).where(::Sequel.like(:mime_types, ("%" + mime_type + "%"))).order(::Sequel[:version].desc).each do |entry|
            result << {:uuid => entry[:uuid].to_sym, :type => entry[:type].to_sym, :ufs => entry[:ufs].to_sym, :title => entry[:title], :version => entry[:version]}
          end
        else
          @connector[:formats].filter(the_filter).order(::Sequel[:version].desc).each do |entry|
            result << {:uuid => entry[:uuid].to_sym, :type => entry[:type].to_sym, :ufs => entry[:ufs].to_sym, :title => entry[:title], :version => entry[:version]}
          end
        end
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Attempted to access a defunct Database"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:search_options => (search_options)}})
  end
  result
end
format_load(search_options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 3158
def format_load(search_options={})
  result = nil
  begin
    if self.alive?()
      if self.open?
        format_stub = self.format_list(search_options).first
        if format_stub
          format_record = @connector[:formats].filter({:uuid => (format_stub[:uuid].to_s)}).first
          if format_record
            content = ""
            @connector[:text_page].filter({:parent_uuid => (format_stub[:uuid].to_s)}).order(:ordinal).each do |entry|
              content << entry[:content]
            end
            format_record.delete(:dbid)
            format_record[:ufs] = format_stub[:ufs]
            format_record[:type] = format_stub[:type]
            if content.size > 0
              if content.base64?
                content = content.decode64
              end
              if content.json?
                content = ::JSON::parse(content.to_s, {:symbolize_names => true})
              end
              if content[:type]
                content = ::Hash.gxg_import(content)
              end
              format_record[:content] = content
            else
              format_record[:content] = nil
            end
            #
            if format_record[:mime_types].size > 0
              if format_record[:mime_types].include?(",")
                format_record[:mime_types] = format_record[:mime_types].split(",")
              else
                format_record[:mime_types] = [(format_record[:mime_types])]
              end
            end
            #
            result = format_record
          end
        end
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Attempted to access a defunct Database"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:search_options => (search_options)}})
  end
  result
end
format_template(type=:structure) click to toggle source

Format handing methods

# File lib/gxg/gxg_database.rb, line 3078
def format_template(type=:structure)
  result = nil
  begin
    if self.alive?
      if self.open?
        unless type.is_any?(::String, ::Symbol)
          raise ArgumentError, "You must supply a type as a String or Symbol:  :structure or :binary"
        end
        the_uuid = ::GxG::uuid_generate()
        while (@connector[:formats].filter({:uuid => (the_uuid)}).count > 0 or @connector[:element_text].filter({:uuid => (the_uuid)}).count > 0)
          the_uuid = ::GxG::uuid_generate()
        end
        result = {:uuid => (the_uuid.to_sym), :type => (type.to_s), :ufs => "unspecified", :title => "", :version => 0.0, :mime_types => [], :content => nil}
        case type
        when :structure
          result[:content] = {}
        when :binary
          result[:content] = {:sample_size => 0, :recognition => "", :import => "", :export => ""}
        else
          raise Exception, "Invalid format type specified: #{type.inspect}.  Use :structure or :binary"
        end
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Attempted to access a defunct Database"
    end
  rescue Exception => the_error
    result = nil
    log_error({:error => the_error, :parameters => {:type => (type)}})
  end
  result
end
format_update(format_record=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 3318
def format_update(format_record=nil)
  format_record = format_record.clone
  result = false
  begin
    if self.alive?()
      if self.open?
        unless self.db_permissions()[:write]
          raise Exception, "Unable to write to database"
        end
        if format_record.is_a?(::Hash)
          unless ::GxG::valid_uuid?(format_record[:uuid])
            raise Exception, "Invalid UUID passed for the format"
          end
          record = @connector[:formats].filter({:uuid => format_record[:uuid].to_s}).first
          if record
            format_update = {}
            record.keys.each do |the_key|
              if [:type, :ufs, :title, :version, :mime_types].include?(the_key)
                case the_key
                when :type
                  unless format_record[:type].is_any?(::String, ::Symbol)
                    raise Exception, "You must pass the format_record[:type] as a String or Symbol"
                  end
                when :ufs
                  unless format_record[:ufs].is_any?(::String, ::Symbol)
                    raise Exception, "You must pass the format_record[:ufs] as a String or Symbol"
                  end
                when :title
                  unless format_record[:title].is_a?(::String)
                    raise Exception, "You must pass the format_record[:title] as a String"
                  end
                when :version
                  unless format_record[:version].is_a?(::Float)
                    raise Exception, "You must pass the format_record[:version] as a Float"
                  end
                when :mime_types
                  unless format_record[:mime_types].is_any?(::String, ::Array)
                    raise Exception, "You must pass the format_record[:mime_types] as a String"
                  end
                end
                #
                if the_key == :mime_types
                  if format_record[:mime_types].is_a?(::Array)
                    the_mimes = format_record[:mime_types].join(",").to_s[0..4096]
                  else
                    the_mimes = format_record[:mime_types].to_s[0..4096]
                  end
                  format_record[:mime_types] = the_mimes
                end
                #
                if format_record[(the_key)] != record[(the_key)]
                  format_update[(the_key)] = format_record[(the_key)]
                end
              end
            end                  
            if format_update.keys.size > 0
              # FIXME: :type and :ufs are being passed as a Symbols, but DB requires them to be a strings:
              if format_update[:type].is_a?(::Symbol)
                format_update[:type] = format_update[:type].to_s
              end
              if format_update[:ufs].is_a?(::Symbol)
                format_update[:ufs] = format_update[:ufs].to_s
              end
              @connector[:formats].filter({:uuid => format_record[:uuid].to_s}).update(format_update)
            end
            if format_record[:content].is_a?(::Hash)
              unless self.persistable?(format_record[:content])
                raise Exception, "You must pass the format_record[:content] as a Hash of persistable elements"
              end
              old_segments = []
              content = format_record[:content].gxg_export.to_json.encode64
              @connector[:text_page].select(:dbid).where({:parent_uuid => format_record[:uuid].to_s}).order(:ordinal).each do |entry|
                old_segments << entry[:dbid]
              end
              if content.size == 0
                if old_segments.size > 0
                  @connector[:text_page].filter({:parent_uuid => format_record[:uuid].to_s}).delete
                end
              else
                new_segments = ::GxG::apportioned_ranges(content.size, 4096)
                if old_segments.size > new_segments.size
                  the_count = old_segments.size
                else
                  the_count = new_segments.size
                end
                manifest = []
                (0..(the_count - 1)).each do |the_ordinal|
                  if new_segments[(the_ordinal)] and old_segments[(the_ordinal)]
                    #overwrite with new segment range
                    manifest << {:operation => :overwrite, :dbid => (old_segments[(the_ordinal)]), :ordinal => (the_ordinal), :portion => (new_segments[(the_ordinal)])}
                  else
                    if new_segments[(the_ordinal)]
                      # create new segment at this ordinal
                      manifest << {:operation => :create, :ordinal => (the_ordinal), :portion => (new_segments[(the_ordinal)])}
                    else
                      # delete old segment
                      manifest << {:operation => :delete, :dbid => (old_segments[(the_ordinal)])}
                    end
                  end
                end
                manifest.each do |action|
                  case action[:operation]
                  when :overwrite
                    @connector[:text_page].filter({:dbid => (action[:dbid])}).update({:ordinal => (action[:ordinal]), :length => (content[(action[:portion])].size), :content => (content[(action[:portion])])})
                  when :create
                    @connector[:text_page].insert({:parent_uuid => (record[:uuid]), :ordinal => (action[:ordinal]), :length => (content[(action[:portion])].size), :content => (content[(action[:portion])])})
                  when :delete
                    @connector[:text_page].filter({:dbid => (action[:dbid])}).delete
                  end
                end
                @connector[:formats].filter({:uuid => format_record[:uuid].to_s}).update({:version => (format_record[:version].to_f + 0.00001)})
                #
              end
            end
            #
            result = true
          else
            result = self.format_create(format_record)
          end
        else
          raise ArgumentError, "You must supply a valid format record as a Hash"
        end
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Attempted to access a defunct Database"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:format_record => (format_record)}})
  end
  result
end
group_create(options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 1177
def group_create(options={})
  result = nil
  if @authority
    result = @authority.group_create(options)
  else
    if self.alive?
      if self.open?
        if self.db_permissions()[:write]
          begin
            unless options.is_a?(::Hash)
              raise ArgumentError, "Options must be passed as a Hash"
            end
            #
            title = (options[:title] || "Untitled Group")
            seo = (options[:seo] || title.downcase.gsub(" ", "_"))
            if options[:default_role].is_a?(::Hash)
              role_title = (options[:default_role][:title] || (title + " Members"))
              role_seo = (options[:default_role][:seo] || role_title.downcase.gsub(" ", "_"))
            else
              role_title = (title + " Members")
              role_seo = role_title.downcase.gsub(" ", "_")
            end
            #
            the_uuid = ::GxG::uuid_generate()
            while (@connector[:groups].filter({:uuid => (the_uuid.to_s)}).count > 0)
              the_uuid = ::GxG::uuid_generate()
            end
            @connector[:groups].insert({:uuid => (the_uuid.to_s), :title => (title.to_s), :seo => (seo.to_s)})
            role_uuid = self.role_create(the_uuid, role_title, role_seo)
            if role_uuid
              @connector[:groups].filter({:uuid => (the_uuid.to_s)}).update({:default_role => (role_uuid.to_s)})
              result = {:group => the_uuid.to_sym, :default_role => role_uuid.to_sym}
            else
              @connector[:groups].filter({:uuid => (the_uuid.to_s)}).delete
              raise Exception, "Could not create default role for group.  Aborting."
            end
          rescue Exception => the_error
            log_error({:error => the_error, :parameters => {:options => (options)}})
          end
        end
      end
    end
  end
  result
end
group_credential(details={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 1308
def group_credential(details={})
  result = nil
  if @authority
    result = @authority.group_credential(details)
  else
    begin
      unless self.alive?
        raise Exception, "Database inactive"
      end
      unless self.open?
        raise Exception, "Database not available"
      end
      unless details.is_any?(::Hash, ::GxG::Database::PersistedHash)
        raise ArgumentError, "group and role specifiers must be provided within a Hash or PeristedHash"
      end
      #
      if details[:group].is_a?(::String)
        group_record = self.group_fetch({:title => details[:group]})
        if group_record
          role_title_specified = (details[:role] || (group_record[:title].to_s + " Members")).to_s
          group_roles = self.group_roles(group_record[:uuid].to_sym)
          group_roles.each do |role_profile|
            if role_profile[:title] == role_title_specified
              result = role_profile[:uuid].to_s.to_sym
              break
            end
          end
        end
      end
      #
    rescue Exception => the_error
      log_error({:error => the_error, :parameters => {:details => (details)}})
    end
  end
  result
end
group_delete(group_uuid=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 1275
def group_delete(group_uuid=nil)
  result = false
  if @authority
    result = @authority.group_delete(group_uuid)
  else
    if self.alive?
      if self.open?
        if self.db_permissions()[:write]
          begin
            if ::GxG::valid_uuid?(group_uuid)
              record = @connector[:groups].filter({:uuid => (group_uuid.to_s)}).first
              if record
                @connector[:groups].filter({:uuid => (group_uuid.to_s)}).update({:default_role => "__role_deleted__"})
                role_list = @connector[:roles].select(:uuid).where({:group_uuid => (group_uuid.to_s)})
                role_list.each do |role|
                  self.role_destroy(role[:uuid].to_sym)
                end
                @connector[:groups].filter({:uuid => (group_uuid.to_s)}).delete
              end
              result = true
            else
              raise ArgumentError, "You must specify a valid group UUID (as a String or Symbol)"
            end
          rescue Exception => the_error
            log_error({:error => the_error, :parameters => {:group_uuid => (group_uuid)}})
          end
        end
      end
    end
  end
  result
end
group_exist?(the_specifier=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 1090
def group_exist?(the_specifier=nil)
  result = nil
  if @authority
    result = @authority.group_exist?(the_specifier)
  else
    if self.alive?
      if self.open?
        if GxG::valid_uuid?(the_specifier)
          # uuid search
          the_filter = {:uuid => the_specifier.to_s}
        else
          # title search
          the_filter = {:title => the_specifier.to_s}
        end
        if @connector[:groups].filter(the_filter).count > 0
          result = true
        end
      end
    end
  end
  result
end
group_fetch(search_options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 1113
def group_fetch(search_options={})
  result = nil
  if @authority
    result = @authority.group_fetch(search_options)
  else
    if self.alive?
      if self.open?
        begin
          record = @connector[:groups].filter(search_options).first
          if record
            result = record
          end
        rescue Exception => the_error
          log_error({:error => the_error, :parameters => {:options => (search_options)}})
        end
      end
    end
  end
  result
end
group_manifest() click to toggle source
# File lib/gxg/gxg_database.rb, line 1134
def group_manifest()
  result = {}
  if @authority
    result = @authority.group_manifest()
  else
    if self.alive?
      if self.open?
        # intitialize result tree
        @connector[:groups].filter({:parent_uuid => ""}).each do |the_group|
          # dbid, uuid, parent_uuid, default_role, seo, title, version
          result[(the_group[:uuid].to_s.to_sym)] = {:title => the_group[:title], :seo => the_group[:seo], :version => the_group[:version], :groups => {}, :roles => {}}
        end
        # flesh out tree
        build_list = result.keys
        while build_list.size > 0 do
          group_uuid = build_list.shift
          if group_uuid
            the_group = nil
            result.search do |item, selector, container|
              if selector == group_uuid
                the_group = item
                break
              end
            end
            if the_group
              @connector[:groups].filter({:parent_uuid => group_uuid.to_s}).each do |subgroup|
                the_group[:groups][(subgroup[:uuid].to_s.to_sym)] = {:title => subgroup[:title], :seo => subgroup[:seo], :version => subgroup[:version], :groups => {}, :roles => {}}
                build_list << subgroup[:uuid].to_s.to_sym
              end
              @connector[:roles].filter({:group_uuid => group_uuid.to_s}).each do |the_role|
                the_group[:roles][(the_role[:uuid].to_s.to_sym)] = {:title => the_role[:title], :seo => the_role[:seo], :version => the_role[:version]}
              end
            end
            #
          end
        end
        #
      end
    end
  end
  result
end
group_roles(group_uuid=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 1076
def group_roles(group_uuid=nil)
  result = []
  if @authority
      result = @authority.group_roles(group_uuid)
  else
      if ::GxG::valid_uuid?(group_uuid)
          @connector[:roles].filter(:group_uuid => group_uuid).each do |the_entry|
              result << {:role => (the_entry[:title]), :uuid => (the_entry[:uuid])}
          end
      end
  end
  result
end
group_update(group_uuid=nil, options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 1223
def group_update(group_uuid=nil, options={})
  result = false
  if @authority
    result = @authority.group_update(group_uuid, options)
  else
    if self.alive?
      if self.open?
        if self.db_permissions()[:write]
          begin
            if ::GxG::valid_uuid?(group_uuid)
              unless options.is_a?(::Hash)
                raise ArgumentError, "Options must be passed as a Hash"
              end
              title = options[:title]
              seo = options[:seo]
              if title.is_a?(::String) or seo.is_a?(::String) or ::GxG::valid_uuid?(options[:default_role]) or ::GxG::valid_uuid?(options[:parent_uuid])
                the_update = {}
                if title
                  the_update[:title] = title.to_s[0..255]
                end
                if seo
                  the_update[:seo] = seo.to_s[0..255]
                end
                if options[:default_role]
                  the_update[:default_role] = options[:default_role].to_s[0..36]
                end
                if options[:parent_uuid]
                  the_update[:parent_uuid] = options[:parent_uuid].to_s[0..36]
                end
                record = @connector[:groups].select(:version).where({:uuid => (group_uuid.to_s)}).first
                if record
                  the_update[:version] = (record[:version] + 0.0001)
                else
                  log_warn("Could not update version for group #{group_uuid}")
                end
                @connector[:groups].filter({:uuid => (group_uuid.to_s)}).update(the_update)
                # Review : BE SURE to also update the title of the default "<group-title> Members" role.
                result = true
              end
            else
              raise ArgumentError, "You must specify a valid group UUID (as a String or Symbol)"
            end
          rescue Exception => the_error
            log_error({:error => the_error, :parameters => {:group_uuid => (group_uuid), :options => (options)}})
          end
        end
      end
    end
  end
  result
end
import(credential=nil, the_record=nil) click to toggle source

Import methods (deprecated in favor of sychronize_records)

# File lib/gxg/gxg_database.rb, line 3788
def import(credential=nil, the_record=nil)
  #
  result = nil
  if self.alive?
    if self.open?
      if self.db_permissions()[:write]
        cleanup_manifest = []
        begin
          unless ::GxG::valid_uuid?(credential)
            raise ArgumentError, "You must supply a valid credential UUID (as a String or Symbol)"
          end
          if the_record.is_a?(::Hash)
            case the_record[:type]
            when :element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime
              new_dbid = @connector[(the_record[:type])].insert({:version => (the_record[:version]), :content => (the_record[:content])})
              self.assign_element_permission((the_record[:type]), (new_dbid), credential, {:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true})
              result = {:table => (the_record[:table]), :dbid => (new_dbid)}
            when :element_text
              the_uuid = ::GxG::uuid_generate()
              while (@connector[:element_text].filter({:uuid => the_uuid}).count > 0)
                the_uuid = ::GxG::uuid_generate()
              end
              new_dbid = @connector[:element_text].insert({:uuid => (the_uuid), :version => (the_record[:version]), :length => (the_record[:content].size)})
              cleanup_manifest << {:table => :element_text, :dbid => (new_dbid)}
              ::GxG::apportioned_ranges(the_record[:content].size, 4096).each_with_index do |the_range,the_ordinal|  
                @connector[:text_page].insert({:parent_uuid => (the_uuid), :ordinal => (the_ordinal), :length => (the_record[:content][(the_range)].size), :content => (the_record[:content][(the_range)])})
              end
              self.assign_element_permission((the_record[:type]), (new_dbid), credential, {:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true})
              result = {:table => :element_text, :dbid => (new_dbid)}
            when :element_binary
              the_uuid = ::GxG::uuid_generate()
              while (@connector[:element_binary].filter({:uuid => the_uuid}).count > 0)
                the_uuid = ::GxG::uuid_generate()
              end
              new_dbid = @connector[:element_binary].insert({:uuid => (the_uuid), :version => (the_record[:version]), :length => (the_record[:content].size)})
              cleanup_manifest << {:table => :element_binary, :dbid => (new_dbid)}
              ::GxG::apportioned_ranges(the_record[:content].size, 65536).each_with_index do |the_range,the_ordinal|  
                @connector[:binary_page].insert({:parent_uuid => (the_uuid), :ordinal => (the_ordinal), :length => (the_record[:content].data()[(the_range)].size), :content => (the_record[:content].data()[(the_range)])})
              end
              self.assign_element_permission((the_record[:type]), (new_dbid), credential, {:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true})
              result = {:table => :element_binary, :dbid => (new_dbid)}
            when :element_array
              # {:type => :element_array, :uuid => @uuid, :title => @title, :version => @version, :content => []}
              existing = @connector[(the_record[:type])].select(:dbid, :version).where({:uuid => the_record[:uuid].to_s}).first
              if existing
                if the_record[:version] > existing[:version]
                  unless self.element_destroy(credential, :element_array, existing[:dbid])
                    raise Exception, "Error replacing array element - Aborting"
                  end
                  existing = nil
                else
                  log_warn("Import record is older than existing one - Skipping")
                  new_dbid = existing[:dbid]
                end
              end
              unless existing
                new_dbid = @connector[(the_record[:type])].insert({:uuid => (the_record[:uuid].to_s), :title => (the_record[:title]), :version => (the_record[:version])})
                cleanup_manifest << {:table => :element_array, :dbid => (new_dbid)}
                self.assign_element_permission(:element_array, (new_dbid), credential, {:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true})
                the_record[:content].each_with_index do |element, indexer|
                  new_address = self.import(credential, (element))
                  if new_address
                    cleanup_manifest << new_address
                    @connector[:array_links].insert({:parent_uuid => (the_record[:uuid].to_s), :ordinal => (indexer), :element => (::GxG::Database::Database::element_table_index(new_address[:table])), :elementid => new_address[:dbid]})
                  else
                    raise Exception, "Error processing the import record - Aborting"
                  end
                end
              end
              result = {:table => :element_array, :dbid => (new_dbid)}
            when :element_hash
              # {:type => :element_hash, :uuid => @uuid, :title => @title, :version => @version, :format => @format, :content => {}}
              existing = @connector[(the_record[:type])].select(:dbid, :version).where({:uuid => the_record[:uuid].to_s}).first
              if existing
                if the_record[:version] > existing[:version]
                  unless self.element_destroy(credential, :element_hash, existing[:dbid])
                    raise Exception, "Error replacing hash element - Aborting"
                  end
                  existing = nil
                else
                  log_warn("Import record is older than existing one - Skipping")
                  new_dbid = existing[:dbid]
                end
              end
              unless existing
                new_dbid = @connector[(the_record[:type])].insert({:uuid => (the_record[:uuid].to_s), :title => (the_record[:title]), :version => (the_record[:version]), :format => (the_record[:format].to_s)})
                cleanup_manifest << {:table => :element_hash, :dbid => (new_dbid)}
                self.assign_element_permission(:element_hash, (new_dbid), credential, {:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true})
                the_record[:content].keys.each_with_index do |the_key, indexer|
                  new_address = self.import(credential, (the_record[:content][(the_key)]))
                  if new_address
                    cleanup_manifest << new_address
                    @connector[:hash_links].insert({:parent_uuid => (the_record[:uuid].to_s), :property => (the_key.to_s), :ordinal => (indexer), :element => (::GxG::Database::Database::element_table_index(new_address[:table])), :elementid => new_address[:dbid]})
                  else
                    raise Exception, "Error processing the import record - Aborting"
                  end
                end
              end
              result = {:table => :element_hash, :dbid => (new_dbid)}
            else
              raise ArgumentError, "Invalid table specified"
            end
          else
            raise ArgumentError, "You must supply an import record as a Hash"
          end
        rescue Exception => the_error
          # clean up
          cleanup_manifest.each do |entry|
            self.element_destroy(credential, entry[:table], entry[:dbid])
          end
          log_error({:error => the_error, :parameters => {:the_record => (the_record)}})
        end
      else
        log_warn("Cannot import records into a read-only Database - Aborting")
      end
    end
  end
  result
end
initialize_clone() click to toggle source

Comm objects cannot be cloned - returns nil

# File lib/gxg/gxg_database.rb, line 5102
def initialize_clone
  nil
end
Also aliased as: initialize_dup, dup
initialize_dup()
Alias for: initialize_clone
inspect() click to toggle source
# File lib/gxg/gxg_database.rb, line 431
def inspect()
  "<Database: #{this().to_uri()}>"
end
iterative_persist(old_root=nil, credential=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 2558
def iterative_persist(old_root=nil, credential=nil)
  # New PersistedArray, or PersistedHash interface:
  # mount element: {:database => <database>, :uuid => <uuid>, :credential => <uuid>, :delegate => nil/<uuid>, :parent => nil/<an-object>}
  # create element: {:database => <database>, :credential => <uuid>, :delegate => nil/<uuid>, :parent => nil/<an-object>}
  #
  result = nil
  begin
    # db open?
    # write permissions on db?
    unless ::GxG::valid_uuid?(credential)
      raise ArgumentError, "You MUST provide a valid UUID as a credential."
    end
    unless old_root.is_any?(::Array, ::Hash)
      raise ArgumentError, "You MUST provide either an Array or a Hash."
    end
    unless self.persistable?(old_root)
      raise ArgumentError, "The object you are attempting to persist contains a non-persistable item."
    end
    if old_root.is_a?(::Array)
      original_partner = ::GxG::Database::PersistedArray.new({:database => self, :credential => credential})
      original_partner.get_reservation()
      self.enforce_permission_policy({:action => :extend, :credential => credential, :source => original_partner, :destination => original_partner})
      #
    end
    if old_root.is_a?(::Hash)
      original_partner = ::GxG::Database::PersistedHash.new({:database => self, :credential => credential})
      original_partner.get_reservation()
      self.enforce_permission_policy({:action => :extend, :credential => credential, :source => original_partner, :destination => original_partner})
    end
    if old_root.is_any?(::GxG::Database::PersistedArray, ::GxG::Database::PersistedHash)
      # TODO: support subsuming already persisted objects.
    end
    paring_data = [{:parent => nil, :parent_selector => nil, :object => old_root, :partner => original_partner}]
    children_of = Proc.new do |the_parent=nil|
      list = []
      paring_data.each do |node|
        if node[:parent].object_id == the_parent.object_id
          list << node
        end
      end
      list
    end
    #
    parent_of = Proc.new do |the_parent=nil|
      output = nil
      paring_data.each do |entry|
        if entry[:object].object_id == the_parent.object_id
          output = entry
        end
      end
      output
    end
    find_partner = Proc.new do |the_object|
      found_partner = nil
      paring_data.each do |the_record|
        if the_record.is_a?(::Hash)
          if the_record[:object].object_id == the_object.object_id
            found_partner = the_record[:partner]
            break
          end
        end
      end
      found_partner
    end
    # build paring data:
    delegate_permission = nil
    old_root.search do |the_value, the_selector, the_container|
      if the_value.is_a?(::Array)
        paring_data << {:parent => the_container, :parent_selector => the_selector, :object => the_value, :partner => ::GxG::Database::PersistedArray.new({:database => self, :credential => credential})}
      else
        if the_value.is_a?(::Hash)
          paring_data << {:parent => the_container, :parent_selector => the_selector, :object => the_value, :partner => ::GxG::Database::PersistedHash.new({:database => self, :credential => credential})}
        else
          paring_data << {:parent => the_container, :parent_selector => the_selector, :object => the_value, :partner => the_value}
        end
      end
    end
    # Assign objects to structure in order by parent / parent_selector
    link_db = [(paring_data[0])]
    while link_db.size > 0
      entry = link_db.shift
      if entry.is_a?(::Hash)
        if entry[:object].is_any?(::Array, ::Hash)
          # get children and assign
          children = children_of.call(entry[:object])
          children.each do |child|
            entry[:partner][(child[:parent_selector])] = child[:partner]
            if child[:partner].is_any?(::GxG::Database::PersistedArray, ::GxG::Database::PersistedHash)
              link_db << child
            end
          end
        end
      end
    end
    result = original_partner
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:object => old_root, :credential => credential}})
  end
  result
end
new_structure_from_format(credential=nil, search_options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 3212
def new_structure_from_format(credential=nil, search_options={})
  result = nil
  begin
    if self.alive?()
      if self.open?
        unless ::GxG::valid_uuid?(credential)
          raise ArgumentError, "You must supply a valid credential UUID (as a String or Symbol)"
        end
        format = self.format_load(search_options)
        if format
          # TODO: add support for :binary formats.
          unless format[:type] == :structure
            raise Exception, "Only formats of type :structure are supported"
          end
          result = self.try_persist(format[:content], credential)
          if result.is_a?(::GxG::Database::PersistedHash)
            result.set_format(format[:uuid].to_sym)
            @connector[:element_hash].filter({:uuid => result.uuid.to_s}).update({:format => format[:uuid].to_s})
          end
        end
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Attempted to access a defunct Database"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:search_options => (search_options)}})
  end
  result
end
open?() click to toggle source
# File lib/gxg/gxg_database.rb, line 403
def open?()
  begin
    @connector.synchronize do |connection|
      @active = @connector.valid_connection?(connection)
    end
  rescue => the_error
    @active = false
    log_error({:error => the_error, :parameters => nil})
  end
  @active
end
permission_policy() click to toggle source

Permission policy support:

# File lib/gxg/gxg_database.rb, line 3611
def permission_policy()
  result = nil
  begin
    if self.alive?()
      if self.open?()
        if @authority
          result = @authority.permission_policy()
        else
          result = @permission_policy
        end
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Attempted to access a defunct Database"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {}})
  end
  result
end
permission_policy_load() click to toggle source
# File lib/gxg/gxg_database.rb, line 3633
def permission_policy_load()
  result = false
  begin
    if self.alive?()
      if self.open?()
        if @authority
          result = @authority.permission_policy_load()
        else
          @permission_policy = (self[:permission_policy] || [])
          result = true
        end
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Attempted to access a defunct Database"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {}})
  end
  result
end
permission_policy_save() click to toggle source
# File lib/gxg/gxg_database.rb, line 3656
def permission_policy_save()
  result = false
  begin
    if self.alive?()
      if self.open?()
        if @authority
          result = @authority.permission_policy_save()
        else
          self[:permission_policy] = (@permission_policy || [])
          result = true
        end
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Attempted to access a defunct Database"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {}})
  end
  result
end
persistable?(the_object) click to toggle source
# File lib/gxg/gxg_database.rb, line 2536
def persistable?(the_object)
  result = true
  unless the_object.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
    if the_object.is_any?(::Hash, ::Array)
      the_object.search do |item, selector, container|
        if result
          if ::GxG::Database::Database::element_table_for_instance(item) == :unspecified
            result = false
            break
          end
        end
        nil
      end
    else
      if ::GxG::Database::Database::element_table_for_instance(the_object) == :unspecified
        result = false
      end
    end
  end
  result
end
release_element_locks(reservation_uuid=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 2878
def release_element_locks(reservation_uuid=nil)
  result = false
  begin
    if self.alive?
      if self.open?
        unless ::GxG::valid_uuid?(reservation_uuid)
          raise ArgumentError, "You must supply a valid reservation UUID (as a String or Symbol) to release locks"
        end
        if self.db_permissions()[:write]
          @connector[:element_locks].filter({:reservation => reservation_uuid.to_s}).delete
        end
        # on read-only db, no reservation was made so mission accomplished
        result = true
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Database not available (defunct)"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:reservation => (reservation_uuid)}})
  end
  result
end
remove_element_permissions(table=:unspecified, dbid=0, options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 1574
def remove_element_permissions(table=:unspecified, dbid=0, options={})
  result = false
  begin
    unless self.alive?
      raise Exception, "Database inactive"
    end
    unless self.open?
      raise Exception, "Database not available"
    end
    unless dbid.is_a?(::Integer)
      raise ArgumentError, "dbid must be specified with a Integer"
    end
    unless options.is_a?(::Hash)
      raise ArgumentError, "permissions must be specified with a Hash"
    end
    credential = options[:credential]
    if credential
      unless ::GxG::valid_uuid?(credential)
        raise ArgumentError, "You must specify a valid credential UUID (as a String or Symbol)"
      end
    end
    if table.is_a?(::Integer)
      table = ::GxG::Database::Database::element_table_by_index(table)
    end
    # Review : change in permission policy
    # if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :element_binary, :element_array, :element_hash].include?(table)
    if [:element_array, :element_hash].include?(table)
      if credential
        @connector[:permissions].filter({:element_table => (table.to_s), :elementid => (dbid), :credential => (credential.to_s)}).delete
      else
        @connector[:permissions].filter({:element_table => (table.to_s), :elementid => (dbid)}).delete
      end
      result = true
    else
      raise ArgumentError, "Invalid table specified"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:table => (table), :dbid => (dbid), :options => (options)}})
  end
  result
end
reservation_add_element(reservation_uuid=nil, table=:unspecified, dbid=0) click to toggle source
# File lib/gxg/gxg_database.rb, line 2903
def reservation_add_element(reservation_uuid=nil, table=:unspecified, dbid=0)
  result = false
  #
  begin
    if self.alive?
      if self.open?
        unless ::GxG::valid_uuid?(reservation_uuid)
          raise ArgumentError, "You must supply a valid reservation UUID (as a String or Symbol) to add an element to the reserve locks"
        end
        record = @connector[:element_locks].select(:type, :reservation, :credential).where({:reservation => reservation_uuid.to_s}).first
        if record
          type = record[:type].to_sym
          credential = record[:credential].to_sym
          manifest = self.element_manifest(table, dbid, false)
          if type == :write
            if self.db_permissions()[:write]
              #
              manifest.each do |entry|
                if @connector[:element_locks].filter({:type => (type.to_s), :reservation => reservation_uuid.to_s, :element_table => entry[:table].to_s, :elementid => entry[:dbid]}).count == 0
                  @connector[:element_locks].insert({:type => (type.to_s), :reservation => reservation_uuid.to_s, :credential => credential.to_s, :element_table => entry[:table].to_s, :elementid => entry[:dbid]})
                end
              end
              result = true
            end
          else
            # read
            if self.db_permissions()[:write]
              #
              manifest.each do |entry|
                @connector[:element_locks].insert({:type => (type.to_s), :reservation => reservation_uuid.to_s, :credential => credential.to_s, :element_table => entry[:table].to_s, :elementid => entry[:dbid]})
              end
              result = true
            end
          end
        end
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Database not available (defunct)"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:reservation => (reservation_uuid)}})
  end
  #
  result
end
reservation_remove_element(reservation_uuid=nil, table=:unspecified, dbid=0) click to toggle source
# File lib/gxg/gxg_database.rb, line 2951
def reservation_remove_element(reservation_uuid=nil, table=:unspecified, dbid=0)
  result = false
  #
  begin
    if self.alive?
      if self.open?
        unless ::GxG::valid_uuid?(reservation_uuid)
          raise ArgumentError, "You must supply a valid reservation UUID (as a String or Symbol) to remove element from reserve locks"
        end
        record = @connector[:element_locks].select(:reservation).where({:reservation => reservation_uuid.to_s}).first
        if record
          manifest = self.element_manifest(table, dbid, false)
          if self.db_permissions()[:write]
            #
            manifest.each do |entry|
              if @connector[:element_locks].filter({:reservation => reservation_uuid.to_s, :element_table => entry[:table].to_s, :elementid => entry[:dbid]}).count > 0
                @connector[:element_locks].filter({:reservation => reservation_uuid.to_s, :element_table => entry[:table].to_s, :elementid => entry[:dbid]}).delete
              end
            end
            result = true
          end
        end
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Database not available (defunct)"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:reservation => (reservation_uuid)}})
  end
  #
  result
end
reserve_element_locks(credential=nil, manifest=[], type=:read) click to toggle source

Element Write-Lock Handling methods

# File lib/gxg/gxg_database.rb, line 2816
def reserve_element_locks(credential=nil, manifest=[], type=:read)
  result = nil
  begin
    if self.alive?
      if self.open?
        unless ::GxG::valid_uuid?(credential)
          raise ArgumentError, "You must supply a valid credential UUID to reserve locks"
        end
        unless manifest.is_a?(::Array)
          raise ArguementError, "You must supply an Array of tables and record ids to reserve for writing"
        end
        unless [:write, :read].include?(type)
          raise ArgumentError, "You must specify a type of reservation: either :write or :read are supported"
        end
        if manifest.size > 0
          reservation_uuid = ::GxG::uuid_generate()
          while @connector[:element_locks].filter({:reservation => (reservation_uuid.to_s)}).count > 0
            reservation_uuid = ::GxG::uuid_generate()
          end
          if type == :write
            if self.db_permissions()[:write]
              # Write-lock must be unique to the elements
              manifest.each do |entry|
                if @connector[:element_locks].filter({:type => (type.to_s), :element_table => entry[:table].to_s, :elementid => entry[:dbid]}).count > 0
                  self.release_element_locks(reservation_uuid)
                  # raise Exception, "A reservation already exists for element #{entry[:table]}:#{entry[:dbid]}"
                  # Note - just silently fail and return Nil - no reservation for you.
                  break
                else
                  @connector[:element_locks].insert({:type => (type.to_s), :reservation => reservation_uuid.to_s, :credential => credential.to_s, :element_table => entry[:table].to_s, :elementid => entry[:dbid]})
                end
              end
              # if write-reservation was made
              if @connector[:element_locks].filter({:reservation => reservation_uuid.to_s}).count > 0
                result = reservation_uuid.to_sym
              end
            end
          else
            # Read-lock reservation - can share elements
            if self.db_permissions()[:write]
              manifest.each do |entry|
                @connector[:element_locks].insert({:type => (type.to_s), :reservation => reservation_uuid.to_s, :credential => credential.to_s, :element_table => entry[:table].to_s, :elementid => entry[:dbid]})
                #
              end
            end
            # Note - on a read-only db it will act as though it has a read-reservation since no deletions can be made.
            result = reservation_uuid.to_sym
          end
        end
        #
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Database not available (defunct)"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:credential => (credential), :manifest => (manifest), :type => (type)}})
  end
  result
end
retrieve_by_address(the_address={}, credential=nil, delegate=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 2687
def retrieve_by_address(the_address={}, credential=nil, delegate=nil)
  result = nil
  begin
    unless ::GxG::valid_uuid?(credential)
      raise ArgumentError, "You must supply a valid credential UUID (as a String or Symbol)"
    end
    if self.alive?
      if self.open?
        address = {}
        if the_address[:database]
          unless the_address[:database] == self
            raise ArgumentError, "Database mismatch.  Call this method on database #{the_address[:database].inspect}"
          end
          address[:database] = the_address[:database]
        else
          address[:database] = self
        end
        unless ((the_address[:table]) and (the_address[:dbid].is_a?(::Integer)))
          raise ArgumentError, "Invalid database address: #{the_address.inspect}"
        end
        if the_address[:table].is_a?(::Integer)
          address[:table] = ::GxG::Database::Database::element_table_by_index(the_address[:table])
        else
          address[:table] = the_address[:table]
        end
        address[:dbid] = the_address[:dbid]
        unless self.element_in_trash?(address[:table], address[:dbid])
          if [:persisted_array, :persisted_hash].include?(address[:table])
            the_permission = address[:database].effective_element_permission(address[:table], address[:dbid], credential)
          else
            the_permission = {:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => true}
          end
          # Review ????
          # puts "Effective Permission: #{the_permission.inspect} for #{address[:table].inspect},#{address[:dbid].inspect}"
          if the_permission[:read] == true
            case address[:table]
            when :element_array
              record = address[:database].connector()[(address[:table].to_s.to_sym)].select(:uuid).where({:dbid => (address[:dbid])}).first
              if record
                result = ::GxG::Database::PersistedArray.new({:database => (address[:database]), :uuid => (record[:uuid].to_sym), :credential => (credential), :delegate => (delegate)})
              else
                raise Exception, "Unable to retrieve PersistedArray"
              end
            when :element_hash
              record = address[:database].connector()[:element_hash].select(:uuid, :format).where({:dbid => (address[:dbid])}).first
              if record
                result = ::GxG::Database::PersistedHash.new({:database => (address[:database]), :uuid => (record[:uuid].to_sym), :credential => (credential), :delegate => (delegate)})
                if result
                  if record[:format].to_s.size > 0
                    result.set_format(record[:format].to_sym)
                  end
                end
              else
                raise Exception, "Unable to retrieve PersistedHash"
              end
            else
              raise Exception, "Invalid table specifier: #{address[:table].inspect}"
            end
          else
            # At this point the idea is that if you don't have permissions to read it, you never see it
            # raise Exception, "You don't have permission to retrieve this element"
          end
          #
        end
        #
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Database not available (defunct)"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:address => (the_address), :credential => (credential), :delegate => (delegate)}})
  end
  result
end
retrieve_by_uuid(uuid=nil, credential=nil, delegate=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 2764
def retrieve_by_uuid(uuid=nil, credential=nil, delegate=nil)
  result = nil
  begin
    if self.alive?
      if self.open?
        address = nil
        record = @connector[:element_hash].filter({:uuid => (uuid.to_s)}).first
        if record
          address = {:database => self, :table => :element_hash, :dbid => (record[:dbid])}
        else
          record = @connector[:element_array].filter({:uuid => (uuid.to_s)}).first
          if record
            address = {:database => self, :table => :element_array, :dbid => (record[:dbid])}
          end
        end
        if address
          result = self.retrieve_by_address(address, credential, delegate)
        else
          # ### Review : Experimental Code - attempt to seemlessly integrate dbs of different roles into in-memory structures.
          already_checked = [(self)]
          ::GxG::DB[:roles].each_pair do |the_db_role, the_database|
            unless already_checked.include?(the_database)
              record = the_database.connector[:element_hash].filter({:uuid => (uuid.to_s)}).first
              if record
                address = {:database => the_database, :table => :element_hash, :dbid => (record[:dbid])}
                result = the_database.retrieve_by_address(address, credential, delegate)
                break
              else
                record = the_database.connector[:element_array].filter({:uuid => (uuid.to_s)}).first
                if record
                  address = {:database => the_database, :table => :element_array, :dbid => (record[:dbid])}
                  result = the_database.retrieve_by_address(address, credential, delegate)
                  break
                end
              end
              already_checked << the_database
            end
          end
          #
        end
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Database not available (defunct)"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:uuid => (uuid), :credential => (credential), :delegate => (delegate)}})
  end
  result
end
revoke_element_permissions(table=:unspecified, dbid=0, credential=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 1398
def revoke_element_permissions(table=:unspecified, dbid=0, credential=nil)
  result = false
  begin
    unless self.alive?
      raise Exception, "Database inactive"
    end
    unless self.open?
      raise Exception, "Database not available"
    end
    unless dbid.is_a?(::Integer)
      raise ArgumentError, "dbid must be specified with a Integer"
    end
    unless ::GxG::valid_uuid?(credential)
      raise ArgumentError, "This option requires a valid credential UUID (as a String or Symbol)"
    end
    if table.is_a?(::Integer)
      table = ::GxG::Database::Database::element_table_by_index(table)
    end
    # Review : change in permission policy
    # if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :element_binary, :element_array, :element_hash].include?(table)
    if [:element_array, :element_hash].include?(table)
      @connector[:permissions].filter({:element_table => (table.to_s), :elementid => (dbid), :credential => (credential.to_s)}).delete
      result = true
    else
      raise ArgumentError, "Invalid table specified"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:table => (table), :dbid => (dbid), :options => (options)}})
  end
  result
end
revoke_permissions_by_uuid(the_uuid=nil, credential=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 1480
def revoke_permissions_by_uuid(the_uuid=nil, credential=nil)
  result = []
  begin
    if self.alive?
      if self.open?
        found = @connector[:element_hash].select(:dbid, :uuid).filter({:uuid => the_uuid.to_s}).first
        if found
          result = self.revoke_element_permissions(:element_hash,(found[:dbid]),credential)
        else
          found = @connector[:element_array].select(:dbid, :uuid).filter({:uuid => the_uuid.to_s}).first
          if found
            result = self.revoke_element_permissions(:element_array,(found[:dbid]),credential)
          end
        end
      end
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:uuid => (the_uuid)}})
  end
  result
end
role_add_user(role_uuid=nil, credential=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 930
def role_add_user(role_uuid=nil, credential=nil)
  result = false
  if @authority
    result = @authority.role_add_user(role_uuid, credential)
  else
    if self.alive?
      if self.open?
        if self.db_permissions()[:write]
          begin
            if ::GxG::valid_uuid?(role_uuid)
              if ::GxG::valid_uuid?(credential)
                if @connector[:user_roles].filter({:role_uuid => (role_uuid.to_s), :user_uuid => (credential.to_s)}).count == 0
                  @connector[:user_roles].insert({:role_uuid => (role_uuid.to_s), :user_uuid => (credential.to_s)})
                end
                result = true
              else
                raise ArgumentError, "You must specify a valid user credential UUID (as a String or Symbol)"
              end
            else
              raise ArgumentError, "You must specify a valid role UUID (as a String or Symbol)"
            end
          rescue Exception => the_error
            log_error({:error => the_error, :parameters => {:role_uuid => (role_uuid), :credential => (credential)}})
          end
        end
      end
    end
  end
  result
end
role_create(group_uuid=nil, title="", seo="") click to toggle source
# File lib/gxg/gxg_database.rb, line 808
def role_create(group_uuid=nil, title="", seo="")
  result = nil
  if @authority
    result = @authority.role_create(title,seo)
  else
    if self.alive?
      if self.open?
        if self.db_permissions()[:write]
          begin
            if ::GxG::valid_uuid?(group_uuid)
              #
              if title.to_s.size <= 256
                #
                if title.to_s.size == 0
                  title = "Member"
                end
                unless seo.to_s.size <= 256
                  raise ArgumentError, "Oversized SEO attempted (256 Character Limit): #{seo}"
                end
                if seo.to_s.size == 0
                  seo = title.downcase.gsub(" ","_")[0..255]
                end
                the_uuid = ::GxG::uuid_generate()
                while (@connector[:roles].filter({:uuid => (the_uuid.to_s)}).count > 0)
                  the_uuid = ::GxG::uuid_generate()
                end
                @connector[:roles].insert({:uuid => (the_uuid.to_s), :group_uuid => (group_uuid.to_s), :title => (title.to_s), :seo => (seo.to_s)})
                result = the_uuid.to_sym
              else
                raise ArgumentError, "Oversized title attempted (256 Character Limit): #{title}"
              end
            else
              raise ArgumentError, "You must specify a valid group UUID to link to (as a String or Symbol)"
            end
          rescue Exception => the_error
            log_error({:error => the_error, :parameters => {:group_uuid => (group_uuid), :title => (title), :seo => (seo)}})
          end
        end
      end
    end
  end
  result
end
role_destroy(role_uuid=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 888
def role_destroy(role_uuid=nil)
  result = false
  if @authority
    result = @authority.role_destroy(role_uuid)
  else
    if self.alive?
      if self.open?
        if self.db_permissions()[:write]
          begin
            if ::GxG::valid_uuid?(role_uuid)
              # cannot destroy if still linked as group's default role
              record = @connector[:roles].filter({:uuid => (role_uuid.to_s)}).first
              if record
                group_record = @connector[:groups].filter({:uuid => (record[:group_uuid].to_s)}).first
                if group_record
                  if role_uuid.to_s != group_record[:default_role].to_s
                    the_list = self.db_list()
                    the_list << (self)
                    the_list.each do |the_db|
                      the_db.connector()[:permissions].filter({:credential => (role_uuid.to_s)}).delete
                      the_db.connector()[:user_roles].filter({:role_uuid => (role_uuid.to_s)}).delete
                    end
                    @connector[:roles].filter({:uuid => (role_uuid.to_s)}).delete
                    result = true
                  else
                    log_warn("You cannot destroy a group's default role")
                  end
                end
              end
            else
              raise ArgumentError, "You must specify a valid role UUID (as a String or Symbol)"
            end
          rescue Exception => the_error
            log_error({:error => the_error, :parameters => {:role_uuid => (role_uuid)}})
          end
        end
      end
    end
  end
  result
end
role_exist?(credential=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 792
def role_exist?(credential=nil)
  result = nil
  if @authority
    result = @authority.role_exist?(credential)
  else
    if self.alive?
      if self.open?
        if @connector[:roles].filter({:uuid => (credential.to_s)}).count > 0
          result = true
        end
      end
    end
  end
  result
end
role_fetch(search_options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 1062
def role_fetch(search_options={})
  result = nil
  if @authority
    result = @authority.role_fetch(search_options)
  else
    if self.alive?
      if self.open?
        result = @connector[:roles].filter(search_options).first
      end
    end
  end
  result
end
role_group(role_uuid=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 1040
def role_group(role_uuid=nil)
  result = nil
  if @authority
    result = @authority.role_group(role_uuid)
  else
    if self.alive?
      if self.open?
        if GxG::valid_uuid?(role_uuid)
          record = @connector[:roles].filter({:uuid => (role_uuid.to_s)}).first
          if record
            group = self.group_fetch({:uuid => record[:group_uuid].to_s})
            if group
              result = group
            end
          end
        end
      end
    end
  end
  result
end
role_member?(role_uuid=nil, credential=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 992
def role_member?(role_uuid=nil, credential=nil)
  result = false
  if @authority
    result = @authority.role_member?(role_uuid, credential)
  else
    if self.alive?
      if self.open?
        begin
          if ::GxG::valid_uuid?(role_uuid)
            if ::GxG::valid_uuid?(credential)
              if @connector[:user_roles].filter({:role_uuid => (role_uuid.to_s), :user_uuid => (credential.to_s)}).count > 0
                result = true
              end
            else
              raise ArgumentError, "You must specify a valid user credential UUID (as a String or Symbol)"
            end
          else
            raise ArgumentError, "You must specify a valid role UUID (as a String or Symbol)"
          end
        rescue Exception => the_error
          log_error({:error => the_error, :parameters => {:role_uuid => (role_uuid), :credential => (credential)}})
        end
      end
    end
  end
  result
end
role_members(role_uuid=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 1020
def role_members(role_uuid=nil)
  result = []
  if @authority
    result = @authority.role_members(role_uuid)
  else
    if self.alive?
      if self.open?
        if GxG::valid_uuid?(role_uuid)
          @connector[:user_roles].filter({:role_uuid => (role_uuid.to_s)}).each do |the_record|
            unless result.include?(the_record[:user_uuid].to_s.to_sym)
              result << the_record[:user_uuid].to_s.to_sym
            end
          end
        end
      end
    end
  end
  result
end
role_remove_user(role_uuid=nil, credential=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 961
def role_remove_user(role_uuid=nil, credential=nil)
  result = false
  if @authority
    result = @authority.role_remove_user(role_uuid, credential)
  else
    if self.alive?
      if self.open?
        if self.db_permissions()[:write]
          begin
            if ::GxG::valid_uuid?(role_uuid)
              if ::GxG::valid_uuid?(credential)
                if @connector[:user_roles].filter({:role_uuid => (role_uuid.to_s), :user_uuid => (credential.to_s)}).count > 0
                  @connector[:user_roles].filter({:role_uuid => (role_uuid.to_s), :user_uuid => (credential.to_s)}).delete
                end
                result = true
              else
                raise ArgumentError, "You must specify a valid user credential UUID (as a String or Symbol)"
              end
            else
              raise ArgumentError, "You must specify a valid role UUID (as a String or Symbol)"
            end
          rescue Exception => the_error
            log_error({:error => the_error, :parameters => {:role_uuid => (role_uuid), :credential => (credential)}})
          end
        end
      end
    end
  end
  result
end
role_update(role_uuid=nil, data={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 852
def role_update(role_uuid=nil, data={})
  # data: :title, :seo
  result = false
  if @authority
    result = @authority.role_update(role_uuid,data)
  else
    if self.alive?
      if self.open?
        if self.db_permissions()[:write]
          begin
            unless data.is_a?(::Hash)
              raise Exception, "Update data must be passed in a Hash"
            end
            if ::GxG::valid_uuid?(role_uuid)
              the_title = (data[:title] || "Member")
              the_seo = (data[:seo] || the_title.downcase.gsub(" ", "_"))
              record = @connector[:roles].filter({:uuid => (role_uuid.to_s)}).first
              if record
                @connector[:roles].filter({:uuid => (role_uuid.to_s)}).update({:title => (the_title), :seo => (the_seo), :version => (record[:version] + 0.0001)})
                result = true
              else
                raise Exception, "Attempted to update a non-existent role: #{role_uuid}"
              end
            else
              raise ArgumentError, "You must specify a valid role UUID (as a String or Symbol)"
            end
          rescue Exception => the_error
            log_error({:error => the_error, :parameters => {:role_uuid => (role_uuid), :data => (data)}})
          end
        end
      end
    end
  end
  result
end
search_database(credential=nil, criteria={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 4468
def search_database(credential=nil, criteria={})
  # Usage: search_database(credential, {:ufs => "the.ufs.code", :properties => [{:the_property => {:equals => value}}]})
  #
  # criteria[:properties] :
  # For all
  # {:property_name => {:equals => value}}
  # For :element_integer, :element_float, :element_bigdecimal
  # {:property_name => {:greater_than => value, :greater_or_equal => value, :less_than => value, :less_or_equal => value}}
  # For :element_datetime, Note: if you pass text as a date ::Chronic will be used to parse it.
  # {:property_name => {:at => value, :before => value, :at_or_before => value, :after => value, :at_or_after => value, :between => <range-value>}
  # For Text, Binary
  # {:property_name => {:include => value}}
  #
  # criteria[:element] :
  # similar to criteria[:property] except that the entire table for the type is searched and no property dereferencing needed.
  #
  result = []
  criterium = []
  criteria_error = false
  unless criteria.is_a?(::Hash)
    criteria_error = true
  end
  unless criteria_error
    common_criteria = criteria.clone
    properties = (common_criteria.delete(:properties) || [])
    unless properties.is_a?(::Array)
      criteria_error = true
    end
    elements = (common_criteria.delete(:elements) || [])
    unless elements.is_a?(::Array)
      criteria_error = true
    end
  end
  #
  unless criteria_error
    if properties.size > 0 && elements.size > 0
      criteria_error = true
      log_warn("You MUST select EITHER :properites OR :elements, not both.")
    end
  end
  #
  unless criteria_error
    # Prepare criterium
    if common_criteria[:select].is_a?(::Array)
      unless common_criteria[:select].include?(:uuid)
        common_criteria[:select] << :uuid
      end
    else
      common_criteria[:select] = [:uuid]
    end
    #
    if common_criteria[:ufs]
      criterium << {:ufs => common_criteria[:ufs]}
    end
    if common_criteria[:format]
      criterium << {:format => common_criteria[:format]}
    end
    #
    if properties.size > 0
      properties.each do |the_property_search|
        criterium << ((common_criteria.clone).merge({:property => the_property_search}))
      end
    end
    if elements.size > 0
      elements.each do |the_element_search|
        criterium << ((common_criteria.clone).merge({:element => the_element_search}))
      end
    end
  end
  #
  result_sets = []
  # if properties.size == 0 && elements.size == 0
  #   result_sets << self.uuid_list(credential, criteria)
  # else
    criterium.each do |the_criteria|
      result_sets << self.uuid_list(credential, the_criteria)
    end
  # end
  scores = {}
  result_sets.each do |the_result|
    the_result.each do |the_answer|
      if scores.keys.include?(the_answer[:uuid])
        scores[(the_answer[:uuid])] = (scores[(the_answer[:uuid])] + 1)
      else
        scores[(the_answer[:uuid])] = 1
      end
    end
  end
  scores.keys.each do |the_uuid|
    if scores[(the_uuid)] == result_sets.size
      result_sets[0].each do |the_record|
        if the_record[:uuid] == the_uuid
          result << the_record
          break
        end
      end
    end
  end
  #
  result
end
serialize() click to toggle source

### Various methods Comm objects cannot be serialized - return encoded nil

# File lib/gxg/gxg_database.rb, line 5097
def serialize()
  "marshal:BAgw"
end
setting_keys() click to toggle source

Settings methods

# File lib/gxg/gxg_database.rb, line 3480
def setting_keys()
  result = []
  begin
    if self.alive?()
      if self.open?()
        @connector[:settings].all.each do |the_entry|
          result << the_entry[:title].to_sym
        end
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Attempted to access a defunct Database"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:setting_key => setting_key}})
  end
  result
end
structure_attached?(the_uuid=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 2201
def structure_attached?(the_uuid=nil)
  # Review : rewrite - in use
  result = false
  record = self.structural_link(the_uuid)
  if record
    result = true
  end
  result
end
structure_detach(the_uuid=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 2151
def structure_detach(the_uuid=nil)
  if ::GxG::valid_uuid?(the_uuid)
    record = self.structural_link(the_uuid)
    if record
      record[:database].connector()[(record[:table])].filter({:dbid => record[:dbid]}).update({:element => "element_boolean", :element_boolean => -1, :element_hash_uuid => "", :element_array_uuid => ""})
      true
    else
      false
    end
  else
    false
  end
end
sync_export(credential=nil, uuid_list=[], options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 5029
def sync_export(credential=nil, uuid_list=[], options={})
  result = {:formats => {}, :records => []}
  if uuid_list.is_any?(::Array, ::GxG::Database::PersistedArray)
    uuid_list.each do |the_reference|
      the_uuid = the_reference
      if ::GxG::valid_uuid?(the_uuid)
        the_object = self.retrieve_by_uuid(the_uuid, credential)
        if the_object
          object_record = the_object.export()
          object_record.search do |item,selector,container|
            if selector == :format || selector == :constraint
              if item.to_s.size > 0
                format_uuid = item
                unless result[:formats][(format_uuid.to_s.to_sym)].is_a?(::Hash)
                  format_sample = self.format_load({:uuid => format_uuid.to_s.to_sym})
                  format_sample[:content] = format_sample[:content].gxg_export()
                  result[:formats][(format_uuid.to_s.to_sym)] = format_sample
                end
              end
            end
          end
          result[:records] << object_record
          #
        end
      end
    end
  end
  result
end
sync_import(credential=nil, the_records={:formats => {}, :records => []}, options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 5059
def sync_import(credential=nil, the_records={:formats => {}, :records => []}, options={})
  result = false
  #
  if the_records.is_a?(::Hash)
    if the_records[:formats].is_a?(::Hash)
      op_frame = {:operation => :merge_format, :data => []}
      the_records[:formats].each_pair do |the_uuid, the_format_record|
        # gxg_import format content prior to sync update op
        the_format_record[:content] = ::Hash.gxg_import(the_format_record[:content])
        op_frame[:data] << the_format_record
      end
      if op_frame[:data].size > 0
        self.synchronize_records([(op_frame)],credential)
      end
    end
    #
    if the_records[:records].is_a?(::Array)
      if the_records[:records].size > 0
        self.synchronize_records([{:operation => :merge, :data => the_records[:records]}],credential)
        result = true
      end
    end
  end
  #
  result
end
synchronize_records(the_records=[], credential=nil, options={}) click to toggle source

Synchronize records: (and supports)

# File lib/gxg/gxg_database.rb, line 4571
def synchronize_records(the_records=[], credential=nil, options={})
  # Review : rewrite for new architecture.
  result = {:status => :completed}
  #
  total_records_processed = 0
  total_formats_processed = 0
  # List of format uuids needed from the OTHER database to complete the sync.
  formats_needed = []
  # List of format records we are sharing.
  formats_provided = []
  # records on THIS database that are higher version than submitted version.
  updates_provided = []
  # In case something goes horribly wrong:
  clean_up_list = []
  #
  begin
    if self.alive?
      if self.open?
        unless ::GxG::valid_uuid?(credential)
          raise ArgumentError, "You MUST provide a valid UUID as credential."
        end
        #
        if the_records.is_a?(::String)
          if the_records.base64?
            the_records = the_records.decode64
          end
          if the_records.json?
            the_records = ::JSON.parse(the_records,{:symbolize_names => true})
          end
        end
        if the_records.is_a?(::Hash)
          the_records = [(the_records)]
        end
        unless the_records.is_a?(::Array)
          raise ArgumentError, "You MUST provide: Base64, JSON, Hash, or Array of operation Hashes."
        end
        # Process each operation in the_records, data is inline under :data key.
        the_records.each do |the_operation|
          if the_operation.is_a?(::Hash)
            if [:merge, :delete, :fetch, :merge_format, :delete_format, :formats_provided, :formats_needed].include?(the_operation[:operation])
              #
              case the_operation[:operation]
              when :merge
                unless self.db_permissions()[:write]
                  raise Exception, "Attempted to alter a read-only database."
                end
                manifest = []
                if the_operation[:data].is_a?(::Array)
                  manifest = the_operation[:data]
                else
                  if the_operation[:data].is_a?(::Hash)
                    manifest = [(the_operation[:data])]
                  else
                    log_warn("Invalid record sepecifier or manifiest (ignoring): #{the_operation[:data].inspect}")
                  end
                end
                manifest.each do |entry|
                  if entry[:format]
                    unless self.format_list({:uuid => (entry[:format])}).size > 0
                      raise Exception, "Attempted to merge with unknown :format #{entry[:format].inspect}. Synchronize formats first, then records."
                    end
                  end
                  # fetch existing:
                  # if existing - compare versions - if greater provide, if lesser update, else add to db.
                  queue = [(entry)]
                  while queue.size > 0 do
                    record = queue.shift
                    if ::GxG::valid_uuid?(record[:uuid])
                      formatting = {:format => nil, :constraint => nil}
                      existing = self.retrieve_by_uuid(record[:uuid], credential)
                      unless existing
                        # Note: since there is no way to create a Persisted Object with a given UUID, this method is used to create the object: object will be updated later.
                        unless @connector[(record[:type].to_s.downcase.to_sym)].filter({:uuid => record[:uuid].to_s}).count > 0
                          # This prevents no-element-retrieved-due-to-permission issue causing an 'add duplicate uuid object' situation:
                          dbid = @connector[(record[:type].to_s.downcase.to_sym)].insert({:uuid => record[:uuid].to_s, :title => "Merged Persisted Object"})
                          self.assign_element_permission(record[:type].to_s.downcase.to_sym,dbid,credential,{:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true})
                          #
                        end
                        existing = self.retrieve_by_uuid(record[:uuid], credential)
                      end
                      if existing
                        # ### Compare versions
                        if existing.version > record[:version]
                          action = :provide
                        else
                          if existing.version < record[:version]
                            action = :update
                          else
                            action = :ignore
                          end
                        end
                        # ### Take Action
                        case action
                        when :provide
                          updates_provided << {:operation => :merge, :data => [(existing.export())]}
                          existing.deactivate
                          total_records_processed += 1
                        when :update
                          # ### Prelude
                          if record[:format].to_s.size > 0
                            formatting[:format] = record[:format].to_s
                          end
                          if record[:constraint].to_s.size > 0
                            formatting[:constraint] = record[:constraint].to_s
                          end
                          clean_up_list << existing
                          existing.get_reservation()
                          unless existing.write_permission?() && existing.write_reserved?()
                            raise Exception, "Failed to secure write permission and write reservation for this credential."
                          end
                          existing.title = (record[:title])
                          # ### Update Elements
                          if record[:content].is_a?(::Hash)
                            # Review : What to do / how to handle formatted existing Hashes??
                            record[:content].each_pair do |property, element_record|
                              if element_record[:uuid]
                                # ### Element is Hash or Array
                                element = self.retrieve_by_uuid(element_record[:uuid], credential)
                                unless element
                                  # ### Create blank element record and retrieve
                                  # Note: since there is no way to create a Persisted Object with a given UUID, this method is used to create the object: object will be updated later.
                                  unless @connector[(element_record[:type].to_s.downcase.to_sym)].filter({:uuid => element_record[:uuid].to_s}).count > 0
                                    # This prevents no-element-retrieved-due-to-permission issue causing an 'add duplicate uuid object' situation:
                                    dbid = @connector[(element_record[:type].to_s.downcase.to_sym)].insert({:uuid => element_record[:uuid].to_s, :title => "Merged Persisted Object"})
                                    self.assign_element_permission(element_record[:type].to_s.downcase.to_sym,dbid,credential,{:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true})
                                    #
                                  end
                                  element = self.retrieve_by_uuid(element_record[:uuid], credential)
                                end
                                if element
                                  # ### Ensure Element Linking
                                  # Review : Warning - absence of a :write permission can bugger this up.
                                  clean_up_list << element
                                  element.get_reservation()
                                  unless element.write_permission?() && element.write_reserved?()
                                    raise Exception, "Failed to secure write permission and write reservation for this credential."
                                  end
                                  existing[(property)] = element
                                  # element.deactivate ??
                                end
                                # Note: return to processing queue to set its elements
                                queue << element_record
                              else
                                # ### Base Element
                                unless existing.version(property) > element_record[:version]
                                  the_content = nil
                                  case element_record[:type].to_s.downcase.to_sym
                                  when :element_boolean, :element_integer, :element_float
                                    the_content = element_record[:content]
                                  when :element_bigdecimal
                                    the_content = ::BigDecimal.new(element_record[:content].to_s)
                                  when :element_datetime
                                    the_content = ::DateTime::parse(element_record[:content].to_s)
                                  when :element_text
                                    the_content = element_record[:content].to_s
                                  when :element_binary
                                    the_content = ::GxG::ByteArray.new(element_record[:content].to_s.decode64)
                                  end
                                  existing[(property)] = the_content
                                end
                              end
                            end
                          else
                            if record[:content].is_a?(::Array)
                              record[:content].each_with_index do |element_record, indexer|
                                if element_record[:uuid]
                                  # ### Element is Hash or Array
                                  element = self.retrieve_by_uuid(element_record[:uuid], credential)
                                  unless element
                                    # ### Create blank element record and retrieve
                                    # Note: since there is no way to create a Persisted Object with a given UUID, this method is used to create the object: object will be updated later.
                                    unless @connector[(element_record[:type].to_s.downcase.to_sym)].filter({:uuid => element_record[:uuid].to_s}).count > 0
                                      # This prevents no-element-retrieved-due-to-permission issue causing an 'add duplicate uuid object' situation:
                                      dbid = @connector[(element_record[:type].to_s.downcase.to_sym)].insert({:uuid => element_record[:uuid].to_s, :title => "Merged Persisted Object"})
                                      self.assign_element_permission(element_record[:type].to_s.downcase.to_sym,dbid,credential,{:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true})
                                      #
                                    end
                                    element = self.retrieve_by_uuid(element_record[:uuid], credential)
                                  end
                                  if element
                                    # ### Ensure Element Linking
                                    # Review : Warning - absence of a :write permission can bugger this up.
                                    clean_up_list << element
                                    element.get_reservation()
                                    unless element.write_permission?() && element.write_reserved?()
                                      raise Exception, "Failed to secure write permission and write reservation for this credential."
                                    end
                                    existing[(indexer)] = element
                                    # element.deactivate ??
                                  end
                                  # Note: return to processing queue to set its elements
                                  queue << element_record
                                else
                                  # ### Base Element
                                  unless existing.version(indexer) > element_record[:version]
                                    the_content = nil
                                    case element_record[:type].to_s.downcase.to_sym
                                    when :element_boolean, :element_integer, :element_float
                                      the_content = element_record[:content]
                                    when :element_bigdecimal
                                      the_content = ::BigDecimal.new(element_record[:content].to_s)
                                    when :element_datetime
                                      the_content = ::DateTime::parse(element_record[:content].to_s)
                                    when :element_text
                                      the_content = element_record[:content].to_s
                                    when :element_binary
                                      the_content = ::GxG::ByteArray.new(element_record[:content].to_s.decode64)
                                    end
                                    existing[(indexer)] = the_content
                                  end
                                end
                                #
                              end
                            end
                          end
                          # ### Set Fromatting / Constraints
                          if existing.is_a?(::GxG::Database::PersistedHash)
                            if formatting[:format].to_s.size > 0
                              existing.format = (formatting[:format])
                            end
                          end
                          if existing.is_a?(::GxG::Database::PersistedArray)
                            if formatting[:constraint].to_s.size > 0
                              existing.constraint = (formatting[:constraint])
                            end
                          end
                          # ### Conclude Existing
                          existing.version = (record[:version])
                          existing.save
                          existing.deactivate
                          total_records_processed += 1
                        end
                      end
                    end
                  end
                  #
                end
              when :delete
                unless self.db_permissions()[:write]
                  raise Exception, "Attempted to alter a read-only database."
                end
                #
                manifest = []
                if the_operation[:data].is_a?(::Array)
                  manifest = the_operation[:data]
                else
                  if the_operation[:data].is_a?(::Hash)
                    manifest = [(the_operation[:data])]
                  else
                    log_warn("Invalid record sepecifier or manifiest (ignoring): #{the_operation[:data].inspect}")
                  end
                end
                manifest.each do |entry|
                  if ::GxG::valid_uuid?(entry[:uuid])
                    existing = self.retrieve_by_uuid(entry[:uuid].to_sym, credential)
                    if existing
                      the_address = existing.db_address()
                      existing.deactivate
                      if self.element_destroy(credential,the_address[:table],the_address[:dbid])
                        total_records_processed += 1
                      else
                        log_warn("Record #{entry[:uuid].inspect} was not deleted.")
                      end
                    else
                      log_warn("Record #{entry[:uuid].inspect} was not found.")
                    end
                  else
                    log_warn("Invalid UUID specifier (ignoring): #{entry[:uuid].inspect}")
                  end
                end
                #
              when :fetch
                # wrap export record in a :merge operation and add to updates_provided.
                manifest = []
                if the_operation[:data].is_a?(::Array)
                  manifest = the_operation[:data]
                else
                  if the_operation[:data].is_a?(::Hash)
                    manifest = [(the_operation[:data])]
                  else
                    log_warn("Invalid record sepecifier or manifiest (ignoring): #{the_operation[:data].inspect}")
                  end
                end
                manifest.each do |entry|
                  if ::GxG::valid_uuid?(entry[:uuid])
                    existing = self.retrieve_by_uuid(entry[:uuid].to_sym, credential)
                    if existing
                      updates_provided << {:operation => :merge, :data => [(existing.export())]}
                      existing.deactivate
                      total_records_processed += 1
                    else
                      log_warn("Record #{entry[:uuid].inspect} was not found.")
                    end
                  else
                    log_warn("Invalid UUID specifier (ignoring): #{entry[:uuid].inspect}")
                  end
                end
                #
              when :merge_format
                unless self.db_permissions()[:write]
                  raise Exception, "Attempted to alter a read-only database."
                end
                # add format record if missing - check for existing, and provide if ours is newer.
                manifest = []
                if the_operation[:data].is_a?(::Array)
                  manifest = the_operation[:data]
                else
                  if the_operation[:data].is_a?(::Hash)
                    manifest = [(the_operation[:data])]
                  else
                    log_warn("Invalid record sepecifier or manifiest (ignoring): #{the_operation[:data].inspect}")
                  end
                end
                manifest.each do |entry|
                  if ::GxG::valid_uuid?(entry[:uuid])
                    existing = self.format_load({:uuid => entry[:uuid].to_sym})
                    if existing.is_a?(::Hash)
                      if existing[:version] < entry[:version]
                        if self.format_update(entry)
                          total_formats_processed += 1
                        else
                          log_warn("Could not update Format #{entry[:uuid].inspect}")
                        end
                      end
                      if existing[:version] > entry[:version]
                        unless formats_provided.include?(existing)
                          formats_provided << existing
                          total_formats_processed += 1
                        end
                      end
                    else
                      if self.format_create(entry)
                        total_formats_processed += 1
                      else
                        log_warn("Could not create Format #{entry[:uuid].inspect}")
                      end
                    end
                  else
                    log_warn("Invalid Format specifier (ignoring): #{entry[:uuid].inspect}")
                  end
                end
              when :delete_format
                unless self.db_permissions()[:write]
                  raise Exception, "Attempted to alter a read-only database."
                end
                # If the format is in use, log_warn that you're ignoring the directive.
                manifest = []
                if the_operation[:data].is_a?(::Array)
                  manifest = the_operation[:data]
                else
                  if the_operation[:data].is_a?(::Hash)
                    manifest = [(the_operation[:data])]
                  else
                    log_warn("Invalid record sepecifier or manifiest (ignoring): #{the_operation[:data].inspect}")
                  end
                end
                manifest.each do |entry|
                  if ::GxG::valid_uuid?(entry[:uuid])
                    if @connector[:element_hash].filter({:format => entry[:uuid].to_s}).count == 0 && @connector[:element_array].filter({:constraint => entry[:uuid].to_s}).count == 0
                      # Not in use, safe to delete
                      if self.format_destroy({:uuid => entry[:uuid].to_sym})
                        total_formats_processed += 1
                      end
                    else
                      log_warn("Format #{entry[:uuid].inspect} in use (ignorning).")
                    end
                  else
                    log_warn("Invalid format specifier on :delete directive (ignorning): #{entry[:uuid].inspect}")
                  end
                end
              when :formats_provided
                unless self.db_permissions()[:write]
                  raise Exception, "Attempted to alter a read-only database."
                end
                # compare uuids against db-installed formats and add to formats_needed if missing.
                manifest = []
                if the_operation[:data].is_a?(::Array)
                  manifest = the_operation[:data]
                else
                  if the_operation[:data].is_a?(::Hash)
                    manifest = [(the_operation[:data])]
                  else
                    log_warn("Invalid record sepecifier or manifiest (ignoring): #{the_operation[:data].inspect}")
                  end
                end
                manifest.each do |entry|
                  if ::GxG::valid_uuid?(entry[:uuid])
                    if self.format_list({:uuid => (entry[:uuid])}).size == 0
                      record = {:uuid => (entry[:uuid].to_sym)}
                      unless formats_needed.include?(record)
                        formats_needed << record
                        total_formats_processed += 1
                      end
                    end
                  else
                    log_warn("Invalid Format specifier (ignoring): #{entry[:uuid].inspect}")
                  end
                end
              when :formats_needed
                # Gather up existing format records to share.
                manifest = []
                if the_operation[:data].is_a?(::Array)
                  manifest = the_operation[:data]
                else
                  if the_operation[:data].is_a?(::Hash)
                    manifest = [(the_operation[:data])]
                  else
                    log_warn("Invalid record sepecifier or manifiest (ignoring): #{the_operation[:data].inspect}")
                  end
                end
                manifest.each do |entry|
                  if ::GxG::valid_uuid?(entry[:uuid])
                    existing = self.format_load({:uuid => entry[:uuid].to_sym})
                    if existing.is_a?(::Hash)
                      unless formats_provided.include?(existing)
                        formats_provided << existing
                        total_formats_processed += 1
                      end
                    end
                  else
                    log_warn("Invalid Format specifier (ignoring): #{entry[:uuid].inspect}")
                  end
                end
                #
              end
            else
              log_warn("Invalid operation (ignoring): #{the_operation[:operation].inspect}")
            end
          else
            raise Exception, "Invalid formatted operation passed (MUST be a Hash): #{the_operation.inspect}"
          end
        end
        #
      else
        raise Exception, "Database not available."
      end
    else
      raise Exception, "Attempted to access a defunct database."
    end
  rescue Exception => the_error
    clean_up_list.each do |the_object|
      if the_object.alive?
        the_object.release_reservation()
        the_object.deactivate()
      end
    end
    result[:status] = :failed
    #log_error({:error => the_error, :parameters => {:records => (the_records), :options => (options)}})
    log_error({:error => the_error, :parameters => {}})
  end
  result[:formats_needed] = formats_needed
  result[:formats_provided] = formats_provided
  result[:record_updates] = updates_provided
  result[:records_processed] = total_records_processed
  result[:formats_processed] = total_formats_processed
  result
end
to_uri() click to toggle source
# File lib/gxg/gxg_database.rb, line 427
def to_uri()
  ::URI.parse(@url.to_s)
end
try_persist(the_object=nil, credential=nil, options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 2659
def try_persist(the_object=nil, credential=nil, options={})
  result = nil
  if the_object.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
    result = the_object
  else
    begin
      unless ::GxG::valid_uuid?(credential)
        raise ArgumentError, "You must supply a credential (36 character limit) as a String or Symbol"
      end
      unless options.is_a?(::Hash)
        raise ArgumentError, "You must supply persisting options as a Hash"
      end
      table = ::GxG::Database::Database::element_table_for_instance(the_object)
      if table == :unspecified
        raise ArgumentError, "You provided an object that cannot be persisted."
      end
      if [:element_hash, :element_array].include?(table)
        result = self.iterative_persist(the_object, credential)
      else
        result = the_object
      end
    rescue Exception => the_error
      log_error({:error => the_error, :parameters => {:object => the_object, :credential => credential, :options => options}})
    end
  end
  result
end
update_vfs_permission(file_id=nil, credential=nil, permission={:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false}) click to toggle source
# File lib/gxg/gxg_database.rb, line 1814
def update_vfs_permission(file_id=nil, credential=nil, permission={:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false})
  result = false
  begin
    unless self.alive?
      raise Exception, "Database inactive"
    end
    unless self.open?
      raise Exception, "Database not available"
    end
    unless file_id.is_a?(::String)
      raise ArgumentError, "file_id must be specified with a String"
    end
    unless permission.is_a?(::Hash)
      raise ArgumentError, "permission must be specified with a Hash"
    end
    unless ::GxG::valid_uuid?(credential)
      raise ArgumentError, "You must specify a valid credential UUID (as a String or Symbol)"
    end
    #
    record = @connector[:file_permissions].filter({:file_id => file_id.to_s, :credential => credential.to_s}).first
    if record
      update = true
      dbid = record.delete(:dbid)
    else
      update = false
      dbid = nil
      record = {:file_id => file_id.to_s, :credential => credential.to_s, :execute => 0, :rename => 0, :move => 0, :destroy => 0, :create => 0, :write => 0, :read => 0}
    end
    permission.keys.each do |the_permission_key|
      if permission[(the_permission_key)] == true
        record[(the_permission_key)] = 1
      else
        record[(the_permission_key)] = 0
      end
    end
    if update == true
      @connector[:file_permissions].filter({:dbid => dbid}).update(record)
    else
      @connector[:file_permissions].insert(record)
    end
    result = true
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:file_id => (file_id), :credential => (credential)}})
  end
  result
end
user_create(the_user_id="", the_password="", use_credential=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 581
def user_create(the_user_id="", the_password="", use_credential=nil)
  result = false
  if @authority
    result = @authority.user_create(the_user_id, the_password)
  else
    if self.alive?
      if self.open?
        if self.db_permissions()[:write]
          begin
            if the_user_id.to_s.size <= 256
              if the_password.to_s.size > 0
                if self.user_id_available?(the_user_id)
                  if ::GxG::valid_uuid?(use_credential)
                    the_uuid = use_credential.to_s
                    if (@connector[:users].filter({:uuid => (the_uuid.to_s)}).count > 0)
                      raise Exception, "That credential UUID is already in use"
                    end
                  else
                    the_uuid = ::GxG::uuid_generate()
                    while (@connector[:users].filter({:uuid => (the_uuid.to_s)}).count > 0)
                      the_uuid = ::GxG::uuid_generate()
                    end
                  end
                  salt = ::SecureRandom.base64(24)
                  pbkdf2 = ::OpenSSL::PKCS5::pbkdf2_hmac_sha1(the_password, salt, 1000, 24)
                  the_pass_hash = [salt, ::Base64.strict_encode64(pbkdf2)].join("\t")
                  @connector[:users].insert({:uuid => (the_uuid), :user_id => (the_user_id.to_s), :password_hash => (the_pass_hash)})
                  result = true
                else
                  raise Exception, "UserID not available: #{the_user_id}"
                end
              else
                raise ArgumentError, "Empty password not supported"
              end
            else
              raise ArgumentError, "Oversized UserID attempted: #{the_user_id}"
            end
          rescue Exception => the_error
            log_error({:error => the_error, :parameters => {:user_id => the_user_id}})
          end
        end
      end
    end
  end
  result
end
user_credential(the_user_id="", the_password="") click to toggle source
# File lib/gxg/gxg_database.rb, line 543
def user_credential(the_user_id="", the_password="")
  result = nil
  if @authority
    result = @authority.user_credential(the_user_id, the_password)
  else
    if self.alive?
      if self.open?
        begin
          if the_user_id.to_s.size <= 256
            if the_password.to_s.size > 0
              record = @connector[:users].select(:uuid, :user_id, :password_hash).where({:user_id => (the_user_id.to_s)}).first
              if record
                salt = record[:password_hash].split("\t")[0].to_s
                pbkdf2 = ::Base64.decode64(record[:password_hash].split("\t")[1].to_s)
                tester = ::OpenSSL::PKCS5::pbkdf2_hmac_sha1(the_password.to_s, salt, 1000, pbkdf2.length)
                if pbkdf2 == tester
                  result = record[:uuid].to_sym
                else
                  log_warn("Password attempt invalid for #{the_user_id}")
                end
              else
                raise Exception, "UserID not found: #{the_user_id}"
              end
            else
              raise Exception, "Empty password not supported"
            end
          else
            raise Exception, "Oversized UserID attempted: #{the_user_id}"
          end
        rescue Exception => the_error
          log_error({:error => the_error, :parameters => {:user_id => the_user_id}})
        end
      end
    end
  end
  result
end
user_destroy(credential=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 707
def user_destroy(credential=nil)
  result = false
  if @authority
    result = @authority.user_destroy(credential)
  else
    if self.alive?
      if self.open?
        if self.db_permissions()[:write]
          begin
            if ::GxG::valid_uuid?(credential)
              if @connector[:users].filter({:uuid => (credential.to_s)}).count > 0
                the_list = self.db_list()
                the_list << (self)
                the_list.each do |the_db|
                  the_db.connector()[:permissions].filter({:credential => (credential.to_s)}).delete
                  the_db.connector()[:user_roles].filter({:user_uuid => (credential.to_s)}).delete
                end
                @connector[:users].filter({:uuid => (credential.to_s)}).delete
                result = true
              end
            else
              raise ArgumentError, "Invalid credential argument: #{credential}"
            end
          rescue Exception => the_error
            log_error({:error => the_error, :parameters => {:credential => credential}})
          end
        end
      end
    end
  end
  result
end
user_exist?(the_user_id) click to toggle source
# File lib/gxg/gxg_database.rb, line 513
def user_exist?(the_user_id)
  result = false
  if @authority
    result = @authority.user_exist?(the_user_id)
  else
    if self.alive?
      if self.open?
        begin
          if ::GxG::valid_uuid?(the_user_id)
            if @connector[:users].filter({:uuid => (the_user_id.to_s)}).count > 0
              result = true
            end
          else
            if the_user_id.to_s.size <= 256
              if @connector[:users].filter({:user_id => (the_user_id.to_s)}).count > 0
                result = true
              end
            else
              raise ArgumentError, "Oversized UserID attempted: #{the_user_id}"
            end
          end
        rescue Exception => the_error
          log_error({:error => the_error, :parameters => {:user_id => the_user_id}})
        end
      end
    end
  end
  result
end
user_fetch(search_options={}) click to toggle source
# File lib/gxg/gxg_database.rb, line 740
def user_fetch(search_options={})
  result = nil
  if @authority
    result = @authority.user_fetch(search_options)
  else
    if self.alive?
      if self.open?
        begin
          result = @connector[:users].filter(search_options).first
        rescue Exception => the_error
          log_error({:error => the_error, :parameters => {:credential => (credential)}})
        end
      end
    end
  end
  result
end
user_id_available?(the_user_id) click to toggle source
# File lib/gxg/gxg_database.rb, line 489
def user_id_available?(the_user_id)
  result = false
  if @authority
    result = @authority.user_id_available?(the_user_id)
  else
    if self.alive?
      if self.open?
        begin
          if the_user_id.to_s.size <= 256
            if @connector[:users].filter({:user_id => (the_user_id.to_s)}).count == 0
              result = true
            end
          else
            raise ArgumentError, "Oversized UserID attempted: #{the_user_id}"
          end
        rescue Exception => the_error
          log_error({:error => the_error, :parameters => {:user_id => the_user_id}})
        end
      end
    end
  end
  result
end
user_manifest(include_password=false) click to toggle source

User, Role, and Group methods

# File lib/gxg/gxg_database.rb, line 464
def user_manifest(include_password=false)
  result = []
  if @authority
    result = @authority.user_manifest(include_password)
  else
    if self.alive?
      if self.open?
        begin
          if include_password == true
            dataset = @connector[:users].select(:uuid, :user_id, :password_hash, :version).all
          else
            dataset = @connector[:users].select(:uuid, :user_id, :version).all
          end
          dataset.each do |entry|
            result << entry
          end
        rescue Exception => the_error
          log_error({:error => the_error, :parameters => {}})
        end
      end
    end
  end
  result
end
user_roles(credential=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 758
def user_roles(credential=nil)
  result = []
  if @authority
    result = @authority.user_roles(credential)
  else
    if self.alive?
      if self.open?
        begin
          if ::GxG::valid_uuid?(credential)
            memberships = @connector[:user_roles].select(:role_uuid).where({:user_uuid => (credential.to_s)})
            pull_list = []
            memberships.each do |record|
              unless pull_list.find_index(record[:role_uuid].to_sym)
                pull_list << record[:role_uuid].to_sym
              end
            end
            pull_list.each do |role_uuid|
              record = @connector[:roles].filter({:uuid => (role_uuid.to_s)})
              if record
                result << {:credential => (role_uuid), :title => (record[:title]), :seo => (record[:seo])}
              end
            end
          else
            raise ArgumentError, "You must supply a valid user credential (as a String or Symbol)"
          end
        rescue Exception => the_error
          log_error({:error => the_error, :parameters => {:credential => (credential)}})
        end
      end
    end
  end
  result
end
user_set_password(credential=nil, old_password="", new_password="") click to toggle source
# File lib/gxg/gxg_database.rb, line 662
def user_set_password(credential=nil, old_password="", new_password="")
  result = false
  if @authority
    result = @authority.user_set_password(credential, old_password, new_password)
  else
    if self.alive?
      if self.open?
        if self.db_permissions()[:write]
          begin
            if ::GxG::valid_uuid?(credential)
              if new_password.to_s.size > 0
                if @connector[:users].filter({:uuid => (credential.to_s)}).count > 0
                  record = @connector[:users].filter({:uuid => (credential.to_s)}).first
                  if record
                    if self.user_credential(record[:user_id], old_password).to_s == credential.to_s
                      salt = ::SecureRandom.base64(24)
                      pbkdf2 = ::OpenSSL::PKCS5::pbkdf2_hmac_sha1(new_password, salt, 1000, 24)
                      the_pass_hash = [salt, ::Base64.strict_encode64(pbkdf2)].join("\t")
                      @connector[:users].filter({:uuid => (credential.to_s)}).update({:password_hash => (the_pass_hash), :version => (record[:version] + 0.0001)})
                      result = true
                    else
                      log_warn("Invalid password change attempted for #{credential}")
                    end
                  else
                    raise Exception, "Could not retrieve user record: #{credential}"
                  end
                else
                  raise Exception, "No user with that credential exists"
                end
              else
                raise ArgumentError, "Empty password not supported"
              end
            else
              raise ArgumentError, "Invalid credential argument: #{credential}"
            end
          rescue Exception => the_error
            log_error({:error => the_error, :parameters => {:credential => credential}})
          end
        end
      end
    end
  end
  result
end
user_update(credential=nil, user_id=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 628
def user_update(credential=nil, user_id=nil)
  result = false
  if @authority
    result = @authority.user_update(credential, user_id)
  else
    if self.alive?
      if self.open?
        if self.db_permissions()[:write]
          begin
            if ::GxG::valid_uuid?(credential)
              if self.user_id_available?(user_id.to_s)
                record = @connector[:users].filter({:uuid => (credential.to_s)}).first
                if record
                  @connector[:users].filter({:uuid => (credential.to_s)}).update({:user_id => (user_id), :version => (record[:version] + 0.0001)})
                  result = true
                else
                  raise Exception, "User record not found"
                end
              else
                log_warn("UserID is not available: #{user_id.to_s}")
              end
            else
              raise ArgumentError, "You must supply a valid user credential (as a String or Symbol)"
            end
          rescue Exception => the_error
            log_error({:error => the_error, :parameters => {:credential => credential, :user_id => user_id}})
          end
        end
      end
    end
  end
  result
end
uuid_list(credential=nil, criteria={}) click to toggle source

Search function method

# File lib/gxg/gxg_database.rb, line 3908
def uuid_list(credential=nil, criteria={})
  # will return an array of all structures the credential has (at least) read access to
  result = []
  begin
    if self.alive?
      if self.open?
        unless ::GxG::valid_uuid?(credential)
          raise ArgumentError, "You must supply a valid credential UUID (as a String or Symbol)"
        end
        unless criteria.is_a?(::Hash)
          raise ArgumentError, "You must supply a search criteria as a Hash"
        end
        hash_criteria = {}
        array_criteria = {}
        # Limit, Offset, and Page selection
        if criteria[:limit].is_a?(::Integer)
          limit = criteria[:limit]
        else
          limit = nil
        end
        if criteria[:offset].is_a?(::Integer)
          offset = criteria[:offset]
        else
          offset = 0
        end
        if criteria[:page].is_a?(::Integer)
          page = criteria[:page]
          unless limit
            limit = 100
          end
          offset = ((page * limit) - 1)
        else
          page = nil
        end
        # UUID, Title, and Format searches
        if ::GxG::valid_uuid?(criteria[:uuid])
          hash_criteria[:uuid] = criteria[:uuid].to_s
          array_criteria[:uuid] = criteria[:uuid].to_s
        end
        if criteria[:title].is_a?(::String)
          hash_criteria[:title] = criteria[:title].to_s[0..256]
          array_criteria[:title] = criteria[:title].to_s[0..256]
        end
        if criteria[:format].is_any?([::String, ::Symbol])
          if ::GxG::valid_uuid?(criteria[:format])
            format_list = self.format_list({:uuid => criteria[:format].to_sym})
            unless format_list.size > 0
              raise ArgumentError, "Format not found: #{criteria[:format].inspect}"
            end
            hash_criteria[:format] = criteria[:format].to_s
          end
        end
        if criteria[:ufs].is_any?(::String, ::Symbol)
          if criteria[:ufs_version].is_a?(::Float)
            format_list = self.format_list({:ufs => criteria[:ufs].to_sym, :version => criteria[:ufs_version]})
          else
            format_list = self.format_list({:ufs => criteria[:ufs].to_sym})
          end
          unless format_list.size > 0
            if criteria[:ufs_version].is_a?(::Float)
              raise ArgumentError, "Format not found: #{criteria[:ufs].inspect}, Version: #{criteria[:ufs_version].inspect}"
            else
              raise ArgumentError, "Format not found: #{criteria[:ufs].inspect}"
            end
          end
          hash_criteria[:format] = format_list[0][:uuid].to_s
        end
        # Output column selection: (very very basic at first)
        selectables = [:uuid, :title, :version]
        selected = []
        if criteria[:select].is_any?(::Symbol, ::Array)
          if criteria[:select].is_a?(::Array)
            criteria[:select].each do |the_column_symbol|
              if selectables.include?(the_column_symbol)
                selected << the_column_symbol
              end
            end
          else
            if selectables.include?(criteria[:select])
              selected << criteria[:select]
            end
          end
        end
        if selected.size == 0
          selected << :uuid
        end
        #
        reduce_to_datetime = Proc.new do |the_value|
          the_result = nil
          db_content = nil
          if the_value.is_a?(::String)
            if the_value.include?("between")
              the_times = the_value.split("between")[1].split("and")
              the_times[0] = ::Chronic.parse(the_times[0])
              the_times[1] = ::Chronic.parse(the_times[1])
              if the_times[0].is_a?(::Time) && the_times[1].is_a?(::Time)
                db_content = ((the_times[0].to_datetime)..(the_times[1].to_datetime))
              else
                raise Exception, "Unable to understand your time specification text: #{the_value.inspect}"
              end
            else
              if the_value.valid_time? || the_value.valid_date? || the_value.valid_datetime_nolocale? || the_value.valid_datetime?
                db_content = ::DateTime::parse(the_value)
              else
                the_times = ::Chronic.parse(the_value)
                if the_times.is_a?(::Time)
                  db_content = the_times.to_datetime
                else
                  raise Exception, "Unable to understand your time specification text: #{the_value.inspect}"
                end
              end
            end
          end
          if the_value.is_a?(::Range)
            the_times = [(the_value.first), (the_value.last)]
            if the_times[0].is_a?(::Time)
              the_times[0] = the_times[0].to_datetime
            end
            if the_times[0].is_a?(::Date)
              the_times[0] = ::DateTime::parse(the_times[0].to_s)
            end
            if the_times[1].is_a?(::Time)
              the_times[1] = the_times[1].to_datetime
            end
            if the_times[1].is_a?(::Date)
              the_times[1] = ::DateTime::parse(the_times[1].to_s)
            end
            the_times = ((the_times[0])..(the_times[1]))
            if the_times.first.is_a?(::DateTime) && the_value.last.is_a?(::DateTime)
              db_content = the_times
            else
              raise Exception, "Invalid Range of dates, use DateTime objects in the Range: #{the_value.inspect}"
            end
          end
          if the_value.is_any?(::Time, ::Date)
            db_content = ::DateTime::parse(the_value.to_s)
          end
          if the_value.is_a?(::DateTime)
            db_content = the_value
          end
          if db_content
            result = db_content
          else
            raise Exception, "Unable to reduce to a DateTime with this input: #{the_value.inspect}"
          end
          the_result
        end
        #
        db_content_value = Proc.new do |the_value|
          the_result = nil
          the_table = ::GxG::Database::Database::element_table_for_instance(the_value)
          if the_table == :unspecified
            raise Exception, "Invalid value passed as persistable: #{the_value.inspect}"
          else
            db_content = nil
            case the_table
            when :element_boolean
              if the_value.is_a?(::TrueClass)
                db_content = 1
              else
                if the_value.is_a?(::FalseClass)
                  db_content = 0
                else
                  db_content = -1
                end
              end
            when :element_binary
              db_content = ""
              the_value.each do |the_byte|
                db_content << the_byte.to_s(base=16)
              end
            when :element_text
              if the_value.valid_time? || the_value.valid_date? || the_value.valid_datetime_nolocale? || the_value.valid_datetime?
                db_content = reduce_to_datetime.call(the_value)
              else
                db_content = the_value
              end
            else
              db_content = the_value
            end
            if db_content
              the_result = db_content
            else
              raise Exception, "Could not cast the value to something useful: #{the_value.inspect}"
            end
          end
          the_result
        end
        #
        find_property_records = Proc.new do |a_selector, a_container|
          a_result = []
          a_container.each do |item|
            if item[(a_selector)]
              a_result << item
            end
          end
          a_result
        end
        find_element_records = Proc.new do |a_selector, a_container|
          a_result = []
          a_container.each do |item|
            if item[(a_selector)]
              a_result << item
            end
          end
          a_result
        end
        found_list = []
        # criteria[:property] :
        # For all
        # {:property_name => {:equals => value}}
        # For :element_integer, :element_float, :element_bigdecimal
        # {:property_name => {:greater_than => value, :greater_or_equal => value, :less_than => value, :less_or_equal => value}}
        # For :element_datetime, Note: if you pass text as a date ::Chronic will be used to parse it.
        # {:property_name => {:at => value, :before => value, :at_or_before => value, :after => value, :at_or_after => value, :between => <range-value>}
        # For Text, Binary
        # {:property_name => {:include => value}}
        #
        # criteria[:element] :
        # similar to criteria[:property] except that the entire table for the type is searched and no property dereferencing needed.
        #
        if criteria[:property] || criteria[:element]
          # Expansion
          # Text Search: @connector[:text_page].where(::Sequel.like(:content,'%#{search_text}%'))
          # Binary Search: @connector[:binary_page].where(::Sequel.like(:content,'%#{byte_sequence}%'))
          # self.element_parent_address(the_table=:unspecified, the_dbid=0)
          if criteria[:property].is_a?(::Hash)
            # Only ONE property key can be compared (TODO: expand to multiple keys)
            property_matches = []
            last_key = nil
            #
            criteria[:property].keys.each do |property_key|
              # compare each key's value to qualify the parent object:
              # {:html => {:include => "\n"}}
              comparison_op = criteria[:property][(property_key)].keys[0].to_sym
              if criteria[:property][(property_key)][(comparison_op)].is_any?(::String, ::Range) && [:at, :before, :after, :at_or_before, :at_or_after, :between].include?(comparison_op)
                comparison_value = reduce_to_datetime.call(criteria[:property][(property_key)][(comparison_op)])
                table_test = ::GxG::Database::Database::element_table_for_instance(comparison_value)
              else
                table_test = ::GxG::Database::Database::element_table_for_instance(criteria[:property][(property_key)][(comparison_op)])
                comparison_value = db_content_value.call(criteria[:property][(property_key)][(comparison_op)])
              end
              #
              if [:element_hash, :element_array].include?(table_test)
                # Only properties with base elements can be compared - not structures (TODO: expand this)
                log_warn("Attempted to compare a structure as a property value (not supported, ignoring).")
                next
              end
              # Review : rewrite - adapt to new arch.
              match_uuid_list = []
              # comparison_value
              @connector[:hash_properties].filter({:property => property_key.to_s}).each do |entry|
                element_value = nil
                case entry[:element]
                when "element_boolean"
                  case entry[:element_boolean]
                  when -1
                    element_value = nil
                  when 0
                    element_value = false
                  when 1
                    element_value = nil
                  end
                when "element_integer"
                  element_value = entry[:element_integer]
                when "element_float"
                  element_value = entry[:element_float]
                when "element_bigdecimal"
                  element_value = ::BigDecimal.new(entry[:element_bigdecimal].to_s)
                when "element_datetime"
                  element_value = entry[:element_datetime]
                when "element_text"
                  if entry[:element_text_uuid].to_s.size > 0
                    # Review: issue with Base64: decode64 mangles non-base64 text but does it w/o error now.
                    element_value = ""
                    @connector[:text_page].filter({:uuid => entry[:element_text_uuid].to_s}).order(:ordinal).each do |text_page|
                      element_value << text_page[:content]
                    end
                  else
                    element_value = entry[:element_text]
                  end
                when "element_binary"
                  element_value = ::GxG::ByteArray.new
                  @connector[:binary_page].filter({:uuid => entry[:element_binary_uuid].to_s}).order(:ordinal).each do |binary_page|
                    element_value << binary_page[:content]
                  end
                end
                #
                begin
                  case comparison_op
                  when :equals, :at
                    if element_value == comparison_value
                      match_uuid_list << entry[:parent_uuid].to_sym
                    end
                  when :greater_than, :after
                    if element_value > comparison_value
                      match_uuid_list << entry[:parent_uuid].to_sym
                    end
                  when :greater_or_equal, :at_or_after
                    if element_value >= comparison_value
                      match_uuid_list << entry[:parent_uuid].to_sym
                    end
                  when :less_than, :before
                    if element_value < comparison_value
                      match_uuid_list << entry[:parent_uuid].to_sym
                    end
                  when :less_or_equal, :at_or_before
                    if element_value <= comparison_value
                      match_uuid_list << entry[:parent_uuid].to_sym
                    end
                  when :between
                    if comparison_value.include?(element_value)
                      match_uuid_list << entry[:parent_uuid].to_sym
                    end
                  when :include
                    if element_value.to_s.include?(comparison_value.to_s)
                      match_uuid_list << entry[:parent_uuid].to_sym
                    end
                  when :match
                    if element_value.to_s.match(comparison_value)
                      match_uuid_list << entry[:parent_uuid].to_sym
                    end
                  end
                rescue Exception => cast_error
                  # Probably a type casting error (comparison of dissimilar types)
                  next
                end
              end
              #
              match_uuid_list.each do |the_matched_uuid|
                # Add to main found list
                parent_record = @connector[:element_hash].select(:uuid, :version, :title).where({:uuid => the_matched_uuid.to_s}).first
                if parent_record
                  new_record = {}
                  selected.each do |the_selected_key|
                    if parent_record.keys.include?(the_selected_key)
                      new_record[(the_selected_key)] = parent_record[(the_selected_key)]
                      if ::GxG::valid_uuid?(new_record[(the_selected_key)])
                        new_record[(the_selected_key)] = new_record[(the_selected_key)].to_sym
                      end
                    end
                  end
                  unless found_list.include?(new_record)
                    found_list << new_record
                  end
                end
              end
              #
              if last_key != property_key
                last_key = property_key
              end
              #
            end
            #
          else
            if criteria[:element].is_a?(::Array)
              criteria[:element].each_with_index do |the_element, element_index|
                comparison_op = criteria[:element][(element_index)].keys[0].to_sym
                if criteria[:element][(element_index)][(comparison_op)].is_any?(::String, ::Range) && [:at, :before, :after, :at_or_before, :at_or_after, :between].include?(comparison_op)
                  comparison_value = reduce_to_datetime.call(criteria[:element][(element_index)][(comparison_op)])
                  element_table = ::GxG::Database::Database::element_table_for_instance(comparison_value)
                else
                  element_table = ::GxG::Database::Database::element_table_for_instance(criteria[:element][(element_index)][(comparison_op)])
                  comparison_value = db_content_value.call(criteria[:element][(element_index)][(comparison_op)])
                end
                # Structural comparison not supported.
                if [:element_hash, :element_array].include?(element_table)
                  log_warn("Attempted to compare a structure as an element (not supported, ignoring).")
                  next
                end
                match_uuid_list = []
                # comparison_value
                @connector[:array_elements].filter({:element => element_table.to_s}).each do |entry|
                  element_value = nil
                  case entry[:element]
                  when "element_boolean"
                    case entry[:element_boolean]
                    when -1
                      element_value = nil
                    when 0
                      element_value = false
                    when 1
                      element_value = nil
                    end
                  when "element_integer"
                    element_value = entry[:element_integer]
                  when "element_float"
                    element_value = entry[:element_float]
                  when "element_bigdecimal"
                    element_value = ::BigDecimal.new(entry[:element_bigdecimal].to_s)
                  when "element_datetime"
                    element_value = entry[:element_datetime]
                  when "element_text"
                    if entry[:element_text_uuid].to_s.size > 0
                      # Review: issue with Base64: decode64 mangles non-base64 text but does it w/o error now.
                      element_value = ""
                      @connector[:text_page].filter({:uuid => entry[:element_text_uuid].to_s}).order(:ordinal).each do |text_page|
                        element_value << text_page[:content]
                      end
                    else
                      element_value = entry[:element_text]
                    end
                  when "element_binary"
                    element_value = ::GxG::ByteArray.new
                    @connector[:binary_page].filter({:uuid => entry[:element_binary_uuid].to_s}).order(:ordinal).each do |binary_page|
                      element_value << binary_page[:content]
                    end
                  end
                  #
                  begin
                    case comparison_op
                    when :equals, :at
                      if element_value == comparison_value
                        match_uuid_list << entry[:parent_uuid].to_sym
                      end
                    when :greater_than, :after
                      if element_value > comparison_value
                        match_uuid_list << entry[:parent_uuid].to_sym
                      end
                    when :greater_or_equal, :at_or_after
                      if element_value >= comparison_value
                        match_uuid_list << entry[:parent_uuid].to_sym
                      end
                    when :less_than, :before
                      if element_value < comparison_value
                        match_uuid_list << entry[:parent_uuid].to_sym
                      end
                    when :less_or_equal, :at_or_before
                      if element_value <= comparison_value
                        match_uuid_list << entry[:parent_uuid].to_sym
                      end
                    when :between
                      if comparison_value.include?(element_value)
                        match_uuid_list << entry[:parent_uuid].to_sym
                      end
                    when :include
                      if element_value.to_s.include?(comparison_value.to_s)
                        match_uuid_list << entry[:parent_uuid].to_sym
                      end
                    when :match
                      if element_value.to_s.match(comparison_value)
                        match_uuid_list << entry[:parent_uuid].to_sym
                      end
                    end
                  rescue Exception => cast_error
                    # Probably a type casting error (comparison of dissimilar types)
                    next
                  end
                  # end - comparison loop
                end
                #
                match_uuid_list.each do |the_matched_uuid|
                  # Add to main found list
                  parent_record = @connector[:element_array].select(:uuid, :version, :title).where({:uuid => the_matched_uuid.to_s}).first
                  if parent_record
                    new_record = {}
                    selected.each do |the_selected_key|
                      if parent_record.keys.include?(the_selected_key)
                        new_record[(the_selected_key)] = parent_record[(the_selected_key)]
                        if ::GxG::valid_uuid?(new_record[(the_selected_key)])
                          new_record[(the_selected_key)] = new_record[(the_selected_key)].to_sym
                        end
                      end
                    end
                    unless found_list.include?(new_record)
                      found_list << new_record
                    end
                  end
                end
                #
                # unless last_index == element_index
                #   last_index = element_index
                # end
              end
              #
            else
              # Criteria Expansion Here
            end
          end
        else
          @connector[:element_hash].filter(hash_criteria).each do |entry|
            new_record = {}
            selected.each do |the_key|
              if ::GxG::valid_uuid?(entry[(the_key)])
                new_record[(the_key)] = entry[(the_key)].to_sym
              else
                new_record[(the_key)] = entry[(the_key)]
              end
            end
            found_list << new_record
          end
          #
          unless hash_criteria[:format]
            @connector[:element_array].filter(array_criteria).each do |entry|
              new_record = {}
              selected.each do |the_key|
                if ::GxG::valid_uuid?(entry[(the_key)])
                  new_record[(the_key)] = entry[(the_key)].to_sym
                else
                  new_record[(the_key)] = entry[(the_key)]
                end
              end
              found_list << new_record
            end
          end
        end
        #
        # Sorting Options Here: (Expansion)
        if criteria[:order].is_any?(::Symbol, ::Hash)
          ascending = true
          sort_key = nil
          if criteria[:order].is_a?(::Hash)
            if criteria[:order][:ascending].is_a?(::Symbol)
              sort_key = criteria[:order][:ascending]
            end
            if criteria[:order][:descending].is_a?(::Symbol)
              sort_key = criteria[:order][:descending]
              ascending = false
            end
          else
            sort_key = criteria[:order]
          end
          if selected.include?(sort_key)
            found_list = found_list.sort do |entry, another|
              entry[(sort_key)] <=> another[(sort_key)]
            end
            unless ascending
              found_list.reverse!
            end
          end
        end
        # Impose result set limit and offset
        if limit.is_a?(::Integer)
          if found_list.size > 0
            if (offset + (limit - 1)) <= (found_list.size - 1)
              found_list = found_list[((offset)..(offset + (limit - 1)))]
            else
              if offset <= (found_list.size - 1)
                found_list = found_list[((offset)..(-1))]
              end
            end
          end
        end
        #
        found_list.size.times do
          result << found_list.shift
        end
        #
      else
        raise Exception, "Database not available"
      end
    else
      raise Exception, "Attempted to access a defunct Database"
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:credential => (credential), :criteria => (criteria)}})
  end
  result
end
vfs_permission(file_id=nil, credential=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 1642
def vfs_permission(file_id=nil, credential=nil)
  result = []
  begin
    unless self.alive?
      raise Exception, "Database inactive"
    end
    unless self.open?
      raise Exception, "Database not available"
    end
    unless file_id.is_a?(::String)
      raise ArgumentError, "dbid must be specified with a String"
    end
    if credential
      unless ::GxG::valid_uuid?(credential)
        raise ArgumentError, "This option requires a valid credential UUID (as a String or Symbol)"
      end
    end
    #
    if credential
      list = @connector[:file_permissions].filter({:file_id => (file_id.to_s), :credential => (credential.to_s)})
    else
      list = @connector[:file_permissions].filter({:file_id => (file_id.to_s)})
    end
    list.each do |record|
      # [:execute, :rename, :move, :destroy, :create, :write, :read]
      entry = {:credential => (record[:credential].to_sym), :permissions => {}}
      [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
        if record[(the_permission)] == 1
          entry[:permissions][(the_permission)] = true
        else
          entry[:permissions][(the_permission)] = false
        end
      end
      result << entry
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:file_id => (file_id), :credential => (credential)}})
  end
  result
end
vfs_permission_exist?(file_id=nil, credential=nil) click to toggle source

Effective Permission Handling methods VFS File permission mappings

# File lib/gxg/gxg_database.rb, line 1617
def vfs_permission_exist?(file_id=nil, credential=nil)
  result = false
  begin
    unless self.alive?
      raise Exception, "Database inactive"
    end
    unless self.open?
      raise Exception, "Database not available"
    end
    unless file_id.is_a?(::String)
      raise ArgumentError, "file_id must be specified with a String"
    end
    unless ::GxG::valid_uuid?(credential)
      raise ArgumentError, "You must specify a valid credential UUID (as a String or Symbol)"
    end
    #
    if @connector[:file_permissions].filter({:file_id => file_id.to_s, :credential => credential.to_s}).count > 0
      result = true
    end
  rescue Exception => the_error
    log_error({:error => the_error, :parameters => {:file_id => (file_id), :credential => (credential)}})
  end
  result
end
vfs_permission_manifest(file_id=nil, credential=nil) click to toggle source
# File lib/gxg/gxg_database.rb, line 1683
def vfs_permission_manifest(file_id=nil, credential=nil)
  result = []
  self.vfs_permission(file_id, credential).each do |entry|
    the_record = {:credential => nil, :permissions => {}, :details => {}}
    #
    the_record[:credential] = entry[:credential]
    the_record[:permissions] = entry[:permissions]
    if self.role_exist?(entry[:credential])
      role = self.role_fetch({:uuid => entry[:credential].to_s})
      group = self.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]
    else
      if self.user_exist?(entry[:credential])
        user = self.user_fetch({:uuid => entry[:credential].to_s})
        the_record[:details][:user_title] = user[:user_id]
      else
        log_warn("Invalid User Credential Detected: #{entry[:credential].to_s.to_sym.inspect}")
        the_record[:details][:user_title] = "Invalid User Credential #{entry[:credential].to_s.to_sym.inspect} !"
      end
    end
    result << the_record
  end
  result
end