sent_notification.rb 2.91 KB
Newer Older
1 2
# frozen_string_literal: true

Douwe Maan's avatar
Douwe Maan committed
3
class SentNotification < ActiveRecord::Base
4
  serialize :position, Gitlab::Diff::Position # rubocop:disable Cop/ActiveRecordSerialize
5

Douwe Maan's avatar
Douwe Maan committed
6
  belongs_to :project
7
  belongs_to :noteable, polymorphic: true # rubocop:disable Cop/PolymorphicAssociations
Douwe Maan's avatar
Douwe Maan committed
8 9
  belongs_to :recipient, class_name: "User"

10
  validates :recipient, presence: true
11
  validates :reply_key, presence: true, uniqueness: true
Douwe Maan's avatar
Douwe Maan committed
12 13
  validates :noteable_id, presence: true, unless: :for_commit?
  validates :commit_id, presence: true, if: :for_commit?
14
  validates :in_reply_to_discussion_id, format: { with: /\A\h{40}\z/, allow_nil: true }
15
  validate :note_valid
Douwe Maan's avatar
Douwe Maan committed
16

17
  after_save :keep_around_commit, if: :for_commit?
18

19
  class << self
20 21 22 23
    def reply_key
      SecureRandom.hex(16)
    end

24 25 26 27
    def for(reply_key)
      find_by(reply_key: reply_key)
    end

Douwe Maan's avatar
Douwe Maan committed
28
    def record(noteable, recipient_id, reply_key = self.reply_key, attrs = {})
29 30 31 32 33 34 35 36
      noteable_id = nil
      commit_id = nil
      if noteable.is_a?(Commit)
        commit_id = noteable.id
      else
        noteable_id = noteable.id
      end

37
      attrs.reverse_merge!(
38 39 40 41 42 43
        project: noteable.project,
        recipient_id: recipient_id,
        reply_key: reply_key,

        noteable_type: noteable.class.name,
        noteable_id: noteable_id,
44
        commit_id: commit_id
45
      )
46

47
      create(attrs)
48 49
    end

Douwe Maan's avatar
Douwe Maan committed
50
    def record_note(note, recipient_id, reply_key = self.reply_key, attrs = {})
51
      attrs[:in_reply_to_discussion_id] = note.discussion_id if note.part_of_discussion?
52 53

      record(note.noteable, recipient_id, reply_key, attrs)
54
    end
Douwe Maan's avatar
Douwe Maan committed
55 56
  end

57
  def unsubscribable?
58
    !(for_commit? || for_snippet?)
59 60
  end

Douwe Maan's avatar
Douwe Maan committed
61 62 63 64
  def for_commit?
    noteable_type == "Commit"
  end

65 66 67 68
  def for_snippet?
    noteable_type.end_with?('Snippet')
  end

Douwe Maan's avatar
Douwe Maan committed
69 70
  def noteable
    if for_commit?
Douwe Maan's avatar
Douwe Maan committed
71
      project.commit(commit_id) rescue nil
Douwe Maan's avatar
Douwe Maan committed
72 73 74 75
    else
      super
    end
  end
76

77 78 79 80 81 82 83 84 85 86 87 88 89
  def position=(new_position)
    if new_position.is_a?(String)
      new_position = JSON.parse(new_position) rescue nil
    end

    if new_position.is_a?(Hash)
      new_position = new_position.with_indifferent_access
      new_position = Gitlab::Diff::Position.new(new_position)
    end

    super(new_position)
  end

90 91 92
  def to_param
    self.reply_key
  end
93

Douwe Maan's avatar
Douwe Maan committed
94 95 96 97 98 99 100 101
  def create_reply(message, dryrun: false)
    klass = dryrun ? Notes::BuildService : Notes::CreateService
    klass.new(self.project, self.recipient, reply_params.merge(note: message)).execute
  end

  private

  def reply_params
102
    {
103 104
      noteable_type: self.noteable_type,
      noteable_id: self.noteable_id,
105 106
      commit_id: self.commit_id,
      in_reply_to_discussion_id: self.in_reply_to_discussion_id
107 108 109 110
    }
  end

  def note_valid
Douwe Maan's avatar
Douwe Maan committed
111 112 113 114 115
    note = create_reply('Test', dryrun: true)

    unless note.valid?
      self.errors.add(:base, "Note parameters are invalid: #{note.errors.full_messages.to_sentence}")
    end
116 117
  end

118 119 120
  def keep_around_commit
    project.repository.keep_around(self.commit_id)
  end
Douwe Maan's avatar
Douwe Maan committed
121
end