Commit eb8e92c9 authored by Vijay Hawoldar's avatar Vijay Hawoldar

Fix error when editing Snippets with image blob

Views do not currently support binary blob
data and thus will throw an error. This change
will redirect the user if they try to edit or update
a snippet with binary data.
parent bd187a56
...@@ -3,6 +3,10 @@ ...@@ -3,6 +3,10 @@
module SnippetsActions module SnippetsActions
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do
before_action :redirect_if_binary, only: [:edit, :update]
end
def edit def edit
# We need to load some info from the existing blob # We need to load some info from the existing blob
snippet.content = blob.data snippet.content = blob.data
...@@ -52,4 +56,8 @@ module SnippetsActions ...@@ -52,4 +56,8 @@ module SnippetsActions
flash.now[:alert] = repository_errors.first if repository_errors.present? flash.now[:alert] = repository_errors.first if repository_errors.present?
recaptcha_check_with_fallback(repository_errors.empty?) { render :edit } recaptcha_check_with_fallback(repository_errors.empty?) { render :edit }
end end
def redirect_if_binary
redirect_to gitlab_snippet_path(snippet) if blob&.binary?
end
end end
---
title: Resolve Snippet actions with binary data
merge_request: 28191
author:
type: fixed
...@@ -116,7 +116,7 @@ describe Projects::SnippetsController do ...@@ -116,7 +116,7 @@ describe Projects::SnippetsController do
end end
context 'when the snippet is public' do context 'when the snippet is public' do
it 'rejects the shippet' do it 'rejects the snippet' do
expect { create_snippet(project, visibility_level: Snippet::PUBLIC) } expect { create_snippet(project, visibility_level: Snippet::PUBLIC) }
.not_to change { Snippet.count } .not_to change { Snippet.count }
expect(response).to render_template(:new) expect(response).to render_template(:new)
...@@ -164,6 +164,7 @@ describe Projects::SnippetsController do ...@@ -164,6 +164,7 @@ describe Projects::SnippetsController do
describe 'PUT #update' do describe 'PUT #update' do
let(:project) { create :project, :public } let(:project) { create :project, :public }
let(:visibility_level) { Snippet::PUBLIC }
let(:snippet) { create :project_snippet, author: user, project: project, visibility_level: visibility_level } let(:snippet) { create :project_snippet, author: user, project: project, visibility_level: visibility_level }
def update_snippet(snippet_params = {}, additional_params = {}) def update_snippet(snippet_params = {}, additional_params = {})
...@@ -174,13 +175,27 @@ describe Projects::SnippetsController do ...@@ -174,13 +175,27 @@ describe Projects::SnippetsController do
put :update, params: { put :update, params: {
namespace_id: project.namespace.to_param, namespace_id: project.namespace.to_param,
project_id: project, project_id: project,
id: snippet.id, id: snippet,
project_snippet: { title: 'Title', content: 'Content' }.merge(snippet_params) project_snippet: { title: 'Title', content: 'Content' }.merge(snippet_params)
}.merge(additional_params) }.merge(additional_params)
snippet.reload snippet.reload
end end
it_behaves_like 'updating snippet checks blob is binary' do
let_it_be(:title) { 'Foo' }
let(:params) do
{
namespace_id: project.namespace.to_param,
project_id: project,
id: snippet.id,
project_snippet: { title: title }
}
end
subject { put :update, params: params }
end
context 'when the snippet is spam' do context 'when the snippet is spam' do
before do before do
allow_next_instance_of(Spam::AkismetService) do |instance| allow_next_instance_of(Spam::AkismetService) do |instance|
...@@ -198,9 +213,7 @@ describe Projects::SnippetsController do ...@@ -198,9 +213,7 @@ describe Projects::SnippetsController do
end end
context 'when the snippet is public' do context 'when the snippet is public' do
let(:visibility_level) { Snippet::PUBLIC } it 'rejects the snippet' do
it 'rejects the shippet' do
expect { update_snippet(title: 'Foo') } expect { update_snippet(title: 'Foo') }
.not_to change { snippet.reload.title } .not_to change { snippet.reload.title }
end end
...@@ -245,7 +258,7 @@ describe Projects::SnippetsController do ...@@ -245,7 +258,7 @@ describe Projects::SnippetsController do
context 'when the private snippet is made public' do context 'when the private snippet is made public' do
let(:visibility_level) { Snippet::PRIVATE } let(:visibility_level) { Snippet::PRIVATE }
it 'rejects the shippet' do it 'rejects the snippet' do
expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) } expect { update_snippet(title: 'Foo', visibility_level: Snippet::PUBLIC) }
.not_to change { snippet.reload.title } .not_to change { snippet.reload.title }
end end
...@@ -549,4 +562,19 @@ describe Projects::SnippetsController do ...@@ -549,4 +562,19 @@ describe Projects::SnippetsController do
end end
end end
end end
describe 'GET #edit' do
it_behaves_like 'editing snippet checks blob is binary' do
let(:snippet) { create(:project_snippet, :private, project: project, author: user) }
let(:params) do
{
namespace_id: project.namespace,
project_id: project,
id: snippet
}
end
subject { get :edit, params: params }
end
end
end end
...@@ -308,7 +308,7 @@ describe SnippetsController do ...@@ -308,7 +308,7 @@ describe SnippetsController do
end end
context 'when the snippet is public' do context 'when the snippet is public' do
it 'rejects the shippet' do it 'rejects the snippet' do
expect { create_snippet(visibility_level: Snippet::PUBLIC) } expect { create_snippet(visibility_level: Snippet::PUBLIC) }
.not_to change { Snippet.count } .not_to change { Snippet.count }
end end
...@@ -354,6 +354,7 @@ describe SnippetsController do ...@@ -354,6 +354,7 @@ describe SnippetsController do
describe 'PUT #update' do describe 'PUT #update' do
let(:project) { create :project } let(:project) { create :project }
let(:visibility_level) { Snippet::PUBLIC }
let(:snippet) { create :personal_snippet, author: user, project: project, visibility_level: visibility_level } let(:snippet) { create :personal_snippet, author: user, project: project, visibility_level: visibility_level }
def update_snippet(snippet_params = {}, additional_params = {}) def update_snippet(snippet_params = {}, additional_params = {})
...@@ -367,6 +368,12 @@ describe SnippetsController do ...@@ -367,6 +368,12 @@ describe SnippetsController do
snippet.reload snippet.reload
end end
it_behaves_like 'updating snippet checks blob is binary' do
let_it_be(:title) { 'Foo' }
subject { put :update, params: { id: snippet, personal_snippet: { title: title } } }
end
context 'when the snippet is spam' do context 'when the snippet is spam' do
before do before do
allow_next_instance_of(Spam::AkismetService) do |instance| allow_next_instance_of(Spam::AkismetService) do |instance|
...@@ -429,9 +436,7 @@ describe SnippetsController do ...@@ -429,9 +436,7 @@ describe SnippetsController do
end end
context 'when the snippet is public' do context 'when the snippet is public' do
let(:visibility_level) { Snippet::PUBLIC } it 'rejects the snippet' do
it 'rejects the shippet' do
expect { update_snippet(title: 'Foo') } expect { update_snippet(title: 'Foo') }
.not_to change { snippet.reload.title } .not_to change { snippet.reload.title }
end end
...@@ -779,4 +784,12 @@ describe SnippetsController do ...@@ -779,4 +784,12 @@ describe SnippetsController do
end end
end end
end end
describe 'GET #edit' do
it_behaves_like 'editing snippet checks blob is binary' do
let_it_be(:snippet) { create(:personal_snippet, :public, :repository, author: user) }
subject { get :edit, params: { id: snippet } }
end
end
end end
# frozen_string_literal: true
RSpec.shared_examples 'editing snippet checks blob is binary' do
before do
sign_in(user)
allow_next_instance_of(Blob) do |blob|
allow(blob).to receive(:binary?).and_return(binary)
end
subject
end
context 'when blob is text' do
let(:binary) { false }
it 'responds with status 200' do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template(:edit)
end
end
context 'when blob is binary' do
let(:binary) { true }
it 'redirects away' do
expect(response).to redirect_to(gitlab_snippet_path(snippet))
end
end
end
RSpec.shared_examples 'updating snippet checks blob is binary' do
before do
sign_in(user)
allow_next_instance_of(Blob) do |blob|
allow(blob).to receive(:binary?).and_return(binary)
end
subject
end
context 'when blob is text' do
let(:binary) { false }
it 'updates successfully' do
expect(snippet.reload.title).to eq title
expect(response).to redirect_to(gitlab_snippet_path(snippet))
end
end
context 'when blob is binary' do
let(:binary) { true }
it 'redirects away without updating' do
expect(response).to redirect_to(gitlab_snippet_path(snippet))
expect(snippet.reload.title).not_to eq title
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment