diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-20 18:40:28 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-20 18:40:28 +0300 |
commit | b595cb0c1dec83de5bdee18284abe86614bed33b (patch) | |
tree | 8c3d4540f193c5ff98019352f554e921b3a41a72 /lib/gitlab/quick_actions | |
parent | 2f9104a328fc8a4bddeaa4627b595166d24671d0 (diff) |
Add latest changes from gitlab-org/gitlab@15-2-stable-eev15.2.0-rc42
Diffstat (limited to 'lib/gitlab/quick_actions')
-rw-r--r-- | lib/gitlab/quick_actions/issuable_actions.rb | 26 | ||||
-rw-r--r-- | lib/gitlab/quick_actions/users_extractor.rb | 94 |
2 files changed, 107 insertions, 13 deletions
diff --git a/lib/gitlab/quick_actions/issuable_actions.rb b/lib/gitlab/quick_actions/issuable_actions.rb index 259d9e38d65..3b85d6952a1 100644 --- a/lib/gitlab/quick_actions/issuable_actions.rb +++ b/lib/gitlab/quick_actions/issuable_actions.rb @@ -23,7 +23,7 @@ module Gitlab _('Closed this %{quick_action_target}.') % { quick_action_target: quick_action_target.to_ability_name.humanize(capitalize: false) } end - types Issuable + types ::Issuable condition do quick_action_target.persisted? && quick_action_target.open? && @@ -45,7 +45,7 @@ module Gitlab _('Reopened this %{quick_action_target}.') % { quick_action_target: quick_action_target.to_ability_name.humanize(capitalize: false) } end - types Issuable + types ::Issuable condition do quick_action_target.persisted? && quick_action_target.closed? && @@ -63,7 +63,7 @@ module Gitlab _('Changed the title to "%{title_param}".') % { title_param: title_param } end params '<New title>' - types Issuable + types ::Issuable condition do quick_action_target.persisted? && current_user.can?(:"update_#{quick_action_target.to_ability_name}", quick_action_target) @@ -82,7 +82,7 @@ module Gitlab end end params '~label1 ~"label 2"' - types Issuable + types ::Issuable condition do current_user.can?(:"set_#{quick_action_target.to_ability_name}_metadata", quick_action_target) && find_labels.any? @@ -102,7 +102,7 @@ module Gitlab end end params '~label1 ~"label 2"' - types Issuable + types ::Issuable condition do quick_action_target.persisted? && quick_action_target.labels.any? && @@ -134,7 +134,7 @@ module Gitlab "Replaces all labels with #{labels.join(' ')} #{'label'.pluralize(labels.count)}." if labels.any? end params '~label1 ~"label 2"' - types Issuable + types ::Issuable condition do quick_action_target.persisted? && quick_action_target.labels.any? && @@ -147,7 +147,7 @@ module Gitlab desc { _('Add a to do') } explanation { _('Adds a to do.') } execution_message { _('Added a to do.') } - types Issuable + types ::Issuable condition do quick_action_target.persisted? && !TodoService.new.todo_exist?(quick_action_target, current_user) @@ -159,7 +159,7 @@ module Gitlab desc { _('Mark to do as done') } explanation { _('Marks to do as done.') } execution_message { _('Marked to do as done.') } - types Issuable + types ::Issuable condition do quick_action_target.persisted? && TodoService.new.todo_exist?(quick_action_target, current_user) @@ -177,7 +177,7 @@ module Gitlab _('Subscribed to this %{quick_action_target}.') % { quick_action_target: quick_action_target.to_ability_name.humanize(capitalize: false) } end - types Issuable + types ::Issuable condition do quick_action_target.persisted? && !quick_action_target.subscribed?(current_user, project) @@ -195,7 +195,7 @@ module Gitlab _('Unsubscribed from this %{quick_action_target}.') % { quick_action_target: quick_action_target.to_ability_name.humanize(capitalize: false) } end - types Issuable + types ::Issuable condition do quick_action_target.persisted? && quick_action_target.subscribed?(current_user, project) @@ -212,7 +212,7 @@ module Gitlab _("Toggled :%{name}: emoji award.") % { name: name } if name end params ':emoji:' - types Issuable + types ::Issuable condition do quick_action_target.persisted? end @@ -228,14 +228,14 @@ module Gitlab desc { _("Append the comment with %{shrug}") % { shrug: SHRUG } } params '<Comment>' - types Issuable + types ::Issuable substitution :shrug do |comment| "#{comment} #{SHRUG}" end desc { _("Append the comment with %{tableflip}") % { tableflip: TABLEFLIP } } params '<Comment>' - types Issuable + types ::Issuable substitution :tableflip do |comment| "#{comment} #{TABLEFLIP}" end diff --git a/lib/gitlab/quick_actions/users_extractor.rb b/lib/gitlab/quick_actions/users_extractor.rb new file mode 100644 index 00000000000..06e04c74312 --- /dev/null +++ b/lib/gitlab/quick_actions/users_extractor.rb @@ -0,0 +1,94 @@ +# frozen_string_literal: true + +module Gitlab + module QuickActions + class UsersExtractor + MAX_QUICK_ACTION_USERS = 100 + + Error = Class.new(ArgumentError) + TooManyError = Class.new(Error) do + def limit + MAX_QUICK_ACTION_USERS + end + end + + MissingError = Class.new(Error) + TooManyFoundError = Class.new(TooManyError) + TooManyRefsError = Class.new(TooManyError) + + attr_reader :text, :current_user, :project, :group, :target + + def initialize(current_user, project:, group:, target:, text:) + @current_user = current_user + @project = project + @group = group + @target = target + @text = text + end + + def execute + return [] unless text.present? + + users = collect_users + + check_users!(users) + + users + end + + private + + def collect_users + users = [] + users << current_user if me? + users += find_referenced_users if references.any? + + users + end + + def check_users!(users) + raise TooManyFoundError if users.size > MAX_QUICK_ACTION_USERS + + found = found_names(users) + missing = references.filter_map do + "'#{_1}'" unless found.include?(_1.downcase.delete_prefix('@')) + end + + raise MissingError, missing.to_sentence if missing.present? + end + + def found_names(users) + users.map(&:username).map(&:downcase).to_set + end + + def find_referenced_users + raise TooManyRefsError if references.size > MAX_QUICK_ACTION_USERS + + User.by_username(usernames).limit(MAX_QUICK_ACTION_USERS) + end + + def usernames + references.map { _1.delete_prefix('@') } + end + + def references + @references ||= begin + refs = args - ['me'] + # nb: underscores may be passed in escaped to protect them from markdown rendering + refs.map! { _1.gsub(/\\_/, '_') } + refs + end + end + + def args + @args ||= text.split(/\s|,/).map(&:strip).select(&:present?).uniq - ['and'] + end + + def me? + args&.include?('me') + end + end + end +end + +Gitlab::QuickActions::UsersExtractor.prepend_mod_with('Gitlab::QuickActions::UsersExtractor') |