Welcome to mirror list, hosted at ThFree Co, Russian Federation.

resource_label_event.rb « models « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 98fc9e7bae89a1906bf049fa1c4b07f5fc1025eb (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
136
137
# frozen_string_literal: true

class ResourceLabelEvent < ApplicationRecord
  include Importable
  include Gitlab::Utils::StrongMemoize
  include CacheMarkdownField

  cache_markdown_field :reference

  belongs_to :user
  belongs_to :issue
  belongs_to :merge_request
  belongs_to :label

  scope :created_after, ->(time) { where('created_at > ?', time) }
  scope :inc_relations, -> { includes(:label, :user) }

  validates :user, presence: { unless: :importing? }, on: :create
  validates :label, presence: { unless: :importing? }, on: :create
  validate :exactly_one_issuable

  after_save :expire_etag_cache
  after_destroy :expire_etag_cache

  enum action: {
    add: 1,
    remove: 2
  }

  def self.issuable_attrs
    %i(issue merge_request).freeze
  end

  def self.preload_label_subjects(events)
    labels = events.map(&:label).compact
    project_labels, group_labels = labels.partition { |label| label.is_a? ProjectLabel }

    preloader = ActiveRecord::Associations::Preloader.new
    preloader.preload(project_labels, { project: :project_feature })
    preloader.preload(group_labels, :group)
  end

  def issuable
    issue || merge_request
  end

  def discussion_id(resource = nil)
    strong_memoize(:discussion_id) do
      Digest::SHA1.hexdigest(discussion_id_key.join("-"))
    end
  end

  def project
    issuable.project
  end

  def group
    issuable.group if issuable.respond_to?(:group)
  end

  def outdated_markdown?
    return true if label_id.nil? && reference.present?

    reference.nil? || latest_cached_markdown_version != cached_markdown_version
  end

  def banzai_render_context(field)
    super.merge(pipeline: 'label', only_path: true)
  end

  def refresh_invalid_reference
    # label_id could be nullified on label delete
    self.reference = '' if label_id.nil?

    # reference is not set for events which were not rendered yet
    self.reference ||= label_reference

    if changed?
      save
    elsif invalidated_markdown_cache?
      refresh_markdown_cache!
    end
  end

  private

  def label_reference
    if local_label?
      label.to_reference(format: :id)
    elsif label.is_a?(GroupLabel)
      label.to_reference(label.group, target_project: resource_parent, format: :id)
    else
      label.to_reference(resource_parent, format: :id)
    end
  end

  def exactly_one_issuable
    issuable_count = self.class.issuable_attrs.count { |attr| self["#{attr}_id"] }

    return true if issuable_count == 1

    # if none of issuable IDs is set, check explicitly if nested issuable
    # object is set, this is used during project import
    if issuable_count == 0 && importing?
      issuable_count = self.class.issuable_attrs.count { |attr| self.public_send(attr) } # rubocop:disable GitlabSecurity/PublicSend

      return true if issuable_count == 1
    end

    errors.add(:base, "Exactly one of #{self.class.issuable_attrs.join(', ')} is required")
  end

  def expire_etag_cache
    issuable.expire_note_etag_cache
  end

  def local_label?
    params = { include_ancestor_groups: true }
    if resource_parent.is_a?(Project)
      params[:project_id] = resource_parent.id
    else
      params[:group_id] = resource_parent.id
    end

    LabelsFinder.new(nil, params).execute(skip_authorization: true).where(id: label.id).any?
  end

  def resource_parent
    issuable.project || issuable.group
  end

  def discussion_id_key
    [self.class.name, created_at, user_id]
  end
end

ResourceLabelEvent.prepend_if_ee('EE::ResourceLabelEvent')