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 'lib/gitlab/quick_actions/users_extractor.rb')
-rw-r--r--lib/gitlab/quick_actions/users_extractor.rb94
1 files changed, 94 insertions, 0 deletions
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')