diff options
Diffstat (limited to 'app/controllers')
95 files changed, 1196 insertions, 949 deletions
diff --git a/app/controllers/abuse_reports_controller.rb b/app/controllers/abuse_reports_controller.rb index 2eac0cabf7a..ed13ead63f9 100644 --- a/app/controllers/abuse_reports_controller.rb +++ b/app/controllers/abuse_reports_controller.rb @@ -1,7 +1,9 @@ class AbuseReportsController < ApplicationController + before_action :set_user, only: [:new] + def new @abuse_report = AbuseReport.new - @abuse_report.user_id = params[:user_id] + @abuse_report.user_id = @user.id @ref_url = params.fetch(:ref_url, '') end @@ -27,4 +29,14 @@ class AbuseReportsController < ApplicationController user_id )) end + + def set_user + @user = User.find_by(id: params[:user_id]) + + if @user.nil? + redirect_to root_path, alert: "Cannot create the abuse report. The user has been deleted." + elsif @user.blocked? + redirect_to @user, alert: "Cannot create the abuse report. This user has been blocked." + end + end end diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 4d4b8a8425f..8367c22d1ca 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -71,89 +71,18 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController params[:application_setting][:disabled_oauth_sign_in_sources] = AuthHelper.button_based_providers.map(&:to_s) - Array(enabled_oauth_sign_in_sources) + + params[:application_setting][:restricted_visibility_levels]&.delete("") params.delete(:domain_blacklist_raw) if params[:domain_blacklist_file] params.require(:application_setting).permit( - application_setting_params_ce + visible_application_setting_attributes ) end - def application_setting_params_ce - [ - :admin_notification_email, - :after_sign_out_path, - :after_sign_up_text, - :akismet_api_key, - :akismet_enabled, - :container_registry_token_expire_delay, - :default_artifacts_expire_in, - :default_branch_protection, - :default_group_visibility, - :default_project_visibility, - :default_projects_limit, - :default_snippet_visibility, - :domain_blacklist_enabled, + def visible_application_setting_attributes + ApplicationSettingsHelper.visible_attributes + [ :domain_blacklist_file, - :domain_blacklist_raw, - :domain_whitelist_raw, - :email_author_in_body, - :enabled_git_access_protocol, - :gravatar_enabled, - :help_page_text, - :help_page_hide_commercial_content, - :help_page_support_url, - :home_page_url, - :housekeeping_bitmaps_enabled, - :housekeeping_enabled, - :housekeeping_full_repack_period, - :housekeeping_gc_period, - :housekeeping_incremental_repack_period, - :html_emails_enabled, - :koding_enabled, - :koding_url, - :plantuml_enabled, - :plantuml_url, - :max_artifacts_size, - :max_attachment_size, - :max_pages_size, - :metrics_enabled, - :metrics_host, - :metrics_method_call_threshold, - :metrics_packet_size, - :metrics_pool_size, - :metrics_port, - :metrics_sample_interval, - :metrics_timeout, - :recaptcha_enabled, - :recaptcha_private_key, - :recaptcha_site_key, - :repository_checks_enabled, - :require_two_factor_authentication, - :session_expire_delay, - :sign_in_text, - :signin_enabled, - :signup_enabled, - :sentry_dsn, - :sentry_enabled, - :clientside_sentry_dsn, - :clientside_sentry_enabled, - :send_user_confirmation_email, - :shared_runners_enabled, - :shared_runners_text, - :sidekiq_throttling_enabled, - :sidekiq_throttling_factor, - :two_factor_grace_period, - :user_default_external, - :user_oauth_applications, - :unique_ips_limit_per_user, - :unique_ips_limit_time_window, - :unique_ips_limit_enabled, - :version_check_enabled, - :terminal_max_session_time, - :polling_interval_multiplier, - :prometheus_metrics_enabled, - :usage_ping_enabled, - disabled_oauth_sign_in_sources: [], import_sources: [], repository_storages: [], diff --git a/app/controllers/admin/applications_controller.rb b/app/controllers/admin/applications_controller.rb index 434ff6b2a62..16590e66d61 100644 --- a/app/controllers/admin/applications_controller.rb +++ b/app/controllers/admin/applications_controller.rb @@ -50,6 +50,6 @@ class Admin::ApplicationsController < Admin::ApplicationController # Only allow a trusted parameter "white list" through. def application_params - params[:doorkeeper_application].permit(:name, :redirect_uri, :scopes) + params.require(:doorkeeper_application).permit(:name, :redirect_uri, :trusted, :scopes) end end diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb index 8360ce08bdc..05e749c00c0 100644 --- a/app/controllers/admin/dashboard_controller.rb +++ b/app/controllers/admin/dashboard_controller.rb @@ -1,6 +1,6 @@ class Admin::DashboardController < Admin::ApplicationController def index - @projects = Project.with_route.limit(10) + @projects = Project.without_deleted.with_route.limit(10) @users = User.limit(10) @groups = Group.with_route.limit(10) end diff --git a/app/controllers/admin/hook_logs_controller.rb b/app/controllers/admin/hook_logs_controller.rb index aa069b89563..3017f96c26f 100644 --- a/app/controllers/admin/hook_logs_controller.rb +++ b/app/controllers/admin/hook_logs_controller.rb @@ -10,9 +10,9 @@ class Admin::HookLogsController < Admin::ApplicationController end def retry - status, message = hook.execute(hook_log.request_data, hook_log.trigger) + result = hook.execute(hook_log.request_data, hook_log.trigger) - set_hook_execution_notice(status, message) + set_hook_execution_notice(result) redirect_to edit_admin_hook_path(@hook) end diff --git a/app/controllers/admin/hooks_controller.rb b/app/controllers/admin/hooks_controller.rb index 054c3500b35..77e3c95d197 100644 --- a/app/controllers/admin/hooks_controller.rb +++ b/app/controllers/admin/hooks_controller.rb @@ -38,9 +38,9 @@ class Admin::HooksController < Admin::ApplicationController end def test - status, message = hook.execute(sample_hook_data, 'system_hooks') + result = TestHooks::SystemService.new(hook, current_user, params[:trigger]).execute - set_hook_execution_notice(status, message) + set_hook_execution_notice(result) redirect_back_or_default end @@ -66,15 +66,4 @@ class Admin::HooksController < Admin::ApplicationController :url ) end - - def sample_hook_data - { - event_name: "project_create", - name: "Ruby", - path: "ruby", - project_id: 1, - owner_name: "Someone", - owner_email: "example@gitlabhq.com" - } - end end diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb index a1975c0e341..0b6cd71e651 100644 --- a/app/controllers/admin/projects_controller.rb +++ b/app/controllers/admin/projects_controller.rb @@ -3,18 +3,9 @@ class Admin::ProjectsController < Admin::ApplicationController before_action :group, only: [:show, :transfer] def index - params[:sort] ||= 'latest_activity_desc' - @projects = Project.with_statistics - @projects = @projects.in_namespace(params[:namespace_id]) if params[:namespace_id].present? - @projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present? - @projects = @projects.with_push if params[:with_push].present? - @projects = @projects.abandoned if params[:abandoned].present? - @projects = @projects.where(last_repository_check_failed: true) if params[:last_repository_check_failed].present? - @projects = @projects.non_archived unless params[:archived].present? - @projects = @projects.personal(current_user) if params[:personal].present? - @projects = @projects.search(params[:name]) if params[:name].present? - @projects = @projects.sort(@sort = params[:sort]) - @projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]) + finder = Admin::ProjectsFinder.new(params: params, current_user: current_user) + @projects = finder.execute + @sort = finder.sort respond_to do |format| format.html @@ -40,14 +31,14 @@ class Admin::ProjectsController < Admin::ApplicationController ::Projects::TransferService.new(@project, current_user, params.dup).execute(namespace) @project.reload - redirect_to admin_namespace_project_path(@project.namespace, @project) + redirect_to admin_project_path(@project) end def repository_check RepositoryCheck::SingleRepositoryWorker.perform_async(@project.id) redirect_to( - admin_namespace_project_path(@project.namespace, @project), + admin_project_path(@project), notice: 'Repository check was triggered.' ) end diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index b09eef17c23..fa1bc72560e 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -54,7 +54,7 @@ class Admin::UsersController < Admin::ApplicationController end def block - if user.block + if update_user { |user| user.block } redirect_back_or_admin_user(notice: "Successfully blocked") else redirect_back_or_admin_user(alert: "Error occurred. User was not blocked") @@ -64,7 +64,7 @@ class Admin::UsersController < Admin::ApplicationController def unblock if user.ldap_blocked? redirect_back_or_admin_user(alert: "This user cannot be unlocked manually from GitLab") - elsif user.activate + elsif update_user { |user| user.activate } redirect_back_or_admin_user(notice: "Successfully unblocked") else redirect_back_or_admin_user(alert: "Error occurred. User was not unblocked") @@ -72,7 +72,7 @@ class Admin::UsersController < Admin::ApplicationController end def unlock - if user.unlock_access! + if update_user { |user| user.unlock_access! } redirect_back_or_admin_user(alert: "Successfully unlocked") else redirect_back_or_admin_user(alert: "Error occurred. User was not unlocked") @@ -80,7 +80,7 @@ class Admin::UsersController < Admin::ApplicationController end def confirm - if user.confirm + if update_user { |user| user.confirm } redirect_back_or_admin_user(notice: "Successfully confirmed") else redirect_back_or_admin_user(alert: "Error occurred. User was not confirmed") @@ -88,7 +88,8 @@ class Admin::UsersController < Admin::ApplicationController end def disable_two_factor - user.disable_two_factor! + update_user { |user| user.disable_two_factor! } + redirect_to admin_user_path(user), notice: 'Two-factor Authentication has been disabled for this user' end @@ -124,15 +125,18 @@ class Admin::UsersController < Admin::ApplicationController end respond_to do |format| - user.skip_reconfirmation! - if user.update_attributes(user_params_with_pass) + result = Users::UpdateService.new(user, user_params_with_pass).execute do |user| + user.skip_reconfirmation! + end + + if result[:status] == :success format.html { redirect_to [:admin, user], notice: 'User was successfully updated.' } format.json { head :ok } else # restore username to keep form action url. user.username = params[:id] format.html { render "edit" } - format.json { render json: user.errors, status: :unprocessable_entity } + format.json { render json: [result[:message]], status: result[:status] } end end end @@ -148,13 +152,16 @@ class Admin::UsersController < Admin::ApplicationController def remove_email email = user.emails.find(params[:email_id]) - email.destroy - - user.update_secondary_emails! + success = Emails::DestroyService.new(user, email: email.email).execute respond_to do |format| - format.html { redirect_back_or_admin_user(notice: "Successfully removed email.") } - format.js { head :ok } + if success + format.html { redirect_back_or_admin_user(notice: 'Successfully removed email.') } + format.json { head :ok } + else + format.html { redirect_back_or_admin_user(alert: 'There was an error removing the e-mail.') } + format.json { render json: 'There was an error removing the e-mail.', status: 400 } + end end end @@ -202,4 +209,10 @@ class Admin::UsersController < Admin::ApplicationController :website_url ] end + + def update_user(&block) + result = Users::UpdateService.new(user).execute(&block) + + result[:status] == :success + end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 91694ebcd1d..d14b1dbecf6 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -9,7 +9,7 @@ class ApplicationController < ActionController::Base include SentryHelper include WorkhorseHelper include EnforcesTwoFactorAuthentication - include Peek::Rblineprof::CustomControllerHelpers + include WithPerformanceBar before_action :authenticate_user_from_private_token! before_action :authenticate_user_from_rss_token! @@ -40,6 +40,10 @@ class ApplicationController < ActionController::Base render_404 end + rescue_from(ActionController::UnknownFormat) do + render_404 + end + rescue_from Gitlab::Access::AccessDeniedError do |exception| render_403 end @@ -64,23 +68,18 @@ class ApplicationController < ActionController::Base end end - def peek_enabled? - return false unless Gitlab::PerformanceBar.enabled? - return false unless current_user + protected - if RequestStore.active? - if RequestStore.store.key?(:peek_enabled) - RequestStore.store[:peek_enabled] - else - RequestStore.store[:peek_enabled] = cookies[:perf_bar_enabled].present? - end - else - cookies[:perf_bar_enabled].present? + def append_info_to_payload(payload) + super + payload[:remote_ip] = request.remote_ip + + if current_user.present? + payload[:user_id] = current_user.id + payload[:username] = current_user.username end end - protected - # This filter handles both private tokens and personal access tokens def authenticate_user_from_private_token! token = params[:private_token].presence || request.headers['PRIVATE-TOKEN'].presence @@ -106,6 +105,8 @@ class ApplicationController < ActionController::Base end def log_exception(exception) + Raven.capture_exception(exception) if sentry_enabled? + application_trace = ActionDispatch::ExceptionWrapper.new(env, exception).application_trace application_trace.map!{ |t| " #{t}\n" } logger.error "\n#{exception.class.name} (#{exception.message}):\n#{application_trace.join}" @@ -179,7 +180,7 @@ class ApplicationController < ActionController::Base end def check_password_expiration - if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && !current_user.ldap_user? + if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && current_user.allow_password_authentication? return redirect_to new_profile_password_path end end diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb index fe331a883c1..3120916c5bb 100644 --- a/app/controllers/autocomplete_controller.rb +++ b/app/controllers/autocomplete_controller.rb @@ -5,10 +5,10 @@ class AutocompleteController < ApplicationController def users @users ||= User.none - @users = @users.search(params[:search]) if params[:search].present? - @users = @users.where.not(id: params[:skip_users]) if params[:skip_users].present? @users = @users.active @users = @users.reorder(:name) + @users = @users.search(params[:search]) if params[:search].present? + @users = @users.where.not(id: params[:skip_users]) if params[:skip_users].present? @users = @users.page(params[:page]).per(params[:per_page]) if params[:todo_filter].present? && current_user diff --git a/app/controllers/concerns/creates_commit.rb b/app/controllers/concerns/creates_commit.rb index 1a9904bbe57..782f0be9c4a 100644 --- a/app/controllers/concerns/creates_commit.rb +++ b/app/controllers/concerns/creates_commit.rb @@ -78,8 +78,7 @@ module CreatesCommit end def new_merge_request_path - new_namespace_project_merge_request_path( - @project_to_commit_into.namespace, + project_new_merge_request_path( @project_to_commit_into, merge_request: { source_project_id: @project_to_commit_into.id, @@ -91,7 +90,7 @@ module CreatesCommit end def existing_merge_request_path - namespace_project_merge_request_path(@project.namespace, @project, @merge_request) + project_merge_request_path(@project, @merge_request) end def merge_request_exists? diff --git a/app/controllers/concerns/hooks_execution.rb b/app/controllers/concerns/hooks_execution.rb index 846cd60518f..a22e46b4860 100644 --- a/app/controllers/concerns/hooks_execution.rb +++ b/app/controllers/concerns/hooks_execution.rb @@ -3,11 +3,14 @@ module HooksExecution private - def set_hook_execution_notice(status, message) - if status && status >= 200 && status < 400 - flash[:notice] = "Hook executed successfully: HTTP #{status}" - elsif status - flash[:alert] = "Hook executed successfully but returned HTTP #{status} #{message}" + def set_hook_execution_notice(result) + http_status = result[:http_status] + message = result[:message] + + if http_status && http_status >= 200 && http_status < 400 + flash[:notice] = "Hook executed successfully: HTTP #{http_status}" + elsif http_status + flash[:alert] = "Hook executed successfully but returned HTTP #{http_status} #{message}" else flash[:alert] = "Hook execution failed: #{message}" end diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb index 650ec1e326a..b43b2c5621f 100644 --- a/app/controllers/concerns/issuable_collections.rb +++ b/app/controllers/concerns/issuable_collections.rb @@ -1,6 +1,7 @@ module IssuableCollections extend ActiveSupport::Concern include SortingHelper + include Gitlab::IssuableMetadata included do helper_method :issues_finder @@ -9,45 +10,12 @@ module IssuableCollections private - def issuable_meta_data(issuable_collection, collection_type) - # map has to be used here since using pluck or select will - # throw an error when ordering issuables by priority which inserts - # a new order into the collection. - # We cannot use reorder to not mess up the paginated collection. - issuable_ids = issuable_collection.map(&:id) - - return {} if issuable_ids.empty? - - issuable_note_count = Note.count_for_collection(issuable_ids, @collection_type) - issuable_votes_count = AwardEmoji.votes_for_collection(issuable_ids, @collection_type) - issuable_merge_requests_count = - if collection_type == 'Issue' - MergeRequestsClosingIssues.count_for_collection(issuable_ids) - else - [] - end - - issuable_ids.each_with_object({}) do |id, issuable_meta| - downvotes = issuable_votes_count.find { |votes| votes.awardable_id == id && votes.downvote? } - upvotes = issuable_votes_count.find { |votes| votes.awardable_id == id && votes.upvote? } - notes = issuable_note_count.find { |notes| notes.noteable_id == id } - merge_requests = issuable_merge_requests_count.find { |mr| mr.first == id } - - issuable_meta[id] = Issuable::IssuableMeta.new( - upvotes.try(:count).to_i, - downvotes.try(:count).to_i, - notes.try(:count).to_i, - merge_requests.try(:last).to_i - ) - end - end - def issues_collection issues_finder.execute.preload(:project, :author, :assignees, :labels, :milestone, project: :namespace) end def merge_requests_collection - merge_requests_finder.execute.preload(:source_project, :target_project, :author, :assignee, :labels, :milestone, :merge_request_diff, :head_pipeline, target_project: :namespace) + merge_requests_finder.execute.preload(:source_project, :target_project, :author, :assignee, :labels, :milestone, :head_pipeline, target_project: :namespace, merge_request_diff: :merge_request_diff_commits) end def issues_finder @@ -64,10 +32,10 @@ module IssuableCollections def filter_params set_sort_order_from_cookie - set_default_scope set_default_state - @filter_params = params.dup + # Skip irrelevant Rails routing params + @filter_params = params.dup.except(:controller, :action, :namespace_id) @filter_params[:sort] ||= default_sort_order @sort = @filter_params[:sort] @@ -87,10 +55,6 @@ module IssuableCollections @filter_params end - def set_default_scope - params[:scope] = 'all' if params[:scope].blank? - end - def set_default_state params[:state] = 'opened' if params[:state].blank? end diff --git a/app/controllers/concerns/membership_actions.rb b/app/controllers/concerns/membership_actions.rb index 47d9ae350ae..c6b1e443de6 100644 --- a/app/controllers/concerns/membership_actions.rb +++ b/app/controllers/concerns/membership_actions.rb @@ -70,7 +70,7 @@ module MembershipActions def members_page_url if membershipable.is_a?(Project) - project_settings_members_path(membershipable) + project_project_members_path(membershipable) else polymorphic_url([membershipable, :members]) end diff --git a/app/controllers/concerns/milestone_actions.rb b/app/controllers/concerns/milestone_actions.rb index 1ff785ac2ca..081f3336780 100644 --- a/app/controllers/concerns/milestone_actions.rb +++ b/app/controllers/concerns/milestone_actions.rb @@ -45,7 +45,7 @@ module MilestoneActions def milestone_redirect_path if @project - namespace_project_milestone_path(@project.namespace, @project, @milestone) + project_milestone_path(@project, @milestone) elsif @group group_milestone_path(@group, @milestone.safe_title, title: @milestone.title) else diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb index a57d9e6e6c0..af5f683bab5 100644 --- a/app/controllers/concerns/notes_actions.rb +++ b/app/controllers/concerns/notes_actions.rb @@ -4,6 +4,7 @@ module NotesActions included do before_action :authorize_admin_note!, only: [:update, :destroy] + before_action :note_project, only: [:create] end def index @@ -28,7 +29,8 @@ module NotesActions merge_request_diff_head_sha: params[:merge_request_diff_head_sha], in_reply_to_discussion_id: params[:in_reply_to_discussion_id] ) - @note = Notes::CreateService.new(project, current_user, create_params).execute + + @note = Notes::CreateService.new(note_project, current_user, create_params).execute if @note.is_a?(Note) Banzai::NoteRenderer.render([@note], @project, current_user) @@ -177,4 +179,22 @@ module NotesActions def notes_finder @notes_finder ||= NotesFinder.new(project, current_user, finder_params) end + + def note_project + return @note_project if defined?(@note_project) + return nil unless project + + note_project_id = params[:note_project_id] + + @note_project = + if note_project_id.present? + Project.find(note_project_id) + else + project + end + + return access_denied! unless can?(current_user, :create_note, @note_project) + + @note_project + end end diff --git a/app/controllers/concerns/repository_settings_redirect.rb b/app/controllers/concerns/repository_settings_redirect.rb index 0854c73a02f..0576f0e6e70 100644 --- a/app/controllers/concerns/repository_settings_redirect.rb +++ b/app/controllers/concerns/repository_settings_redirect.rb @@ -2,6 +2,6 @@ module RepositorySettingsRedirect extend ActiveSupport::Concern def redirect_to_repository_settings(project) - redirect_to namespace_project_settings_repository_path(project.namespace, project) + redirect_to project_settings_repository_path(project) end end diff --git a/app/controllers/concerns/requires_health_token.rb b/app/controllers/concerns/requires_health_token.rb deleted file mode 100644 index 34ab1a97649..00000000000 --- a/app/controllers/concerns/requires_health_token.rb +++ /dev/null @@ -1,25 +0,0 @@ -module RequiresHealthToken - extend ActiveSupport::Concern - included do - before_action :validate_health_check_access! - end - - private - - def validate_health_check_access! - render_404 unless token_valid? - end - - def token_valid? - token = params[:token].presence || request.headers['TOKEN'] - token.present? && - ActiveSupport::SecurityUtils.variable_size_secure_compare( - token, - current_application_settings.health_check_access_token - ) - end - - def render_404 - render file: Rails.root.join('public', '404'), layout: false, status: '404' - end -end diff --git a/app/controllers/concerns/requires_whitelisted_monitoring_client.rb b/app/controllers/concerns/requires_whitelisted_monitoring_client.rb new file mode 100644 index 00000000000..ad2f4bbc486 --- /dev/null +++ b/app/controllers/concerns/requires_whitelisted_monitoring_client.rb @@ -0,0 +1,33 @@ +module RequiresWhitelistedMonitoringClient + extend ActiveSupport::Concern + included do + before_action :validate_ip_whitelisted_or_valid_token! + end + + private + + def validate_ip_whitelisted_or_valid_token! + render_404 unless client_ip_whitelisted? || valid_token? + end + + def client_ip_whitelisted? + ip_whitelist.any? { |e| e.include?(Gitlab::RequestContext.client_ip) } + end + + def ip_whitelist + @ip_whitelist ||= Settings.monitoring.ip_whitelist.map(&IPAddr.method(:new)) + end + + def valid_token? + token = params[:token].presence || request.headers['TOKEN'] + token.present? && + ActiveSupport::SecurityUtils.variable_size_secure_compare( + token, + current_application_settings.health_check_access_token + ) + end + + def render_404 + render file: Rails.root.join('public', '404'), layout: false, status: '404' + end +end diff --git a/app/controllers/concerns/spammable_actions.rb b/app/controllers/concerns/spammable_actions.rb index b68d76aeff0..ada0dde87fb 100644 --- a/app/controllers/concerns/spammable_actions.rb +++ b/app/controllers/concerns/spammable_actions.rb @@ -9,9 +9,9 @@ module SpammableActions def mark_as_spam if SpamService.new(spammable).mark_as_spam! - redirect_to spammable, notice: "#{spammable.spammable_entity_type.titlecase} was submitted to Akismet successfully." + redirect_to spammable_path, notice: "#{spammable.spammable_entity_type.titlecase} was submitted to Akismet successfully." else - redirect_to spammable, alert: 'Error with Akismet. Please check the logs for more info.' + redirect_to spammable_path, alert: 'Error with Akismet. Please check the logs for more info.' end end @@ -25,7 +25,7 @@ module SpammableActions def recaptcha_check_with_fallback(&fallback) if spammable.valid? - redirect_to spammable + redirect_to spammable_path elsif render_recaptcha? ensure_spam_config_loaded! @@ -56,6 +56,10 @@ module SpammableActions raise NotImplementedError, "#{self.class} does not implement #{__method__}" end + def spammable_path + raise NotImplementedError, "#{self.class} does not implement #{__method__}" + end + def authorize_submit_spammable! access_denied! unless current_user.admin? end diff --git a/app/controllers/concerns/with_performance_bar.rb b/app/controllers/concerns/with_performance_bar.rb new file mode 100644 index 00000000000..ed253042701 --- /dev/null +++ b/app/controllers/concerns/with_performance_bar.rb @@ -0,0 +1,17 @@ +module WithPerformanceBar + extend ActiveSupport::Concern + + included do + include Peek::Rblineprof::CustomControllerHelpers + end + + def peek_enabled? + return false unless Gitlab::PerformanceBar.enabled?(current_user) + + if RequestStore.active? + RequestStore.fetch(:peek_enabled) { cookies[:perf_bar_enabled].present? } + else + cookies[:perf_bar_enabled].present? + end + end +end diff --git a/app/controllers/dashboard/labels_controller.rb b/app/controllers/dashboard/labels_controller.rb index dd1d46a68c7..9dcb3a0eb6d 100644 --- a/app/controllers/dashboard/labels_controller.rb +++ b/app/controllers/dashboard/labels_controller.rb @@ -1,9 +1,14 @@ class Dashboard::LabelsController < Dashboard::ApplicationController def index - labels = LabelsFinder.new(current_user).execute - respond_to do |format| format.json { render json: LabelSerializer.new.represent_appearance(labels) } end end + + def labels + finder_params = { project_ids: projects.select(:id) } + labels = LabelsFinder.new(current_user, finder_params).execute + + GlobalLabel.build_collection(labels) + end end diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb index 28c90548cc1..59e5b5e4775 100644 --- a/app/controllers/dashboard/todos_controller.rb +++ b/app/controllers/dashboard/todos_controller.rb @@ -1,6 +1,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController include ActionView::Helpers::NumberHelper + before_action :authorize_read_project!, only: :index before_action :find_todos, only: [:index, :destroy_all] def index @@ -49,6 +50,15 @@ class Dashboard::TodosController < Dashboard::ApplicationController private + def authorize_read_project! + project_id = params[:project_id] + + if project_id.present? + project = Project.find(project_id) + render_404 unless can?(current_user, :read_project, project) + end + end + def find_todos @todos ||= TodosFinder.new(current_user, params).execute end diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index e52fa766044..5c10d7bc261 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -2,15 +2,18 @@ class Groups::MilestonesController < Groups::ApplicationController include MilestoneActions before_action :group_projects - before_action :milestone, only: [:show, :update, :merge_requests, :participants, :labels] - before_action :authorize_admin_milestones!, only: [:new, :create, :update] + before_action :milestone, only: [:edit, :show, :update, :merge_requests, :participants, :labels] + before_action :authorize_admin_milestones!, only: [:edit, :new, :create, :update] def index respond_to do |format| format.html do - @milestone_states = GlobalMilestone.states_count(@projects) + @milestone_states = GlobalMilestone.states_count(group_projects, group) @milestones = Kaminari.paginate_array(milestones).page(params[:page]) end + format.json do + render json: milestones.map { |m| m.for_display.slice(:title, :name) } + end end end @@ -19,49 +22,41 @@ class Groups::MilestonesController < Groups::ApplicationController end def create - project_ids = params[:milestone][:project_ids].reject(&:blank?) - title = milestone_params[:title] + @milestone = Milestones::CreateService.new(group, current_user, milestone_params).execute - if create_milestones(project_ids) - redirect_to milestone_path(title) + if @milestone.persisted? + redirect_to milestone_path else - render_new_with_error(project_ids.empty?) + render "new" end end def show end - def update - @milestone.milestones.each do |milestone| - Milestones::UpdateService.new(milestone.project, current_user, milestone_params).execute(milestone) - end - - redirect_back_or_default(default: milestone_path(@milestone.title)) + def edit + render_404 if @milestone.is_legacy_group_milestone? end - private - - def create_milestones(project_ids) - return false unless project_ids.present? + def update + # Keep this compatible with legacy group milestones where we have to update + # all projects milestones states at once. + if @milestone.is_legacy_group_milestone? + update_params = milestone_params.select { |key| key == "state_event" } + milestones = @milestone.milestones + else + update_params = milestone_params + milestones = [@milestone] + end - ActiveRecord::Base.transaction do - @projects.where(id: project_ids).each do |project| - Milestones::CreateService.new(project, current_user, milestone_params).execute - end + milestones.each do |milestone| + Milestones::UpdateService.new(milestone.parent, current_user, update_params).execute(milestone) end - true - rescue ActiveRecord::ActiveRecordError => e - flash.now[:alert] = "An error occurred while creating the milestone: #{e.message}" - false + redirect_to milestone_path end - def render_new_with_error(empty_project_ids) - @milestone = Milestone.new(milestone_params) - @milestone.errors.add(:base, "Please select at least one project.") if empty_project_ids - render :new - end + private def authorize_admin_milestones! return render_404 unless can?(current_user, :admin_milestones, group) @@ -71,16 +66,31 @@ class Groups::MilestonesController < Groups::ApplicationController params.require(:milestone).permit(:title, :description, :start_date, :due_date, :state_event) end - def milestone_path(title) - group_milestone_path(@group, title.to_slug.to_s, title: title) + def milestone_path + if @milestone.is_legacy_group_milestone? + group_milestone_path(group, @milestone.safe_title, title: @milestone.title) + else + group_milestone_path(group, @milestone.iid) + end end def milestones - @milestones = GroupMilestone.build_collection(@group, @projects, params) + search_params = params.merge(group_ids: group.id) + + milestones = MilestonesFinder.new(search_params).execute + legacy_milestones = GroupMilestone.build_collection(group, group_projects, params) + + milestones + legacy_milestones end def milestone - @milestone = GroupMilestone.build(@group, @projects, params[:title]) + @milestone = + if params[:title] + GroupMilestone.build(group, group_projects, params[:title]) + else + group.milestones.find_by_iid(params[:id]) + end + render_404 unless @milestone end end diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb new file mode 100644 index 00000000000..0142ad8278c --- /dev/null +++ b/app/controllers/groups/settings/ci_cd_controller.rb @@ -0,0 +1,24 @@ +module Groups + module Settings + class CiCdController < Groups::ApplicationController + before_action :authorize_admin_pipeline! + + def show + define_secret_variables + end + + private + + def define_secret_variables + @variable = Ci::GroupVariable.new(group: group) + .present(current_user: current_user) + @variables = group.variables.order_key_asc + .map { |variable| variable.present(current_user: current_user) } + end + + def authorize_admin_pipeline! + return render_404 unless can?(current_user, :admin_pipeline, group) + end + end + end +end diff --git a/app/controllers/groups/variables_controller.rb b/app/controllers/groups/variables_controller.rb new file mode 100644 index 00000000000..10038ff3ad9 --- /dev/null +++ b/app/controllers/groups/variables_controller.rb @@ -0,0 +1,64 @@ +module Groups + class VariablesController < Groups::ApplicationController + before_action :variable, only: [:show, :update, :destroy] + before_action :authorize_admin_build! + + def index + redirect_to group_settings_ci_cd_path(group) + end + + def show + end + + def update + if variable.update(variable_params) + redirect_to group_variables_path(group), + notice: 'Variable was successfully updated.' + else + render "show" + end + end + + def create + @variable = group.variables.create(variable_params) + .present(current_user: current_user) + + if @variable.persisted? + redirect_to group_settings_ci_cd_path(group), + notice: 'Variable was successfully created.' + else + render "show" + end + end + + def destroy + if variable.destroy + redirect_to group_settings_ci_cd_path(group), + status: 302, + notice: 'Variable was successfully removed.' + else + redirect_to group_settings_ci_cd_path(group), + status: 302, + notice: 'Failed to remove the variable.' + end + end + + private + + def variable_params + params.require(:variable).permit(*variable_params_attributes) + end + + def variable_params_attributes + %i[key value protected] + end + + def variable + @variable ||= group.variables.find(params[:id]).present(current_user: current_user) + end + + def authorize_admin_build! + return render_404 unless can?(current_user, :admin_build, group) + end + end +end diff --git a/app/controllers/health_check_controller.rb b/app/controllers/health_check_controller.rb index 5d3109b7187..c3d18991fd4 100644 --- a/app/controllers/health_check_controller.rb +++ b/app/controllers/health_check_controller.rb @@ -1,3 +1,3 @@ class HealthCheckController < HealthCheck::HealthCheckController - include RequiresHealthToken + include RequiresWhitelistedMonitoringClient end diff --git a/app/controllers/health_controller.rb b/app/controllers/health_controller.rb index abc832e6ddc..98c2aaa3526 100644 --- a/app/controllers/health_controller.rb +++ b/app/controllers/health_controller.rb @@ -1,10 +1,13 @@ class HealthController < ActionController::Base protect_from_forgery with: :exception - include RequiresHealthToken + include RequiresWhitelistedMonitoringClient CHECKS = [ Gitlab::HealthChecks::DbCheck, - Gitlab::HealthChecks::RedisCheck, + Gitlab::HealthChecks::Redis::RedisCheck, + Gitlab::HealthChecks::Redis::CacheCheck, + Gitlab::HealthChecks::Redis::QueuesCheck, + Gitlab::HealthChecks::Redis::SharedStateCheck, Gitlab::HealthChecks::FsShardsCheck ].freeze diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index 7625187c7be..0982a61902b 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -63,7 +63,7 @@ class InvitesController < ApplicationController when Project project = member.source label = "project #{project.name_with_namespace}" - path = namespace_project_path(project.namespace, project) + path = project_path(project) when Group group = member.source label = "group #{group.name}" diff --git a/app/controllers/metrics_controller.rb b/app/controllers/metrics_controller.rb index 0e9a19c0b6f..37587a52eaf 100644 --- a/app/controllers/metrics_controller.rb +++ b/app/controllers/metrics_controller.rb @@ -1,12 +1,12 @@ class MetricsController < ActionController::Base - include RequiresHealthToken + include RequiresWhitelistedMonitoringClient protect_from_forgery with: :exception before_action :validate_prometheus_metrics def index - render text: metrics_service.metrics_text, content_type: 'text/plain; verssion=0.0.4' + render text: metrics_service.metrics_text, content_type: 'text/plain; version=0.0.4' end private diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index b82681b197e..323d5d26eb6 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -1,5 +1,6 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController include AuthenticatesWithTwoFactor + include Devise::Controllers::Rememberable protect_from_forgery except: [:kerberos, :saml, :cas3] @@ -115,8 +116,10 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController if @user.persisted? && @user.valid? log_audit_event(@user, with: oauth['provider']) if @user.two_factor_enabled? + params[:remember_me] = '1' if remember_me? prompt_for_two_factor(@user) else + remember_me(@user) if remember_me? sign_in_and_redirect(@user) end else @@ -147,4 +150,9 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController AuditEventService.new(user, user, options) .for_authentication.security_event end + + def remember_me? + request_params = request.env['omniauth.params'] + (request_params['remember_me'] == '1') if request_params.present? + end end diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb index a8575e037e4..aa8cf630032 100644 --- a/app/controllers/passwords_controller.rb +++ b/app/controllers/passwords_controller.rb @@ -1,6 +1,8 @@ class PasswordsController < Devise::PasswordsController + include Gitlab::CurrentSettings + before_action :resource_from_email, only: [:create] - before_action :prevent_ldap_reset, only: [:create] + before_action :check_password_authentication_available, only: [:create] before_action :throttle_reset, only: [:create] def edit @@ -25,7 +27,7 @@ class PasswordsController < Devise::PasswordsController def update super do |resource| - if resource.valid? && resource.require_password? + if resource.valid? && resource.require_password_creation? resource.update_attribute(:password_automatically_set, false) end end @@ -38,11 +40,11 @@ class PasswordsController < Devise::PasswordsController self.resource = resource_class.find_by_email(email) end - def prevent_ldap_reset - return unless resource && resource.ldap_user? + def check_password_authentication_available + return if current_application_settings.password_authentication_enabled? && (resource.nil? || resource.allow_password_authentication?) redirect_to after_sending_reset_password_instructions_path_for(resource_name), - alert: "Cannot reset password for LDAP user." + alert: "Password authentication is unavailable." end def throttle_reset diff --git a/app/controllers/profiles/avatars_controller.rb b/app/controllers/profiles/avatars_controller.rb index 933e0f3bceb..408650aac54 100644 --- a/app/controllers/profiles/avatars_controller.rb +++ b/app/controllers/profiles/avatars_controller.rb @@ -1,9 +1,8 @@ class Profiles::AvatarsController < Profiles::ApplicationController def destroy @user = current_user - @user.remove_avatar! - @user.save + Users::UpdateService.new(@user).execute { |user| user.remove_avatar! } redirect_to profile_path, status: 302 end diff --git a/app/controllers/profiles/emails_controller.rb b/app/controllers/profiles/emails_controller.rb index 5655fb2ba0e..17b66df43e7 100644 --- a/app/controllers/profiles/emails_controller.rb +++ b/app/controllers/profiles/emails_controller.rb @@ -5,9 +5,9 @@ class Profiles::EmailsController < Profiles::ApplicationController end def create - @email = current_user.emails.new(email_params) + @email = Emails::CreateService.new(current_user, email_params).execute - if @email.save + if @email.errors.blank? NotificationService.new.new_email(@email) else flash[:alert] = @email.errors.full_messages.first @@ -18,9 +18,8 @@ class Profiles::EmailsController < Profiles::ApplicationController def destroy @email = current_user.emails.find(params[:id]) - @email.destroy - current_user.update_secondary_emails! + Emails::DestroyService.new(current_user, email: @email.email).execute respond_to do |format| format.html { redirect_to profile_emails_url, status: 302 } diff --git a/app/controllers/profiles/gpg_keys_controller.rb b/app/controllers/profiles/gpg_keys_controller.rb new file mode 100644 index 00000000000..6779cc6ddac --- /dev/null +++ b/app/controllers/profiles/gpg_keys_controller.rb @@ -0,0 +1,47 @@ +class Profiles::GpgKeysController < Profiles::ApplicationController + before_action :set_gpg_key, only: [:destroy, :revoke] + + def index + @gpg_keys = current_user.gpg_keys + @gpg_key = GpgKey.new + end + + def create + @gpg_key = current_user.gpg_keys.new(gpg_key_params) + + if @gpg_key.save + redirect_to profile_gpg_keys_path + else + @gpg_keys = current_user.gpg_keys.select(&:persisted?) + render :index + end + end + + def destroy + @gpg_key.destroy + + respond_to do |format| + format.html { redirect_to profile_gpg_keys_url, status: 302 } + format.js { head :ok } + end + end + + def revoke + @gpg_key.revoke + + respond_to do |format| + format.html { redirect_to profile_gpg_keys_url, status: 302 } + format.js { head :ok } + end + end + + private + + def gpg_key_params + params.require(:gpg_key).permit(:key) + end + + def set_gpg_key + @gpg_key = current_user.gpg_keys.find(params[:id]) + end +end diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb index a271e2dfc4b..960b7512602 100644 --- a/app/controllers/profiles/notifications_controller.rb +++ b/app/controllers/profiles/notifications_controller.rb @@ -7,7 +7,9 @@ class Profiles::NotificationsController < Profiles::ApplicationController end def update - if current_user.update_attributes(user_params) + result = Users::UpdateService.new(current_user, user_params).execute + + if result[:status] == :success flash[:notice] = "Notification settings saved" else flash[:alert] = "Failed to save new settings" diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb index 6217ec5ecef..c423761ab24 100644 --- a/app/controllers/profiles/passwords_controller.rb +++ b/app/controllers/profiles/passwords_controller.rb @@ -15,17 +15,17 @@ class Profiles::PasswordsController < Profiles::ApplicationController return end - new_password = user_params[:password] - new_password_confirmation = user_params[:password_confirmation] - - result = @user.update_attributes( - password: new_password, - password_confirmation: new_password_confirmation, + password_attributes = { + password: user_params[:password], + password_confirmation: user_params[:password_confirmation], password_automatically_set: false - ) + } + + result = Users::UpdateService.new(@user, password_attributes).execute + + if result[:status] == :success + Users::UpdateService.new(@user, password_expires_at: nil).execute - if result - @user.update_attributes(password_expires_at: nil) redirect_to root_path, notice: 'Password successfully changed' else render :new @@ -46,7 +46,9 @@ class Profiles::PasswordsController < Profiles::ApplicationController return end - if @user.update_attributes(password_attributes) + result = Users::UpdateService.new(@user, password_attributes).execute + + if result[:status] == :success flash[:notice] = "Password was successfully updated. Please login with it" redirect_to new_user_session_path else @@ -75,7 +77,7 @@ class Profiles::PasswordsController < Profiles::ApplicationController end def authorize_change_password! - return render_404 if @user.ldap_user? + render_404 unless @user.allow_password_authentication? end def user_params diff --git a/app/controllers/profiles/preferences_controller.rb b/app/controllers/profiles/preferences_controller.rb index 5414142e2df..1e557c47638 100644 --- a/app/controllers/profiles/preferences_controller.rb +++ b/app/controllers/profiles/preferences_controller.rb @@ -6,7 +6,9 @@ class Profiles::PreferencesController < Profiles::ApplicationController def update begin - if @user.update_attributes(preferences_params) + result = Users::UpdateService.new(user, preferences_params).execute + + if result[:status] == :success flash[:notice] = 'Preferences saved.' else flash[:alert] = 'Failed to save preferences.' diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb index 313cdcd1c15..1a4f77639e7 100644 --- a/app/controllers/profiles/two_factor_auths_controller.rb +++ b/app/controllers/profiles/two_factor_auths_controller.rb @@ -10,7 +10,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController current_user.otp_grace_period_started_at = Time.current end - current_user.save! if current_user.changed? + Users::UpdateService.new(current_user).execute! if two_factor_authentication_required? && !current_user.two_factor_enabled? two_factor_authentication_reason( @@ -41,9 +41,9 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController def create if current_user.validate_and_consume_otp!(params[:pin_code]) - current_user.otp_required_for_login = true - @codes = current_user.generate_otp_backup_codes! - current_user.save! + Users::UpdateService.new(current_user, otp_required_for_login: true).execute! do |user| + @codes = user.generate_otp_backup_codes! + end render 'create' else @@ -70,8 +70,9 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController end def codes - @codes = current_user.generate_otp_backup_codes! - current_user.save! + Users::UpdateService.new(current_user).execute! do |user| + @codes = user.generate_otp_backup_codes! + end end def destroy diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index f98a9e24de1..076076fd1b3 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -12,39 +12,47 @@ class ProfilesController < Profiles::ApplicationController user_params.except!(:email) if @user.external_email? respond_to do |format| - if @user.update_attributes(user_params) + result = Users::UpdateService.new(@user, user_params).execute + + if result[:status] == :success message = "Profile was successfully updated" + format.html { redirect_back_or_default(default: { action: 'show' }, options: { notice: message }) } format.json { render json: { message: message } } else - message = @user.errors.full_messages.uniq.join('. ') - format.html { redirect_back_or_default(default: { action: 'show' }, options: { alert: "Failed to update profile. #{message}" }) } - format.json { render json: { message: message }, status: :unprocessable_entity } + format.html { redirect_back_or_default(default: { action: 'show' }, options: { alert: result[:message] }) } + format.json { render json: result } end end end def reset_private_token - if current_user.reset_authentication_token! - flash[:notice] = "Private token was successfully reset" + Users::UpdateService.new(@user).execute! do |user| + user.reset_authentication_token! end + flash[:notice] = "Private token was successfully reset" + redirect_to profile_account_path end def reset_incoming_email_token - if current_user.reset_incoming_email_token! - flash[:notice] = "Incoming email token was successfully reset" + Users::UpdateService.new(@user).execute! do |user| + user.reset_incoming_email_token! end + flash[:notice] = "Incoming email token was successfully reset" + redirect_to profile_account_path end def reset_rss_token - if current_user.reset_rss_token! - flash[:notice] = "RSS token was successfully reset" + Users::UpdateService.new(@user).execute! do |user| + user.reset_rss_token! end + flash[:notice] = "RSS token was successfully reset" + redirect_to profile_account_path end @@ -55,12 +63,13 @@ class ProfilesController < Profiles::ApplicationController end def update_username - if @user.update_attributes(username: user_params[:username]) - options = { notice: "Username successfully changed" } - else - message = @user.errors.full_messages.uniq.join('. ') - options = { alert: "Username change failed - #{message}" } - end + result = Users::UpdateService.new(@user, username: user_params[:username]).execute + + options = if result[:status] == :success + { notice: "Username successfully changed" } + else + { alert: "Username change failed - #{result[:message]}" } + end redirect_back_or_default(default: { action: 'show' }, options: options) end diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb index 3d7ce4f0222..221e01b415a 100644 --- a/app/controllers/projects/application_controller.rb +++ b/app/controllers/projects/application_controller.rb @@ -22,6 +22,7 @@ class Projects::ApplicationController < ApplicationController def project return @project if @project + return nil unless params[:project_id] || params[:id] path = File.join(params[:namespace_id], params[:project_id] || params[:id]) auth_proc = ->(project) { !project.pending_delete? } @@ -76,13 +77,13 @@ class Projects::ApplicationController < ApplicationController def require_non_empty_project # Be sure to return status code 303 to avoid a double DELETE: # http://api.rubyonrails.org/classes/ActionController/Redirecting.html - redirect_to namespace_project_path(@project.namespace, @project), status: 303 if @project.empty_repo? + redirect_to project_path(@project), status: 303 if @project.empty_repo? end def require_branch_head unless @repository.branch_exists?(@ref) redirect_to( - namespace_project_tree_path(@project.namespace, @project, @ref), + project_tree_path(@project, @ref), notice: "This action is not allowed unless you are on a branch" ) end diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index ea036b1f705..f637a9a803b 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -46,7 +46,7 @@ class Projects::ArtifactsController < Projects::ApplicationController def keep build.keep_artifacts! - redirect_to namespace_project_job_path(project.namespace, project, build) + redirect_to project_job_path(project, build) end def latest_succeeded diff --git a/app/controllers/projects/badges_controller.rb b/app/controllers/projects/badges_controller.rb index 6c25cd83a24..06ba73d8e8d 100644 --- a/app/controllers/projects/badges_controller.rb +++ b/app/controllers/projects/badges_controller.rb @@ -3,11 +3,11 @@ class Projects::BadgesController < Projects::ApplicationController before_action :authorize_admin_project!, only: [:index] before_action :no_cache_headers, except: [:index] - def build - build_status = Gitlab::Badge::Build::Status + def pipeline + pipeline_status = Gitlab::Badge::Pipeline::Status .new(project, params[:ref]) - render_badge build_status + render_badge pipeline_status end def coverage diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index a82d6fd5a4a..49ea2945675 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -27,9 +27,9 @@ class Projects::BlobController < Projects::ApplicationController def create create_commit(Files::CreateService, success_notice: "The file has been successfully created.", - success_path: -> { namespace_project_blob_path(@project.namespace, @project, File.join(@branch_name, @file_path)) }, + success_path: -> { project_blob_path(@project, File.join(@branch_name, @file_path)) }, failure_view: :new, - failure_path: namespace_project_new_blob_path(@project.namespace, @project, @ref)) + failure_path: project_new_blob_path(@project, @ref)) end def show @@ -63,7 +63,7 @@ class Projects::BlobController < Projects::ApplicationController @path = params[:file_path] if params[:file_path].present? create_commit(Files::UpdateService, success_path: -> { after_edit_path }, failure_view: :edit, - failure_path: namespace_project_blob_path(@project.namespace, @project, @id)) + failure_path: project_blob_path(@project, @id)) rescue Files::UpdateService::FileChangedError @conflict = true @@ -83,9 +83,9 @@ class Projects::BlobController < Projects::ApplicationController def destroy create_commit(Files::DeleteService, success_notice: "The file has been successfully deleted.", - success_path: -> { namespace_project_tree_path(@project.namespace, @project, @branch_name) }, + success_path: -> { project_tree_path(@project, @branch_name) }, failure_view: :show, - failure_path: namespace_project_blob_path(@project.namespace, @project, @id)) + failure_path: project_blob_path(@project, @id)) end def diff @@ -118,7 +118,7 @@ class Projects::BlobController < Projects::ApplicationController else if tree = @repository.tree(@commit.id, @path) if tree.entries.any? - return redirect_to namespace_project_tree_path(@project.namespace, @project, File.join(@ref, @path)) + return redirect_to project_tree_path(@project, File.join(@ref, @path)) end end @@ -143,10 +143,10 @@ class Projects::BlobController < Projects::ApplicationController def after_edit_path from_merge_request = MergeRequestsFinder.new(current_user, project_id: @project.id).execute.find_by(iid: params[:from_merge_request_iid]) if from_merge_request && @branch_name == @ref - diffs_namespace_project_merge_request_path(from_merge_request.target_project.namespace, from_merge_request.target_project, from_merge_request) + + diffs_project_merge_request_path(from_merge_request.target_project, from_merge_request) + "##{hexdigest(@path)}" else - namespace_project_blob_path(@project.namespace, @project, File.join(@branch_name, @path)) + project_blob_path(@project, File.join(@branch_name, @path)) end end diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index 94a752c21eb..747768eefb1 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -8,7 +8,7 @@ class Projects::BranchesController < Projects::ApplicationController before_action :authorize_push_code!, only: [:new, :create, :destroy, :destroy_all_merged] def index - @sort = params[:sort].presence || sort_value_name + @sort = params[:sort].presence || sort_value_recently_updated @branches = BranchesFinder.new(@repository, params).execute @branches = Kaminari.paginate_array(@branches).page(params[:page]) @@ -52,7 +52,7 @@ class Projects::BranchesController < Projects::ApplicationController redirect_to url_to_autodeploy_setup(project, branch_name), notice: view_context.autodeploy_flash_notice(branch_name) else - redirect_to namespace_project_tree_path(@project.namespace, @project, branch_name) + redirect_to project_tree_path(@project, branch_name) end else @error = result[:message] @@ -62,7 +62,7 @@ class Projects::BranchesController < Projects::ApplicationController format.json do if result[:status] == :success - render json: { name: branch_name, url: namespace_project_tree_url(@project.namespace, @project, branch_name) } + render json: { name: branch_name, url: project_tree_url(@project, branch_name) } else render json: result[:messsage], status: :unprocessable_entity end @@ -79,7 +79,7 @@ class Projects::BranchesController < Projects::ApplicationController flash_type = result[:status] == :error ? :alert : :notice flash[flash_type] = result[:message] - redirect_to namespace_project_branches_path(@project.namespace, @project), status: 303 + redirect_to project_branches_path(@project), status: 303 end format.js { render nothing: true, status: result[:return_code] } @@ -90,7 +90,7 @@ class Projects::BranchesController < Projects::ApplicationController def destroy_all_merged DeleteMergedBranchesService.new(@project, current_user).async_execute - redirect_to namespace_project_branches_path(@project.namespace, @project), + redirect_to project_branches_path(@project), notice: 'Merged branches are being deleted. This can take some time depending on the number of branches. Please refresh the page to see changes.' end @@ -106,8 +106,7 @@ class Projects::BranchesController < Projects::ApplicationController end def url_to_autodeploy_setup(project, branch_name) - namespace_project_new_blob_path( - project.namespace, + project_new_blob_path( project, branch_name, file_name: '.gitlab-ci.yml', diff --git a/app/controllers/projects/build_artifacts_controller.rb b/app/controllers/projects/build_artifacts_controller.rb index f34a198634e..b45e5d7ff43 100644 --- a/app/controllers/projects/build_artifacts_controller.rb +++ b/app/controllers/projects/build_artifacts_controller.rb @@ -7,23 +7,23 @@ class Projects::BuildArtifactsController < Projects::ApplicationController before_action :validate_artifacts! def download - redirect_to download_namespace_project_job_artifacts_path(project.namespace, project, job) + redirect_to download_project_job_artifacts_path(project, job) end def browse - redirect_to browse_namespace_project_job_artifacts_path(project.namespace, project, job, path: params[:path]) + redirect_to browse_project_job_artifacts_path(project, job, path: params[:path]) end def file - redirect_to file_namespace_project_job_artifacts_path(project.namespace, project, job, path: params[:path]) + redirect_to file_project_job_artifacts_path(project, job, path: params[:path]) end def raw - redirect_to raw_namespace_project_job_artifacts_path(project.namespace, project, job, path: params[:path]) + redirect_to raw_project_job_artifacts_path(project, job, path: params[:path]) end def latest_succeeded - redirect_to latest_succeeded_namespace_project_artifacts_path(project.namespace, project, job, ref_name_and_path: params[:ref_name_and_path], job: params[:job]) + redirect_to latest_succeeded_project_artifacts_path(project, job, ref_name_and_path: params[:ref_name_and_path], job: params[:job]) end private diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb index 1334a231788..230b072dcea 100644 --- a/app/controllers/projects/builds_controller.rb +++ b/app/controllers/projects/builds_controller.rb @@ -2,15 +2,15 @@ class Projects::BuildsController < Projects::ApplicationController before_action :authorize_read_build! def index - redirect_to namespace_project_jobs_path(project.namespace, project) + redirect_to project_jobs_path(project) end def show - redirect_to namespace_project_job_path(project.namespace, project, job) + redirect_to project_job_path(project, job) end def raw - redirect_to raw_namespace_project_job_path(project.namespace, project, job) + redirect_to raw_project_job_path(project, job) end private diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 7c3cce1c241..6de125e7e80 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -38,9 +38,14 @@ class Projects::CommitController < Projects::ApplicationController format.json do Gitlab::PollingInterval.set_header(response, interval: 10_000) - render json: PipelineSerializer - .new(project: @project, current_user: @current_user) - .represent(@pipelines) + render json: { + pipelines: PipelineSerializer + .new(project: @project, current_user: @current_user) + .represent(@pipelines), + count: { + all: @pipelines.count + } + } end end end @@ -80,16 +85,16 @@ class Projects::CommitController < Projects::ApplicationController end def successful_change_path - referenced_merge_request_url || namespace_project_commits_url(@project.namespace, @project, @branch_name) + referenced_merge_request_url || project_commits_url(@project, @branch_name) end def failed_change_path - referenced_merge_request_url || namespace_project_commit_url(@project.namespace, @project, params[:id]) + referenced_merge_request_url || project_commit_url(@project, params[:id]) end def referenced_merge_request_url if merge_request = @commit.merged_merge_request(current_user) - namespace_project_merge_request_url(merge_request.target_project.namespace, merge_request.target_project, merge_request) + project_merge_request_url(merge_request.target_project, merge_request) end end diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb index 37b5a6e9d48..2de9900d449 100644 --- a/app/controllers/projects/commits_controller.rb +++ b/app/controllers/projects/commits_controller.rb @@ -6,18 +6,9 @@ class Projects::CommitsController < Projects::ApplicationController before_action :require_non_empty_project before_action :assign_ref_vars before_action :authorize_download_code! + before_action :set_commits def show - @limit, @offset = (params[:limit] || 40).to_i, (params[:offset] || 0).to_i - search = params[:search] - - @commits = - if search.present? - @repository.find_commits_by_message(search, @ref, @path, @limit, @offset) - else - @repository.commits(@ref, path: @path, limit: @limit, offset: @offset) - end - @note_counts = project.notes.where(commit_id: @commits.map(&:id)) .group(:commit_id).count @@ -37,4 +28,33 @@ class Projects::CommitsController < Projects::ApplicationController end end end + + def signatures + respond_to do |format| + format.json do + render json: { + signatures: @commits.select(&:has_signature?).map do |commit| + { + commit_sha: commit.sha, + html: view_to_html_string('projects/commit/_signature', signature: commit.signature) + } + end + } + end + end + end + + private + + def set_commits + @limit, @offset = (params[:limit] || 40).to_i, (params[:offset] || 0).to_i + search = params[:search] + + @commits = + if search.present? + @repository.find_commits_by_message(search, @ref, @path, @limit, @offset) + else + @repository.commits(@ref, path: @path, limit: @limit, offset: @offset) + end + end end diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index ef400c4d745..c8613c0d634 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -31,9 +31,9 @@ class Projects::CompareController < Projects::ApplicationController from: params[:from].presence, to: params[:to].presence } - redirect_to namespace_project_compare_index_path(@project.namespace, @project, from_to_vars) + redirect_to project_compare_index_path(@project, from_to_vars) else - redirect_to namespace_project_compare_path(@project.namespace, @project, + redirect_to project_compare_path(@project, params[:from], params[:to]) end end diff --git a/app/controllers/projects/deployments_controller.rb b/app/controllers/projects/deployments_controller.rb index 6644deb49c9..47c312ffddf 100644 --- a/app/controllers/projects/deployments_controller.rb +++ b/app/controllers/projects/deployments_controller.rb @@ -22,6 +22,22 @@ class Projects::DeploymentsController < Projects::ApplicationController render_404 end + def additional_metrics + return render_404 unless deployment.has_additional_metrics? + + respond_to do |format| + format.json do + metrics = deployment.additional_metrics + + if metrics.any? + render json: metrics + else + head :no_content + end + end + end + end + private def deployment diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index efe83776834..29e223a5273 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -15,6 +15,8 @@ class Projects::EnvironmentsController < Projects::ApplicationController respond_to do |format| format.html format.json do + Gitlab::PollingInterval.set_header(response, interval: 3_000) + render json: { environments: EnvironmentSerializer .new(project: @project, current_user: @current_user) @@ -63,7 +65,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController @environment = project.environments.create(environment_params) if @environment.persisted? - redirect_to namespace_project_environment_path(project.namespace, project, @environment) + redirect_to project_environment_path(project, @environment) else render :new end @@ -71,7 +73,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController def update if @environment.update(environment_params) - redirect_to namespace_project_environment_path(project.namespace, project, @environment) + redirect_to project_environment_path(project, @environment) else render :edit end @@ -86,7 +88,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController if stop_action polymorphic_url([project.namespace.becomes(Namespace), project, stop_action]) else - namespace_project_environment_url(project.namespace, project, @environment) + project_environment_url(project, @environment) end respond_to do |format| @@ -129,6 +131,16 @@ class Projects::EnvironmentsController < Projects::ApplicationController end end + def additional_metrics + respond_to do |format| + format.json do + additional_metrics = environment.additional_metrics || {} + + render json: additional_metrics, status: additional_metrics.any? ? :ok : :no_content + end + end + end + private def verify_api_request! diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb index 1eb3800e49d..3f83bef2c79 100644 --- a/app/controllers/projects/forks_controller.rb +++ b/app/controllers/projects/forks_controller.rb @@ -44,12 +44,12 @@ class Projects::ForksController < Projects::ApplicationController if @forked_project.saved? && @forked_project.forked? if @forked_project.import_in_progress? - redirect_to namespace_project_import_path(@forked_project.namespace, @forked_project, continue: continue_params) + redirect_to project_import_path(@forked_project, continue: continue_params) else if continue_params redirect_to continue_params[:to], notice: continue_params[:notice] else - redirect_to namespace_project_path(@forked_project.namespace, @forked_project), notice: "The project '#{@forked_project.name}' was successfully forked." + redirect_to project_path(@forked_project), notice: "The project '#{@forked_project.name}' was successfully forked." end end else diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb index df5221fe95f..57372f9e79d 100644 --- a/app/controllers/projects/graphs_controller.rb +++ b/app/controllers/projects/graphs_controller.rb @@ -29,7 +29,7 @@ class Projects::GraphsController < Projects::ApplicationController end def ci - redirect_to charts_namespace_project_pipelines_path(@project.namespace, @project) + redirect_to charts_project_pipelines_path(@project) end private diff --git a/app/controllers/projects/group_links_controller.rb b/app/controllers/projects/group_links_controller.rb index deb33a2f0ff..f59200d3b1f 100644 --- a/app/controllers/projects/group_links_controller.rb +++ b/app/controllers/projects/group_links_controller.rb @@ -22,7 +22,7 @@ class Projects::GroupLinksController < Projects::ApplicationController flash[:alert] = 'Please select a group.' end - redirect_to namespace_project_settings_members_path(project.namespace, project) + redirect_to project_project_members_path(project) end def update @@ -36,7 +36,7 @@ class Projects::GroupLinksController < Projects::ApplicationController respond_to do |format| format.html do - redirect_to namespace_project_settings_members_path(project.namespace, project), status: 302 + redirect_to project_project_members_path(project), status: 302 end format.js { head :ok } end diff --git a/app/controllers/projects/hook_logs_controller.rb b/app/controllers/projects/hook_logs_controller.rb index 354f0d6db3a..745e89fc843 100644 --- a/app/controllers/projects/hook_logs_controller.rb +++ b/app/controllers/projects/hook_logs_controller.rb @@ -14,11 +14,11 @@ class Projects::HookLogsController < Projects::ApplicationController end def retry - status, message = hook.execute(hook_log.request_data, hook_log.trigger) + result = hook.execute(hook_log.request_data, hook_log.trigger) - set_hook_execution_notice(status, message) + set_hook_execution_notice(result) - redirect_to edit_namespace_project_hook_path(@project.namespace, @project, @hook) + redirect_to edit_project_hook_path(@project, @hook) end private diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb index f5143280154..85d35900c71 100644 --- a/app/controllers/projects/hooks_controller.rb +++ b/app/controllers/projects/hooks_controller.rb @@ -9,6 +9,10 @@ class Projects::HooksController < Projects::ApplicationController layout "project_settings" + def index + redirect_to project_settings_integrations_path(@project) + end + def create @hook = @project.hooks.new(hook_params) @hook.save @@ -17,7 +21,7 @@ class Projects::HooksController < Projects::ApplicationController @hooks = @project.hooks.select(&:persisted?) flash[:alert] = @hook.errors.full_messages.join.html_safe end - redirect_to namespace_project_settings_integrations_path(@project.namespace, @project) + redirect_to project_settings_integrations_path(@project) end def edit @@ -26,20 +30,16 @@ class Projects::HooksController < Projects::ApplicationController def update if hook.update_attributes(hook_params) flash[:notice] = 'Hook was successfully updated.' - redirect_to namespace_project_settings_integrations_path(@project.namespace, @project) + redirect_to project_settings_integrations_path(@project) else render 'edit' end end def test - if !@project.empty_repo? - status, message = TestHookService.new.execute(hook, current_user) + result = TestHooks::ProjectService.new(hook, current_user, params[:trigger]).execute - set_hook_execution_notice(status, message) - else - flash[:alert] = 'Hook execution failed. Ensure the project has commits.' - end + set_hook_execution_notice(result) redirect_back_or_default(default: { action: 'index' }) end @@ -47,7 +47,7 @@ class Projects::HooksController < Projects::ApplicationController def destroy hook.destroy - redirect_to namespace_project_settings_integrations_path(@project.namespace, @project), status: 302 + redirect_to project_settings_integrations_path(@project), status: 302 end private diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb index 4b143434ea5..49aa32119ef 100644 --- a/app/controllers/projects/imports_controller.rb +++ b/app/controllers/projects/imports_controller.rb @@ -17,7 +17,7 @@ class Projects::ImportsController < Projects::ApplicationController @project.reload.import_schedule end - redirect_to namespace_project_import_path(@project.namespace, @project) + redirect_to project_import_path(@project) end def show @@ -25,10 +25,10 @@ class Projects::ImportsController < Projects::ApplicationController if continue_params redirect_to continue_params[:to], notice: continue_params[:notice] else - redirect_to namespace_project_path(@project.namespace, @project), notice: finished_notice + redirect_to project_path(@project), notice: finished_notice end elsif @project.import_failed? - redirect_to new_namespace_project_import_path(@project.namespace, @project) + redirect_to new_project_import_path(@project) else if continue_params && continue_params[:notice_now] flash.now[:notice] = continue_params[:notice_now] @@ -50,19 +50,19 @@ class Projects::ImportsController < Projects::ApplicationController def require_no_repo if @project.repository_exists? - redirect_to namespace_project_path(@project.namespace, @project) + redirect_to project_path(@project) end end def redirect_if_progress if @project.import_in_progress? - redirect_to namespace_project_import_path(@project.namespace, @project) + redirect_to project_import_path(@project) end end def redirect_if_no_import if @project.repository_exists? && @project.no_import? - redirect_to namespace_project_path(@project.namespace, @project) + redirect_to project_path(@project) end end end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index dfc6baa34a4..e2ccabb22db 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -8,7 +8,6 @@ class Projects::IssuesController < Projects::ApplicationController prepend_before_action :authenticate_user!, only: [:new] - before_action :redirect_to_external_issue_tracker, only: [:index, :new] before_action :check_issues_available! before_action :issue, except: [:index, :new, :create, :bulk_update] @@ -238,20 +237,24 @@ class Projects::IssuesController < Projects::ApplicationController alias_method :awardable, :issue alias_method :spammable, :issue + def spammable_path + project_issue_path(@project, @issue) + end + def authorize_update_issue! - return render_404 unless can?(current_user, :update_issue, @issue) + render_404 unless can?(current_user, :update_issue, @issue) end def authorize_admin_issues! - return render_404 unless can?(current_user, :admin_issue, @project) + render_404 unless can?(current_user, :admin_issue, @project) end def authorize_create_merge_request! - return render_404 unless can?(current_user, :push_code, @project) && @issue.can_be_worked_on?(current_user) + render_404 unless can?(current_user, :push_code, @project) && @issue.can_be_worked_on?(current_user) end def check_issues_available! - return render_404 unless @project.feature_available?(:issues, current_user) && @project.default_issues_tracker? + return render_404 unless @project.feature_available?(:issues, current_user) end def redirect_to_external_issue_tracker @@ -262,15 +265,27 @@ class Projects::IssuesController < Projects::ApplicationController if action_name == 'new' redirect_to external.new_issue_path else - redirect_to external.project_path + redirect_to external.issue_tracker_path end end def issue_params - params.require(:issue).permit( - :title, :assignee_id, :position, :description, :confidential, - :milestone_id, :due_date, :state_event, :task_num, :lock_version, label_ids: [], assignee_ids: [] - ) + 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 + ] + [{ label_ids: [], assignee_ids: [] }] end def authenticate_user! diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb index cb4f46388fd..96abdac91b6 100644 --- a/app/controllers/projects/jobs_controller.rb +++ b/app/controllers/projects/jobs_controller.rb @@ -38,7 +38,7 @@ class Projects::JobsController < Projects::ApplicationController build.cancel if can?(current_user, :update_build, build) end - redirect_to namespace_project_jobs_path(project.namespace, project) + redirect_to project_jobs_path(project) end def show @@ -108,7 +108,7 @@ class Projects::JobsController < Projects::ApplicationController def erase if @build.erase(erased_by: current_user) - redirect_to namespace_project_job_path(project.namespace, project, @build), + redirect_to project_job_path(project, @build), notice: "Build has been successfully erased!" else respond_422 @@ -137,6 +137,6 @@ class Projects::JobsController < Projects::ApplicationController end def build_path(build) - namespace_project_job_path(build.project.namespace, build.project, build) + project_job_path(build.project, build) end end diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb index daa973c9281..480a2dff262 100644 --- a/app/controllers/projects/labels_controller.rb +++ b/app/controllers/projects/labels_controller.rb @@ -33,7 +33,7 @@ class Projects::LabelsController < Projects::ApplicationController if @label.valid? respond_to do |format| - format.html { redirect_to namespace_project_labels_path(@project.namespace, @project) } + format.html { redirect_to project_labels_path(@project) } format.json { render json: @label } end else @@ -51,7 +51,7 @@ class Projects::LabelsController < Projects::ApplicationController @label = Labels::UpdateService.new(label_params).execute(@label) if @label.valid? - redirect_to namespace_project_labels_path(@project.namespace, @project) + redirect_to project_labels_path(@project) else render :edit end @@ -61,12 +61,11 @@ class Projects::LabelsController < Projects::ApplicationController Gitlab::IssuesLabels.generate(@project) if params[:redirect] == 'issues' - redirect_to namespace_project_issues_path(@project.namespace, @project) + redirect_to project_issues_path(@project) elsif params[:redirect] == 'merge_requests' - redirect_to namespace_project_merge_requests_path(@project.namespace, - @project) + redirect_to project_merge_requests_path(@project) else - redirect_to namespace_project_labels_path(@project.namespace, @project) + redirect_to project_labels_path(@project) end end @@ -74,7 +73,7 @@ class Projects::LabelsController < Projects::ApplicationController @label.destroy @labels = find_labels - redirect_to namespace_project_labels_path(@project.namespace, @project), + redirect_to project_labels_path(@project), status: 302, notice: 'Label was removed' end @@ -114,7 +113,7 @@ class Projects::LabelsController < Projects::ApplicationController return render_404 unless promote_service.execute(@label) respond_to do |format| format.html do - redirect_to(namespace_project_labels_path(@project.namespace, @project), + redirect_to(project_labels_path(@project), notice: 'Label was promoted to a Group Label') end format.js @@ -125,7 +124,7 @@ class Projects::LabelsController < Projects::ApplicationController respond_to do |format| format.html do - redirect_to(namespace_project_labels_path(@project.namespace, @project), + redirect_to(project_labels_path(@project), notice: 'Failed to promote label due to internal error. Please contact administrators.') end format.js diff --git a/app/controllers/projects/mattermosts_controller.rb b/app/controllers/projects/mattermosts_controller.rb index 38f7e6eb5e9..0f6add3e287 100644 --- a/app/controllers/projects/mattermosts_controller.rb +++ b/app/controllers/projects/mattermosts_controller.rb @@ -16,12 +16,10 @@ class Projects::MattermostsController < Projects::ApplicationController if result flash[:notice] = 'This service is now configured' - redirect_to edit_namespace_project_service_path( - @project.namespace, @project, service) + redirect_to edit_project_service_path(@project, service) else flash[:alert] = message || 'Failed to configure service' - redirect_to new_namespace_project_mattermost_path( - @project.namespace, @project) + redirect_to new_project_mattermost_path(@project) end end diff --git a/app/controllers/projects/merge_requests/application_controller.rb b/app/controllers/projects/merge_requests/application_controller.rb new file mode 100644 index 00000000000..6602b204fcb --- /dev/null +++ b/app/controllers/projects/merge_requests/application_controller.rb @@ -0,0 +1,47 @@ +class Projects::MergeRequests::ApplicationController < Projects::ApplicationController + before_action :check_merge_requests_available! + before_action :merge_request + before_action :authorize_read_merge_request! + before_action :ensure_ref_fetched + + private + + def merge_request + @issuable = @merge_request ||= @project.merge_requests.find_by!(iid: params[:id]) + end + + # Make sure merge requests created before 8.0 + # have head file in refs/merge-requests/ + def ensure_ref_fetched + @merge_request.ensure_ref_fetched + end + + def merge_request_params + params.require(:merge_request).permit(merge_request_params_attributes) + end + + def merge_request_params_attributes + [ + :assignee_id, + :description, + :force_remove_source_branch, + :lock_version, + :milestone_id, + :source_branch, + :source_project_id, + :state_event, + :target_branch, + :target_project_id, + :task_num, + :title, + + label_ids: [] + ] + end + + def set_pipeline_variables + @pipelines = @merge_request.all_pipelines + @pipeline = @merge_request.head_pipeline + @statuses_count = @pipeline.present? ? @pipeline.statuses.relevant.count : 0 + end +end diff --git a/app/controllers/projects/merge_requests/conflicts_controller.rb b/app/controllers/projects/merge_requests/conflicts_controller.rb new file mode 100644 index 00000000000..28afef101a9 --- /dev/null +++ b/app/controllers/projects/merge_requests/conflicts_controller.rb @@ -0,0 +1,66 @@ +class Projects::MergeRequests::ConflictsController < Projects::MergeRequests::ApplicationController + include IssuableActions + + before_action :authorize_can_resolve_conflicts! + + def show + respond_to do |format| + format.html do + labels + end + + format.json do + if @conflicts_list.can_be_resolved_in_ui? + render json: @conflicts_list + elsif @merge_request.can_be_merged? + render json: { + message: 'The merge conflicts for this merge request have already been resolved. Please return to the merge request.', + type: 'error' + } + else + render json: { + message: 'The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally.', + type: 'error' + } + end + end + end + end + + def conflict_for_path + return render_404 unless @conflicts_list.can_be_resolved_in_ui? + + file = @conflicts_list.file_for_path(params[:old_path], params[:new_path]) + + return render_404 unless file + + render json: file, full_content: true + end + + def resolve_conflicts + return render_404 unless @conflicts_list.can_be_resolved_in_ui? + + if @merge_request.can_be_merged? + render status: :bad_request, json: { message: 'The merge conflicts for this merge request have already been resolved.' } + return + end + + begin + ::MergeRequests::Conflicts::ResolveService + .new(merge_request) + .execute(current_user, params) + + flash[:notice] = 'All merge conflicts were resolved. The merge request can now be merged.' + + render json: { redirect_to: project_merge_request_url(@project, @merge_request, resolved_conflicts: true) } + rescue Gitlab::Conflict::ResolutionError => e + render status: :bad_request, json: { message: e.message } + end + end + + def authorize_can_resolve_conflicts! + @conflicts_list = ::MergeRequests::Conflicts::ListService.new(@merge_request) + + return render_404 unless @conflicts_list.can_be_resolved_by?(current_user) + end +end diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb new file mode 100644 index 00000000000..f35d53896ba --- /dev/null +++ b/app/controllers/projects/merge_requests/creations_controller.rb @@ -0,0 +1,128 @@ +class Projects::MergeRequests::CreationsController < Projects::MergeRequests::ApplicationController + include DiffForPath + include DiffHelper + + skip_before_action :merge_request + skip_before_action :ensure_ref_fetched + before_action :authorize_create_merge_request! + before_action :apply_diff_view_cookie!, only: [:diffs, :diff_for_path] + before_action :build_merge_request, except: [:create] + + def new + define_new_vars + end + + def create + @target_branches ||= [] + @merge_request = ::MergeRequests::CreateService.new(project, current_user, merge_request_params).execute + + if @merge_request.valid? + redirect_to(merge_request_path(@merge_request)) + else + @source_project = @merge_request.source_project + @target_project = @merge_request.target_project + + define_new_vars + render action: "new" + end + end + + def pipelines + @pipelines = @merge_request.all_pipelines + + Gitlab::PollingInterval.set_header(response, interval: 10_000) + + render json: { + pipelines: PipelineSerializer + .new(project: @project, current_user: @current_user) + .represent(@pipelines) + } + end + + def diffs + @diffs = if @merge_request.can_be_created + @merge_request.diffs(diff_options) + else + [] + end + @diff_notes_disabled = true + + @environment = @merge_request.environments_for(current_user).last + + render json: { html: view_to_html_string('projects/merge_requests/creations/_diffs', diffs: @diffs, environment: @environment) } + end + + def diff_for_path + @diffs = @merge_request.diffs(diff_options) + @diff_notes_disabled = true + + render_diff_for_path(@diffs) + end + + def branch_from + # This is always source + @source_project = @merge_request.nil? ? @project : @merge_request.source_project + + if params[:ref].present? + @ref = params[:ref] + @commit = @repository.commit("refs/heads/#{@ref}") + end + + render layout: false + end + + def branch_to + @target_project = selected_target_project + + if params[:ref].present? + @ref = params[:ref] + @commit = @target_project.commit("refs/heads/#{@ref}") + end + + render layout: false + end + + def update_branches + @target_project = selected_target_project + @target_branches = @target_project.repository.branch_names + + render layout: false + end + + private + + def build_merge_request + params[:merge_request] ||= ActionController::Parameters.new(source_project: @project) + @merge_request = ::MergeRequests::BuildService.new(project, current_user, merge_request_params.merge(diff_options: diff_options)).execute + end + + def define_new_vars + @noteable = @merge_request + + @target_branches = if @merge_request.target_project + @merge_request.target_project.repository.branch_names + else + [] + end + + @target_project = @merge_request.target_project + @source_project = @merge_request.source_project + @commits = @merge_request.commits + @commit = @merge_request.diff_head_commit + + @note_counts = Note.where(commit_id: @commits.map(&:id)) + .group(:commit_id).count + + @labels = LabelsFinder.new(current_user, project_id: @project.id).execute + + set_pipeline_variables + end + + def selected_target_project + if @project.id.to_s == params[:target_project_id] || @project.forked_project_link.nil? + @project + else + @project.forked_project_link.forked_from_project + end + end +end diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb new file mode 100644 index 00000000000..330b7df4541 --- /dev/null +++ b/app/controllers/projects/merge_requests/diffs_controller.rb @@ -0,0 +1,66 @@ +class Projects::MergeRequests::DiffsController < Projects::MergeRequests::ApplicationController + include DiffForPath + include DiffHelper + include RendersNotes + + before_action :apply_diff_view_cookie! + before_action :define_diff_vars + before_action :define_diff_comment_vars + + def show + @environment = @merge_request.environments_for(current_user).last + + render json: { html: view_to_html_string("projects/merge_requests/diffs/_diffs") } + end + + def diff_for_path + render_diff_for_path(@diffs) + end + + private + + def define_diff_vars + @merge_request_diff = + if params[:diff_id] + @merge_request.merge_request_diffs.viewable.find(params[:diff_id]) + else + @merge_request.merge_request_diff + end + + @merge_request_diffs = @merge_request.merge_request_diffs.viewable.select_without_diff + @comparable_diffs = @merge_request_diffs.select { |diff| diff.id < @merge_request_diff.id } + + if params[:start_sha].present? + @start_sha = params[:start_sha] + @start_version = @comparable_diffs.find { |diff| diff.head_commit_sha == @start_sha } + + unless @start_version + @start_sha = @merge_request_diff.head_commit_sha + @start_version = @merge_request_diff + end + end + + @compare = + if @start_sha + @merge_request_diff.compare_with(@start_sha) + else + @merge_request_diff + end + + @diffs = @compare.diffs(diff_options) + end + + def define_diff_comment_vars + @new_diff_note_attrs = { + noteable_type: 'MergeRequest', + noteable_id: @merge_request.id + } + + @diff_notes_disabled = false + + @use_legacy_diff_notes = !@merge_request.has_complete_diff_refs? + + @grouped_diff_discussions = @merge_request.grouped_diff_discussions(@compare.diff_refs) + @notes = prepare_notes_for_rendering(@grouped_diff_discussions.values.flatten.flat_map(&:notes)) + end +end diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 164a8824277..d361e661d0e 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -1,38 +1,17 @@ -class Projects::MergeRequestsController < Projects::ApplicationController +class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationController include ToggleSubscriptionAction - include DiffForPath - include DiffHelper include IssuableActions include RendersNotes include ToggleAwardEmoji include IssuableCollections - before_action :check_merge_requests_available! - before_action :merge_request, only: [ - :edit, :update, :show, :diffs, :commits, :conflicts, :conflict_for_path, :pipelines, :merge, - :pipeline_status, :ci_environments_status, :toggle_subscription, :cancel_merge_when_pipeline_succeeds, :remove_wip, :resolve_conflicts, :assign_related_issues, :commit_change_content - ] - before_action :validates_merge_request, only: [:show, :diffs, :commits, :pipelines] - before_action :define_show_vars, only: [:diffs, :commits, :conflicts, :conflict_for_path, :builds, :pipelines] - before_action :ensure_ref_fetched, only: [:show, :diffs, :commits, :builds, :conflicts, :conflict_for_path, :pipelines] - before_action :close_merge_request_without_source_project, only: [:show, :diffs, :commits, :builds, :pipelines] - before_action :check_if_can_be_merged, only: :show - before_action :apply_diff_view_cookie!, only: [:new_diffs] - before_action :build_merge_request, only: [:new, :new_diffs] - - # Allow read any merge_request - before_action :authorize_read_merge_request! - - # Allow write(create) merge_request - before_action :authorize_create_merge_request!, only: [:new, :create] - - # Allow modify merge_request + skip_before_action :merge_request, only: [:index, :bulk_update] + skip_before_action :ensure_ref_fetched, only: [:index, :bulk_update] + before_action :authorize_update_merge_request!, only: [:close, :edit, :update, :remove_wip, :sort] before_action :authenticate_user!, only: [:assign_related_issues] - before_action :authorize_can_resolve_conflicts!, only: [:conflicts, :conflict_for_path, :resolve_conflicts] - def index @collection_type = "MergeRequest" @merge_requests = merge_requests_collection @@ -72,10 +51,30 @@ class Projects::MergeRequestsController < Projects::ApplicationController end def show + validates_merge_request + ensure_ref_fetched + close_merge_request_without_source_project + check_if_can_be_merged + respond_to do |format| format.html do - define_discussion_vars - define_show_vars + # Build a note object for comment form + @note = @project.notes.new(noteable: @merge_request) + + @discussions = @merge_request.discussions + @notes = prepare_notes_for_rendering(@discussions.flat_map(&:notes)) + + @noteable = @merge_request + @commits_count = @merge_request.commits_count + + if @merge_request.locked_long_ago? + @merge_request.unlock_mr + @merge_request.close + end + + labels + + set_pipeline_variables end format.json do @@ -98,198 +97,45 @@ class Projects::MergeRequestsController < Projects::ApplicationController end end - def diffs - apply_diff_view_cookie! - - respond_to do |format| - format.html { define_discussion_vars } - format.json do - define_diff_vars - define_diff_comment_vars - - @environment = @merge_request.environments_for(current_user).last - - render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") } - end - end - end - - # With an ID param, loads the MR at that ID. Otherwise, accepts the same params as #new - # and uses that (unsaved) MR. - # - def diff_for_path - if params[:id] - merge_request - define_diff_vars - define_diff_comment_vars - else - build_merge_request - @compare = @merge_request - @diffs = @compare.diffs(diff_options) - @diff_notes_disabled = true - end - - render_diff_for_path(@diffs) - end - def commits - respond_to do |format| - format.html do - define_discussion_vars - - render 'show' - end - format.json do - # Get commits from repository - # or from cache if already merged - @commits = @merge_request.commits - @note_counts = Note.where(commit_id: @commits.map(&:id)) - .group(:commit_id).count - - render json: { html: view_to_html_string('projects/merge_requests/show/_commits') } - end - end - end - - def conflicts - respond_to do |format| - format.html { define_discussion_vars } - - format.json do - if @conflicts_list.can_be_resolved_in_ui? - render json: @conflicts_list - elsif @merge_request.can_be_merged? - render json: { - message: 'The merge conflicts for this merge request have already been resolved. Please return to the merge request.', - type: 'error' - } - else - render json: { - message: 'The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally.', - type: 'error' - } - end - end - end - end - - def conflict_for_path - return render_404 unless @conflicts_list.can_be_resolved_in_ui? - - file = @conflicts_list.file_for_path(params[:old_path], params[:new_path]) - - return render_404 unless file - - render json: file, full_content: true - end - - def resolve_conflicts - return render_404 unless @conflicts_list.can_be_resolved_in_ui? - - if @merge_request.can_be_merged? - render status: :bad_request, json: { message: 'The merge conflicts for this merge request have already been resolved.' } - return - end - - begin - MergeRequests::Conflicts::ResolveService - .new(merge_request) - .execute(current_user, params) - - flash[:notice] = 'All merge conflicts were resolved. The merge request can now be merged.' + # Get commits from repository + # or from cache if already merged + @commits = @merge_request.commits + @note_counts = Note.where(commit_id: @commits.map(&:id)) + .group(:commit_id).count - render json: { redirect_to: namespace_project_merge_request_url(@project.namespace, @project, @merge_request, resolved_conflicts: true) } - rescue Gitlab::Conflict::ResolutionError => e - render status: :bad_request, json: { message: e.message } - end + render json: { html: view_to_html_string('projects/merge_requests/_commits') } end def pipelines @pipelines = @merge_request.all_pipelines - respond_to do |format| - format.html do - define_discussion_vars - - render 'show' - end - - format.json do - Gitlab::PollingInterval.set_header(response, interval: 10_000) + Gitlab::PollingInterval.set_header(response, interval: 10_000) - render json: PipelineSerializer - .new(project: @project, current_user: @current_user) - .represent(@pipelines) - end - end - end - - def new - respond_to do |format| - format.html { define_new_vars } - format.json do - define_pipelines_vars - - Gitlab::PollingInterval.set_header(response, interval: 10_000) - - render json: { - pipelines: PipelineSerializer - .new(project: @project, current_user: @current_user) - .represent(@pipelines) - } - end - end - end - - def new_diffs - respond_to do |format| - format.html do - define_new_vars - @show_changes_tab = true - render "new" - end - format.json do - @diffs = if @merge_request.can_be_created - @merge_request.diffs(diff_options) - else - [] - end - @diff_notes_disabled = true - - @environment = @merge_request.environments_for(current_user).last - - render json: { html: view_to_html_string('projects/merge_requests/_new_diffs', diffs: @diffs, environment: @environment) } - end - end - end - - def create - @target_branches ||= [] - @merge_request = MergeRequests::CreateService.new(project, current_user, merge_request_params).execute - - if @merge_request.valid? - redirect_to(merge_request_path(@merge_request)) - else - @source_project = @merge_request.source_project - @target_project = @merge_request.target_project - render action: "new" - end + render json: { + pipelines: PipelineSerializer + .new(project: @project, current_user: @current_user) + .represent(@pipelines), + count: { + all: @pipelines.count + } + } end def edit - @source_project = @merge_request.source_project - @target_project = @merge_request.target_project - @target_branches = @merge_request.target_project.repository.branch_names + define_edit_vars end def update - @merge_request = MergeRequests::UpdateService.new(project, current_user, merge_request_params).execute(@merge_request) + @merge_request = ::MergeRequests::UpdateService.new(project, current_user, merge_request_params).execute(@merge_request) respond_to do |format| format.html do if @merge_request.valid? redirect_to([@merge_request.target_project.namespace.becomes(Namespace), @merge_request.target_project, @merge_request]) else + define_edit_vars + render :edit end end @@ -299,11 +145,13 @@ class Projects::MergeRequestsController < Projects::ApplicationController end end rescue ActiveRecord::StaleObjectError + define_edit_vars if request.format.html? + render_conflict_response end def remove_wip - @merge_request = MergeRequests::UpdateService + @merge_request = ::MergeRequests::UpdateService .new(project, current_user, wip_event: 'unwip') .execute(@merge_request) @@ -319,7 +167,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController return access_denied! end - MergeRequests::MergeWhenPipelineSucceedsService + ::MergeRequests::MergeWhenPipelineSucceedsService .new(@project, current_user) .cancel(@merge_request) @@ -338,53 +186,19 @@ class Projects::MergeRequestsController < Projects::ApplicationController end end - def branch_from - # This is always source - @source_project = @merge_request.nil? ? @project : @merge_request.source_project - - if params[:ref].present? - @ref = params[:ref] - @commit = @repository.commit("refs/heads/#{@ref}") - end - - render layout: false - end - - def branch_to - @target_project = selected_target_project - - if params[:ref].present? - @ref = params[:ref] - @commit = @target_project.commit("refs/heads/#{@ref}") - end - - render layout: false - end - - def update_branches - @target_project = selected_target_project - @target_branches = @target_project.repository.branch_names - - render layout: false - end - def assign_related_issues - result = MergeRequests::AssignIssuesService.new(project, current_user, merge_request: @merge_request).execute + result = ::MergeRequests::AssignIssuesService.new(project, current_user, merge_request: @merge_request).execute - respond_to do |format| - format.html do - case result[:count] - when 0 - flash[:error] = "Failed to assign you issues related to the merge request" - when 1 - flash[:notice] = "1 issue has been assigned to you" - else - flash[:notice] = "#{result[:count]} issues have been assigned to you" - end - - redirect_to(merge_request_path(@merge_request)) - end + case result[:count] + when 0 + flash[:error] = "Failed to assign you issues related to the merge request" + when 1 + flash[:notice] = "1 issue has been assigned to you" + else + flash[:notice] = "#{result[:count]} issues have been assigned to you" end + + redirect_to(merge_request_path(@merge_request)) end def pipeline_status @@ -402,22 +216,25 @@ class Projects::MergeRequestsController < Projects::ApplicationController stop_url = if environment.stop_action? && can?(current_user, :create_deployment, environment) - stop_namespace_project_environment_path(project.namespace, project, environment) + stop_project_environment_path(project, environment) end metrics_url = if can?(current_user, :read_environment, environment) && environment.has_metrics? - metrics_namespace_project_environment_deployment_path(environment.project.namespace, - environment.project, - environment, - deployment) + metrics_project_environment_deployment_path(environment.project, environment, deployment) + end + + metrics_monitoring_url = + if can?(current_user, :read_environment, environment) + environment_metrics_path(environment) end { id: environment.id, name: environment.name, - url: namespace_project_environment_path(project.namespace, project, environment), + url: project_environment_path(project, environment), metrics_url: metrics_url, + metrics_monitoring_url: metrics_monitoring_url, stop_url: stop_url, external_url: environment.external_url, external_url_formatted: environment.formatted_external_url, @@ -432,17 +249,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController protected - def selected_target_project - if @project.id.to_s == params[:target_project_id] || @project.forked_project_link.nil? - @project - else - @project.forked_project_link.forked_from_project - end - end - - def merge_request - @issuable = @merge_request ||= @project.merge_requests.find_by!(iid: params[:id]) - end alias_method :subscribable_resource, :merge_request alias_method :issuable, :merge_request alias_method :awardable, :merge_request @@ -455,12 +261,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController return render_404 unless can?(current_user, :admin_merge_request, @merge_request) end - def authorize_can_resolve_conflicts! - @conflicts_list = MergeRequests::Conflicts::ListService.new(@merge_request) - - return render_404 unless @conflicts_list.can_be_resolved_by?(current_user) - end - def validates_merge_request # Show git not found page # if there is no saved commits between source & target branch @@ -470,141 +270,17 @@ class Projects::MergeRequestsController < Projects::ApplicationController end end - def define_show_vars - @noteable = @merge_request - @commits_count = @merge_request.commits_count - - if @merge_request.locked_long_ago? - @merge_request.unlock_mr - @merge_request.close - end - - labels - define_pipelines_vars - end - - # Discussion tab data is rendered on html responses of actions - # :show, :diff, :commits, :builds. but not when request the data through AJAX - def define_discussion_vars - # Build a note object for comment form - @note = @project.notes.new(noteable: @merge_request) - - @discussions = @merge_request.discussions - @notes = prepare_notes_for_rendering(@discussions.flat_map(&:notes)) - end - - def define_diff_vars - @merge_request_diff = - if params[:diff_id] - @merge_request.merge_request_diffs.viewable.find(params[:diff_id]) - else - @merge_request.merge_request_diff - end - - @merge_request_diffs = @merge_request.merge_request_diffs.viewable.select_without_diff - @comparable_diffs = @merge_request_diffs.select { |diff| diff.id < @merge_request_diff.id } - - if params[:start_sha].present? - @start_sha = params[:start_sha] - @start_version = @comparable_diffs.find { |diff| diff.head_commit_sha == @start_sha } - - unless @start_version - @start_sha = @merge_request_diff.head_commit_sha - @start_version = @merge_request_diff - end - end - - @compare = - if @start_sha - @merge_request_diff.compare_with(@start_sha) - else - @merge_request_diff - end - - @diffs = @compare.diffs(diff_options) - end - - def define_diff_comment_vars - @new_diff_note_attrs = { - noteable_type: 'MergeRequest', - noteable_id: @merge_request.id - } - - @diff_notes_disabled = false - - @use_legacy_diff_notes = !@merge_request.has_complete_diff_refs? - - @grouped_diff_discussions = @merge_request.grouped_diff_discussions(@compare.diff_refs) - @notes = prepare_notes_for_rendering(@grouped_diff_discussions.values.flatten.flat_map(&:notes)) - end - - def define_pipelines_vars - @pipelines = @merge_request.all_pipelines - @pipeline = @merge_request.head_pipeline - @statuses_count = @pipeline.present? ? @pipeline.statuses.relevant.count : 0 - end - - def define_new_vars - @noteable = @merge_request - - @target_branches = if @merge_request.target_project - @merge_request.target_project.repository.branch_names - else - [] - end - - @target_project = merge_request.target_project - @source_project = merge_request.source_project - @commits = @merge_request.compare_commits.reverse - @commit = @merge_request.diff_head_commit - - @note_counts = Note.where(commit_id: @commits.map(&:id)) - .group(:commit_id).count - - @labels = LabelsFinder.new(current_user, project_id: @project.id).execute - - @show_changes_tab = params[:show_changes].present? - - define_pipelines_vars - end - def invalid_mr # Render special view for MR with removed target branch render 'invalid' end - def merge_request_params - params.require(:merge_request) - .permit(merge_request_params_ce) - end - - def merge_request_params_ce - [ - :assignee_id, - :description, - :force_remove_source_branch, - :lock_version, - :milestone_id, - :source_branch, - :source_project_id, - :state_event, - :target_branch, - :target_project_id, - :task_num, - :title, - - label_ids: [] - ] - end - def merge_params - params.permit(:should_remove_source_branch, :commit_message) + params.permit(merge_params_attributes) end - # Make sure merge requests created before 8.0 - # have head file in refs/merge-requests/ - def ensure_ref_fetched - @merge_request.ensure_ref_fetched + def merge_params_attributes + [:should_remove_source_branch, :commit_message] end def merge_when_pipeline_succeeds_active? @@ -612,11 +288,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController @merge_request.head_pipeline && @merge_request.head_pipeline.active? end - def build_merge_request - params[:merge_request] ||= ActionController::Parameters.new(source_project: @project) - @merge_request = MergeRequests::BuildService.new(project, current_user, merge_request_params.merge(diff_options: diff_options)).execute - end - def close_merge_request_without_source_project if !@merge_request.source_project && @merge_request.open? @merge_request.close @@ -644,7 +315,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController return :failed unless @merge_request.head_pipeline if @merge_request.head_pipeline.active? - MergeRequests::MergeWhenPipelineSucceedsService + ::MergeRequests::MergeWhenPipelineSucceedsService .new(@project, current_user, merge_params) .execute(@merge_request) @@ -668,4 +339,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController def serializer MergeRequestSerializer.new(current_user: current_user, project: merge_request.project) end + + def define_edit_vars + @source_project = @merge_request.source_project + @target_project = @merge_request.target_project + @target_branches = @merge_request.target_project.repository.branch_names + end end diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb index 953b1e83e49..c94384d2a1a 100644 --- a/app/controllers/projects/milestones_controller.rb +++ b/app/controllers/projects/milestones_controller.rb @@ -13,20 +13,16 @@ class Projects::MilestonesController < Projects::ApplicationController respond_to :html def index - @milestones = - case params[:state] - when 'all' then @project.milestones - when 'closed' then @project.milestones.closed - else @project.milestones.active - end - @sort = params[:sort] || 'due_date_asc' - @milestones = @milestones.sort(@sort) + @milestones = milestones.sort(@sort) respond_to do |format| format.html do @project_namespace = @project.namespace.becomes(Namespace) - @milestones = @milestones.includes(:project) + # We need to show group milestones in the JSON response + # so that people can filter by and assign group milestones, + # but we don't need to show them on the project milestones page itself. + @milestones = @milestones.for_projects @milestones = @milestones.page(params[:page]) end format.json do @@ -45,14 +41,14 @@ class Projects::MilestonesController < Projects::ApplicationController end def show + @project_namespace = @project.namespace.becomes(Namespace) end def create @milestone = Milestones::CreateService.new(project, current_user, milestone_params).execute - if @milestone.save - redirect_to namespace_project_milestone_path(@project.namespace, - @project, @milestone) + if @milestone.valid? + redirect_to project_milestone_path(@project, @milestone) else render "new" end @@ -65,8 +61,7 @@ class Projects::MilestonesController < Projects::ApplicationController format.js format.html do if @milestone.valid? - redirect_to namespace_project_milestone_path(@project.namespace, - @project, @milestone) + redirect_to project_milestone_path(@project, @milestone) else render :edit end @@ -87,6 +82,18 @@ class Projects::MilestonesController < Projects::ApplicationController protected + def milestones + @milestones ||= begin + if @project.group && can?(current_user, :read_group, @project.group) + group = @project.group + end + + search_params = params.merge(project_ids: @project.id, group_ids: group&.id) + + MilestonesFinder.new(search_params).execute + end + end + def milestone @milestone ||= @project.milestones.find_by!(iid: params[:id]) end diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb index 33a152ad34f..dfa5e4f7f46 100644 --- a/app/controllers/projects/network_controller.rb +++ b/app/controllers/projects/network_controller.rb @@ -8,8 +8,8 @@ class Projects::NetworkController < Projects::ApplicationController before_action :assign_commit def show - @url = namespace_project_network_path(@project.namespace, @project, @ref, @options.merge(format: :json)) - @commit_url = namespace_project_commit_path(@project.namespace, @project, 'ae45ca32').gsub("ae45ca32", "%s") + @url = project_network_path(@project, @ref, @options.merge(format: :json)) + @commit_url = project_commit_path(@project, 'ae45ca32').gsub("ae45ca32", "%s") respond_to do |format| format.html do diff --git a/app/controllers/projects/pages_controller.rb b/app/controllers/projects/pages_controller.rb index 28b383e69eb..d421b1a8eb5 100644 --- a/app/controllers/projects/pages_controller.rb +++ b/app/controllers/projects/pages_controller.rb @@ -15,7 +15,7 @@ class Projects::PagesController < Projects::ApplicationController respond_to do |format| format.html do - redirect_to namespace_project_pages_path(@project.namespace, @project), + redirect_to project_pages_path(@project), status: 302, notice: 'Pages were removed' end diff --git a/app/controllers/projects/pages_domains_controller.rb b/app/controllers/projects/pages_domains_controller.rb index dbd011f6c5d..15e77d854dc 100644 --- a/app/controllers/projects/pages_domains_controller.rb +++ b/app/controllers/projects/pages_domains_controller.rb @@ -16,7 +16,7 @@ class Projects::PagesDomainsController < Projects::ApplicationController @domain = @project.pages_domains.create(pages_domain_params) if @domain.valid? - redirect_to namespace_project_pages_path(@project.namespace, @project) + redirect_to project_pages_path(@project) else render 'new' end @@ -27,7 +27,7 @@ class Projects::PagesDomainsController < Projects::ApplicationController respond_to do |format| format.html do - redirect_to namespace_project_pages_path(@project.namespace, @project), + redirect_to project_pages_path(@project), status: 302, notice: 'Domain was removed' end diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb index ef4f083b98f..ec7c645df5a 100644 --- a/app/controllers/projects/pipeline_schedules_controller.rb +++ b/app/controllers/projects/pipeline_schedules_controller.rb @@ -1,10 +1,11 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController + before_action :schedule, except: [:index, :new, :create] + before_action :authorize_read_pipeline_schedule! - before_action :authorize_create_pipeline_schedule!, only: [:new, :create, :edit, :take_ownership, :update] + before_action :authorize_create_pipeline_schedule!, only: [:new, :create] + before_action :authorize_update_pipeline_schedule!, except: [:index, :new, :create] before_action :authorize_admin_pipeline_schedule!, only: [:destroy] - before_action :schedule, only: [:edit, :update, :destroy, :take_ownership] - def index @scope = params[:scope] @all_schedules = PipelineSchedulesFinder.new(@project).execute @@ -33,7 +34,7 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController def update if schedule.update(schedule_params) - redirect_to namespace_project_pipeline_schedules_path(@project.namespace.becomes(Namespace), @project) + redirect_to project_pipeline_schedules_path(@project) else render :edit end @@ -52,7 +53,7 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController redirect_to pipeline_schedules_path(@project), status: 302 else redirect_to pipeline_schedules_path(@project), - status: 302, + status: :forbidden, alert: _("Failed to remove the pipeline schedule") end end @@ -65,6 +66,15 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController def schedule_params params.require(:schedule) - .permit(:description, :cron, :cron_timezone, :ref, :active) + .permit(:description, :cron, :cron_timezone, :ref, :active, + variables_attributes: [:id, :key, :value, :_destroy] ) + end + + def authorize_update_pipeline_schedule! + return access_denied! unless can?(current_user, :update_pipeline_schedule, schedule) + end + + def authorize_admin_pipeline_schedule! + return access_denied! unless can?(current_user, :admin_pipeline_schedule, schedule) end end diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 8effb792689..a3bfbf0694e 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -60,7 +60,7 @@ class Projects::PipelinesController < Projects::ApplicationController .execute(:web, ignore_skip_ci: true, save_on_errors: false) if @pipeline.persisted? - redirect_to namespace_project_pipeline_path(project.namespace, project, @pipeline) + redirect_to project_pipeline_path(project, @pipeline) else render 'new' end @@ -111,7 +111,7 @@ class Projects::PipelinesController < Projects::ApplicationController respond_to do |format| format.html do - redirect_back_or_default default: namespace_project_pipelines_path(project.namespace, project) + redirect_back_or_default default: project_pipelines_path(project) end format.json { head :no_content } @@ -123,7 +123,7 @@ class Projects::PipelinesController < Projects::ApplicationController respond_to do |format| format.html do - redirect_back_or_default default: namespace_project_pipelines_path(project.namespace, project) + redirect_back_or_default default: project_pipelines_path(project) end format.json { head :no_content } @@ -135,7 +135,12 @@ class Projects::PipelinesController < Projects::ApplicationController @charts[:week] = Ci::Charts::WeekChart.new(project) @charts[:month] = Ci::Charts::MonthChart.new(project) @charts[:year] = Ci::Charts::YearChart.new(project) - @charts[:build_times] = Ci::Charts::BuildTime.new(project) + @charts[:pipeline_times] = Ci::Charts::PipelineTime.new(project) + + @counts = {} + @counts[:total] = @project.pipelines.count(:all) + @counts[:success] = @project.pipelines.success.count(:all) + @counts[:failed] = @project.pipelines.failed.count(:all) end private diff --git a/app/controllers/projects/pipelines_settings_controller.rb b/app/controllers/projects/pipelines_settings_controller.rb index 38a47651000..9d24ebe2138 100644 --- a/app/controllers/projects/pipelines_settings_controller.rb +++ b/app/controllers/projects/pipelines_settings_controller.rb @@ -2,13 +2,13 @@ class Projects::PipelinesSettingsController < Projects::ApplicationController before_action :authorize_admin_pipeline! def show - redirect_to namespace_project_settings_ci_cd_path(@project.namespace, @project, params: params) + redirect_to project_settings_ci_cd_path(@project, params: params) end def update if @project.update_attributes(update_params) flash[:notice] = "Pipelines settings for '#{@project.name}' were successfully updated." - redirect_to namespace_project_settings_ci_cd_path(@project.namespace, @project) + redirect_to project_settings_ci_cd_path(@project) else render 'show' end @@ -23,7 +23,7 @@ class Projects::PipelinesSettingsController < Projects::ApplicationController def update_params params.require(:project).permit( :runners_token, :builds_enabled, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex, - :public_builds, :auto_cancel_pending_pipelines + :public_builds, :auto_cancel_pending_pipelines, :ci_config_path ) end end diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index d2d26738582..f8ff7413b53 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -6,8 +6,23 @@ class Projects::ProjectMembersController < Projects::ApplicationController before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access] def index - sort = params[:sort].presence || sort_value_name - redirect_to namespace_project_settings_members_path(@project.namespace, @project, sort: sort) + @sort = params[:sort].presence || sort_value_name + @group_links = @project.project_group_links + + @skip_groups = @group_links.pluck(:group_id) + @skip_groups << @project.namespace_id unless @project.personal? + @skip_groups += @project.group.ancestors.pluck(:id) if @project.group + + @project_members = MembersFinder.new(@project, current_user).execute + + if params[:search].present? + @project_members = @project_members.joins(:user).merge(User.search(params[:search])) + @group_links = @group_links.where(group_id: @project.invited_groups.search(params[:search]).select(:id)) + end + + @project_members = @project_members.sort(@sort).page(params[:page]) + @requesters = AccessRequestsFinder.new(@project).execute(current_user) + @project_member = @project.project_members.new end def update @@ -19,7 +34,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController end def resend_invite - redirect_path = namespace_project_settings_members_path(@project.namespace, @project) + redirect_path = project_project_members_path(@project) @project_member = @project.project_members.find(params[:id]) @@ -42,7 +57,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController return render_404 end - redirect_to(namespace_project_settings_members_path(project.namespace, project), + redirect_to(project_project_members_path(project), notice: notice) end diff --git a/app/controllers/projects/prometheus_controller.rb b/app/controllers/projects/prometheus_controller.rb new file mode 100644 index 00000000000..507468d7102 --- /dev/null +++ b/app/controllers/projects/prometheus_controller.rb @@ -0,0 +1,24 @@ +class Projects::PrometheusController < Projects::ApplicationController + before_action :authorize_read_project! + before_action :require_prometheus_metrics! + + def active_metrics + respond_to do |format| + format.json do + matched_metrics = project.prometheus_service.matched_metrics || {} + + if matched_metrics.any? + render json: matched_metrics + else + head :no_content + end + end + end + end + + private + + def require_prometheus_metrics! + render_404 unless project.prometheus_service.present? + end +end diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb index 2a0b58fae7c..1eb78d8b522 100644 --- a/app/controllers/projects/refs_controller.rb +++ b/app/controllers/projects/refs_controller.rb @@ -13,21 +13,21 @@ class Projects::RefsController < Projects::ApplicationController new_path = case params[:destination] when "tree" - namespace_project_tree_path(@project.namespace, @project, @id) + project_tree_path(@project, @id) when "blob" - namespace_project_blob_path(@project.namespace, @project, @id) + project_blob_path(@project, @id) when "graph" - namespace_project_network_path(@project.namespace, @project, @id, @options) + project_network_path(@project, @id, @options) when "graphs" - namespace_project_graph_path(@project.namespace, @project, @id) + project_graph_path(@project, @id) when "find_file" - namespace_project_find_file_path(@project.namespace, @project, @id) + project_find_file_path(@project, @id) when "graphs_commits" - commits_namespace_project_graph_path(@project.namespace, @project, @id) + commits_project_graph_path(@project, @id) when "badges" - namespace_project_pipelines_settings_path(@project.namespace, @project, ref: @id) + project_pipelines_settings_path(@project, ref: @id) else - namespace_project_commits_path(@project.namespace, @project, @id) + project_commits_path(@project, @id) end redirect_to new_path @@ -62,7 +62,7 @@ class Projects::RefsController < Projects::ApplicationController offset = (@offset + @limit) if contents.size > offset - @more_log_url = logs_file_namespace_project_ref_path(@project.namespace, @project, @ref, @path || '', offset: offset) + @more_log_url = logs_file_project_ref_path(@project, @ref, @path || '', offset: offset) end respond_to do |format| diff --git a/app/controllers/projects/registry/repositories_controller.rb b/app/controllers/projects/registry/repositories_controller.rb index 98e78585be8..71e7dc70a4d 100644 --- a/app/controllers/projects/registry/repositories_controller.rb +++ b/app/controllers/projects/registry/repositories_controller.rb @@ -10,11 +10,11 @@ module Projects def destroy if image.destroy - redirect_to project_container_registry_path(@project), + redirect_to project_container_registry_index_path(@project), status: 302, notice: 'Image repository has been removed successfully!' else - redirect_to project_container_registry_path(@project), + redirect_to project_container_registry_index_path(@project), status: 302, alert: 'Failed to remove image repository!' end diff --git a/app/controllers/projects/registry/tags_controller.rb b/app/controllers/projects/registry/tags_controller.rb index 5050dba3aab..ae72bd03cfb 100644 --- a/app/controllers/projects/registry/tags_controller.rb +++ b/app/controllers/projects/registry/tags_controller.rb @@ -5,11 +5,11 @@ module Projects def destroy if tag.delete - redirect_to project_container_registry_path(@project), + redirect_to project_container_registry_index_path(@project), status: 302, notice: 'Registry tag has been removed successfully!' else - redirect_to project_container_registry_path(@project), + redirect_to project_container_registry_index_path(@project), status: 302, alert: 'Failed to remove registry tag!' end diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb index 2c097cb4d8d..3e0a530fdb9 100644 --- a/app/controllers/projects/releases_controller.rb +++ b/app/controllers/projects/releases_controller.rb @@ -19,7 +19,7 @@ class Projects::ReleasesController < Projects::ApplicationController release.destroy end - redirect_to namespace_project_tag_path(@project.namespace, @project, @tag.name) + redirect_to project_tag_path(@project, @tag.name) end private diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb index 160e632648a..9f9773575a5 100644 --- a/app/controllers/projects/runners_controller.rb +++ b/app/controllers/projects/runners_controller.rb @@ -5,7 +5,7 @@ class Projects::RunnersController < Projects::ApplicationController layout 'project_settings' def index - redirect_to namespace_project_settings_ci_cd_path(@project.namespace, @project) + redirect_to project_settings_ci_cd_path(@project) end def edit @@ -49,7 +49,7 @@ class Projects::RunnersController < Projects::ApplicationController def toggle_shared_runners project.toggle!(:shared_runners_enabled) - redirect_to namespace_project_settings_ci_cd_path(@project.namespace, @project) + redirect_to project_settings_ci_cd_path(@project) end protected diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index 704f8cc8a79..d54a1111f11 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -15,7 +15,7 @@ class Projects::ServicesController < Projects::ApplicationController def update if @service.save(context: :manual_change) - redirect_to(namespace_project_settings_integrations_path(@project.namespace, @project), notice: success_message) + redirect_to(project_settings_integrations_path(@project), notice: success_message) else render 'edit' end diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index 24fe78bc1bd..15a2ff56b92 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -21,7 +21,10 @@ module Projects end def define_secret_variables - @variable = Ci::Variable.new + @variable = Ci::Variable.new(project: project) + .present(current_user: current_user) + @variables = project.variables.order_key_asc + .map { |variable| variable.present(current_user: current_user) } end def define_triggers_variables @@ -32,7 +35,7 @@ module Projects def define_badges_variables @ref = params[:ref] || @project.default_branch || 'master' - @badges = [Gitlab::Badge::Build::Status, + @badges = [Gitlab::Badge::Pipeline::Status, Gitlab::Badge::Coverage::Report] @badges.map! do |badge| diff --git a/app/controllers/projects/settings/members_controller.rb b/app/controllers/projects/settings/members_controller.rb deleted file mode 100644 index 54f9dceddef..00000000000 --- a/app/controllers/projects/settings/members_controller.rb +++ /dev/null @@ -1,27 +0,0 @@ -module Projects - module Settings - class MembersController < Projects::ApplicationController - include SortingHelper - - def show - @sort = params[:sort].presence || sort_value_name - @group_links = @project.project_group_links - - @skip_groups = @group_links.pluck(:group_id) - @skip_groups << @project.namespace_id unless @project.personal? - @skip_groups += @project.group.ancestors.pluck(:id) if @project.group - - @project_members = MembersFinder.new(@project, current_user).execute - - if params[:search].present? - @project_members = @project_members.joins(:user).merge(User.search(params[:search])) - @group_links = @group_links.where(group_id: @project.invited_groups.search(params[:search]).select(:id)) - end - - @project_members = @project_members.sort(@sort).page(params[:page]) - @requesters = AccessRequestsFinder.new(@project).execute(current_user) - @project_member = @project.project_members.new - end - end - end -end diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb index 98dd307bd9d..d07143d294f 100644 --- a/app/controllers/projects/snippets_controller.rb +++ b/app/controllers/projects/snippets_controller.rb @@ -30,7 +30,7 @@ class Projects::SnippetsController < Projects::ApplicationController ).execute @snippets = @snippets.page(params[:page]) if @snippets.out_of_range? && @snippets.total_pages != 0 - redirect_to namespace_project_snippets_path(page: @snippets.total_pages) + redirect_to project_snippets_path(@project, page: @snippets.total_pages) end end @@ -79,7 +79,7 @@ class Projects::SnippetsController < Projects::ApplicationController @snippet.destroy - redirect_to namespace_project_snippets_path(@project.namespace, @project), status: 302 + redirect_to project_snippets_path(@project), status: 302 end protected @@ -90,6 +90,10 @@ class Projects::SnippetsController < Projects::ApplicationController alias_method :awardable, :snippet alias_method :spammable, :snippet + def spammable_path + project_snippet_path(@project, @snippet) + end + def authorize_read_project_snippet! return render_404 unless can?(current_user, :read_project_snippet, @snippet) end diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb index ebc9f4edab4..b62d7d9b7c5 100644 --- a/app/controllers/projects/tags_controller.rb +++ b/app/controllers/projects/tags_controller.rb @@ -35,7 +35,7 @@ class Projects::TagsController < Projects::ApplicationController if result[:status] == :success @tag = result[:tag] - redirect_to namespace_project_tag_path(@project.namespace, @project, @tag.name) + redirect_to project_tag_path(@project, @tag.name) else @error = result[:message] @message = params[:message] @@ -50,7 +50,7 @@ class Projects::TagsController < Projects::ApplicationController respond_to do |format| if result[:status] == :success format.html do - redirect_to namespace_project_tags_path(@project.namespace, @project), status: 303 + redirect_to project_tags_path(@project), status: 303 end format.js @@ -58,7 +58,7 @@ class Projects::TagsController < Projects::ApplicationController @error = result[:message] format.html do - redirect_to namespace_project_tags_path(@project.namespace, @project), + redirect_to project_tags_path(@project), alert: @error, status: 303 end diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index 266a15c1cf9..30181ac3bdf 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -16,7 +16,7 @@ class Projects::TreeController < Projects::ApplicationController if tree.entries.empty? if @repository.blob_at(@commit.id, @path) return redirect_to( - namespace_project_blob_path(@project.namespace, @project, + project_blob_path(@project, File.join(@ref, @path)) ) elsif @path.present? @@ -37,8 +37,8 @@ class Projects::TreeController < Projects::ApplicationController return render_404 unless @commit_params.values.all? create_commit(Files::CreateDirService, success_notice: "The directory has been successfully created.", - success_path: namespace_project_tree_path(@project.namespace, @project, File.join(@branch_name, @dir_name)), - failure_path: namespace_project_tree_path(@project.namespace, @project, @ref)) + success_path: project_tree_path(@project, File.join(@branch_name, @dir_name)), + failure_path: project_tree_path(@project, @ref)) end private diff --git a/app/controllers/projects/triggers_controller.rb b/app/controllers/projects/triggers_controller.rb index e86adddd77f..e04145dd0b3 100644 --- a/app/controllers/projects/triggers_controller.rb +++ b/app/controllers/projects/triggers_controller.rb @@ -7,7 +7,7 @@ class Projects::TriggersController < Projects::ApplicationController layout 'project_settings' def index - redirect_to namespace_project_settings_ci_cd_path(@project.namespace, @project) + redirect_to project_settings_ci_cd_path(@project) end def create @@ -19,7 +19,7 @@ class Projects::TriggersController < Projects::ApplicationController flash[:alert] = 'You could not create a new trigger.' end - redirect_to namespace_project_settings_ci_cd_path(@project.namespace, @project) + redirect_to project_settings_ci_cd_path(@project) end def take_ownership @@ -29,7 +29,7 @@ class Projects::TriggersController < Projects::ApplicationController flash[:alert] = 'You could not take ownership of trigger.' end - redirect_to namespace_project_settings_ci_cd_path(@project.namespace, @project) + redirect_to project_settings_ci_cd_path(@project) end def edit @@ -37,7 +37,7 @@ class Projects::TriggersController < Projects::ApplicationController def update if trigger.update(trigger_params) - redirect_to namespace_project_settings_ci_cd_path(@project.namespace, @project), notice: 'Trigger was successfully updated.' + redirect_to project_settings_ci_cd_path(@project), notice: 'Trigger was successfully updated.' else render action: "edit" end @@ -50,7 +50,7 @@ class Projects::TriggersController < Projects::ApplicationController flash[:alert] = "Could not remove the trigger." end - redirect_to namespace_project_settings_ci_cd_path(@project.namespace, @project), status: 302 + redirect_to project_settings_ci_cd_path(@project), status: 302 end private @@ -69,8 +69,7 @@ class Projects::TriggersController < Projects::ApplicationController def trigger_params params.require(:trigger).permit( - :description, - trigger_schedule_attributes: [:id, :active, :cron, :cron_timezone, :ref] + :description ) end end diff --git a/app/controllers/projects/variables_controller.rb b/app/controllers/projects/variables_controller.rb index 50e25a00f03..6a825137564 100644 --- a/app/controllers/projects/variables_controller.rb +++ b/app/controllers/projects/variables_controller.rb @@ -1,50 +1,60 @@ class Projects::VariablesController < Projects::ApplicationController + before_action :variable, only: [:show, :update, :destroy] before_action :authorize_admin_build! layout 'project_settings' def index - redirect_to namespace_project_settings_ci_cd_path(@project.namespace, @project) + redirect_to project_settings_ci_cd_path(@project) end def show - @variable = @project.variables.find(params[:id]) end def update - @variable = @project.variables.find(params[:id]) - - if @variable.update_attributes(project_params) - redirect_to namespace_project_variables_path(project.namespace, project), notice: 'Variable was successfully updated.' + if variable.update(variable_params) + redirect_to project_variables_path(project), + notice: 'Variable was successfully updated.' else - render action: "show" + render "show" end end def create - @variable = Ci::Variable.new(project_params) + @variable = project.variables.create(variable_params) + .present(current_user: current_user) - if @variable.valid? && @project.variables << @variable - flash[:notice] = 'Variables were successfully updated.' - redirect_to namespace_project_settings_ci_cd_path(project.namespace, project) + if @variable.persisted? + redirect_to project_settings_ci_cd_path(project), + notice: 'Variable was successfully created.' else render "show" end end def destroy - @key = @project.variables.find(params[:id]) - @key.destroy - - redirect_to namespace_project_settings_ci_cd_path(project.namespace, project), - status: 302, - notice: 'Variable was successfully removed.' + if variable.destroy + redirect_to project_settings_ci_cd_path(project), + status: 302, + notice: 'Variable was successfully removed.' + else + redirect_to project_settings_ci_cd_path(project), + status: 302, + notice: 'Failed to remove the variable.' + end end private - def project_params - params.require(:variable) - .permit([:id, :key, :value, :protected, :_destroy]) + def variable_params + params.require(:variable).permit(*variable_params_attributes) + end + + def variable_params_attributes + %i[id key value protected _destroy] + end + + def variable + @variable ||= project.variables.find(params[:id]).present(current_user: current_user) end end diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb index e54b90b8d52..968d880886c 100644 --- a/app/controllers/projects/wikis_controller.rb +++ b/app/controllers/projects/wikis_controller.rb @@ -49,12 +49,15 @@ class Projects::WikisController < Projects::ApplicationController if @page.valid? redirect_to( - namespace_project_wiki_path(@project.namespace, @project, @page), + project_wiki_path(@project, @page), notice: 'Wiki was successfully updated.' ) else render 'edit' end + rescue WikiPage::PageChangedError + @conflict = true + render 'edit' end def create @@ -62,7 +65,7 @@ class Projects::WikisController < Projects::ApplicationController if @page.persisted? redirect_to( - namespace_project_wiki_path(@project.namespace, @project, @page), + project_wiki_path(@project, @page), notice: 'Wiki was successfully updated.' ) else @@ -75,7 +78,7 @@ class Projects::WikisController < Projects::ApplicationController unless @page redirect_to( - namespace_project_wiki_path(@project.namespace, @project, :home), + project_wiki_path(@project, :home), notice: "Page not found" ) end @@ -85,7 +88,7 @@ class Projects::WikisController < Projects::ApplicationController @page = @project_wiki.find_page(params[:id]) WikiPages::DestroyService.new(@project, current_user).execute(@page) - redirect_to namespace_project_wiki_path(@project.namespace, @project, :home), + redirect_to project_wiki_path(@project, :home), status: 302, notice: "Page was successfully deleted" end @@ -119,6 +122,6 @@ class Projects::WikisController < Projects::ApplicationController end def wiki_params - params.require(:wiki).permit(:title, :content, :format, :message) + params.require(:wiki).permit(:title, :content, :format, :message, :last_commit_sha) end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 5480814874b..2d7cbd4614e 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -50,10 +50,13 @@ class ProjectsController < Projects::ApplicationController respond_to do |format| if result[:status] == :success flash[:notice] = _("Project '%{project_name}' was successfully updated.") % { project_name: @project.name } + format.html do redirect_to(edit_project_path(@project)) end else + flash[:alert] = result[:message] + format.html { render 'edit' } end @@ -92,12 +95,12 @@ class ProjectsController < Projects::ApplicationController def show if @project.import_in_progress? - redirect_to namespace_project_import_path(@project.namespace, @project) + redirect_to project_import_path(@project) return end if @project.pending_delete? - flash[:alert] = _("Project '%{project_name}' queued for deletion.") % { project_name: @project.name } + flash.now[:alert] = _("Project '%{project_name}' queued for deletion.") % { project_name: @project.name } end respond_to do |format| @@ -293,10 +296,10 @@ class ProjectsController < Projects::ApplicationController def project_params params.require(:project) - .permit(project_params_ce) + .permit(project_params_attributes) end - def project_params_ce + def project_params_attributes [ :avatar, :build_allow_git_fetch, diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 4a579601785..d58c8d14a75 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -44,7 +44,7 @@ class SearchController < ApplicationController query = params[:search].strip.downcase found_by_commit_sha = Commit.valid_hash?(query) && only_commit.sha.start_with?(query) - redirect_to namespace_project_commit_path(@project.namespace, @project, only_commit) if found_by_commit_sha + redirect_to project_commit_path(@project, only_commit) if found_by_commit_sha end end end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 0d8186dce02..9e743685d60 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -5,6 +5,14 @@ class SessionsController < Devise::SessionsController skip_before_action :check_two_factor_requirement, only: [:destroy] + # Explicitly call protect from forgery before anything else. Otherwise the + # CSFR-token might be cleared before authentication is done. This was the case + # when LDAP was enabled and the `OmniauthCallbacksController` is loaded + # + # *Note:* `prepend: true` is the default for rails4, but this will be changed + # to `prepend: false` in rails5. + protect_from_forgery prepend: true, with: :exception + prepend_before_action :check_initial_setup, only: [:new] prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create] @@ -15,12 +23,7 @@ class SessionsController < Devise::SessionsController def new set_minimum_password_length - @ldap_servers = - if Gitlab.config.ldap.enabled - Gitlab::LDAP::Config.servers - else - [] - end + @ldap_servers = Gitlab::LDAP::Config.available_servers super end @@ -48,7 +51,7 @@ class SessionsController < Devise::SessionsController private def login_counter - @login_counter ||= Gitlab::Metrics.counter(:user_session_logins, 'User sign in count') + @login_counter ||= Gitlab::Metrics.counter(:user_session_logins_total, 'User sign in count') end # Handle an "initial setup" state, where there's only one user, it's an admin, @@ -58,12 +61,13 @@ class SessionsController < Devise::SessionsController user = User.admins.last - return unless user && user.require_password? + return unless user && user.require_password_creation? - token = user.generate_reset_token - user.save + Users::UpdateService.new(user).execute do |user| + @token = user.generate_reset_token + end - redirect_to edit_user_password_path(reset_password_token: token), + redirect_to edit_user_password_path(reset_password_token: @token), notice: "Please create a password for your new account." end diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index 3d86dd2ea2c..8c3abd0a085 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -107,6 +107,10 @@ class SnippetsController < ApplicationController alias_method :awardable, :snippet alias_method :spammable, :snippet + def spammable_path + snippet_path(@snippet) + end + def authorize_read_snippet! return if can?(current_user, :read_personal_snippet, @snippet) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 8131eba6a2f..4ee855806ab 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -73,10 +73,7 @@ class UsersController < ApplicationController end def calendar - calendar = contributions_calendar - @activity_dates = calendar.activity_dates - - render 'calendar', layout: false + render json: contributions_calendar.activity_dates end def calendar_activities |