diaspora/lib/archive_validator/relayable_validator.rb
cmrd Senya f85f167f50 Implement archive import backend
This implements archive import feature.

The feature is divided in two main subfeatures: archive validation and archive import.

Archive validation performs different validation on input user archive. This can be
used without actually running import, e.g. when user wants to check the archive
before import from the frontend. Validators may add messages and modify the archive.

Validators are separated in two types: critical validators and non-critical validators.

If validations by critical validators fail it means we can't import archive.

If non-critical validations fail, we can import archive, but some warning messages
are rendered.

Also validators may change archive contents, e.g. when some entity can't be
imported it may be removed from the archive.

Validators' job is to take away complexity from the importer and perform the validations
which are not implemented in other parts of the system, e.g. DB validations or
diaspora_federation entity validations.

Archive importer then takes the modified archive from the validator and imports it.

In order to incapsulate high-level migration logic a MigrationService is
introduced. MigrationService links ArchiveValidator, ArchiveImporter and
AccountMigration.

Also here is introduced a rake task which may be used by podmins to run archive
import.
2019-04-26 18:41:27 +03:00

66 lines
1.7 KiB
Ruby

# frozen_string_literal: true
class ArchiveValidator
# We have to validate relayables before import because during import we'll not be able to fetch parent anymore
# because parent author will point to ourselves.
class RelayableValidator < BaseValidator
include EntitiesHelper
def initialize(archive_hash, relayable)
@relayable = relayable
super(archive_hash)
end
private
def validate
self.valid = parent_present?
end
attr_reader :relayable
alias json relayable
# TODO: use diaspora federation to fetch parent where possible
# For own relayables we could just use RelatedEntity.fetch;
# For others' relayables we should check the present "own posts" first, and then if the target post is missing from
# there we could try to fetch it with RelatedEntity.fetch.
# Common methods used by subclasses:
def missing_parent_message
messages.push("Parent entity for #{self} is missing. Impossible to import, ignoring.")
end
def parent_present?
parent.present? || (missing_parent_message && false)
end
def parent
@parent ||= find_parent
end
def find_parent
if entity_type == "poll_participation"
post_find_by_poll_guid(parent_guid)
else
post_find_by_guid(parent_guid)
end
end
def parent_guid
entity_data.fetch("parent_guid")
end
def post_find_by_guid(guid)
posts.find {|post|
post.fetch("entity_data").fetch("guid") == guid
}
end
def post_find_by_poll_guid(guid)
posts.find {|post|
post.fetch("entity_data").fetch("poll", nil)&.fetch("entity_data", nil)&.fetch("guid", nil) == guid
}
end
end
end