1# frozen_string_literal: true 2 3module Boards 4 class IssuesController < Boards::ApplicationController 5 # This is the maximum amount of issues which can be moved by one request to 6 # bulk_move for now. This is temporary and might be removed in future by 7 # introducing an alternative (async?) approach. 8 # (related: https://gitlab.com/groups/gitlab-org/-/epics/382) 9 MAX_MOVE_ISSUES_COUNT = 50 10 11 include BoardsResponses 12 include ControllerWithCrossProjectAccessCheck 13 14 requires_cross_project_access if: -> { board&.group_board? } 15 16 before_action :disable_query_limiting, only: [:bulk_move] 17 before_action :authorize_read_issue, only: [:index] 18 before_action :authorize_create_issue, only: [:create] 19 before_action :authorize_update_issue, only: [:update] 20 skip_before_action :authenticate_user!, only: [:index] 21 before_action :validate_id_list, only: [:bulk_move] 22 before_action :can_move_issues?, only: [:bulk_move] 23 24 feature_category :team_planning 25 26 def index 27 list_service = Boards::Issues::ListService.new(board_parent, current_user, filter_params) 28 issues = issues_from(list_service) 29 30 ::Boards::Issues::ListService.initialize_relative_positions(board, current_user, issues) 31 32 render_issues(issues, list_service.metadata) 33 end 34 35 def create 36 service = Boards::Issues::CreateService.new(board_parent, project, current_user, issue_params) 37 issue = service.execute 38 39 if issue.valid? 40 render json: serialize_as_json(issue) 41 else 42 render json: issue.errors, status: :unprocessable_entity 43 end 44 end 45 46 def bulk_move 47 service = Boards::Issues::MoveService.new(board_parent, current_user, move_params(true)) 48 49 issues = Issue.find(params[:ids]) 50 51 render json: service.execute_multiple(issues) 52 end 53 54 def update 55 service = Boards::Issues::MoveService.new(board_parent, current_user, move_params) 56 57 if service.execute(issue) 58 head :ok 59 else 60 head :unprocessable_entity 61 end 62 end 63 64 private 65 66 def issues_from(list_service) 67 issues = list_service.execute 68 issues.page(params[:page]).per(params[:per] || 20) 69 .without_count 70 .preload(associations_to_preload) # rubocop: disable CodeReuse/ActiveRecord 71 .load 72 end 73 74 def associations_to_preload 75 [ 76 :milestone, 77 :assignees, 78 project: [ 79 :route, 80 { 81 namespace: [:route] 82 } 83 ], 84 labels: [:priorities], 85 notes: [:award_emoji, :author] 86 ] 87 end 88 89 def can_move_issues? 90 head(:forbidden) unless can?(current_user, :admin_issue, board) 91 end 92 93 def serializer_options(issues) 94 {} 95 end 96 97 def render_issues(issues, metadata) 98 data = { issues: serialize_as_json(issues, opts: serializer_options(issues)) } 99 data.merge!(metadata) 100 101 render json: data 102 end 103 104 def issue 105 @issue ||= issues_finder.find(params[:id]) 106 end 107 108 def filter_params 109 params.permit(*Boards::Issues::ListService.valid_params).merge(board_id: params[:board_id], id: params[:list_id]) 110 .reject { |_, value| value.nil? } 111 end 112 113 def issues_finder 114 if board.group_board? 115 IssuesFinder.new(current_user, group_id: board_parent.id) 116 else 117 IssuesFinder.new(current_user, project_id: board_parent.id) 118 end 119 end 120 121 def project 122 @project ||= if board.group_board? 123 Project.find(issue_params[:project_id]) 124 else 125 board_parent 126 end 127 end 128 129 def move_params(multiple = false) 130 id_param = multiple ? :ids : :id 131 params.permit(id_param, :board_id, :from_list_id, :to_list_id, :move_before_id, :move_after_id) 132 end 133 134 def issue_params 135 params.require(:issue) 136 .permit(:title, :milestone_id, :project_id) 137 .merge(board_id: params[:board_id], list_id: params[:list_id]) 138 end 139 140 def serializer 141 IssueSerializer.new(current_user: current_user) 142 end 143 144 def serialize_as_json(resource, opts: {}) 145 opts.merge!(include_full_project_path: board.group_board?, serializer: 'board') 146 147 serializer.represent(resource, opts) 148 end 149 150 def disable_query_limiting 151 Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/issues/35174') 152 end 153 154 def validate_id_list 155 head(:bad_request) unless params[:ids].is_a?(Array) 156 head(:unprocessable_entity) if params[:ids].size > MAX_MOVE_ISSUES_COUNT 157 end 158 end 159end 160 161Boards::IssuesController.prepend_mod_with('Boards::IssuesController') 162