summaryrefslogtreecommitdiff
path: root/app/controllers/concerns/snippets_actions.rb
blob: 5552fd663f7b17fd67eb9fc25b9c942a62e01886 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# frozen_string_literal: true

module SnippetsActions
  extend ActiveSupport::Concern

  include RendersNotes
  include RendersBlob
  include PaginatedCollection
  include Gitlab::NoteableMetadata
  include Snippets::SendBlob
  include SnippetsSort

  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
    # We need to load some info from the existing blob
    snippet.content = blob.data
    snippet.file_name = blob.path

    render 'edit'
  end

  # This endpoint is being replaced by Snippets::BlobController#raw
  # Support for old raw links will be maintainted via this action but
  # it will only return the first blob found,
  # see: https://gitlab.com/gitlab-org/gitlab/-/issues/217775
  def raw
    workhorse_set_content_type!

    # Until we don't migrate all snippets to version
    # snippets we need to support old `SnippetBlob`
    # blobs
    if defined?(blob.snippet)
      send_data(
        convert_line_endings(blob.data),
        type: 'text/plain; charset=utf-8',
        disposition: content_disposition,
        filename: Snippet.sanitized_file_name(blob.name)
      )
    else
      send_snippet_blob(snippet, blob)
    end
  end

  def js_request?
    request.format.js?
  end

  # rubocop:disable Gitlab/ModuleWithInstanceVariables
  def show
    respond_to do |format|
      format.html do
        conditionally_expand_blob(blob)
        @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
        conditionally_expand_blob(blob)
        render_blob_json(blob)
      end

      format.js do
        if @snippet.embeddable?
          conditionally_expand_blobs(blobs)

          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

  # rubocop:disable Gitlab/ModuleWithInstanceVariables
  def blob
    @blob ||= blobs.first
  end

  def blobs
    @blobs ||= if snippet.empty_repo?
                 [snippet.blob]
               else
                 snippet.blobs
               end
  end
  # rubocop:enable Gitlab/ModuleWithInstanceVariables

  def convert_line_endings(content)
    params[:line_ending] == 'raw' ? content : content.gsub(/\r\n/, "\n")
  end

  def handle_repository_error(action)
    errors = Array(snippet.errors.delete(:repository))

    flash.now[:alert] = errors.first if errors.present?

    recaptcha_check_with_fallback(errors.empty?) { render action }
  end

  def redirect_if_binary
    return if Feature.enabled?(:snippets_binary_blob)

    redirect_to gitlab_snippet_path(snippet) if blob&.binary?
  end
end