module DiasporaFederation::Entities::Relayable

This is a module that defines common properties for relayable entities which include Like, Comment, Participation, Message, etc. Each relayable has a parent, identified by guid. Relayables are also signed and signing/verification logic is embedded into Salmon XML processing code.

Attributes

additional_data[R]

Additional properties from parsed input object @return [Hash] additional elements

Public Class Methods

included(klass) click to toggle source

On inclusion of this module the required properties for a relayable are added to the object that includes it.

@!attribute [r] author

The diaspora* ID of the author
@see Person#author
@return [String] diaspora* ID

@!attribute [r] guid

A random string of at least 16 chars
@see Validation::Rule::Guid
@return [String] comment guid

@!attribute [r] parent_guid

@see StatusMessage#guid
@return [String] parent guid

@!attribute [r] author_signature

Contains a signature of the entity using the private key of the author of a relayable itself.
The presence of this signature is mandatory. Without it the entity won't be accepted by
a target pod.
@return [String] author signature

@!attribute [r] parent

Meta information about the parent object
@return [RelatedEntity] parent entity

@param [Entity] klass the entity in which it is included

# File lib/diaspora_federation/entities/relayable.rb, line 43
def self.included(klass)
  klass.class_eval do
    property :author, :string
    property :guid, :string
    property :parent_guid, :string
    property :author_signature, :string, default: nil
    entity :parent, Entities::RelatedEntity
  end

  klass.extend Parsing
end
new(data, signature_order=nil, additional_data={}) click to toggle source

Initializes a new relayable Entity with order and additional xml elements

@param [Hash] data entity data @param [Array] signature_order order for the signature @param [Hash] additional_data additional xml elements @see DiasporaFederation::Entity#initialize

Calls superclass method
# File lib/diaspora_federation/entities/relayable.rb, line 61
def initialize(data, signature_order=nil, additional_data={})
  self.signature_order = signature_order if signature_order
  self.additional_data = additional_data

  super(data)
end

Public Instance Methods

sender_valid?(sender) click to toggle source
# File lib/diaspora_federation/entities/relayable.rb, line 77
def sender_valid?(sender)
  (sender == author && parent.root.local) || sender == parent.root.author
end
signature_order() click to toggle source

The order for signing @return [Array]

# File lib/diaspora_federation/entities/relayable.rb, line 97
def signature_order
  @signature_order || (self.class.class_props.keys.reject {|key|
    self.class.optional_props.include?(key) && public_send(key).nil?
  } - %i[author_signature parent])
end
to_json(*_args) click to toggle source
Calls superclass method
# File lib/diaspora_federation/entities/relayable.rb, line 86
def to_json(*_args)
  super.merge!(property_order: signature_order).tap {|json_hash|
    missing_properties = json_hash[:property_order] - json_hash[:entity_data].keys
    missing_properties.each {|property|
      json_hash[:entity_data][property] = nil
    }
  }
end
to_s() click to toggle source

@return [String] string representation of this object

# File lib/diaspora_federation/entities/relayable.rb, line 82
def to_s
  "#{super}#{":#{parent_type}" if respond_to?(:parent_type)}:#{parent_guid}"
end
verify_signature() click to toggle source

Verifies the author_signature if needed. @see DiasporaFederation::Entities::Signable#verify_signature

@raise [SignatureVerificationFailed] if the signature is not valid @raise [PublicKeyNotFound] if no public key is found

# File lib/diaspora_federation/entities/relayable.rb, line 73
def verify_signature
  super(author, :author_signature) unless author == parent.root.author
end

Private Instance Methods

additional_data=(additional_data) click to toggle source
# File lib/diaspora_federation/entities/relayable.rb, line 143
def additional_data=(additional_data)
  @additional_data = additional_data.reject {|name, _| name =~ /signature/ }
end
enriched_properties() click to toggle source

Update the signatures with the keys of the author and the parent if the signatures are not there yet and if the keys are available.

@return [Hash] properties with updated signatures

Calls superclass method
# File lib/diaspora_federation/entities/relayable.rb, line 121
def enriched_properties
  super.merge(additional_data).tap do |hash|
    hash[:author_signature] = author_signature || sign_with_author unless author == parent.root.author
  end
end
sign_with_author() click to toggle source

Sign with author key @raise [AuthorPrivateKeyNotFound] if the author private key is not found @return [String] A Base64 encoded signature of signature_data with key

# File lib/diaspora_federation/entities/relayable.rb, line 108
def sign_with_author
  privkey = DiasporaFederation.callbacks.trigger(:fetch_private_key, author)
  raise AuthorPrivateKeyNotFound, "author=#{author} obj=#{self}" if privkey.nil?

  sign_with_key(privkey).tap do
    logger.info "event=sign status=complete signature=author_signature author=#{author} obj=#{self}"
  end
end
signature_data() click to toggle source

@return [String] signature data string

# File lib/diaspora_federation/entities/relayable.rb, line 148
def signature_data
  data = normalized_properties.merge(additional_data)
  signature_order.map {|name| data[name] }.join(";")
end
signature_order=(order) click to toggle source
# File lib/diaspora_federation/entities/relayable.rb, line 137
def signature_order=(order)
  prop_names = self.class.class_props.keys.map(&:to_s)
  @signature_order = order.grep_v(/signature/)
                          .map {|name| prop_names.include?(name) ? name.to_sym : name }
end
xml_elements() click to toggle source

Sort all XML elements according to the order used for the signatures.

@return [Hash] sorted xml elements

Calls superclass method
# File lib/diaspora_federation/entities/relayable.rb, line 130
def xml_elements
  data = super
  order = signature_order
  order += %i[author_signature] unless author == parent.root.author
  order.to_h {|element| [element, data[element].to_s] }
end