diff options
Diffstat (limited to 'app/controllers')
30 files changed, 495 insertions, 162 deletions
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0fdd4d2cb47..2caffec66ac 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -13,12 +13,14 @@ class ApplicationController < ActionController::Base before_action :authenticate_sessionless_user! before_action :authenticate_user! + before_action :enforce_terms!, if: -> { Gitlab::CurrentSettings.current_application_settings.enforce_terms }, + unless: :peek_request? 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 +112,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 +271,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 +365,12 @@ 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 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_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/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/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/import/base_controller.rb b/app/controllers/import/base_controller.rb index c84fc2d305d..bcb856ce3f4 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..ed89bed029b 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 @@ -37,51 +31,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController 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 - # 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/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/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/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb index 7497b5012ec..dd12d30a085 100644 --- a/app/controllers/projects/jobs_controller.rb +++ b/app/controllers/projects/jobs_controller.rb @@ -78,8 +78,6 @@ class Projects::JobsController < Projects::ApplicationController result.merge!(trace.to_h) end - result[:html] = result[:html].presence || 'No job log' - render json: result end end 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..bc13b8ad7ba 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -33,9 +33,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..898e88344db 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -104,9 +104,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 +166,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 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/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index d80ef8113aa..177c8a54099 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_authorized_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/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/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..95c5c3432d5 --- /dev/null +++ b/app/controllers/users/terms_controller.rb @@ -0,0 +1,66 @@ +module Users + class TermsController < ApplicationController + include InternalRedirect + + skip_before_action :enforce_terms! + 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 |