gitlab-org--gitlab-foss/app/controllers/projects/issues_controller.rb
Sean McGivern c2fc40668c Refactor IssuableFinder to extract model-specific logic
By extracting a new `filter_items` method, we can override that in the
IssuesFinder and MergeRequestsFinder separately, so we don't need checks that
the model is the correct one, because we can just use the class we're in to know
that.

We can do the same for the VALID_PARAMS constant, by making it a class method.
2018-02-21 10:31:29 +00:00

258 lines
7.2 KiB
Ruby

class Projects::IssuesController < Projects::ApplicationController
include RendersNotes
include ToggleSubscriptionAction
include IssuableActions
include ToggleAwardEmoji
include IssuableCollections
include SpammableActions
prepend_before_action :authenticate_user!, only: [:new]
before_action :whitelist_query_limiting, only: [:create, :create_merge_request, :move, :bulk_update]
before_action :check_issues_available!
before_action :issue, except: [:index, :new, :create, :bulk_update]
before_action :set_issuables_index, only: [:index]
# Allow write(create) issue
before_action :authorize_create_issue!, only: [:new, :create]
# Allow modify issue
before_action :authorize_update_issuable!, only: [:edit, :update, :move]
# Allow create a new branch and empty WIP merge request from current issue
before_action :authorize_create_merge_request!, only: [:create_merge_request]
respond_to :html
def index
@issues = @issuables
respond_to do |format|
format.html
format.atom { render layout: 'xml.atom' }
format.json do
render json: {
html: view_to_html_string("projects/issues/_issues"),
labels: @labels.as_json(methods: :text_color)
}
end
end
end
def new
params[:issue] ||= ActionController::Parameters.new(
assignee_ids: ""
)
build_params = issue_params.merge(
merge_request_to_resolve_discussions_of: params[:merge_request_to_resolve_discussions_of],
discussion_to_resolve: params[:discussion_to_resolve]
)
service = Issues::BuildService.new(project, current_user, build_params)
@issue = @noteable = service.execute
@merge_request_to_resolve_discussions_of = service.merge_request_to_resolve_discussions_of
@discussion_to_resolve = service.discussions_to_resolve.first if params[:discussion_to_resolve]
respond_with(@issue)
end
def edit
respond_with(@issue)
end
def discussions
notes = @issue.notes
.inc_relations_for_view
.includes(:noteable)
.fresh
notes = prepare_notes_for_rendering(notes)
notes = notes.reject { |n| n.cross_reference_not_visible_for?(current_user) }
discussions = Discussion.build_collection(notes, @issue)
render json: DiscussionSerializer.new(project: @project, noteable: @issue, current_user: current_user).represent(discussions)
end
def create
create_params = issue_params.merge(spammable_params).merge(
merge_request_to_resolve_discussions_of: params[:merge_request_to_resolve_discussions_of],
discussion_to_resolve: params[:discussion_to_resolve]
)
service = Issues::CreateService.new(project, current_user, create_params)
@issue = service.execute
if service.discussions_to_resolve.count(&:resolved?) > 0
flash[:notice] = if service.discussion_to_resolve_id
"Resolved 1 discussion."
else
"Resolved all discussions."
end
end
respond_to do |format|
format.html do
recaptcha_check_with_fallback { render :new }
end
format.js do
@link = @issue.attachment.url.to_js
end
end
end
def move
params.require(:move_to_project_id)
if params[:move_to_project_id].to_i > 0
new_project = Project.find(params[:move_to_project_id])
return render_404 unless issue.can_move?(current_user, new_project)
@issue = Issues::UpdateService.new(project, current_user, target_project: new_project).execute(issue)
end
respond_to do |format|
format.json do
render_issue_json
end
end
rescue ActiveRecord::StaleObjectError
render_conflict_response
end
def referenced_merge_requests
@merge_requests, @closed_by_merge_requests = ::Issues::FetchReferencedMergeRequestsService.new(project, current_user).execute(issue)
respond_to do |format|
format.json do
render json: {
html: view_to_html_string('projects/issues/_merge_requests')
}
end
end
end
def related_branches
@related_branches = @issue.related_branches(current_user)
respond_to do |format|
format.json do
render json: {
html: view_to_html_string('projects/issues/_related_branches')
}
end
end
end
def can_create_branch
can_create = current_user &&
can?(current_user, :push_code, @project) &&
@issue.can_be_worked_on?(current_user)
respond_to do |format|
format.json do
render json: { can_create_branch: can_create, has_related_branch: @issue.has_related_branch? }
end
end
end
def create_merge_request
create_params = params.slice(:branch_name, :ref).merge(issue_iid: issue.iid)
result = ::MergeRequests::CreateFromIssueService.new(project, current_user, create_params).execute
if result[:status] == :success
render json: MergeRequestCreateSerializer.new.represent(result[:merge_request])
else
render json: result[:messsage], status: :unprocessable_entity
end
end
protected
def issue
return @issue if defined?(@issue)
# The Sortable default scope causes performance issues when used with find_by
@issuable = @noteable = @issue ||= @project.issues.where(iid: params[:id]).reorder(nil).take!
@note = @project.notes.new(noteable: @issuable)
return render_404 unless can?(current_user, :read_issue, @issue)
@issue
end
alias_method :subscribable_resource, :issue
alias_method :issuable, :issue
alias_method :awardable, :issue
alias_method :spammable, :issue
def spammable_path
project_issue_path(@project, @issue)
end
def authorize_create_merge_request!
render_404 unless can?(current_user, :push_code, @project) && @issue.can_be_worked_on?(current_user)
end
def render_issue_json
if @issue.valid?
render json: serializer.represent(@issue)
else
render json: { errors: @issue.errors.full_messages }, status: :unprocessable_entity
end
end
def issue_params
params.require(:issue).permit(*issue_params_attributes)
end
def issue_params_attributes
%i[
title
assignee_id
position
description
confidential
milestone_id
due_date
state_event
task_num
lock_version
discussion_locked
] + [{ label_ids: [], assignee_ids: [] }]
end
def authenticate_user!
return if current_user
notice = "Please sign in to create the new issue."
if request.get? && !request.xhr?
store_location_for :user, request.fullpath
end
redirect_to new_user_session_path, notice: notice
end
def serializer
IssueSerializer.new(current_user: current_user, project: issue.project)
end
def update_service
update_params = issue_params.merge(spammable_params)
Issues::UpdateService.new(project, current_user, update_params)
end
def finder_type
IssuesFinder
end
def whitelist_query_limiting
# Also see the following issues:
#
# 1. https://gitlab.com/gitlab-org/gitlab-ce/issues/42423
# 2. https://gitlab.com/gitlab-org/gitlab-ce/issues/42424
# 3. https://gitlab.com/gitlab-org/gitlab-ce/issues/42426
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/42422')
end
end