diff options
author | Luke Bennett <lukeeeebennettplus@gmail.com> | 2018-05-28 12:27:06 +0100 |
---|---|---|
committer | Luke Bennett <lukeeeebennettplus@gmail.com> | 2018-05-28 12:27:06 +0100 |
commit | a9583bc9562512bd046a7f2c32fd267f32a5dac2 (patch) | |
tree | af91d0688d49850746de400afdacb5389c0cfb16 /app/controllers | |
parent | a3e472e0a7a6b6ec5654edd20b947ba660ed2dc3 (diff) | |
parent | 265b1fafe64ae9fe8a3e92d83c1678b47533ba86 (diff) | |
download | gitlab-ce-a9583bc9562512bd046a7f2c32fd267f32a5dac2.tar.gz |
Merge remote-tracking branch 'origin/master' into 39549-label-list-page-redesign-with-draggable-labels
Diffstat (limited to 'app/controllers')
51 files changed, 640 insertions, 231 deletions
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 8958eab0423..cdfe3d6ab1e 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -52,7 +52,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController private def set_application_setting - @application_setting = ApplicationSetting.current + @application_setting = ApplicationSetting.current_without_cache end def application_setting_params diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb index e85cdcb8db7..737942f3eb2 100644 --- a/app/controllers/admin/dashboard_controller.rb +++ b/app/controllers/admin/dashboard_controller.rb @@ -1,5 +1,11 @@ class Admin::DashboardController < Admin::ApplicationController + include CountHelper + + COUNTED_ITEMS = [Project, User, Group, ForkedProjectLink, Issue, MergeRequest, + Note, Snippet, Key, Milestone].freeze + def index + @counts = Gitlab::Database::Count.approximate_counts(COUNTED_ITEMS) @projects = Project.order_id_desc.without_deleted.with_route.limit(10) @users = User.order_id_desc.limit(10) @groups = Group.order_id_desc.with_route.limit(10) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0fdd4d2cb47..2843d70c645 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -13,12 +13,13 @@ class ApplicationController < ActionController::Base before_action :authenticate_sessionless_user! before_action :authenticate_user! + before_action :enforce_terms!, if: :should_enforce_terms? before_action :validate_user_service_ticket! before_action :check_password_expiration before_action :ldap_security_check before_action :sentry_context before_action :default_headers - before_action :add_gon_variables, unless: -> { request.path.start_with?('/-/peek') } + before_action :add_gon_variables, unless: :peek_request? before_action :configure_permitted_parameters, if: :devise_controller? before_action :require_email, unless: :devise_controller? @@ -110,7 +111,8 @@ class ApplicationController < ActionController::Base def log_exception(exception) Raven.capture_exception(exception) if sentry_enabled? - application_trace = ActionDispatch::ExceptionWrapper.new(env, exception).application_trace + backtrace_cleaner = Gitlab.rails5? ? env["action_dispatch.backtrace_cleaner"] : env + application_trace = ActionDispatch::ExceptionWrapper.new(backtrace_cleaner, exception).application_trace application_trace.map! { |t| " #{t}\n" } logger.error "\n#{exception.class.name} (#{exception.message}):\n#{application_trace.join}" end @@ -268,6 +270,27 @@ class ApplicationController < ActionController::Base end end + def enforce_terms! + return unless current_user + return if current_user.terms_accepted? + + if sessionless_user? + render_403 + else + # Redirect to the destination if the request is a get. + # Redirect to the source if it was a post, so the user can re-submit after + # accepting the terms. + redirect_path = if request.get? + request.fullpath + else + URI(request.referer).path if request.referer + end + + flash[:notice] = _("Please accept the Terms of Service before continuing.") + redirect_to terms_path(redirect: redirect_path), status: :found + end + end + def import_sources_enabled? !Gitlab::CurrentSettings.import_sources.empty? end @@ -341,4 +364,18 @@ class ApplicationController < ActionController::Base # Per https://tools.ietf.org/html/rfc5987, headers need to be ISO-8859-1, not UTF-8 response.headers['Page-Title'] = URI.escape(page_title('GitLab')) end + + def sessionless_user? + current_user && !session.keys.include?('warden.user.user.key') + end + + def peek_request? + request.path.start_with?('/-/peek') + end + + def should_enforce_terms? + return false unless Gitlab::CurrentSettings.current_application_settings.enforce_terms + + !(peek_request? || devise_controller?) + end end diff --git a/app/controllers/boards/issues_controller.rb b/app/controllers/boards/issues_controller.rb index 7d7ff217e5d..09e143c23e8 100644 --- a/app/controllers/boards/issues_controller.rb +++ b/app/controllers/boards/issues_controller.rb @@ -94,7 +94,7 @@ module Boards def serialize_as_json(resource) resource.as_json( - only: [:id, :iid, :project_id, :title, :confidential, :due_date, :relative_position], + only: [:id, :iid, :project_id, :title, :confidential, :due_date, :relative_position, :weight], labels: true, issue_endpoints: true, include_full_project_path: board.group_board?, diff --git a/app/controllers/concerns/accepts_pending_invitations.rb b/app/controllers/concerns/accepts_pending_invitations.rb new file mode 100644 index 00000000000..6e8aef52b52 --- /dev/null +++ b/app/controllers/concerns/accepts_pending_invitations.rb @@ -0,0 +1,15 @@ +module AcceptsPendingInvitations + extend ActiveSupport::Concern + + def accept_pending_invitations + return unless resource.active_for_authentication? + + clear_stored_location_for_resource if resource.accept_pending_invitations!.any? + end + + def clear_stored_location_for_resource + session_key = stored_location_key_for(resource) + + session.delete(session_key) + end +end diff --git a/app/controllers/concerns/authenticates_with_two_factor.rb b/app/controllers/concerns/authenticates_with_two_factor.rb index 2fdf346ef44..69a053d4246 100644 --- a/app/controllers/concerns/authenticates_with_two_factor.rb +++ b/app/controllers/concerns/authenticates_with_two_factor.rb @@ -23,6 +23,9 @@ module AuthenticatesWithTwoFactor # # Returns nil def prompt_for_two_factor(user) + # Set @user for Devise views + @user = user # rubocop:disable Gitlab/ModuleWithInstanceVariables + return locked_user_redirect(user) unless user.can?(:log_in) session[:otp_user_id] = user.id diff --git a/app/controllers/concerns/continue_params.rb b/app/controllers/concerns/continue_params.rb index eb3a623acdd..8b7355974df 100644 --- a/app/controllers/concerns/continue_params.rb +++ b/app/controllers/concerns/continue_params.rb @@ -1,4 +1,5 @@ module ContinueParams + include InternalRedirect extend ActiveSupport::Concern def continue_params @@ -6,8 +7,7 @@ module ContinueParams return nil unless continue_params continue_params = continue_params.permit(:to, :notice, :notice_now) - return unless continue_params[:to] && continue_params[:to].start_with?('/') - return if continue_params[:to].start_with?('//') + continue_params[:to] = safe_redirect_path(continue_params[:to]) continue_params end diff --git a/app/controllers/concerns/internal_redirect.rb b/app/controllers/concerns/internal_redirect.rb new file mode 100644 index 00000000000..7409b2e89a5 --- /dev/null +++ b/app/controllers/concerns/internal_redirect.rb @@ -0,0 +1,35 @@ +module InternalRedirect + extend ActiveSupport::Concern + + def safe_redirect_path(path) + return unless path + # Verify that the string starts with a `/` but not a double `/`. + return unless path =~ %r{^/\w.*$} + + uri = URI(path) + # Ignore anything path of the redirect except for the path, querystring and, + # fragment, forcing the redirect within the same host. + full_path_for_uri(uri) + rescue URI::InvalidURIError + nil + end + + def safe_redirect_path_for_url(url) + return unless url + + uri = URI(url) + safe_redirect_path(full_path_for_uri(uri)) if host_allowed?(uri) + rescue URI::InvalidURIError + nil + end + + def host_allowed?(uri) + uri.host == request.host && + uri.port == request.port + end + + def full_path_for_uri(uri) + path_with_query = [uri.path, uri.query].compact.join('?') + [path_with_query, uri.fragment].compact.join("#") + end +end diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb index 0379f76fc3d..c925b4aada5 100644 --- a/app/controllers/concerns/issuable_actions.rb +++ b/app/controllers/concerns/issuable_actions.rb @@ -18,7 +18,6 @@ module IssuableActions def update @issuable = update_service.execute(issuable) # rubocop:disable Gitlab/ModuleWithInstanceVariables - respond_to do |format| format.html do recaptcha_check_if_spammable { render :edit } diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb index 4114ca6bf7c..ca1b80a36a0 100644 --- a/app/controllers/concerns/issuable_collections.rb +++ b/app/controllers/concerns/issuable_collections.rb @@ -57,7 +57,7 @@ module IssuableCollections out_of_range = @issuables.current_page > total_pages # rubocop:disable Gitlab/ModuleWithInstanceVariables if out_of_range - redirect_to(url_for(params.merge(page: total_pages, only_path: true))) + redirect_to(url_for(safe_params.merge(page: total_pages, only_path: true))) end out_of_range @@ -165,8 +165,8 @@ module IssuableCollections [:project, :author, :assignees, :labels, :milestone, project: :namespace] when 'MergeRequest' [ - :source_project, :target_project, :author, :assignee, :labels, :milestone, - head_pipeline: :project, target_project: :namespace, latest_merge_request_diff: :merge_request_diff_commits + :target_project, :author, :assignee, :labels, :milestone, + source_project: :route, head_pipeline: :project, target_project: :namespace, latest_merge_request_diff: :merge_request_diff_commits ] end end diff --git a/app/controllers/concerns/send_file_upload.rb b/app/controllers/concerns/send_file_upload.rb index 55011c89886..237c93daee8 100644 --- a/app/controllers/concerns/send_file_upload.rb +++ b/app/controllers/concerns/send_file_upload.rb @@ -2,6 +2,10 @@ module SendFileUpload def send_upload(file_upload, send_params: {}, redirect_params: {}, attachment: nil, disposition: 'attachment') if attachment redirect_params[:query] = { "response-content-disposition" => "#{disposition};filename=#{attachment.inspect}" } + # By default, Rails will send uploads with an extension of .js with a + # content-type of text/javascript, which will trigger Rails' + # cross-origin JavaScript protection. + send_params[:content_type] = 'text/plain' if File.extname(attachment) == '.js' send_params.merge!(filename: attachment, disposition: disposition) end diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb index 6d9c38d9581..7bc46a6ccc0 100644 --- a/app/controllers/confirmations_controller.rb +++ b/app/controllers/confirmations_controller.rb @@ -1,4 +1,6 @@ class ConfirmationsController < Devise::ConfirmationsController + include AcceptsPendingInvitations + def almost_there flash[:notice] = nil render layout: "devise_empty" @@ -11,6 +13,8 @@ class ConfirmationsController < Devise::ConfirmationsController end def after_confirmation_path_for(resource_name, resource) + accept_pending_invitations + # incoming resource can either be a :user or an :email if signed_in?(:user) after_sign_in(resource) diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb index 9f3bb60b4cc..62213561898 100644 --- a/app/controllers/groups/application_controller.rb +++ b/app/controllers/groups/application_controller.rb @@ -33,6 +33,6 @@ class Groups::ApplicationController < ApplicationController def build_canonical_path(group) params[:group_id] = group.to_param - url_for(params) + url_for(safe_params) end end diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb index 7c2016f0326..e892d1f8dbf 100644 --- a/app/controllers/groups/boards_controller.rb +++ b/app/controllers/groups/boards_controller.rb @@ -2,19 +2,24 @@ class Groups::BoardsController < Groups::ApplicationController include BoardsResponses before_action :assign_endpoint_vars + before_action :boards, only: :index def index - @boards = Boards::ListService.new(group, current_user).execute - respond_with_boards end def show - @board = group.boards.find(params[:id]) + @board = boards.find(params[:id]) respond_with_board end + private + + def boards + @boards ||= Boards::ListService.new(group, current_user).execute + end + def assign_endpoint_vars @boards_endpoint = group_boards_url(group) @namespace_path = group.to_param diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index 134b0dfc0db..ef3eba80154 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -11,13 +11,20 @@ class Groups::GroupMembersController < Groups::ApplicationController :override def index + can_manage_members = can?(current_user, :admin_group_member, @group) + @sort = params[:sort].presence || sort_value_name @project = @group.projects.find(params[:project_id]) if params[:project_id] @members = GroupMembersFinder.new(@group).execute - @members = @members.non_invite unless can?(current_user, :admin_group, @group) + @members = @members.non_invite unless can_manage_members @members = @members.search(params[:search]) if params[:search].present? @members = @members.sort_by_attribute(@sort) + + if can_manage_members && params[:two_factor].present? + @members = @members.filter_by_2fa(params[:two_factor]) + end + @members = @members.page(params[:page]).per(50) @members = present_members(@members.includes(:user)) diff --git a/app/controllers/groups/runners_controller.rb b/app/controllers/groups/runners_controller.rb new file mode 100644 index 00000000000..78992ec7f46 --- /dev/null +++ b/app/controllers/groups/runners_controller.rb @@ -0,0 +1,58 @@ +class Groups::RunnersController < Groups::ApplicationController + # Proper policies should be implemented per + # https://gitlab.com/gitlab-org/gitlab-ce/issues/45894 + before_action :authorize_admin_pipeline! + + before_action :runner, only: [:edit, :update, :destroy, :pause, :resume, :show] + + def show + render 'shared/runners/show' + end + + def edit + end + + def update + if Ci::UpdateRunnerService.new(@runner).update(runner_params) + redirect_to group_runner_path(@group, @runner), notice: 'Runner was successfully updated.' + else + render 'edit' + end + end + + def destroy + @runner.destroy + + redirect_to group_settings_ci_cd_path(@group, anchor: 'runners-settings'), status: 302 + end + + def resume + if Ci::UpdateRunnerService.new(@runner).update(active: true) + redirect_to group_settings_ci_cd_path(@group, anchor: 'runners-settings'), notice: 'Runner was successfully updated.' + else + redirect_to group_settings_ci_cd_path(@group, anchor: 'runners-settings'), alert: 'Runner was not updated.' + end + end + + def pause + if Ci::UpdateRunnerService.new(@runner).update(active: false) + redirect_to group_settings_ci_cd_path(@group, anchor: 'runners-settings'), notice: 'Runner was successfully updated.' + else + redirect_to group_settings_ci_cd_path(@group, anchor: 'runners-settings'), alert: 'Runner was not updated.' + end + end + + private + + def runner + @runner ||= @group.runners.find(params[:id]) + end + + def authorize_admin_pipeline! + return render_404 unless can?(current_user, :admin_pipeline, group) + end + + def runner_params + params.require(:runner).permit(Ci::Runner::FORM_EDITABLE) + end +end diff --git a/app/controllers/groups/settings/badges_controller.rb b/app/controllers/groups/settings/badges_controller.rb index edb334a3d88..ccbd0a3bc02 100644 --- a/app/controllers/groups/settings/badges_controller.rb +++ b/app/controllers/groups/settings/badges_controller.rb @@ -1,12 +1,12 @@ module Groups module Settings class BadgesController < Groups::ApplicationController - include GrapeRouteHelpers::NamedRouteMatcher + include API::Helpers::RelatedResourcesHelpers before_action :authorize_admin_group! def index - @badge_api_endpoint = api_v4_groups_badges_path(id: @group.id) + @badge_api_endpoint = expose_url(api_v4_groups_badges_path(id: @group.id)) end end end diff --git a/app/controllers/import/base_controller.rb b/app/controllers/import/base_controller.rb index c84fc2d305d..663269a0f92 100644 --- a/app/controllers/import/base_controller.rb +++ b/app/controllers/import/base_controller.rb @@ -1,6 +1,17 @@ class Import::BaseController < ApplicationController private + def find_already_added_projects(import_type) + current_user.created_projects.where(import_type: import_type).includes(:import_state) + end + + def find_jobs(import_type) + current_user.created_projects + .includes(:import_state) + .where(import_type: import_type) + .to_json(only: [:id], methods: [:import_status]) + end + def find_or_create_namespace(names, owner) names = params[:target_namespace].presence || names diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb index 61d81ad8a71..77af5fb9c4f 100644 --- a/app/controllers/import/bitbucket_controller.rb +++ b/app/controllers/import/bitbucket_controller.rb @@ -22,16 +22,14 @@ class Import::BitbucketController < Import::BaseController @repos, @incompatible_repos = repos.partition { |repo| repo.valid? } - @already_added_projects = current_user.created_projects.where(import_type: 'bitbucket') + @already_added_projects = find_already_added_projects('bitbucket') already_added_projects_names = @already_added_projects.pluck(:import_source) @repos.to_a.reject! { |repo| already_added_projects_names.include?(repo.full_name) } end def jobs - render json: current_user.created_projects - .where(import_type: 'bitbucket') - .to_json(only: [:id, :import_status]) + render json: find_jobs('bitbucket') end def create diff --git a/app/controllers/import/fogbugz_controller.rb b/app/controllers/import/fogbugz_controller.rb index 669eb31a995..25ec13b8075 100644 --- a/app/controllers/import/fogbugz_controller.rb +++ b/app/controllers/import/fogbugz_controller.rb @@ -46,15 +46,14 @@ class Import::FogbugzController < Import::BaseController @repos = client.repos - @already_added_projects = current_user.created_projects.where(import_type: 'fogbugz') + @already_added_projects = find_already_added_projects('fogbugz') already_added_projects_names = @already_added_projects.pluck(:import_source) @repos.reject! { |repo| already_added_projects_names.include? repo.name } end def jobs - jobs = current_user.created_projects.where(import_type: 'fogbugz').to_json(only: [:id, :import_status]) - render json: jobs + render json: find_jobs('fogbugz') end def create diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb index eb7d5fca367..f67ec4c248b 100644 --- a/app/controllers/import/github_controller.rb +++ b/app/controllers/import/github_controller.rb @@ -24,15 +24,14 @@ class Import::GithubController < Import::BaseController def status @repos = client.repos - @already_added_projects = current_user.created_projects.where(import_type: provider) + @already_added_projects = find_already_added_projects(provider) already_added_projects_names = @already_added_projects.pluck(:import_source) @repos.reject! { |repo| already_added_projects_names.include? repo.full_name } end def jobs - jobs = current_user.created_projects.where(import_type: provider).to_json(only: [:id, :import_status]) - render json: jobs + render json: find_jobs(provider) end def create diff --git a/app/controllers/import/gitlab_controller.rb b/app/controllers/import/gitlab_controller.rb index 18f1d20f5a9..39e2e9e094b 100644 --- a/app/controllers/import/gitlab_controller.rb +++ b/app/controllers/import/gitlab_controller.rb @@ -12,15 +12,14 @@ class Import::GitlabController < Import::BaseController def status @repos = client.projects - @already_added_projects = current_user.created_projects.where(import_type: "gitlab") + @already_added_projects = find_already_added_projects('gitlab') already_added_projects_names = @already_added_projects.pluck(:import_source) @repos = @repos.to_a.reject { |repo| already_added_projects_names.include? repo["path_with_namespace"] } end def jobs - jobs = current_user.created_projects.where(import_type: "gitlab").to_json(only: [:id, :import_status]) - render json: jobs + render json: find_jobs('gitlab') end def create diff --git a/app/controllers/import/google_code_controller.rb b/app/controllers/import/google_code_controller.rb index baa19fb383d..9b26a00f7c7 100644 --- a/app/controllers/import/google_code_controller.rb +++ b/app/controllers/import/google_code_controller.rb @@ -73,15 +73,14 @@ class Import::GoogleCodeController < Import::BaseController @repos = client.repos @incompatible_repos = client.incompatible_repos - @already_added_projects = current_user.created_projects.where(import_type: "google_code") + @already_added_projects = find_already_added_projects('google_code') already_added_projects_names = @already_added_projects.pluck(:import_source) @repos.reject! { |repo| already_added_projects_names.include? repo.name } end def jobs - jobs = current_user.created_projects.where(import_type: "google_code").to_json(only: [:id, :import_status]) - render json: jobs + render json: find_jobs('google_code') end def create diff --git a/app/controllers/ldap/omniauth_callbacks_controller.rb b/app/controllers/ldap/omniauth_callbacks_controller.rb new file mode 100644 index 00000000000..fb24edb8602 --- /dev/null +++ b/app/controllers/ldap/omniauth_callbacks_controller.rb @@ -0,0 +1,31 @@ +class Ldap::OmniauthCallbacksController < OmniauthCallbacksController + extend ::Gitlab::Utils::Override + + def self.define_providers! + return unless Gitlab::Auth::LDAP::Config.enabled? + + Gitlab::Auth::LDAP::Config.available_servers.each do |server| + alias_method server['provider_name'], :ldap + end + end + + # We only find ourselves here + # if the authentication to LDAP was successful. + def ldap + sign_in_user_flow(Gitlab::Auth::LDAP::User) + end + + define_providers! + + override :set_remember_me + def set_remember_me(user) + user.remember_me = params[:remember_me] if user.persisted? + end + + override :fail_login + def fail_login(user) + flash[:alert] = 'Access denied for your LDAP account.' + + redirect_to new_user_session_path + end +end diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index 5e6676ea513..27fd5f7ba37 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -4,18 +4,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController protect_from_forgery except: [:kerberos, :saml, :cas3] - Gitlab.config.omniauth.providers.each do |provider| - define_method provider['name'] do - handle_omniauth - end + def handle_omniauth + omniauth_flow(Gitlab::Auth::OAuth) end - if Gitlab::Auth::LDAP::Config.enabled? - Gitlab::Auth::LDAP::Config.available_servers.each do |server| - define_method server['provider_name'] do - ldap - end - end + AuthHelper.providers_for_base_controller.each do |provider| + alias_method provider, :handle_omniauth end # Extend the standard implementation to also increment @@ -32,56 +26,17 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController # Extend the standard message generation to accept our custom exception def failure_message - exception = env["omniauth.error"] + exception = request.env["omniauth.error"] error = exception.error_reason if exception.respond_to?(:error_reason) error ||= exception.error if exception.respond_to?(:error) error ||= exception.message if exception.respond_to?(:message) - error ||= env["omniauth.error.type"].to_s - error.to_s.humanize if error - end + error ||= request.env["omniauth.error.type"].to_s - # We only find ourselves here - # if the authentication to LDAP was successful. - def ldap - ldap_user = Gitlab::Auth::LDAP::User.new(oauth) - ldap_user.save if ldap_user.changed? # will also save new users - - @user = ldap_user.gl_user - @user.remember_me = params[:remember_me] if ldap_user.persisted? - - # Do additional LDAP checks for the user filter and EE features - if ldap_user.allowed? - if @user.two_factor_enabled? - prompt_for_two_factor(@user) - else - log_audit_event(@user, with: oauth['provider']) - sign_in_and_redirect(@user) - end - else - fail_ldap_login - end + error.to_s.humanize if error end def saml - if current_user - log_audit_event(current_user, with: :saml) - # Update SAML identity if data has changed. - identity = current_user.identities.with_extern_uid(:saml, oauth['uid']).take - if identity.nil? - current_user.identities.create(extern_uid: oauth['uid'], provider: :saml) - redirect_to profile_account_path, notice: 'Authentication method updated' - else - redirect_to after_sign_in_path_for(current_user) - end - else - saml_user = Gitlab::Auth::Saml::User.new(oauth) - saml_user.save if saml_user.changed? - @user = saml_user.gl_user - - continue_login_process - end - rescue Gitlab::Auth::OAuth::User::SignupDisabledError - handle_signup_error + omniauth_flow(Gitlab::Auth::Saml) end def omniauth_error @@ -117,25 +72,36 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController private - def handle_omniauth + def omniauth_flow(auth_module, identity_linker: nil) if current_user - # Add new authentication method - current_user.identities - .with_extern_uid(oauth['provider'], oauth['uid']) - .first_or_create(extern_uid: oauth['uid']) log_audit_event(current_user, with: oauth['provider']) - redirect_to profile_account_path, notice: 'Authentication method updated' - else - oauth_user = Gitlab::Auth::OAuth::User.new(oauth) - oauth_user.save - @user = oauth_user.gl_user - continue_login_process + identity_linker ||= auth_module::IdentityLinker.new(current_user, oauth) + + identity_linker.link + + if identity_linker.changed? + redirect_identity_linked + elsif identity_linker.failed? + redirect_identity_link_failed(identity_linker.error_message) + else + redirect_identity_exists + end + else + sign_in_user_flow(auth_module::User) end - rescue Gitlab::Auth::OAuth::User::SigninDisabledForProviderError - handle_disabled_provider - rescue Gitlab::Auth::OAuth::User::SignupDisabledError - handle_signup_error + end + + def redirect_identity_exists + redirect_to after_sign_in_path_for(current_user) + end + + def redirect_identity_link_failed(error_message) + redirect_to profile_account_path, notice: "Authentication failed: #{error_message}" + end + + def redirect_identity_linked + redirect_to profile_account_path, notice: 'Authentication method updated' end def handle_service_ticket(provider, ticket) @@ -144,21 +110,27 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController session[:service_tickets][provider] = ticket end - def continue_login_process - # Only allow properly saved users to login. - if @user.persisted? && @user.valid? - log_audit_event(@user, with: oauth['provider']) + def sign_in_user_flow(auth_user_class) + auth_user = auth_user_class.new(oauth) + user = auth_user.find_and_update! + + if auth_user.valid_sign_in? + log_audit_event(user, with: oauth['provider']) + + set_remember_me(user) - if @user.two_factor_enabled? - params[:remember_me] = '1' if remember_me? - prompt_for_two_factor(@user) + if user.two_factor_enabled? + prompt_for_two_factor(user) else - remember_me(@user) if remember_me? - sign_in_and_redirect(@user) + sign_in_and_redirect(user) end else - fail_login + fail_login(user) end + rescue Gitlab::Auth::OAuth::User::SigninDisabledForProviderError + handle_disabled_provider + rescue Gitlab::Auth::OAuth::User::SignupDisabledError + handle_signup_error end def handle_signup_error @@ -178,18 +150,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController @oauth ||= request.env['omniauth.auth'] end - def fail_login - error_message = @user.errors.full_messages.to_sentence + def fail_login(user) + error_message = user.errors.full_messages.to_sentence return redirect_to omniauth_error_path(oauth['provider'], error: error_message) end - def fail_ldap_login - flash[:alert] = 'Access denied for your LDAP account.' - - redirect_to new_user_session_path - end - def fail_auth0_login flash[:alert] = 'Wrong extern UID provided. Make sure Auth0 is configured correctly.' @@ -208,6 +174,16 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController .for_authentication.security_event end + def set_remember_me(user) + return unless remember_me? + + if user.two_factor_enabled? + params[:remember_me] = '1' + else + remember_me(user) + end + end + def remember_me? request_params = request.env['omniauth.params'] (request_params['remember_me'] == '1') if request_params.present? diff --git a/app/controllers/profiles/active_sessions_controller.rb b/app/controllers/profiles/active_sessions_controller.rb new file mode 100644 index 00000000000..f0cdc228366 --- /dev/null +++ b/app/controllers/profiles/active_sessions_controller.rb @@ -0,0 +1,14 @@ +class Profiles::ActiveSessionsController < Profiles::ApplicationController + def index + @sessions = ActiveSession.list(current_user) + end + + def destroy + ActiveSession.destroy(current_user, params[:id]) + + respond_to do |format| + format.html { redirect_to profile_active_sessions_url, status: 302 } + format.js { head :ok } + end + end +end diff --git a/app/controllers/profiles/keys_controller.rb b/app/controllers/profiles/keys_controller.rb index f0e5d2aa94e..12a6cd11f80 100644 --- a/app/controllers/profiles/keys_controller.rb +++ b/app/controllers/profiles/keys_controller.rb @@ -23,7 +23,7 @@ class Profiles::KeysController < Profiles::ApplicationController def destroy @key = current_user.keys.find(params[:id]) - @key.destroy + Keys::DestroyService.new(current_user).execute(@key) respond_to do |format| format.html { redirect_to profile_keys_url, status: 302 } diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb index 032bb2267e7..5ab6d103c89 100644 --- a/app/controllers/projects/application_controller.rb +++ b/app/controllers/projects/application_controller.rb @@ -25,7 +25,7 @@ class Projects::ApplicationController < ApplicationController params[:namespace_id] = project.namespace.to_param params[:project_id] = project.to_param - url_for(params) + url_for(safe_params) end def repository diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb index 949e54ff819..e7354a9e1f7 100644 --- a/app/controllers/projects/boards_controller.rb +++ b/app/controllers/projects/boards_controller.rb @@ -4,22 +4,25 @@ class Projects::BoardsController < Projects::ApplicationController before_action :check_issues_available! before_action :authorize_read_board!, only: [:index, :show] + before_action :boards, only: :index before_action :assign_endpoint_vars def index - @boards = Boards::ListService.new(project, current_user).execute - respond_with_boards end def show - @board = project.boards.find(params[:id]) + @board = boards.find(params[:id]) respond_with_board end private + def boards + @boards ||= Boards::ListService.new(project, current_user).execute + end + def assign_endpoint_vars @boards_endpoint = project_boards_path(project) @bulk_issues_path = bulk_update_project_issues_path(project) diff --git a/app/controllers/projects/clusters/applications_controller.rb b/app/controllers/projects/clusters/applications_controller.rb index 90c7fa62216..35885543622 100644 --- a/app/controllers/projects/clusters/applications_controller.rb +++ b/app/controllers/projects/clusters/applications_controller.rb @@ -5,9 +5,10 @@ class Projects::Clusters::ApplicationsController < Projects::ApplicationControll before_action :authorize_create_cluster!, only: [:create] def create - Clusters::Applications::ScheduleInstallationService.new(project, current_user, - application_class: @application_class, - cluster: @cluster).execute + application = @application_class.find_or_create_by!(cluster: @cluster) + + Clusters::Applications::ScheduleInstallationService.new(project, current_user).execute(application) + head :no_content rescue StandardError head :bad_request diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index b7f548e0e63..1d1184d46d1 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -23,8 +23,12 @@ class Projects::CommitController < Projects::ApplicationController respond_to do |format| format.html { render } - format.diff { render text: @commit.to_diff } - format.patch { render text: @commit.to_patch } + format.diff do + send_git_diff(@project.repository, @commit.diff_refs) + end + format.patch do + send_git_patch(@project.repository, @commit.diff_refs) + end end end diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index 2b0c2ca97c0..f93e500a07a 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -8,8 +8,11 @@ class Projects::CompareController < Projects::ApplicationController # Authorize before_action :require_non_empty_project before_action :authorize_download_code! - before_action :define_ref_vars, only: [:index, :show, :diff_for_path] - before_action :define_diff_vars, only: [:show, :diff_for_path] + # Defining ivars + before_action :define_diffs, only: [:show, :diff_for_path] + before_action :define_environment, only: [:show] + before_action :define_diff_notes_disabled, only: [:show, :diff_for_path] + before_action :define_commits, only: [:show, :diff_for_path, :signatures] before_action :merge_request, only: [:index, :show] def index @@ -22,9 +25,9 @@ class Projects::CompareController < Projects::ApplicationController end def diff_for_path - return render_404 unless @compare + return render_404 unless compare - render_diff_for_path(@compare.diffs(diff_options)) + render_diff_for_path(compare.diffs(diff_options)) end def create @@ -41,30 +44,60 @@ class Projects::CompareController < Projects::ApplicationController 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 define_ref_vars - @start_ref = Addressable::URI.unescape(params[:from]) + def compare + return @compare if defined?(@compare) + + @compare = CompareService.new(@project, head_ref).execute(@project, start_ref) + end + + def start_ref + @start_ref ||= Addressable::URI.unescape(params[:from]) + end + + def head_ref + return @ref if defined?(@ref) + @ref = @head_ref = Addressable::URI.unescape(params[:to]) end - def define_diff_vars - @compare = CompareService.new(@project, @head_ref) - .execute(@project, @start_ref) + def define_commits + @commits = compare.present? ? prepare_commits_for_rendering(compare.commits) : [] + end - if @compare - @commits = prepare_commits_for_rendering(@compare.commits) - @diffs = @compare.diffs(diff_options) + def define_diffs + @diffs = compare.present? ? compare.diffs(diff_options) : [] + end - environment_params = @repository.branch_exists?(@head_ref) ? { ref: @head_ref } : { commit: @compare.commit } + def define_environment + if compare + environment_params = @repository.branch_exists?(head_ref) ? { ref: head_ref } : { commit: compare.commit } @environment = EnvironmentsFinder.new(@project, current_user, environment_params).execute.last - - @diff_notes_disabled = true end end + def define_diff_notes_disabled + @diff_notes_disabled = compare.present? + end + def merge_request @merge_request ||= MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened - .find_by(source_project: @project, source_branch: @head_ref, target_branch: @start_ref) + .find_by(source_project: @project, source_branch: head_ref, target_branch: start_ref) end end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 767e492f566..d69015c8665 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -134,11 +134,11 @@ class Projects::IssuesController < Projects::ApplicationController def can_create_branch can_create = current_user && can?(current_user, :push_code, @project) && - @issue.can_be_worked_on?(current_user) + @issue.can_be_worked_on? respond_to do |format| format.json do - render json: { can_create_branch: can_create, has_related_branch: @issue.has_related_branch? } + render json: { can_create_branch: can_create, suggested_branch_name: @issue.suggested_branch_name } end end end @@ -177,7 +177,7 @@ class Projects::IssuesController < Projects::ApplicationController end def authorize_create_merge_request! - 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? end def render_issue_json diff --git a/app/controllers/projects/lfs_storage_controller.rb b/app/controllers/projects/lfs_storage_controller.rb index ebde0df1f7b..43d8867a536 100644 --- a/app/controllers/projects/lfs_storage_controller.rb +++ b/app/controllers/projects/lfs_storage_controller.rb @@ -77,8 +77,7 @@ class Projects::LfsStorageController < Projects::GitHttpClientController def link_to_project!(object) if object && !object.projects.exists?(storage_project.id) - object.projects << storage_project - object.save! + object.lfs_objects_projects.create!(project: storage_project) end end end diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb index 4a377fefc62..81129456ad8 100644 --- a/app/controllers/projects/merge_requests/creations_controller.rb +++ b/app/controllers/projects/merge_requests/creations_controller.rb @@ -83,13 +83,6 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap render layout: false end - def update_branches - @target_project = selected_target_project - @target_branches = @target_project ? @target_project.repository.branch_names : [] - - render layout: false - end - private def build_merge_request diff --git a/app/controllers/projects/mirrors_controller.rb b/app/controllers/projects/mirrors_controller.rb new file mode 100644 index 00000000000..5698ff4e706 --- /dev/null +++ b/app/controllers/projects/mirrors_controller.rb @@ -0,0 +1,67 @@ +class Projects::MirrorsController < Projects::ApplicationController + include RepositorySettingsRedirect + + # Authorize + before_action :remote_mirror, only: [:update] + before_action :check_mirror_available! + before_action :authorize_admin_project! + + layout "project_settings" + + def show + redirect_to_repository_settings(project) + end + + def update + if project.update_attributes(mirror_params) + flash[:notice] = 'Mirroring settings were successfully updated.' + else + flash[:alert] = project.errors.full_messages.join(', ').html_safe + end + + respond_to do |format| + format.html { redirect_to_repository_settings(project) } + format.json do + if project.errors.present? + render json: project.errors, status: :unprocessable_entity + else + render json: ProjectMirrorSerializer.new.represent(project) + end + end + end + end + + def update_now + if params[:sync_remote] + project.update_remote_mirrors + flash[:notice] = "The remote repository is being updated..." + end + + redirect_to_repository_settings(project) + end + + private + + def remote_mirror + @remote_mirror = project.remote_mirrors.first_or_initialize + end + + def check_mirror_available! + Gitlab::CurrentSettings.current_application_settings.mirror_available || current_user&.admin? + end + + def mirror_params_attributes + [ + remote_mirrors_attributes: %i[ + url + id + enabled + only_protected_branches + ] + ] + end + + def mirror_params + params.require(:project).permit(mirror_params_attributes) + end +end diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index 86c50d88a2a..4d4c2af2415 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -8,19 +8,6 @@ class Projects::NotesController < Projects::ApplicationController before_action :authorize_create_note!, only: [:create] before_action :authorize_resolve_note!, only: [:resolve, :unresolve] - # - # This is a fix to make spinach feature tests passing: - # Controller actions are returned from AbstractController::Base and methods of parent classes are - # excluded in order to return only specific controller related methods. - # That is ok for the app (no :create method in ancestors) - # but fails for tests because there is a :create method on FactoryBot (one of the ancestors) - # - # see https://github.com/rails/rails/blob/v4.2.7/actionpack/lib/abstract_controller/base.rb#L78 - # - def create - super - end - def delete_attachment note.remove_attachment! note.update_attribute(:attachment, nil) @@ -33,9 +20,7 @@ class Projects::NotesController < Projects::ApplicationController def resolve return render_404 unless note.resolvable? - note.resolve!(current_user) - - MergeRequests::ResolvedDiscussionNotificationService.new(project, current_user).execute(note.noteable) + Notes::ResolveService.new(project, current_user).execute(note) discussion = note.discussion diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 78d109cf33e..6b40fc2fe68 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -18,19 +18,12 @@ class Projects::PipelinesController < Projects::ApplicationController .page(params[:page]) .per(30) - @running_count = PipelinesFinder - .new(project, scope: 'running').execute.count + @running_count = limited_pipelines_count(project, 'running') + @pending_count = limited_pipelines_count(project, 'pending') + @finished_count = limited_pipelines_count(project, 'finished') + @pipelines_count = limited_pipelines_count(project) - @pending_count = PipelinesFinder - .new(project, scope: 'pending').execute.count - - @finished_count = PipelinesFinder - .new(project, scope: 'finished').execute.count - - @pipelines_count = PipelinesFinder - .new(project).execute.count - - @pipelines.map(&:commit) # List commits for batch loading + Gitlab::Ci::Pipeline::Preloader.preload(@pipelines) respond_to do |format| format.html @@ -41,7 +34,7 @@ class Projects::PipelinesController < Projects::ApplicationController pipelines: PipelineSerializer .new(project: @project, current_user: @current_user) .with_pagination(request, response) - .represent(@pipelines), + .represent(@pipelines, disable_coverage: true), count: { all: @pipelines_count, running: @running_count, @@ -87,7 +80,7 @@ class Projects::PipelinesController < Projects::ApplicationController end def failures - if @pipeline.statuses.latest.failed.present? + if @pipeline.failed_builds.present? render_show else redirect_to pipeline_path(@pipeline) @@ -104,9 +97,18 @@ class Projects::PipelinesController < Projects::ApplicationController @stage = pipeline.legacy_stage(params[:stage]) return not_found unless @stage - respond_to do |format| - format.json { render json: { html: view_to_html_string('projects/pipelines/_stage') } } - end + render json: StageSerializer + .new(project: @project, current_user: @current_user) + .represent(@stage, details: true) + end + + # TODO: This endpoint is used by mini-pipeline-graph + # TODO: This endpoint should be migrated to `stage.json` + def stage_ajax + @stage = pipeline.legacy_stage(params[:stage]) + return not_found unless @stage + + render json: { html: view_to_html_string('projects/pipelines/_stage') } end def retry @@ -157,7 +159,7 @@ class Projects::PipelinesController < Projects::ApplicationController end def create_params - params.require(:pipeline).permit(:ref) + params.require(:pipeline).permit(:ref, variables_attributes: %i[key secret_value]) end def pipeline @@ -172,4 +174,14 @@ class Projects::PipelinesController < Projects::ApplicationController # Also see https://gitlab.com/gitlab-org/gitlab-ce/issues/42343 Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/42339') end + + def authorize_update_pipeline! + return access_denied! unless can?(current_user, :update_pipeline, @pipeline) + end + + def limited_pipelines_count(project, scope = nil) + finder = PipelinesFinder.new(project, scope: scope) + + view_context.limited_counter_with_delimiter(finder.execute) + end end diff --git a/app/controllers/projects/prometheus/metrics_controller.rb b/app/controllers/projects/prometheus/metrics_controller.rb index 1dd886409a5..c6b6243b553 100644 --- a/app/controllers/projects/prometheus/metrics_controller.rb +++ b/app/controllers/projects/prometheus/metrics_controller.rb @@ -25,7 +25,7 @@ module Projects end def require_prometheus_metrics! - render_404 unless prometheus_adapter.can_query? + render_404 unless prometheus_adapter&.can_query? end end end diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb index 937b0e39cbd..d01f324e6fd 100644 --- a/app/controllers/projects/repositories_controller.rb +++ b/app/controllers/projects/repositories_controller.rb @@ -28,11 +28,12 @@ class Projects::RepositoriesController < Projects::ApplicationController end def assign_archive_vars - @id = params[:id] - - return unless @id - - @ref, @filename = extract_ref(@id) + if params[:id] + @ref, @filename = extract_ref(params[:id]) + else + @ref = params[:ref] + @filename = nil + end rescue InvalidPathError render_404 end diff --git a/app/controllers/projects/runner_projects_controller.rb b/app/controllers/projects/runner_projects_controller.rb index 3cb01405b05..0ec2490655f 100644 --- a/app/controllers/projects/runner_projects_controller.rb +++ b/app/controllers/projects/runner_projects_controller.rb @@ -8,7 +8,7 @@ class Projects::RunnerProjectsController < Projects::ApplicationController return head(403) unless can?(current_user, :assign_runner, @runner) - path = runners_path(project) + path = project_runners_path(project) runner_project = @runner.assign_to(project, current_user) if runner_project.persisted? @@ -22,6 +22,6 @@ class Projects::RunnerProjectsController < Projects::ApplicationController runner_project = project.runner_projects.find(params[:id]) runner_project.destroy - redirect_to runners_path(project), status: 302 + redirect_to project_runners_path(project), status: 302 end end diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb index c950d0f7001..bef94cea989 100644 --- a/app/controllers/projects/runners_controller.rb +++ b/app/controllers/projects/runners_controller.rb @@ -1,6 +1,6 @@ class Projects::RunnersController < Projects::ApplicationController before_action :authorize_admin_build! - before_action :set_runner, only: [:edit, :update, :destroy, :pause, :resume, :show] + before_action :runner, only: [:edit, :update, :destroy, :pause, :resume, :show] layout 'project_settings' @@ -13,7 +13,7 @@ class Projects::RunnersController < Projects::ApplicationController def update if Ci::UpdateRunnerService.new(@runner).update(runner_params) - redirect_to runner_path(@runner), notice: 'Runner was successfully updated.' + redirect_to project_runner_path(@project, @runner), notice: 'Runner was successfully updated.' else render 'edit' end @@ -24,26 +24,27 @@ class Projects::RunnersController < Projects::ApplicationController @runner.destroy end - redirect_to runners_path(@project), status: 302 + redirect_to project_runners_path(@project), status: 302 end def resume if Ci::UpdateRunnerService.new(@runner).update(active: true) - redirect_to runners_path(@project), notice: 'Runner was successfully updated.' + redirect_to project_runners_path(@project), notice: 'Runner was successfully updated.' else - redirect_to runners_path(@project), alert: 'Runner was not updated.' + redirect_to project_runners_path(@project), alert: 'Runner was not updated.' end end def pause if Ci::UpdateRunnerService.new(@runner).update(active: false) - redirect_to runners_path(@project), notice: 'Runner was successfully updated.' + redirect_to project_runners_path(@project), notice: 'Runner was successfully updated.' else - redirect_to runners_path(@project), alert: 'Runner was not updated.' + redirect_to project_runners_path(@project), alert: 'Runner was not updated.' end end def show + render 'shared/runners/show' end def toggle_shared_runners @@ -52,9 +53,15 @@ class Projects::RunnersController < Projects::ApplicationController redirect_to project_settings_ci_cd_path(@project) end + def toggle_group_runners + project.toggle_ci_cd_settings!(:group_runners_enabled) + + redirect_to project_settings_ci_cd_path(@project) + end + protected - def set_runner + def runner @runner ||= project.runners.find(params[:id]) end diff --git a/app/controllers/projects/settings/badges_controller.rb b/app/controllers/projects/settings/badges_controller.rb index f7b70dd4b7b..7887bee49c5 100644 --- a/app/controllers/projects/settings/badges_controller.rb +++ b/app/controllers/projects/settings/badges_controller.rb @@ -1,12 +1,12 @@ module Projects module Settings class BadgesController < Projects::ApplicationController - include GrapeRouteHelpers::NamedRouteMatcher + include API::Helpers::RelatedResourcesHelpers before_action :authorize_admin_project! def index - @badge_api_endpoint = api_v4_projects_badges_path(id: @project.id) + @badge_api_endpoint = expose_url(api_v4_projects_badges_path(id: @project.id)) end end end diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index d80ef8113aa..1d850baf012 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -67,10 +67,18 @@ module Projects def define_runners_variables @project_runners = @project.runners.ordered - @assignable_runners = current_user.ci_authorized_runners - .assignable_for(project).ordered.page(params[:page]).per(20) + + @assignable_runners = current_user + .ci_owned_runners + .assignable_for(project) + .ordered + .page(params[:page]).per(20) + @shared_runners = ::Ci::Runner.shared.active + @shared_runners_count = @shared_runners.count(:all) + + @group_runners = ::Ci::Runner.belonging_to_parent_group_of_project(@project.id) end def define_secret_variables diff --git a/app/controllers/projects/settings/integrations_controller.rb b/app/controllers/projects/settings/integrations_controller.rb index 1ff08cce8cb..d9fecfecc40 100644 --- a/app/controllers/projects/settings/integrations_controller.rb +++ b/app/controllers/projects/settings/integrations_controller.rb @@ -11,7 +11,14 @@ module Projects @hook = ProjectHook.new # Services - @services = @project.find_or_initialize_services + @services = @project.find_or_initialize_services(exceptions: service_exceptions) + end + + private + + # Returns a list of services that should be hidden from the list + def service_exceptions + @project.disabled_services.dup end end end diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb index f17056f13e0..4697af4f26a 100644 --- a/app/controllers/projects/settings/repository_controller.rb +++ b/app/controllers/projects/settings/repository_controller.rb @@ -2,6 +2,7 @@ module Projects module Settings class RepositoryController < Projects::ApplicationController before_action :authorize_admin_project! + before_action :remote_mirror, only: [:show] def show render_show @@ -25,6 +26,7 @@ module Projects define_deploy_token define_protected_refs + remote_mirror render 'show' end @@ -41,6 +43,10 @@ module Projects load_gon_index end + def remote_mirror + @remote_mirror = project.remote_mirrors.first_or_initialize + end + def access_levels_options { create_access_levels: levels_for_dropdown, diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb index c4930d3d18d..1b0751f48c5 100644 --- a/app/controllers/projects/wikis_controller.rb +++ b/app/controllers/projects/wikis_controller.rb @@ -29,8 +29,7 @@ class Projects::WikisController < Projects::ApplicationController else return render('empty') unless can?(current_user, :create_wiki, @project) - @page = WikiPage.new(@project_wiki) - @page.title = params[:id] + @page = build_page(title: params[:id]) render 'edit' end @@ -54,7 +53,7 @@ class Projects::WikisController < Projects::ApplicationController else render 'edit' end - rescue WikiPage::PageChangedError, WikiPage::PageRenameError => e + rescue WikiPage::PageChangedError, WikiPage::PageRenameError, Gitlab::Git::Wiki::OperationError => e @error = e render 'edit' end @@ -70,6 +69,11 @@ class Projects::WikisController < Projects::ApplicationController else render action: "edit" end + rescue Gitlab::Git::Wiki::OperationError => e + @page = build_page(wiki_params) + @error = e + + render 'edit' end def history @@ -94,6 +98,9 @@ class Projects::WikisController < Projects::ApplicationController redirect_to project_wiki_path(@project, :home), status: 302, notice: "Page was successfully deleted" + rescue Gitlab::Git::Wiki::OperationError => e + @error = e + render 'edit' end def git_access @@ -116,4 +123,10 @@ class Projects::WikisController < Projects::ApplicationController def wiki_params params.require(:wiki).permit(:title, :content, :format, :message, :last_commit_sha) end + + def build_page(args) + WikiPage.new(@project_wiki).tap do |page| + page.update_attributes(args) + end + end end diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 1848c806c41..f5a222b3a48 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -1,5 +1,6 @@ class RegistrationsController < Devise::RegistrationsController include Recaptcha::Verify + include AcceptsPendingInvitations before_action :whitelist_query_limiting, only: [:destroy] @@ -16,6 +17,7 @@ class RegistrationsController < Devise::RegistrationsController end if !Gitlab::Recaptcha.load_configurations! || verify_recaptcha + accept_pending_invitations super else flash[:alert] = 'There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.' @@ -60,7 +62,7 @@ class RegistrationsController < Devise::RegistrationsController def after_sign_up_path_for(user) Gitlab::AppLogger.info("User Created: username=#{user.username} email=#{user.email} ip=#{request.remote_ip} confirmed:#{user.confirmed?}") - user.confirmed? ? dashboard_projects_path : users_almost_there_path + user.confirmed? ? stored_location_for(user) || dashboard_projects_path : users_almost_there_path end def after_inactive_sign_up_path_for(resource) diff --git a/app/controllers/sent_notifications_controller.rb b/app/controllers/sent_notifications_controller.rb index 04c36b3ebfe..93a71103a09 100644 --- a/app/controllers/sent_notifications_controller.rb +++ b/app/controllers/sent_notifications_controller.rb @@ -17,16 +17,20 @@ class SentNotificationsController < ApplicationController flash[:notice] = "You have been unsubscribed from this thread." if current_user - case noteable - when Issue - redirect_to issue_path(noteable) - when MergeRequest - redirect_to merge_request_path(noteable) - else - redirect_to root_path - end + redirect_to noteable_path(noteable) else redirect_to new_user_session_path end end + + def noteable_path(noteable) + case noteable + when Issue + issue_path(noteable) + when MergeRequest + merge_request_path(noteable) + else + root_path + end + end end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index f3a4aa849c7..1a339f76d26 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,4 +1,5 @@ class SessionsController < Devise::SessionsController + include InternalRedirect include AuthenticatesWithTwoFactor include Devise::Controllers::Rememberable include Recaptcha::ClientHelper @@ -102,18 +103,12 @@ class SessionsController < Devise::SessionsController # we should never redirect to '/users/sign_in' after signing in successfully. return true if redirect_uri.path == new_user_session_path - redirect_to = redirect_uri.to_s if redirect_allowed_to?(redirect_uri) + redirect_to = redirect_uri.to_s if host_allowed?(redirect_uri) @redirect_to = redirect_to store_location_for(:redirect, redirect_to) end - # Overridden in EE - def redirect_allowed_to?(uri) - uri.host == Gitlab.config.gitlab.host && - uri.port == Gitlab.config.gitlab.port - end - def two_factor_enabled? find_user&.two_factor_enabled? end diff --git a/app/controllers/users/terms_controller.rb b/app/controllers/users/terms_controller.rb new file mode 100644 index 00000000000..ab685b9106e --- /dev/null +++ b/app/controllers/users/terms_controller.rb @@ -0,0 +1,70 @@ +module Users + class TermsController < ApplicationController + include InternalRedirect + + skip_before_action :enforce_terms! + skip_before_action :check_password_expiration + skip_before_action :check_two_factor_requirement + skip_before_action :require_email + + before_action :terms + + layout 'terms' + + def index + @redirect = redirect_path + end + + def accept + agreement = Users::RespondToTermsService.new(current_user, viewed_term) + .execute(accepted: true) + + if agreement.persisted? + redirect_to redirect_path + else + flash[:alert] = agreement.errors.full_messages.join(', ') + redirect_to terms_path, redirect: redirect_path + end + end + + def decline + agreement = Users::RespondToTermsService.new(current_user, viewed_term) + .execute(accepted: false) + + if agreement.persisted? + sign_out(current_user) + redirect_to root_path + else + flash[:alert] = agreement.errors.full_messages.join(', ') + redirect_to terms_path, redirect: redirect_path + end + end + + private + + def viewed_term + @viewed_term ||= ApplicationSetting::Term.find(params[:id]) + end + + def terms + unless @term = Gitlab::CurrentSettings.current_application_settings.latest_terms + redirect_to redirect_path + end + end + + def redirect_path + redirect_to_path = safe_redirect_path(params[:redirect]) || safe_redirect_path_for_url(request.referer) + + if redirect_to_path && + excluded_redirect_paths.none? { |excluded| redirect_to_path.include?(excluded) } + redirect_to_path + else + root_path + end + end + + def excluded_redirect_paths + [terms_path, new_user_session_path] + end + end +end |