Commit 4621fa2b authored by Sean McGivern's avatar Sean McGivern Committed by Lin Jen-Shin

Merge branch 'snippets_visibility' into 'security'

Fix snippets visibility for show action - external users can not see internal snippets

See merge request !2087
parent ecbd9da8
...@@ -90,20 +90,20 @@ class SnippetsController < ApplicationController ...@@ -90,20 +90,20 @@ class SnippetsController < ApplicationController
protected protected
def snippet def snippet
@snippet ||= if current_user @snippet ||= PersonalSnippet.find_by(id: params[:id])
PersonalSnippet.where("author_id = ? OR visibility_level IN (?)",
current_user.id,
[Snippet::PUBLIC, Snippet::INTERNAL]).
find(params[:id])
else
PersonalSnippet.find(params[:id])
end
end end
alias_method :awardable, :snippet alias_method :awardable, :snippet
alias_method :spammable, :snippet alias_method :spammable, :snippet
def authorize_read_snippet! def authorize_read_snippet!
authenticate_user! unless can?(current_user, :read_personal_snippet, @snippet) return if can?(current_user, :read_personal_snippet, @snippet)
if current_user
render_404
else
authenticate_user!
end
end end
def authorize_update_snippet! def authorize_update_snippet!
......
---
title: Fix snippets visibility for show action - external users can not see internal snippets
merge_request:
author:
...@@ -25,119 +25,6 @@ describe SnippetsController do ...@@ -25,119 +25,6 @@ describe SnippetsController do
end end
end end
describe 'GET #show' do
context 'when the personal snippet is private' do
let(:personal_snippet) { create(:personal_snippet, :private, author: user) }
context 'when signed in' do
before do
sign_in(user)
end
context 'when signed in user is not the author' do
let(:other_author) { create(:author) }
let(:other_personal_snippet) { create(:personal_snippet, :private, author: other_author) }
it 'responds with status 404' do
get :show, id: other_personal_snippet.to_param
expect(response).to have_http_status(404)
end
end
context 'when signed in user is the author' do
it 'renders the snippet' do
get :show, id: personal_snippet.to_param
expect(assigns(:snippet)).to eq(personal_snippet)
expect(response).to have_http_status(200)
end
end
end
context 'when not signed in' do
it 'redirects to the sign in page' do
get :show, id: personal_snippet.to_param
expect(response).to redirect_to(new_user_session_path)
end
end
end
context 'when the personal snippet is internal' do
let(:personal_snippet) { create(:personal_snippet, :internal, author: user) }
context 'when signed in' do
before do
sign_in(user)
end
it 'renders the snippet' do
get :show, id: personal_snippet.to_param
expect(assigns(:snippet)).to eq(personal_snippet)
expect(response).to have_http_status(200)
end
end
context 'when not signed in' do
it 'redirects to the sign in page' do
get :show, id: personal_snippet.to_param
expect(response).to redirect_to(new_user_session_path)
end
end
end
context 'when the personal snippet is public' do
let(:personal_snippet) { create(:personal_snippet, :public, author: user) }
context 'when signed in' do
before do
sign_in(user)
end
it 'renders the snippet' do
get :show, id: personal_snippet.to_param
expect(assigns(:snippet)).to eq(personal_snippet)
expect(response).to have_http_status(200)
end
end
context 'when not signed in' do
it 'renders the snippet' do
get :show, id: personal_snippet.to_param
expect(assigns(:snippet)).to eq(personal_snippet)
expect(response).to have_http_status(200)
end
end
end
context 'when the personal snippet does not exist' do
context 'when signed in' do
before do
sign_in(user)
end
it 'responds with status 404' do
get :show, id: 'doesntexist'
expect(response).to have_http_status(404)
end
end
context 'when not signed in' do
it 'responds with status 404' do
get :show, id: 'doesntexist'
expect(response).to have_http_status(404)
end
end
end
end
describe 'POST #create' do describe 'POST #create' do
def create_snippet(snippet_params = {}, additional_params = {}) def create_snippet(snippet_params = {}, additional_params = {})
sign_in(user) sign_in(user)
...@@ -350,8 +237,27 @@ describe SnippetsController do ...@@ -350,8 +237,27 @@ describe SnippetsController do
end end
end end
%w(raw download).each do |action| shared_examples "line endings" do |action|
describe "GET #{action}" do context 'CRLF line ending' do
let(:personal_snippet) do
create(:personal_snippet, :public, author: user, content: "first line\r\nsecond line\r\nthird line")
end
it 'returns LF line endings by default' do
get action, id: personal_snippet.to_param
expect(response.body).to eq("first line\nsecond line\nthird line")
end
it 'does not convert line endings when parameter present' do
get action, id: personal_snippet.to_param, line_ending: :raw
expect(response.body).to eq("first line\r\nsecond line\r\nthird line")
end
end
end
shared_examples 'snippet response' do |action|
context 'when the personal snippet is private' do context 'when the personal snippet is private' do
let(:personal_snippet) { create(:personal_snippet, :private, author: user) } let(:personal_snippet) { create(:personal_snippet, :private, author: user) }
...@@ -380,7 +286,11 @@ describe SnippetsController do ...@@ -380,7 +286,11 @@ describe SnippetsController do
end end
it 'has expected headers' do it 'has expected headers' do
if action == :show
expect(response.header['Content-Type']).to eq('text/html; charset=utf-8')
else
expect(response.header['Content-Type']).to eq('text/plain; charset=utf-8') expect(response.header['Content-Type']).to eq('text/plain; charset=utf-8')
end
if action == :download if action == :download
expect(response.header['Content-Disposition']).to match(/attachment/) expect(response.header['Content-Disposition']).to match(/attachment/)
...@@ -423,6 +333,20 @@ describe SnippetsController do ...@@ -423,6 +333,20 @@ describe SnippetsController do
expect(response).to redirect_to(new_user_session_path) expect(response).to redirect_to(new_user_session_path)
end end
end end
context 'when signed in as an external user' do
let(:external_user) { create(:user, external: true) }
before do
sign_in(external_user)
end
it 'responds with status 404' do
get :show, id: personal_snippet.to_param
expect(response).to have_http_status(404)
end
end
end end
context 'when the personal snippet is public' do context 'when the personal snippet is public' do
...@@ -465,14 +389,27 @@ describe SnippetsController do ...@@ -465,14 +389,27 @@ describe SnippetsController do
end end
context 'when not signed in' do context 'when not signed in' do
it 'responds with status 404' do it 'redirects to the sign in page' do
get action, id: 'doesntexist' get action, id: 'doesntexist'
expect(response).to have_http_status(404) expect(response).to redirect_to(new_user_session_path)
end
end end
end end
end end
describe "GET #raw" do
include_examples 'line endings', :raw
include_examples 'snippet response', :raw
end
describe "GET #download" do
include_examples 'line endings', :download
include_examples 'snippet response', :download
end end
describe "GET #show" do
include_examples 'snippet response', :show
end end
context 'award emoji on snippets' do context 'award emoji on snippets' do
......
require 'rails_helper'
feature 'Internal Snippets', feature: true do
let(:internal_snippet) { create(:personal_snippet, :internal) }
describe 'normal user' do
before do
login_as :user
end
scenario 'sees internal snippets' do
visit snippet_path(internal_snippet)
expect(page).to have_content(internal_snippet.content)
end
scenario 'sees raw internal snippets' do
visit raw_snippet_path(internal_snippet)
expect(page).to have_content(internal_snippet.content)
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