104 lines
2.9 KiB
Ruby
104 lines
2.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# Copyright (c) 2010-2011, Diaspora Inc. This file is
|
|
# licensed under the Affero General Public License version 3 or later. See
|
|
# the COPYRIGHT file.
|
|
|
|
class Contact < ApplicationRecord
|
|
include Diaspora::Federated::Base
|
|
|
|
belongs_to :user
|
|
belongs_to :person
|
|
|
|
validates :person_id, uniqueness: {scope: :user_id}
|
|
|
|
delegate :name, :diaspora_handle, :guid, :first_name,
|
|
to: :person, prefix: true
|
|
|
|
has_many :aspect_memberships, dependent: :destroy
|
|
has_many :aspects, through: :aspect_memberships
|
|
|
|
validate :not_contact_for_self,
|
|
:not_blocked_user,
|
|
:not_contact_with_closed_account
|
|
|
|
before_destroy :destroy_notifications
|
|
|
|
scope :all_contacts_of_person, ->(x) { where(person_id: x.id) }
|
|
|
|
# contact.sharing is true when contact.person is sharing with contact.user
|
|
scope :sharing, -> { where(sharing: true) }
|
|
|
|
# contact.receiving is true when contact.user is sharing with contact.person
|
|
scope :receiving, -> { where(receiving: true) }
|
|
|
|
scope :mutual, -> { sharing.receiving }
|
|
|
|
scope :for_a_stream, -> { includes(:aspects, person: :profile).order("profiles.last_name ASC") }
|
|
|
|
scope :only_sharing, -> { sharing.where(receiving: false) }
|
|
|
|
def destroy_notifications
|
|
Notification.where(
|
|
target_type: "Person",
|
|
target_id: person_id,
|
|
recipient_id: user_id,
|
|
type: "Notifications::StartedSharing"
|
|
).destroy_all
|
|
end
|
|
|
|
def mutual?
|
|
sharing && receiving
|
|
end
|
|
|
|
def in_aspect?(aspect)
|
|
if aspect_memberships.loaded?
|
|
aspect_memberships.detect{ |am| am.aspect_id == aspect.id }
|
|
elsif aspects.loaded?
|
|
aspects.detect{ |a| a.id == aspect.id }
|
|
else
|
|
AspectMembership.exists?(:contact_id => self.id, :aspect_id => aspect.id)
|
|
end
|
|
end
|
|
|
|
# Follows back if user setting is set so
|
|
def receive(_recipient_user_ids)
|
|
user.share_with(person, user.auto_follow_back_aspect) if user.auto_follow_back && !receiving
|
|
end
|
|
|
|
# object for local recipients
|
|
def object_to_receive
|
|
Contact.create_or_update_sharing_contact(person.owner, user.person)
|
|
end
|
|
|
|
# @return [Array<Person>] The recipient of the contact
|
|
def subscribers
|
|
[person]
|
|
end
|
|
|
|
# creates or updates a contact with active sharing flag. Returns nil if already sharing.
|
|
def self.create_or_update_sharing_contact(recipient, sender)
|
|
contact = recipient.contacts.find_or_initialize_by(person_id: sender.id)
|
|
|
|
return if contact.sharing
|
|
|
|
contact.update(sharing: true)
|
|
contact
|
|
end
|
|
|
|
private
|
|
|
|
def not_contact_with_closed_account
|
|
errors.add(:base, "Cannot be in contact with a closed account") if person_id && person.closed_account?
|
|
end
|
|
|
|
def not_contact_for_self
|
|
errors.add(:base, "Cannot create self-contact") if person_id && person.owner == user
|
|
end
|
|
|
|
def not_blocked_user
|
|
if receiving && user && user.blocks.where(person_id: person_id).exists?
|
|
errors.add(:base, "Cannot connect to an ignored user")
|
|
end
|
|
end
|
|
end
|