summaryrefslogtreecommitdiff
path: root/app/models/sent_notification.rb
blob: 558e4c1a7ebcbc7819647d89c8138b1046063850 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
class SentNotification < ActiveRecord::Base
  serialize :position, Gitlab::Diff::Position

  belongs_to :project
  belongs_to :noteable, polymorphic: true
  belongs_to :recipient, class_name: "User"

  validates :project, :recipient, presence: true
  validates :reply_key, presence: true, uniqueness: true
  validates :noteable_id, presence: true, unless: :for_commit?
  validates :commit_id, presence: true, if: :for_commit?
  validates :in_reply_to_discussion_id, format: { with: /\A\h{40}\z/, if: :discussion_note? }
  validate :note_valid

  after_save :keep_around_commit

  class << self
    def reply_key
      SecureRandom.hex(16)
    end

    def for(reply_key)
      find_by(reply_key: reply_key)
    end

    def record(noteable, recipient_id, reply_key, attrs = {})
      return unless reply_key

      noteable_id = nil
      commit_id = nil
      if noteable.is_a?(Commit)
        commit_id = noteable.id
      else
        noteable_id = noteable.id
      end

      attrs.reverse_merge!(
        project: noteable.project,
        noteable_type: noteable.class.name,
        noteable_id: noteable_id,
        commit_id: commit_id,
        recipient_id: recipient_id,
        reply_key: reply_key
      )

      create(attrs)
    end

    def record_note(note, recipient_id, reply_key, attrs = {})
      attrs.merge!(
        note_type: note.type,
        in_reply_to_discussion_id: note.discussion_id
      )

      attrs.merge!(note.diff_attributes) if note.diff_note?

      record(note.noteable, recipient_id, reply_key, attrs)
    end
  end

  def unsubscribable?
    !for_commit?
  end

  def for_commit?
    noteable_type == "Commit"
  end

  def discussion_note?
    note_type == DiscussionNote.name
  end

  def noteable
    if for_commit?
      project.commit(commit_id) rescue nil
    else
      super
    end
  end

  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

  def to_param
    self.reply_key
  end

  def create_note(note)
    Notes::CreateService.new(
      self.project,
      self.recipient,
      self.note_params.merge(note: note)
    ).execute
  end

  private

  def note_params
    {
      project: self.project,
      author: self.recipient,
      type: self.note_type,
      noteable_type: self.noteable_type,
      noteable_id: self.noteable_id,
      commit_id: self.commit_id,

      # LegacyDiffNote
      line_code: self.line_code,

      # DiffNote
      position: self.position.to_json,

      # DiscussionNote
      in_reply_to_discussion_id: self.in_reply_to_discussion_id
    }
  end

  def note_valid
    Note.new(note_params.merge(note: "Test")).valid?
  end

  def keep_around_commit
    project.repository.keep_around(self.commit_id)
  end
end