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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/concerns/mentionable.rb')
-rw-r--r--app/models/concerns/mentionable.rb80
1 files changed, 80 insertions, 0 deletions
diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb
index 9b6c57261d8..b43b91699ab 100644
--- a/app/models/concerns/mentionable.rb
+++ b/app/models/concerns/mentionable.rb
@@ -80,6 +80,66 @@ module Mentionable
all_references(current_user).users
end
+ def store_mentions!
+ # if store_mentioned_users_to_db feature flag is not enabled then consider storing operation as succeeded
+ # because we wrap this method in transaction with with_transaction_returning_status, and we need the status to be
+ # successful if mentionable.save is successful.
+ #
+ # This line will get removed when we remove the feature flag.
+ return true unless store_mentioned_users_to_db_enabled?
+
+ refs = all_references(self.author)
+
+ references = {}
+ references[:mentioned_users_ids] = refs.mentioned_users&.pluck(:id).presence
+ references[:mentioned_groups_ids] = refs.mentioned_groups&.pluck(:id).presence
+ references[:mentioned_projects_ids] = refs.mentioned_projects&.pluck(:id).presence
+
+ # One retry should be enough as next time `model_user_mention` should return the existing mention record, that
+ # threw the `ActiveRecord::RecordNotUnique` exception in first place.
+ self.class.safe_ensure_unique(retries: 1) do
+ user_mention = model_user_mention
+ user_mention.mentioned_users_ids = references[:mentioned_users_ids]
+ user_mention.mentioned_groups_ids = references[:mentioned_groups_ids]
+ user_mention.mentioned_projects_ids = references[:mentioned_projects_ids]
+
+ if user_mention.has_mentions?
+ user_mention.save!
+ elsif user_mention.persisted?
+ user_mention.destroy!
+ end
+
+ true
+ end
+ end
+
+ def referenced_users
+ User.where(id: user_mentions.select("unnest(mentioned_users_ids)"))
+ end
+
+ def referenced_projects(current_user = nil)
+ Project.where(id: user_mentions.select("unnest(mentioned_projects_ids)")).public_or_visible_to_user(current_user)
+ end
+
+ def referenced_project_users(current_user = nil)
+ User.joins(:project_members).where(members: { source_id: referenced_projects(current_user) }).distinct
+ end
+
+ def referenced_groups(current_user = nil)
+ # TODO: IMPORTANT: Revisit before using it.
+ # Check DB data for max mentioned groups per mentionable:
+ #
+ # select issue_id, count(mentions_count.men_gr_id) gr_count from
+ # (select DISTINCT unnest(mentioned_groups_ids) as men_gr_id, issue_id
+ # from issue_user_mentions group by issue_id, mentioned_groups_ids) as mentions_count
+ # group by mentions_count.issue_id order by gr_count desc limit 10
+ Group.where(id: user_mentions.select("unnest(mentioned_groups_ids)")).public_or_visible_to_user(current_user)
+ end
+
+ def referenced_group_users(current_user = nil)
+ User.joins(:group_members).where(members: { source_id: referenced_groups }).distinct
+ end
+
def directly_addressed_users(current_user = nil)
all_references(current_user).directly_addressed_users
end
@@ -171,6 +231,26 @@ module Mentionable
def mentionable_params
{}
end
+
+ # User mention that is parsed from model description rather then its related notes.
+ # Models that have a descriprion attribute like Issue, MergeRequest, Epic, Snippet may have such a user mention.
+ # Other mentionable models like Commit, DesignManagement::Design, will never have such record as those do not have
+ # a description attribute.
+ #
+ # Using this method followed by a call to *save* may result in *ActiveRecord::RecordNotUnique* exception
+ # in a multithreaded environment. Make sure to use it within a *safe_ensure_unique* block.
+ def model_user_mention
+ user_mentions.where(note_id: nil).first_or_initialize
+ end
+
+ # We need this method to be checking that store_mentioned_users_to_db feature flag is enabled at the group level
+ # and not the project level as epics are defined at group level and we want to have epics store user mentions as well
+ # for the test period.
+ # During the test period the flag should be enabled at the group level.
+ def store_mentioned_users_to_db_enabled?
+ return Feature.enabled?(:store_mentioned_users_to_db, self.project&.group) if self.respond_to?(:project)
+ return Feature.enabled?(:store_mentioned_users_to_db, self.group) if self.respond_to?(:group)
+ end
end
Mentionable.prepend_if_ee('EE::Mentionable')