otwarchive-symphonyarchive/app/models/external_author.rb

179 lines
5.6 KiB
Ruby
Raw Normal View History

2026-03-11 22:22:11 +00:00
class ExternalAuthor < ApplicationRecord
# send :include, Activation # eventually we will let users create new identities
EMAIL_LENGTH_MIN = 3
EMAIL_LENGTH_MAX = 300
belongs_to :user
has_many :external_author_names, dependent: :destroy
accepts_nested_attributes_for :external_author_names, allow_destroy: true
validates_associated :external_author_names
has_many :external_creatorships, through: :external_author_names
has_many :works, -> { distinct }, through: :external_creatorships, source: :creation, source_type: 'Work'
has_one :invitation
validates :email, uniqueness: {
allow_blank: true,
message: ts('There is already an external author with that email.')
}
validates :email, email_format: true
def self.claimed
where(is_claimed: true)
end
def self.unclaimed
where(is_claimed: false)
end
after_create :create_default_name
def external_work_creatorships
external_creatorships.where("external_creatorships.creation_type = 'Work'")
end
def create_default_name
@default_name = self.external_author_names.build
@default_name.name = self.email.to_s
self.save
end
def default_name
self.external_author_names.select {|external_name| external_name.name == self.email.to_s }.first
end
def names
self.external_author_names
end
def claimed?
is_claimed
end
def claim!(claiming_user)
raise "There is no user claiming this external author." unless claiming_user
raise "This external author is already claimed by another user" if claimed? && self.user != claiming_user
claimed_works = []
external_author_names.each do |external_author_name|
external_author_name.external_work_creatorships.each do |external_creatorship|
work = external_creatorship.creation
other_external_creators = work.external_creatorships - [external_creatorship]
other_unclaimed_creators = other_external_creators.reject(&:claimed?)
# if previously claimed by this user, don't do it again
unless work.users.include?(claiming_user)
# Get the pseud to associate with the work
pseud_to_add = claiming_user.pseuds.select {|pseud| pseud.name == external_author_name.name}.first || claiming_user.default_pseud
# If there are no other unclaimed authors, or if none of the other unclaimed authors have the same archivist,
# remove this user's archivist from the work creators, else just add the claiming user
claiming_user_archivist = external_creatorship.archivist
if other_unclaimed_creators.map(&:archivist).exclude?(claiming_user_archivist)
change_ownership(work, claiming_user_archivist, claiming_user, pseud_to_add)
else
add_creator(work, claiming_user, pseud_to_add)
end
claimed_works << work.id
end
end
end
self.user = claiming_user
self.is_claimed = true
save
notify_user_of_claim(claimed_works)
end
def unclaim!
return false unless self.is_claimed
self.external_work_creatorships.each do |external_creatorship|
# remove user, add archivist back
archivist = external_creatorship.archivist
work = external_creatorship.creation
change_ownership(work, user, archivist)
end
self.user = nil
self.is_claimed = false
save
end
def orphan(remove_pseud)
external_author_names.each do |external_author_name|
external_author_name.external_work_creatorships.each do |external_creatorship|
# remove archivist as owner, convert to the pseud
archivist = external_creatorship.archivist
work = external_creatorship.creation
archivist_pseud = work.pseuds.select {|pseud| archivist.pseuds.include?(pseud)}.first
orphan_pseud = remove_pseud ? User.orphan_account.default_pseud : User.orphan_account.pseuds.find_or_create_by(name: external_author_name.name)
change_ownership(work, archivist, User.orphan_account, orphan_pseud)
end
end
end
def delete_works
self.external_work_creatorships.each do |external_creatorship|
work = external_creatorship.creation
work.destroy
end
end
def block_import
self.do_not_import = true
save
end
def notify_user_of_claim(claimed_work_ids)
# send announcement to user of the stories they have been given
I18n.with_locale(self.user.preference.locale_for_mails) do
UserMailer.claim_notification(self.user_id, claimed_work_ids).deliver_later
end
end
def find_or_invite(archivist = nil)
if self.email
matching_user = User.find_by(email: self.email) || User.find_by_id(self.user_id)
if matching_user
self.claim!(matching_user)
else
# invite person at the email address unless they don't want invites
unless self.do_not_email
@invitation = Invitation.new(invitee_email: self.email, external_author: self, creator: User.current_user)
@invitation.save
end
end
end
end
private
# Add a new creator to the work:
def add_creator(work, creator_to_add, new_pseud = nil)
new_pseud = creator_to_add.default_pseud if new_pseud.nil?
work.transaction do
work.creatorships.find_or_create_by(pseud: new_pseud)
work.chapters.each do |chapter|
chapter.creatorships.find_or_create_by(pseud: new_pseud)
end
end
end
# Transfer ownership of the work from one user to another
def change_ownership(work, old_user, new_user, new_pseud = nil)
raise "No new user provided, cannot change ownership" unless new_user
work.transaction do
add_creator(work, new_user, new_pseud)
work.remove_author(old_user)
end
end
end