diff options
Diffstat (limited to 'app/models/issue.rb')
-rw-r--r-- | app/models/issue.rb | 86 |
1 files changed, 56 insertions, 30 deletions
diff --git a/app/models/issue.rb b/app/models/issue.rb index 3a9a6dba601..7bfc45c1f43 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -1,17 +1,18 @@ require 'carrierwave/orm/activerecord' class Issue < ActiveRecord::Base - include InternalId + include AtomicInternalId include Issuable include Noteable include Referable - include Sortable include Spammable include FasterCacheKeys include RelativePositioning + include TimeTrackable + include ThrottledTouch include IgnorableColumn - ignore_column :position + ignore_column :assignee_id, :branch_name, :deleted_at DueDateStruct = Struct.new(:title, :name).freeze NoDueDate = DueDateStruct.new('No Due Date', '0').freeze @@ -23,15 +24,21 @@ class Issue < ActiveRecord::Base belongs_to :project belongs_to :moved_to, class_name: 'Issue' - has_many :events, as: :target, dependent: :destroy + has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.issues&.maximum(:iid) } - has_many :merge_requests_closing_issues, class_name: 'MergeRequestsClosingIssues', dependent: :delete_all + has_many :events, as: :target, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent + + has_many :merge_requests_closing_issues, + class_name: 'MergeRequestsClosingIssues', + dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent has_many :issue_assignees has_many :assignees, class_name: "User", through: :issue_assignees validates :project, presence: true + alias_attribute :parent_ids, :project_id + scope :in_projects, ->(project_ids) { where(project_id: project_ids) } scope :assigned, -> { where('EXISTS (SELECT TRUE FROM issue_assignees WHERE issue_id = issues.id)') } @@ -45,10 +52,10 @@ class Issue < ActiveRecord::Base scope :order_due_date_asc, -> { reorder('issues.due_date IS NULL, issues.due_date ASC') } scope :order_due_date_desc, -> { reorder('issues.due_date IS NULL, issues.due_date DESC') } - scope :created_after, -> (datetime) { where("created_at >= ?", datetime) } - scope :preload_associations, -> { preload(:labels, project: :namespace) } + scope :public_only, -> { where(confidential: false) } + after_save :expire_etag_cache attr_spammable :title, spam_title: true @@ -58,15 +65,14 @@ class Issue < ActiveRecord::Base state_machine :state, initial: :opened do event :close do - transition [:reopened, :opened] => :closed + transition [:opened] => :closed end event :reopen do - transition closed: :reopened + transition closed: :opened end state :opened - state :reopened state :closed before_transition any => :closed do |issue| @@ -74,18 +80,8 @@ class Issue < ActiveRecord::Base end end - def hook_attrs - assignee_ids = self.assignee_ids - - attrs = { - total_time_spent: total_time_spent, - human_total_time_spent: human_total_time_spent, - human_time_estimate: human_time_estimate, - assignee_ids: assignee_ids, - assignee_id: assignee_ids.first # This key is deprecated - } - - attributes.merge!(attrs) + class << self + alias_method :in_parents, :in_projects end def self.reference_prefix @@ -116,7 +112,8 @@ class Issue < ActiveRecord::Base def self.sort(method, excluded_labels: []) case method.to_s - when 'due_date_asc' then order_due_date_asc + when 'due_date' then order_due_date_asc + when 'due_date_asc' then order_due_date_asc when 'due_date_desc' then order_due_date_desc else super @@ -130,6 +127,10 @@ class Issue < ActiveRecord::Base "id DESC") end + def hook_attrs + Gitlab::HookData::IssueBuilder.new(self).build + end + # Returns a Hash of attributes to be used for Twitter card metadata def card_attributes { @@ -160,7 +161,18 @@ class Issue < ActiveRecord::Base object.all_references(current_user, extractor: ext) end - ext.merge_requests.sort_by(&:iid) + merge_requests = ext.merge_requests.sort_by(&:iid) + + cross_project_filter = -> (merge_requests) do + merge_requests.select { |mr| mr.target_project == project } + end + + Ability.merge_requests_readable_by_user( + merge_requests, current_user, + filters: { + read_cross_project: cross_project_filter + } + ) end # All branches containing the current issue's ID, except for @@ -254,7 +266,12 @@ class Issue < ActiveRecord::Base def as_json(options = {}) super(options).tap do |json| - json[:subscribed] = subscribed?(options[:user], project) if options.key?(:user) && options[:user] + if options.key?(:sidebar_endpoints) && project + url_helper = Gitlab::Routing.url_helpers + + json.merge!(issue_sidebar_endpoint: url_helper.project_issue_path(project, self, format: :json, serializer: 'sidebar'), + toggle_subscription_endpoint: url_helper.toggle_subscription_project_issue_path(project, self)) + end if options.key?(:labels) json[:labels] = labels.as_json( @@ -266,8 +283,21 @@ class Issue < ActiveRecord::Base end end + def discussions_rendered_on_frontend? + true + end + + def update_project_counter_caches + Projects::OpenIssuesCountService.new(project).refresh_cache + end + private + def ensure_metrics + super + metrics.record! + end + # Returns `true` if the given User can read the current Issue. # # This method duplicates the same check of issue_policy.rb @@ -295,11 +325,7 @@ class Issue < ActiveRecord::Base end def expire_etag_cache - key = Gitlab::Routing.url_helpers.realtime_changes_namespace_project_issue_path( - project.namespace, - project, - self - ) + key = Gitlab::Routing.url_helpers.realtime_changes_project_issue_path(project, self) Gitlab::EtagCaching::Store.new.touch(key) end end |