diff options
Diffstat (limited to 'app/controllers')
19 files changed, 145 insertions, 54 deletions
diff --git a/app/controllers/admin/impersonations_controller.rb b/app/controllers/admin/impersonations_controller.rb index 08d7e3b4fa2..65fe22bd8f4 100644 --- a/app/controllers/admin/impersonations_controller.rb +++ b/app/controllers/admin/impersonations_controller.rb @@ -5,23 +5,12 @@ class Admin::ImpersonationsController < Admin::ApplicationController before_action :authenticate_impersonator! def destroy - original_user = current_user - - warden.set_user(impersonator, scope: :user) - - Gitlab::AppLogger.info("User #{impersonator.username} has stopped impersonating #{original_user.username}") - - session[:impersonator_id] = nil - + original_user = stop_impersonation redirect_to admin_user_path(original_user), status: :found end private - def impersonator - @impersonator ||= User.find(session[:impersonator_id]) if session[:impersonator_id] - end - def authenticate_impersonator! render_404 unless impersonator && impersonator.admin? && !impersonator.blocked? end diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index b783c0e2a6f..e93be1c1ba2 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -2,6 +2,7 @@ class Admin::UsersController < Admin::ApplicationController before_action :user, except: [:index, :new, :create] + before_action :check_impersonation_availability, only: :impersonate def index @users = User.order_name_asc.filter(params[:filter]) @@ -227,4 +228,8 @@ class Admin::UsersController < Admin::ApplicationController result[:status] == :success end + + def check_impersonation_availability + access_denied! unless Gitlab.config.gitlab.impersonation_enabled + end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 9b40ffb26a2..65c1576d9d2 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -12,11 +12,11 @@ class ApplicationController < ActionController::Base include WorkhorseHelper include EnforcesTwoFactorAuthentication include WithPerformanceBar + include SessionlessAuthentication # this can be removed after switching to rails 5 # https://gitlab.com/gitlab-org/gitlab-ce/issues/51908 include InvalidUTF8ErrorHandler unless Gitlab.rails5? - before_action :authenticate_sessionless_user! before_action :authenticate_user! before_action :enforce_terms!, if: :should_enforce_terms? before_action :validate_user_service_ticket! @@ -28,6 +28,7 @@ class ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? before_action :require_email, unless: :devise_controller? before_action :set_usage_stats_consent_flag + before_action :check_impersonation_availability around_action :set_locale @@ -153,13 +154,6 @@ class ApplicationController < ActionController::Base end end - # This filter handles personal access tokens, and atom requests with rss tokens - def authenticate_sessionless_user! - user = Gitlab::Auth::RequestAuthenticator.new(request).find_sessionless_user - - sessionless_sign_in(user) if user - end - def log_exception(exception) Raven.capture_exception(exception) if sentry_enabled? @@ -426,25 +420,11 @@ class ApplicationController < ActionController::Base Gitlab::I18n.with_user_locale(current_user, &block) end - def sessionless_sign_in(user) - if user && can?(user, :log_in) - # Notice we are passing store false, so the user is not - # actually stored in the session and a token is needed - # for every request. If you want the token to work as a - # sign in token, you can simply remove store: false. - sign_in(user, store: false, message: :sessionless_sign_in) - end - end - def set_page_title_header # 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 @@ -483,4 +463,28 @@ class ApplicationController < ActionController::Base .new(settings, current_user, application_setting_params) .execute end + + def check_impersonation_availability + return unless session[:impersonator_id] + + unless Gitlab.config.gitlab.impersonation_enabled + stop_impersonation + access_denied! _('Impersonation has been disabled') + end + end + + def stop_impersonation + impersonated_user = current_user + + Gitlab::AppLogger.info("User #{impersonator.username} has stopped impersonating #{impersonated_user.username}") + + warden.set_user(impersonator, scope: :user) + session[:impersonator_id] = nil + + impersonated_user + end + + def impersonator + @impersonator ||= User.find(session[:impersonator_id]) if session[:impersonator_id] + end end diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb index 777b147e2dd..0319948a12f 100644 --- a/app/controllers/concerns/notes_actions.rb +++ b/app/controllers/concerns/notes_actions.rb @@ -6,6 +6,7 @@ module NotesActions extend ActiveSupport::Concern included do + prepend_before_action :normalize_create_params, only: [:create] before_action :set_polling_interval_header, only: [:index] before_action :require_noteable!, only: [:index, :create] before_action :authorize_admin_note!, only: [:update, :destroy] @@ -247,6 +248,15 @@ module NotesActions DiscussionSerializer.new(project: project, noteable: noteable, current_user: current_user, note_entity: ProjectNoteEntity) end + # Avoids checking permissions in the wrong object - this ensures that the object we checked permissions for + # is the object we're actually creating a note in. + def normalize_create_params + params[:note].try do |note| + note[:noteable_id] = params[:target_id] + note[:noteable_type] = params[:target_type].classify + end + end + def note_project strong_memoize(:note_project) do next nil unless project diff --git a/app/controllers/concerns/sessionless_authentication.rb b/app/controllers/concerns/sessionless_authentication.rb new file mode 100644 index 00000000000..590eefc6dab --- /dev/null +++ b/app/controllers/concerns/sessionless_authentication.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# == SessionlessAuthentication +# +# Controller concern to handle PAT and RSS token authentication methods +# +module SessionlessAuthentication + # This filter handles personal access tokens, and atom requests with rss tokens + def authenticate_sessionless_user!(request_format) + user = Gitlab::Auth::RequestAuthenticator.new(request).find_sessionless_user(request_format) + + sessionless_sign_in(user) if user + end + + def sessionless_user? + current_user && !session.keys.include?('warden.user.user.key') + end + + def sessionless_sign_in(user) + if user && can?(user, :log_in) + # Notice we are passing store false, so the user is not + # actually stored in the session and a token is needed + # for every request. If you want the token to work as a + # sign in token, you can simply remove store: false. + sign_in(user, store: false, message: :sessionless_sign_in) + end + end +end diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index e9686ed8d06..57e612d89d3 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -4,6 +4,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController include ParamsBackwardCompatibility include RendersMemberAccess + prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) } before_action :set_non_archived_param before_action :default_sorting skip_cross_project_access_check :index, :starred diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb index b82caf30a91..3fa582cf25b 100644 --- a/app/controllers/dashboard/todos_controller.rb +++ b/app/controllers/dashboard/todos_controller.rb @@ -4,6 +4,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController include ActionView::Helpers::NumberHelper before_action :authorize_read_project!, only: :index + before_action :authorize_read_group!, only: :index before_action :find_todos, only: [:index, :destroy_all] def index @@ -60,6 +61,15 @@ class Dashboard::TodosController < Dashboard::ApplicationController end end + def authorize_read_group! + group_id = params[:group_id] + + if group_id.present? + group = Group.find(group_id) + render_404 unless can?(current_user, :read_group, group) + end + end + def find_todos @todos ||= TodosFinder.new(current_user, todo_params).execute end diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 4ce9be44403..be2d9512c01 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -4,6 +4,9 @@ class DashboardController < Dashboard::ApplicationController include IssuesAction include MergeRequestsAction + prepend_before_action(only: [:issues]) { authenticate_sessionless_user!(:rss) } + prepend_before_action(only: [:issues_calendar]) { authenticate_sessionless_user!(:ics) } + before_action :event_filter, only: :activity before_action :projects, only: [:issues, :merge_requests] before_action :set_show_full_reference, only: [:issues, :merge_requests] diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index a1ec144410b..6ea4758ec32 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -3,6 +3,7 @@ class GraphqlController < ApplicationController # Unauthenticated users have access to the API for public data skip_before_action :authenticate_user! + prepend_before_action(only: [:execute]) { authenticate_sessionless_user!(:api) } before_action :check_graphql_feature_flag! diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 062c8c4e9e1..c5d8ac2ed77 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -9,6 +9,9 @@ class GroupsController < Groups::ApplicationController respond_to :html + prepend_before_action(only: [:show, :issues]) { authenticate_sessionless_user!(:rss) } + prepend_before_action(only: [:issues_calendar]) { authenticate_sessionless_user!(:ics) } + before_action :authenticate_user!, only: [:new, :create] before_action :group, except: [:index, :new, :create] diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb index b50f140dc80..ab4ca56bb49 100644 --- a/app/controllers/oauth/applications_controller.rb +++ b/app/controllers/oauth/applications_controller.rb @@ -9,7 +9,7 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController before_action :verify_user_oauth_applications_enabled, except: :index before_action :authenticate_user! before_action :add_gon_variables - before_action :load_scopes, only: [:index, :create, :edit] + before_action :load_scopes, only: [:index, :create, :edit, :update] helper_method :can? diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb index 84a2a461da7..8ba18aacc58 100644 --- a/app/controllers/projects/commits_controller.rb +++ b/app/controllers/projects/commits_controller.rb @@ -6,6 +6,7 @@ class Projects::CommitsController < Projects::ApplicationController include ExtractsPath include RendersCommits + prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) } before_action :whitelist_query_limiting, except: :commits_root before_action :require_non_empty_project before_action :assign_ref_vars, except: :commits_root diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb index e55065c5817..a10e159ea1e 100644 --- a/app/controllers/projects/imports_controller.rb +++ b/app/controllers/projects/imports_controller.rb @@ -13,10 +13,8 @@ class Projects::ImportsController < Projects::ApplicationController end def create - @project.import_url = params[:project][:import_url] - - if @project.save - @project.reload.import_schedule + if @project.update(safe_import_params) + @project.import_state.reload.schedule end redirect_to project_import_path(@project) @@ -24,7 +22,7 @@ class Projects::ImportsController < Projects::ApplicationController def show if @project.import_finished? - if continue_params + if continue_params&.key?(:to) redirect_to continue_params[:to], notice: continue_params[:notice] else redirect_to project_path(@project), notice: finished_notice @@ -67,4 +65,12 @@ class Projects::ImportsController < Projects::ApplicationController redirect_to project_path(@project) end end + + def import_params + params.require(:project).permit(:import_url) + end + + def safe_import_params + import_params + end end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 308f666394c..c6ab6b4642e 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -9,10 +9,6 @@ class Projects::IssuesController < Projects::ApplicationController include IssuesCalendar include SpammableActions - def self.authenticate_user_only_actions - %i[new] - end - def self.issue_except_actions %i[index calendar new create bulk_update] end @@ -21,7 +17,10 @@ class Projects::IssuesController < Projects::ApplicationController %i[index calendar] end - prepend_before_action :authenticate_user!, only: authenticate_user_only_actions + prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) } + prepend_before_action(only: [:calendar]) { authenticate_sessionless_user!(:ics) } + prepend_before_action :authenticate_new_issue!, only: [:new] + prepend_before_action :store_uri, only: [:new, :show] before_action :whitelist_query_limiting, only: [:create, :create_merge_request, :move, :bulk_update] before_action :check_issues_available! @@ -38,6 +37,8 @@ class Projects::IssuesController < Projects::ApplicationController # Allow create a new branch and empty WIP merge request from current issue before_action :authorize_create_merge_request_from!, only: [:create_merge_request] + before_action :set_suggested_issues_feature_flags, only: [:new] + respond_to :html def index @@ -230,16 +231,18 @@ class Projects::IssuesController < Projects::ApplicationController ] + [{ label_ids: [], assignee_ids: [] }] end - def authenticate_user! + def authenticate_new_issue! return if current_user notice = "Please sign in to create the new issue." + redirect_to new_user_session_path, notice: notice + end + + def store_uri if request.get? && !request.xhr? store_location_for :user, request.fullpath end - - redirect_to new_user_session_path, notice: notice end def serializer @@ -263,4 +266,9 @@ class Projects::IssuesController < Projects::ApplicationController # 3. https://gitlab.com/gitlab-org/gitlab-ce/issues/42426 Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/42422') end + + def set_suggested_issues_feature_flags + push_frontend_feature_flag(:graphql) + push_frontend_feature_flag(:issue_suggestions) + end end diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb index 20998c97730..8e68014a30d 100644 --- a/app/controllers/projects/milestones_controller.rb +++ b/app/controllers/projects/milestones_controller.rb @@ -11,7 +11,10 @@ class Projects::MilestonesController < Projects::ApplicationController before_action :authorize_read_milestone! # Allow admin milestone - before_action :authorize_admin_milestone!, except: [:index, :show, :merge_requests, :participants, :labels, :promote] + before_action :authorize_admin_milestone!, except: [:index, :show, :merge_requests, :participants, :labels] + + # Allow to promote milestone + before_action :authorize_promote_milestone!, only: :promote respond_to :html @@ -78,7 +81,7 @@ class Projects::MilestonesController < Projects::ApplicationController def promote promoted_milestone = Milestones::PromoteService.new(project, current_user).execute(milestone) - flash[:notice] = flash_notice_for(promoted_milestone, project.group) + flash[:notice] = flash_notice_for(promoted_milestone, project_group) respond_to do |format| format.html do @@ -109,6 +112,12 @@ class Projects::MilestonesController < Projects::ApplicationController protected + def project_group + strong_memoize(:project_group) do + project.group + end + end + def milestones strong_memoize(:milestones) do MilestonesFinder.new(search_params).execute @@ -125,13 +134,17 @@ class Projects::MilestonesController < Projects::ApplicationController return render_404 unless can?(current_user, :admin_milestone, @project) end + def authorize_promote_milestone! + return render_404 unless can?(current_user, :admin_milestone, project_group) + end + def milestone_params params.require(:milestone).permit(:title, :description, :start_date, :due_date, :state_event) end def search_params - if request.format.json? && @project.group && can?(current_user, :read_group, @project.group) - groups = @project.group.self_and_ancestors_ids + if request.format.json? && project_group && can?(current_user, :read_group, project_group) + groups = project_group.self_and_ancestors_ids end params.permit(:state).merge(project_ids: @project.id, group_ids: groups) diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb index ad2466a8588..6543711ecfa 100644 --- a/app/controllers/projects/network_controller.rb +++ b/app/controllers/projects/network_controller.rb @@ -8,6 +8,7 @@ class Projects::NetworkController < Projects::ApplicationController before_action :require_non_empty_project before_action :assign_ref_vars before_action :authorize_download_code! + before_action :assign_options before_action :assign_commit def show @@ -29,10 +30,13 @@ class Projects::NetworkController < Projects::ApplicationController render end + def assign_options + @options = params.permit(:filter_ref, :extended_sha1) + end + def assign_commit - return if params[:extended_sha1].blank? + return if @options[:extended_sha1].blank? - @options[:extended_sha1] = params[:extended_sha1] @commit = @repo.commit(@options[:extended_sha1]) end diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb index c8442ff3592..2b28670a49b 100644 --- a/app/controllers/projects/tags_controller.rb +++ b/app/controllers/projects/tags_controller.rb @@ -3,6 +3,8 @@ class Projects::TagsController < Projects::ApplicationController include SortingHelper + prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) } + # Authorize before_action :require_non_empty_project before_action :authorize_download_code! diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 7f4a9f5151b..8bf93bfd68d 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -7,6 +7,8 @@ class ProjectsController < Projects::ApplicationController include PreviewMarkdown include SendFileUpload + prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) } + before_action :whitelist_query_limiting, only: [:create] before_action :authenticate_user!, except: [:index, :show, :activity, :refs] before_action :redirect_git_extension, only: [:show] diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 5b70c69d7f4..8b040dc080e 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -14,6 +14,7 @@ class UsersController < ApplicationController calendar_activities: true skip_before_action :authenticate_user! + prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) } before_action :user, except: [:exists] before_action :authorize_read_user_profile!, only: [:calendar, :calendar_activities, :groups, :projects, :contributed_projects, :snippets] |