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

users_extractor.rb « quick_actions « gitlab « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 06e04c74312e0f8712be756a4ebddec019d743bd (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
# 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')