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