lib/diaspora_federation/entities/account_migration.rb
# frozen_string_literal: true
module DiasporaFederation
module Entities
# This entity is sent when a person changes their diaspora* ID (e.g. when a user migration
# from one to another pod happens).
#
# @see Validators::AccountMigrationValidator
class AccountMigration < Entity
include AccountMigration::Signable
# @!attribute [r] author
# Sender of the AccountMigration message. Usually it is the old diaspora* ID of the person who changes their ID.
# This property is also allowed to be the new diaspora* ID, which is equal to the author of the included
# profile.
# @see Person#author
# @return [String] author diaspora* ID
property :author, :string
# @!attribute [r] profile
# Holds new updated profile of a person, including diaspora* ID
# @return [Person] person new data
entity :profile, Entities::Profile
# @!attribute [r] signature
# Signature that validates original and target diaspora* IDs with the private key of the second identity, other
# than the entity author. So if the author is the old identity then this signature is made with the new identity
# key, and vice versa.
# @return [String] signature
property :signature, :string, default: nil
# @!attribute [r] old_identity
# Optional attribute which keeps old diaspora* ID. Must be present when author attribute contains new diaspora*
# ID.
# @return [String] old identity
property :old_identity, :string, default: nil
# @!attribute [r] remote_photo_path
# The url to the path of the photos on the new pod. Can be empty if photos weren't migrated.
# @return [String] remote photo path
property :remote_photo_path, :string, optional: true
# Returns diaspora* ID of the old person identity.
# @return [String] diaspora* ID of the old person identity
def old_identity
return @old_identity if author_is_new_id?
author
end
# Returns diaspora* ID of the new person identity.
# @return [String] diaspora* ID of the new person identity
def new_identity
profile&.author
end
# @return [String] string representation of this object
alias to_s unique_migration_descriptor
# Shortcut for calling super method with sensible arguments
#
# @see DiasporaFederation::Entities::Signable#verify_signature
def verify_signature
super(signer_id, :signature)
end
# Calls super and additionally does signature verification for the instantiated entity.
#
# @see DiasporaFederation::Entity.from_hash
def self.from_hash(*args)
super.tap(&:verify_signature)
end
private
def author_is_new_id?
author == new_identity
end
def signer_id
author_is_new_id? ? @old_identity : new_identity
end
def enriched_properties
super.tap do |hash|
hash[:signature] = signature || sign_with_respective_key
end
end
# Sign with the key of the #signer_id identity
# @raise [PrivateKeyNotFound] if the signer's private key is not found
# @return [String] A Base64 encoded signature of #signature_data with key
def sign_with_respective_key
privkey = DiasporaFederation.callbacks.trigger(:fetch_private_key, signer_id)
raise PrivateKeyNotFound, "signer=#{signer_id} obj=#{self}" if privkey.nil?
sign_with_key(privkey).tap do
logger.info "event=sign status=complete signature=signature signer=#{signer_id} obj=#{self}"
end
end
# Raised, if creating the signature fails, because the new private key of a user was not found
class PrivateKeyNotFound < RuntimeError
end
end
end
end