summaryrefslogtreecommitdiff
path: root/lib/api/helpers/label_helpers.rb
blob: da0ee8f207e1f03e5ca70ce5a59a959e7622b2a3 (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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# frozen_string_literal: true

module API
  module Helpers
    module LabelHelpers
      extend Grape::API::Helpers

      params :label_create_params do
        requires :name, type: String, desc: 'The name of the label to be created'
        requires :color, type: String, desc: "The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the allowed CSS color names"
        optional :description, type: String, desc: 'The description of label to be created'
      end

      params :label_update_params do
        optional :new_name, type: String, desc: 'The new name of the label'
        optional :color, type: String, desc: "The new color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the allowed CSS color names"
        optional :description, type: String, desc: 'The new description of label'
      end

      params :project_label_update_params do
        use :label_update_params
        optional :priority, type: Integer, desc: 'The priority of the label', allow_blank: true
        at_least_one_of :new_name, :color, :description, :priority
      end

      params :group_label_update_params do
        use :label_update_params
        at_least_one_of :new_name, :color, :description
      end

      def find_label(parent, id_or_title, params = { include_ancestor_groups: true })
        labels = available_labels_for(parent, params)
        label = labels.find_by_id(id_or_title) || labels.find_by_title(id_or_title)

        label || not_found!('Label')
      end

      def get_labels(parent, entity, params = {})
        present paginate(available_labels_for(parent, params)),
                with: entity,
                current_user: current_user,
                parent: parent,
                with_counts: params[:with_counts]
      end

      def get_label(parent, entity, params = {})
        label = find_label(parent, params_id_or_title, params)

        present label, with: entity, current_user: current_user, parent: parent
      end

      def create_label(parent, entity)
        authorize! :admin_label, parent

        label = available_labels_for(parent).find_by_title(params[:name])
        conflict!('Label already exists') if label

        priority = params.delete(:priority)
        label_params = declared_params(include_missing: false)

        label = ::Labels::CreateService.new(label_params).execute(create_service_params(parent))

        if label.persisted?
          if parent.is_a?(Project)
            label.prioritize!(parent, priority) if priority
          end

          present label, with: entity, current_user: current_user, parent: parent
        else
          render_validation_error!(label)
        end
      end

      def update_label(parent, entity)
        authorize! :admin_label, parent

        label = find_label(parent, params_id_or_title, include_ancestor_groups: false)
        update_priority = params.key?(:priority)
        priority = params.delete(:priority)

        # params is used to update the label so we need to remove this field here
        params.delete(:label_id)
        params.delete(:name)

        label = ::Labels::UpdateService.new(declared_params(include_missing: false)).execute(label)
        render_validation_error!(label) unless label.valid?

        if parent.is_a?(Project) && update_priority
          if priority.nil?
            label.unprioritize!(parent)
          else
            label.prioritize!(parent, priority)
          end
        end

        present label, with: entity, current_user: current_user, parent: parent
      end

      def delete_label(parent)
        authorize! :admin_label, parent

        label = find_label(parent, params_id_or_title, include_ancestor_groups: false)

        destroy_conditionally!(label)
      end

      def promote_label(parent)
        authorize! :admin_label, parent

        label = find_label(parent, params[:name], include_ancestor_groups: false)

        begin
          group_label = ::Labels::PromoteService.new(parent, current_user).execute(label)

          if group_label
            present group_label, with: Entities::GroupLabel, current_user: current_user, parent: parent.group
          else
            render_api_error!('Failed to promote project label to group label', 400)
          end
        rescue StandardError => error
          render_api_error!(error.to_s, 400)
        end
      end

      def params_id_or_title
        @params_id_or_title ||= params[:label_id] || params[:name]
      end

      def create_service_params(parent)
        if parent.is_a?(Project)
          { project: parent }
        elsif parent.is_a?(Group)
          { group: parent }
        else
          raise TypeError, 'Parent type is not supported'
        end
      end
    end
  end
end