diff options
Diffstat (limited to 'app/controllers/concerns')
-rw-r--r-- | app/controllers/concerns/enforces_two_factor_authentication.rb | 3 | ||||
-rw-r--r-- | app/controllers/concerns/find_snippet.rb | 24 | ||||
-rw-r--r-- | app/controllers/concerns/integrations_actions.rb | 6 | ||||
-rw-r--r-- | app/controllers/concerns/issuable_actions.rb | 29 | ||||
-rw-r--r-- | app/controllers/concerns/issuable_collections.rb | 3 | ||||
-rw-r--r-- | app/controllers/concerns/issuable_collections_action.rb | 4 | ||||
-rw-r--r-- | app/controllers/concerns/known_sign_in.rb | 2 | ||||
-rw-r--r-- | app/controllers/concerns/milestone_actions.rb | 8 | ||||
-rw-r--r-- | app/controllers/concerns/notes_actions.rb | 6 | ||||
-rw-r--r-- | app/controllers/concerns/preview_markdown.rb | 2 | ||||
-rw-r--r-- | app/controllers/concerns/service_params.rb | 3 | ||||
-rw-r--r-- | app/controllers/concerns/snippet_authorizations.rb | 23 | ||||
-rw-r--r-- | app/controllers/concerns/snippets_actions.rb | 61 | ||||
-rw-r--r-- | app/controllers/concerns/wiki_actions.rb | 232 | ||||
-rw-r--r-- | app/controllers/concerns/workhorse_import_export_upload.rb | 33 |
15 files changed, 404 insertions, 35 deletions
diff --git a/app/controllers/concerns/enforces_two_factor_authentication.rb b/app/controllers/concerns/enforces_two_factor_authentication.rb index d486d734db8..6c443611a60 100644 --- a/app/controllers/concerns/enforces_two_factor_authentication.rb +++ b/app/controllers/concerns/enforces_two_factor_authentication.rb @@ -23,8 +23,7 @@ module EnforcesTwoFactorAuthentication def two_factor_authentication_required? Gitlab::CurrentSettings.require_two_factor_authentication? || - current_user.try(:require_two_factor_authentication_from_group?) || - current_user.try(:ultraauth_user?) + current_user.try(:require_two_factor_authentication_from_group?) end def current_user_requires_two_factor? diff --git a/app/controllers/concerns/find_snippet.rb b/app/controllers/concerns/find_snippet.rb new file mode 100644 index 00000000000..d51f1a1b3ad --- /dev/null +++ b/app/controllers/concerns/find_snippet.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module FindSnippet + extend ActiveSupport::Concern + include Gitlab::Utils::StrongMemoize + + private + + # rubocop:disable CodeReuse/ActiveRecord + def snippet + strong_memoize(:snippet) do + snippet_klass.inc_relations_for_view.find_by(id: snippet_id) + end + end + # rubocop:enable CodeReuse/ActiveRecord + + def snippet_klass + raise NotImplementedError + end + + def snippet_id + params[:id] + end +end diff --git a/app/controllers/concerns/integrations_actions.rb b/app/controllers/concerns/integrations_actions.rb index ff283f9bb62..cc9db7936e8 100644 --- a/app/controllers/concerns/integrations_actions.rb +++ b/app/controllers/concerns/integrations_actions.rb @@ -16,10 +16,12 @@ module IntegrationsActions def update saved = integration.update(service_params[:service]) + overwrite = Gitlab::Utils.to_boolean(params[:overwrite]) respond_to do |format| format.html do if saved + PropagateIntegrationWorker.perform_async(integration.id, overwrite) redirect_to scoped_edit_integration_path(integration), notice: success_message else render 'shared/integrations/edit' @@ -34,6 +36,10 @@ module IntegrationsActions end end + def custom_integration_projects + Project.with_custom_integration_compared_to(integration).page(params[:page]).per(20) + end + def test render json: {}, status: :ok end diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb index 0b1b3f2bcba..98fa8202e25 100644 --- a/app/controllers/concerns/issuable_actions.rb +++ b/app/controllers/concerns/issuable_actions.rb @@ -16,19 +16,6 @@ module IssuableActions end end - def permitted_keys - [ - :issuable_ids, - :assignee_id, - :milestone_id, - :state_event, - :subscription_event, - label_ids: [], - add_label_ids: [], - remove_label_ids: [] - ] - end - def show respond_to do |format| format.html do @@ -221,10 +208,20 @@ module IssuableActions end def bulk_update_params - permitted_keys_array = permitted_keys.dup - permitted_keys_array << { assignee_ids: [] } + params.require(:update).permit(bulk_update_permitted_keys) + end - params.require(:update).permit(permitted_keys_array) + def bulk_update_permitted_keys + [ + :issuable_ids, + :assignee_id, + :milestone_id, + :state_event, + :subscription_event, + assignee_ids: [], + add_label_ids: [], + remove_label_ids: [] + ] end def resource_name diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb index 5aa00af8910..9ef067e8797 100644 --- a/app/controllers/concerns/issuable_collections.rb +++ b/app/controllers/concerns/issuable_collections.rb @@ -5,7 +5,6 @@ module IssuableCollections include PaginatedCollection include SortingHelper include SortingPreference - include Gitlab::IssuableMetadata include Gitlab::Utils::StrongMemoize included do @@ -44,7 +43,7 @@ module IssuableCollections def set_pagination @issuables = @issuables.page(params[:page]) @issuables = per_page_for_relative_position if params[:sort] == 'relative_position' - @issuable_meta_data = issuable_meta_data(@issuables, collection_type, current_user) + @issuable_meta_data = Gitlab::IssuableMetadata.new(current_user, @issuables).data @total_pages = issuable_page_count(@issuables) end # rubocop:enable Gitlab/ModuleWithInstanceVariables diff --git a/app/controllers/concerns/issuable_collections_action.rb b/app/controllers/concerns/issuable_collections_action.rb index 78b3c6771b3..e3ac117660b 100644 --- a/app/controllers/concerns/issuable_collections_action.rb +++ b/app/controllers/concerns/issuable_collections_action.rb @@ -11,7 +11,7 @@ module IssuableCollectionsAction .non_archived .page(params[:page]) - @issuable_meta_data = issuable_meta_data(@issues, collection_type, current_user) + @issuable_meta_data = Gitlab::IssuableMetadata.new(current_user, @issues).data respond_to do |format| format.html @@ -22,7 +22,7 @@ module IssuableCollectionsAction def merge_requests @merge_requests = issuables_collection.page(params[:page]) - @issuable_meta_data = issuable_meta_data(@merge_requests, collection_type, current_user) + @issuable_meta_data = Gitlab::IssuableMetadata.new(current_user, @merge_requests).data end # rubocop:enable Gitlab/ModuleWithInstanceVariables diff --git a/app/controllers/concerns/known_sign_in.rb b/app/controllers/concerns/known_sign_in.rb index 97883d8d08c..c0b9605de58 100644 --- a/app/controllers/concerns/known_sign_in.rb +++ b/app/controllers/concerns/known_sign_in.rb @@ -26,6 +26,6 @@ module KnownSignIn end def notify_user - current_user.notification_service.unknown_sign_in(current_user, request.remote_ip) + current_user.notification_service.unknown_sign_in(current_user, request.remote_ip, current_user.current_sign_in_at) end end diff --git a/app/controllers/concerns/milestone_actions.rb b/app/controllers/concerns/milestone_actions.rb index dbc575a1487..29138e7b014 100644 --- a/app/controllers/concerns/milestone_actions.rb +++ b/app/controllers/concerns/milestone_actions.rb @@ -51,13 +51,7 @@ module MilestoneActions } end - # rubocop:disable Gitlab/ModuleWithInstanceVariables def milestone_redirect_path - if @milestone.global_milestone? - url_for(action: :show, title: @milestone.title) - else - url_for(action: :show) - end + url_for(action: :show) end - # rubocop:enable Gitlab/ModuleWithInstanceVariables end diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb index d4b0d3b2674..d3dfb1813e4 100644 --- a/app/controllers/concerns/notes_actions.rb +++ b/app/controllers/concerns/notes_actions.rb @@ -13,9 +13,7 @@ module NotesActions end def index - current_fetched_at = Time.current.to_i - - notes_json = { notes: [], last_fetched_at: current_fetched_at } + notes_json = { notes: [], last_fetched_at: Time.current.to_i } notes = notes_finder .execute @@ -24,7 +22,7 @@ module NotesActions if notes_filter != UserPreference::NOTES_FILTERS[:only_comments] notes = ResourceEvents::MergeIntoNotesService - .new(noteable, current_user, last_fetched_at: current_fetched_at) + .new(noteable, current_user, last_fetched_at: last_fetched_at) .execute(notes) end diff --git a/app/controllers/concerns/preview_markdown.rb b/app/controllers/concerns/preview_markdown.rb index ba15d611c0d..2916762e31f 100644 --- a/app/controllers/concerns/preview_markdown.rb +++ b/app/controllers/concerns/preview_markdown.rb @@ -32,7 +32,7 @@ module PreviewMarkdown def markdown_context_params case controller_name - when 'wikis' then { pipeline: :wiki, project_wiki: @project_wiki, page_slug: params[:id] } + when 'wikis' then { pipeline: :wiki, wiki: wiki, page_slug: params[:id] } when 'snippets' then { skip_project_check: true } when 'groups' then { group: group } when 'projects' then projects_filter_params diff --git a/app/controllers/concerns/service_params.rb b/app/controllers/concerns/service_params.rb index e2c83f9a069..e78fa8f8250 100644 --- a/app/controllers/concerns/service_params.rb +++ b/app/controllers/concerns/service_params.rb @@ -6,6 +6,7 @@ module ServiceParams ALLOWED_PARAMS_CE = [ :active, :add_pusher, + :alert_events, :api_key, :api_url, :api_version, @@ -28,6 +29,8 @@ module ServiceParams :drone_url, :enable_ssl_verification, :external_wiki_url, + :google_iap_service_account_json, + :google_iap_audience_client_id, # We're using `issues_events` and `merge_requests_events` # in the view so we still need to explicitly state them # here. `Service#event_names` would only give diff --git a/app/controllers/concerns/snippet_authorizations.rb b/app/controllers/concerns/snippet_authorizations.rb new file mode 100644 index 00000000000..9bbb0cc6faa --- /dev/null +++ b/app/controllers/concerns/snippet_authorizations.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module SnippetAuthorizations + extend ActiveSupport::Concern + + private + + def authorize_read_snippet! + return render_404 unless can?(current_user, :read_snippet, snippet) + end + + def authorize_update_snippet! + return render_404 unless can?(current_user, :update_snippet, snippet) + end + + def authorize_admin_snippet! + return render_404 unless can?(current_user, :admin_snippet, snippet) + end + + def authorize_create_snippet! + return render_404 unless can?(current_user, :create_snippet) + end +end diff --git a/app/controllers/concerns/snippets_actions.rb b/app/controllers/concerns/snippets_actions.rb index e78723bdda2..51fc12398d9 100644 --- a/app/controllers/concerns/snippets_actions.rb +++ b/app/controllers/concerns/snippets_actions.rb @@ -3,9 +3,18 @@ module SnippetsActions extend ActiveSupport::Concern include SendsBlob + include RendersNotes + include RendersBlob + include PaginatedCollection + include Gitlab::NoteableMetadata included do + skip_before_action :verify_authenticity_token, + if: -> { action_name == 'show' && js_request? } + before_action :redirect_if_binary, only: [:edit, :update] + + respond_to :html end def edit @@ -43,6 +52,58 @@ module SnippetsActions request.format.js? end + # rubocop:disable Gitlab/ModuleWithInstanceVariables + def show + conditionally_expand_blob(blob) + + respond_to do |format| + format.html do + @note = Note.new(noteable: @snippet, project: @snippet.project) + @noteable = @snippet + + @discussions = @snippet.discussions + @notes = prepare_notes_for_rendering(@discussions.flat_map(&:notes), @noteable) + render 'show' + end + + format.json do + render_blob_json(blob) + end + + format.js do + if @snippet.embeddable? + render 'shared/snippets/show' + else + head :not_found + end + end + end + end + + def update + update_params = snippet_params.merge(spammable_params) + + service_response = Snippets::UpdateService.new(@snippet.project, current_user, update_params).execute(@snippet) + @snippet = service_response.payload[:snippet] + + handle_repository_error(:edit) + end + + def destroy + service_response = Snippets::DestroyService.new(current_user, @snippet).execute + + if service_response.success? + redirect_to gitlab_dashboard_snippets_path(@snippet), status: :found + elsif service_response.http_status == 403 + access_denied! + else + redirect_to gitlab_snippet_path(@snippet), + status: :found, + alert: service_response.message + end + end + # rubocop:enable Gitlab/ModuleWithInstanceVariables + private def content_disposition diff --git a/app/controllers/concerns/wiki_actions.rb b/app/controllers/concerns/wiki_actions.rb new file mode 100644 index 00000000000..b4b4fd84c37 --- /dev/null +++ b/app/controllers/concerns/wiki_actions.rb @@ -0,0 +1,232 @@ +# frozen_string_literal: true + +module WikiActions + include SendsBlob + include Gitlab::Utils::StrongMemoize + extend ActiveSupport::Concern + + included do + before_action :authorize_read_wiki! + before_action :authorize_create_wiki!, only: [:edit, :create] + before_action :authorize_admin_wiki!, only: :destroy + + before_action :wiki + before_action :page, only: [:show, :edit, :update, :history, :destroy] + before_action :load_sidebar, except: [:pages] + + before_action only: [:show, :edit, :update] do + @valid_encoding = valid_encoding? + end + + before_action only: [:edit, :update], unless: :valid_encoding? do + redirect_to wiki_page_path(wiki, page) + end + end + + def new + redirect_to wiki_page_path(wiki, SecureRandom.uuid, random_title: true) + end + + # rubocop:disable Gitlab/ModuleWithInstanceVariables + def pages + @wiki_pages = Kaminari.paginate_array( + wiki.list_pages(sort: params[:sort], direction: params[:direction]) + ).page(params[:page]) + + @wiki_entries = WikiPage.group_by_directory(@wiki_pages) + + render 'shared/wikis/pages' + end + # rubocop:enable Gitlab/ModuleWithInstanceVariables + + # `#show` handles a number of scenarios: + # + # - If `id` matches a WikiPage, then show the wiki page. + # - If `id` is a file in the wiki repository, then send the file. + # - If we know the user wants to create a new page with the given `id`, + # then display a create form. + # - Otherwise show the empty wiki page and invite the user to create a page. + # + # rubocop:disable Gitlab/ModuleWithInstanceVariables + def show + if page + set_encoding_error unless valid_encoding? + + # Assign vars expected by MarkupHelper + @ref = params[:version_id] + @path = page.path + + render 'shared/wikis/show' + elsif file_blob + send_blob(wiki.repository, file_blob, allow_caching: container.public?) + elsif show_create_form? + # Assign a title to the WikiPage unless `id` is a randomly generated slug from #new + title = params[:id] unless params[:random_title].present? + + @page = build_page(title: title) + + render 'shared/wikis/edit' + else + render 'shared/wikis/empty' + end + end + # rubocop:enable Gitlab/ModuleWithInstanceVariables + + def edit + render 'shared/wikis/edit' + end + + # rubocop:disable Gitlab/ModuleWithInstanceVariables + def update + return render('shared/wikis/empty') unless can?(current_user, :create_wiki, container) + + @page = WikiPages::UpdateService.new(container: container, current_user: current_user, params: wiki_params).execute(page) + + if page.valid? + redirect_to( + wiki_page_path(wiki, page), + notice: _('Wiki was successfully updated.') + ) + else + render 'shared/wikis/edit' + end + rescue WikiPage::PageChangedError, WikiPage::PageRenameError, Gitlab::Git::Wiki::OperationError => e + @error = e + render 'shared/wikis/edit' + end + # rubocop:enable Gitlab/ModuleWithInstanceVariables + + # rubocop:disable Gitlab/ModuleWithInstanceVariables + def create + @page = WikiPages::CreateService.new(container: container, current_user: current_user, params: wiki_params).execute + + if page.persisted? + redirect_to( + wiki_page_path(wiki, page), + notice: _('Wiki was successfully updated.') + ) + else + render 'shared/wikis/edit' + end + rescue Gitlab::Git::Wiki::OperationError => e + @page = build_page(wiki_params) + @error = e + render 'shared/wikis/edit' + end + # rubocop:enable Gitlab/ModuleWithInstanceVariables + + # rubocop:disable Gitlab/ModuleWithInstanceVariables + def history + if page + @page_versions = Kaminari.paginate_array(page.versions(page: params[:page].to_i), + total_count: page.count_versions) + .page(params[:page]) + + render 'shared/wikis/history' + else + redirect_to( + wiki_path(wiki), + notice: _("Page not found") + ) + end + end + # rubocop:enable Gitlab/ModuleWithInstanceVariables + + # rubocop:disable Gitlab/ModuleWithInstanceVariables + def destroy + WikiPages::DestroyService.new(container: container, current_user: current_user).execute(page) + + redirect_to wiki_path(wiki), + status: :found, + notice: _("Page was successfully deleted") + rescue Gitlab::Git::Wiki::OperationError => e + @error = e + render 'shared/wikis/edit' + end + # rubocop:enable Gitlab/ModuleWithInstanceVariables + + private + + def container + raise NotImplementedError + end + + def show_create_form? + can?(current_user, :create_wiki, container) && + page.nil? && + # Always show the create form when the wiki has had at least one page created. + # Otherwise, we only show the form when the user has navigated from + # the 'empty wiki' page + (wiki.exists? || params[:view] == 'create') + end + + def wiki + strong_memoize(:wiki) do + wiki = Wiki.for_container(container, current_user) + + # Call #wiki to make sure the Wiki Repo is initialized + wiki.wiki + + wiki + end + rescue Wiki::CouldNotCreateWikiError + flash[:notice] = _("Could not create Wiki Repository at this time. Please try again later.") + redirect_to container + false + end + + def page + strong_memoize(:page) do + wiki.find_page(*page_params) + end + end + + # rubocop:disable Gitlab/ModuleWithInstanceVariables + def load_sidebar + @sidebar_page = wiki.find_sidebar(params[:version_id]) + + unless @sidebar_page # Fallback to default sidebar + @sidebar_wiki_entries, @sidebar_limited = wiki.sidebar_entries + end + end + # rubocop:enable Gitlab/ModuleWithInstanceVariables + + def wiki_params + params.require(:wiki).permit(:title, :content, :format, :message, :last_commit_sha) + end + + def build_page(args = {}) + WikiPage.new(wiki).tap do |page| + page.update_attributes(args) # rubocop:disable Rails/ActiveRecordAliases + end + end + + def page_params + keys = [:id] + keys << :version_id if params[:action] == 'show' + + params.values_at(*keys) + end + + def valid_encoding? + page_encoding == Encoding::UTF_8 + end + + def page_encoding + strong_memoize(:page_encoding) { page&.content&.encoding } + end + + def set_encoding_error + flash.now[:notice] = _("The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository.") + end + + def file_blob + strong_memoize(:file_blob) do + commit = wiki.repository.commit(wiki.default_branch) + + next unless commit + + wiki.repository.blob_at(commit.id, params[:id]) + end + end +end diff --git a/app/controllers/concerns/workhorse_import_export_upload.rb b/app/controllers/concerns/workhorse_import_export_upload.rb new file mode 100644 index 00000000000..3c52f4d7adf --- /dev/null +++ b/app/controllers/concerns/workhorse_import_export_upload.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module WorkhorseImportExportUpload + extend ActiveSupport::Concern + include WorkhorseRequest + + included do + skip_before_action :verify_authenticity_token, only: %i[authorize] + before_action :verify_workhorse_api!, only: %i[authorize] + end + + def authorize + set_workhorse_internal_api_content_type + + authorized = ImportExportUploader.workhorse_authorize( + has_length: false, + maximum_size: Gitlab::CurrentSettings.max_import_size.megabytes + ) + + render json: authorized + rescue SocketError + render json: _("Error uploading file"), status: :internal_server_error + end + + private + + def file_is_valid?(file) + return false unless file.is_a?(::UploadedFile) + + ImportExportUploader::EXTENSION_WHITELIST + .include?(File.extname(file.original_filename).delete('.')) + end +end |