Merge branch 'snippets-finder-visibility' into 'security'
Refactor snippets finder & dont return internal snippets for external users See merge request !2094
This commit is contained in:
parent
576e244b6c
commit
ad309f5d11
23 changed files with 399 additions and 184 deletions
|
@ -1,11 +1,10 @@
|
|||
class Dashboard::SnippetsController < Dashboard::ApplicationController
|
||||
def index
|
||||
@snippets = SnippetsFinder.new.execute(
|
||||
@snippets = SnippetsFinder.new(
|
||||
current_user,
|
||||
filter: :by_user,
|
||||
user: current_user,
|
||||
author: current_user,
|
||||
scope: params[:scope]
|
||||
)
|
||||
).execute
|
||||
@snippets = @snippets.page(params[:page])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class Explore::SnippetsController < Explore::ApplicationController
|
||||
def index
|
||||
@snippets = SnippetsFinder.new.execute(current_user, filter: :all)
|
||||
@snippets = SnippetsFinder.new(current_user).execute
|
||||
@snippets = @snippets.page(params[:page])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -23,12 +23,11 @@ class Projects::SnippetsController < Projects::ApplicationController
|
|||
respond_to :html
|
||||
|
||||
def index
|
||||
@snippets = SnippetsFinder.new.execute(
|
||||
@snippets = SnippetsFinder.new(
|
||||
current_user,
|
||||
filter: :by_project,
|
||||
project: @project,
|
||||
scope: params[:scope]
|
||||
)
|
||||
).execute
|
||||
@snippets = @snippets.page(params[:page])
|
||||
if @snippets.out_of_range? && @snippets.total_pages != 0
|
||||
redirect_to namespace_project_snippets_path(page: @snippets.total_pages)
|
||||
|
|
|
@ -27,12 +27,8 @@ class SnippetsController < ApplicationController
|
|||
|
||||
return render_404 unless @user
|
||||
|
||||
@snippets = SnippetsFinder.new.execute(current_user, {
|
||||
filter: :by_user,
|
||||
user: @user,
|
||||
scope: params[:scope]
|
||||
})
|
||||
.page(params[:page])
|
||||
@snippets = SnippetsFinder.new(current_user, author: @user, scope: params[:scope])
|
||||
.execute.page(params[:page])
|
||||
|
||||
render 'index'
|
||||
else
|
||||
|
|
|
@ -128,12 +128,11 @@ class UsersController < ApplicationController
|
|||
end
|
||||
|
||||
def load_snippets
|
||||
@snippets = SnippetsFinder.new.execute(
|
||||
@snippets = SnippetsFinder.new(
|
||||
current_user,
|
||||
filter: :by_user,
|
||||
user: user,
|
||||
author: user,
|
||||
scope: params[:scope]
|
||||
).page(params[:page])
|
||||
).execute.page(params[:page])
|
||||
end
|
||||
|
||||
def projects_for_current_user
|
||||
|
|
|
@ -67,7 +67,7 @@ class NotesFinder
|
|||
when "merge_request"
|
||||
MergeRequestsFinder.new(@current_user, project_id: @project.id).execute
|
||||
when "snippet", "project_snippet"
|
||||
SnippetsFinder.new.execute(@current_user, filter: :by_project, project: @project)
|
||||
SnippetsFinder.new(@current_user, project: @project).execute
|
||||
when "personal_snippet"
|
||||
PersonalSnippet.all
|
||||
else
|
||||
|
|
|
@ -1,66 +1,74 @@
|
|||
class SnippetsFinder
|
||||
def execute(current_user, params = {})
|
||||
filter = params[:filter]
|
||||
user = params.fetch(:user, current_user)
|
||||
class SnippetsFinder < UnionFinder
|
||||
attr_accessor :current_user, :params
|
||||
|
||||
case filter
|
||||
when :all then
|
||||
snippets(current_user).fresh
|
||||
when :public then
|
||||
Snippet.are_public.fresh
|
||||
when :by_user then
|
||||
by_user(current_user, user, params[:scope])
|
||||
when :by_project
|
||||
by_project(current_user, params[:project], params[:scope])
|
||||
end
|
||||
def initialize(current_user, params = {})
|
||||
@current_user = current_user
|
||||
@params = params
|
||||
end
|
||||
|
||||
def execute
|
||||
items = init_collection
|
||||
items = by_project(items)
|
||||
items = by_author(items)
|
||||
items = by_visibility(items)
|
||||
|
||||
items.fresh
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def snippets(current_user)
|
||||
if current_user
|
||||
Snippet.public_and_internal
|
||||
else
|
||||
# Not authenticated
|
||||
#
|
||||
# Return only:
|
||||
# public snippets
|
||||
Snippet.are_public
|
||||
end
|
||||
def init_collection
|
||||
items = Snippet.all
|
||||
|
||||
accessible(items)
|
||||
end
|
||||
|
||||
def by_user(current_user, user, scope)
|
||||
snippets = user.snippets.fresh
|
||||
def accessible(items)
|
||||
segments = []
|
||||
segments << items.public_to_user(current_user)
|
||||
segments << authorized_to_user(items) if current_user
|
||||
|
||||
if current_user
|
||||
include_private = user == current_user
|
||||
by_scope(snippets, scope, include_private)
|
||||
else
|
||||
snippets.are_public
|
||||
end
|
||||
find_union(segments, Snippet)
|
||||
end
|
||||
|
||||
def by_project(current_user, project, scope)
|
||||
snippets = project.snippets.fresh
|
||||
|
||||
if current_user
|
||||
include_private = project.team.member?(current_user) || current_user.admin?
|
||||
by_scope(snippets, scope, include_private)
|
||||
else
|
||||
snippets.are_public
|
||||
end
|
||||
def authorized_to_user(items)
|
||||
items.where(
|
||||
'author_id = :author_id
|
||||
OR project_id IN (:project_ids)',
|
||||
author_id: current_user.id,
|
||||
project_ids: current_user.authorized_projects.select(:id))
|
||||
end
|
||||
|
||||
def by_scope(snippets, scope = nil, include_private = false)
|
||||
case scope.to_s
|
||||
def by_visibility(items)
|
||||
visibility = params[:visibility] || visibility_from_scope
|
||||
|
||||
return items unless visibility
|
||||
|
||||
items.where(visibility_level: visibility)
|
||||
end
|
||||
|
||||
def by_author(items)
|
||||
return items unless params[:author]
|
||||
|
||||
items.where(author_id: params[:author].id)
|
||||
end
|
||||
|
||||
def by_project(items)
|
||||
return items unless params[:project]
|
||||
|
||||
items.where(project_id: params[:project].id)
|
||||
end
|
||||
|
||||
def visibility_from_scope
|
||||
case params[:scope].to_s
|
||||
when 'are_private'
|
||||
include_private ? snippets.are_private : Snippet.none
|
||||
Snippet::PRIVATE
|
||||
when 'are_internal'
|
||||
snippets.are_internal
|
||||
Snippet::INTERNAL
|
||||
when 'are_public'
|
||||
snippets.are_public
|
||||
Snippet::PUBLIC
|
||||
else
|
||||
include_private ? snippets : snippets.public_and_internal
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -152,18 +152,5 @@ class Snippet < ActiveRecord::Base
|
|||
|
||||
where(table[:content].matches(pattern))
|
||||
end
|
||||
|
||||
def accessible_to(user)
|
||||
return are_public unless user.present?
|
||||
return all if user.admin?
|
||||
|
||||
where(
|
||||
'visibility_level IN (:visibility_levels)
|
||||
OR author_id = :author_id
|
||||
OR project_id IN (:project_ids)',
|
||||
visibility_levels: [Snippet::PUBLIC, Snippet::INTERNAL],
|
||||
author_id: user.id,
|
||||
project_ids: user.authorized_projects.select(:id))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,7 +13,7 @@ class ProjectSnippetPolicy < BasePolicy
|
|||
can! :read_project_snippet
|
||||
end
|
||||
|
||||
if @subject.private? && @subject.project.team.member?(@user)
|
||||
if @subject.project.team.member?(@user)
|
||||
can! :read_project_snippet
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,7 +7,7 @@ module Search
|
|||
end
|
||||
|
||||
def execute
|
||||
snippets = Snippet.accessible_to(current_user)
|
||||
snippets = SnippetsFinder.new(current_user).execute
|
||||
|
||||
Gitlab::SnippetSearchResults.new(snippets, params[:search])
|
||||
end
|
||||
|
|
4
changelogs/unreleased/snippets-finder-visibility.yml
Normal file
4
changelogs/unreleased/snippets-finder-visibility.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Refactor snippets finder & dont return internal snippets for external users
|
||||
merge_request:
|
||||
author:
|
|
@ -17,8 +17,7 @@ module API
|
|||
end
|
||||
|
||||
def snippets_for_current_user
|
||||
finder_params = { filter: :by_project, project: user_project }
|
||||
SnippetsFinder.new.execute(current_user, finder_params)
|
||||
SnippetsFinder.new(current_user, project: user_project).execute
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -8,11 +8,11 @@ module API
|
|||
resource :snippets do
|
||||
helpers do
|
||||
def snippets_for_current_user
|
||||
SnippetsFinder.new.execute(current_user, filter: :by_user, user: current_user)
|
||||
SnippetsFinder.new(current_user, author: current_user).execute
|
||||
end
|
||||
|
||||
def public_snippets
|
||||
SnippetsFinder.new.execute(current_user, filter: :public)
|
||||
SnippetsFinder.new(current_user, visibility: Snippet::PUBLIC).execute
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -18,8 +18,7 @@ module API
|
|||
end
|
||||
|
||||
def snippets_for_current_user
|
||||
finder_params = { filter: :by_project, project: user_project }
|
||||
SnippetsFinder.new.execute(current_user, finder_params)
|
||||
SnippetsFinder.new(current_user, project: user_project).execute
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -8,11 +8,11 @@ module API
|
|||
resource :snippets do
|
||||
helpers do
|
||||
def snippets_for_current_user
|
||||
SnippetsFinder.new.execute(current_user, filter: :by_user, user: current_user)
|
||||
SnippetsFinder.new(current_user, author: current_user).execute
|
||||
end
|
||||
|
||||
def public_snippets
|
||||
SnippetsFinder.new.execute(current_user, filter: :public)
|
||||
SnippetsFinder.new(current_user, visibility: Snippet::PUBLIC).execute
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -3,6 +3,34 @@ require 'spec_helper'
|
|||
describe SnippetsController do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
describe 'GET #index' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
context 'when username parameter is present' do
|
||||
it 'renders snippets of a user when username is present' do
|
||||
get :index, username: user.username
|
||||
|
||||
expect(response).to render_template(:index)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when username parameter is not present' do
|
||||
it 'redirects to explore snippets page when user is not logged in' do
|
||||
get :index
|
||||
|
||||
expect(response).to redirect_to(explore_snippets_path)
|
||||
end
|
||||
|
||||
it 'redirects to snippets dashboard page when user is logged in' do
|
||||
sign_in(user)
|
||||
|
||||
get :index
|
||||
|
||||
expect(response).to redirect_to(dashboard_snippets_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #new' do
|
||||
context 'when signed in' do
|
||||
before do
|
||||
|
|
|
@ -12,4 +12,51 @@ describe 'Dashboard snippets', feature: true do
|
|||
|
||||
it_behaves_like 'paginated snippets'
|
||||
end
|
||||
|
||||
context 'filtering by visibility' do
|
||||
let(:user) { create(:user) }
|
||||
let!(:snippets) do
|
||||
[
|
||||
create(:personal_snippet, :public, author: user),
|
||||
create(:personal_snippet, :internal, author: user),
|
||||
create(:personal_snippet, :private, author: user),
|
||||
create(:personal_snippet, :public)
|
||||
]
|
||||
end
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
|
||||
visit dashboard_snippets_path
|
||||
end
|
||||
|
||||
it 'contains all snippets of logged user' do
|
||||
expect(page).to have_selector('.snippet-row', count: 3)
|
||||
|
||||
expect(page).to have_content(snippets[0].title)
|
||||
expect(page).to have_content(snippets[1].title)
|
||||
expect(page).to have_content(snippets[2].title)
|
||||
end
|
||||
|
||||
it 'contains all private snippets of logged user when clicking on private' do
|
||||
click_link('Private')
|
||||
|
||||
expect(page).to have_selector('.snippet-row', count: 1)
|
||||
expect(page).to have_content(snippets[2].title)
|
||||
end
|
||||
|
||||
it 'contains all internal snippets of logged user when clicking on internal' do
|
||||
click_link('Internal')
|
||||
|
||||
expect(page).to have_selector('.snippet-row', count: 1)
|
||||
expect(page).to have_content(snippets[1].title)
|
||||
end
|
||||
|
||||
it 'contains all public snippets of logged user when clicking on public' do
|
||||
click_link('Public')
|
||||
|
||||
expect(page).to have_selector('.snippet-row', count: 1)
|
||||
expect(page).to have_content(snippets[0].title)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,11 +4,27 @@ describe 'Project snippets', feature: true do
|
|||
context 'when the project has snippets' do
|
||||
let(:project) { create(:empty_project, :public) }
|
||||
let!(:snippets) { create_list(:project_snippet, 2, :public, author: project.owner, project: project) }
|
||||
before do
|
||||
allow(Snippet).to receive(:default_per_page).and_return(1)
|
||||
visit namespace_project_snippets_path(project.namespace, project)
|
||||
let!(:other_snippet) { create(:project_snippet) }
|
||||
|
||||
context 'pagination' do
|
||||
before do
|
||||
allow(Snippet).to receive(:default_per_page).and_return(1)
|
||||
|
||||
visit namespace_project_snippets_path(project.namespace, project)
|
||||
end
|
||||
|
||||
it_behaves_like 'paginated snippets'
|
||||
end
|
||||
|
||||
it_behaves_like 'paginated snippets'
|
||||
context 'list content' do
|
||||
it 'contains all project snippets' do
|
||||
visit namespace_project_snippets_path(project.namespace, project)
|
||||
|
||||
expect(page).to have_selector('.snippet-row', count: 2)
|
||||
|
||||
expect(page).to have_content(snippets[0].title)
|
||||
expect(page).to have_content(snippets[1].title)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
require 'rails_helper'
|
||||
|
||||
feature 'Explore Snippets', feature: true do
|
||||
scenario 'User should see snippets that are not private' do
|
||||
public_snippet = create(:personal_snippet, :public)
|
||||
internal_snippet = create(:personal_snippet, :internal)
|
||||
private_snippet = create(:personal_snippet, :private)
|
||||
let!(:public_snippet) { create(:personal_snippet, :public) }
|
||||
let!(:internal_snippet) { create(:personal_snippet, :internal) }
|
||||
let!(:private_snippet) { create(:personal_snippet, :private) }
|
||||
|
||||
scenario 'User should see snippets that are not private' do
|
||||
login_as create(:user)
|
||||
visit explore_snippets_path
|
||||
|
||||
|
@ -13,4 +13,21 @@ feature 'Explore Snippets', feature: true do
|
|||
expect(page).to have_content(internal_snippet.title)
|
||||
expect(page).not_to have_content(private_snippet.title)
|
||||
end
|
||||
|
||||
scenario 'External user should see only public snippets' do
|
||||
login_as create(:user, :external)
|
||||
visit explore_snippets_path
|
||||
|
||||
expect(page).to have_content(public_snippet.title)
|
||||
expect(page).not_to have_content(internal_snippet.title)
|
||||
expect(page).not_to have_content(private_snippet.title)
|
||||
end
|
||||
|
||||
scenario 'Not authenticated user should see only public snippets' do
|
||||
visit explore_snippets_path
|
||||
|
||||
expect(page).to have_content(public_snippet.title)
|
||||
expect(page).not_to have_content(internal_snippet.title)
|
||||
expect(page).not_to have_content(private_snippet.title)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,14 +3,46 @@ require 'spec_helper'
|
|||
describe 'Snippets tab on a user profile', feature: true, js: true do
|
||||
context 'when the user has snippets' do
|
||||
let(:user) { create(:user) }
|
||||
let!(:snippets) { create_list(:snippet, 2, :public, author: user) }
|
||||
before do
|
||||
allow(Snippet).to receive(:default_per_page).and_return(1)
|
||||
visit user_path(user)
|
||||
page.within('.user-profile-nav') { click_link 'Snippets' }
|
||||
wait_for_ajax
|
||||
|
||||
context 'pagination' do
|
||||
let!(:snippets) { create_list(:snippet, 2, :public, author: user) }
|
||||
|
||||
before do
|
||||
allow(Snippet).to receive(:default_per_page).and_return(1)
|
||||
visit user_path(user)
|
||||
page.within('.user-profile-nav') { click_link 'Snippets' }
|
||||
wait_for_ajax
|
||||
end
|
||||
|
||||
it_behaves_like 'paginated snippets', remote: true
|
||||
end
|
||||
|
||||
it_behaves_like 'paginated snippets', remote: true
|
||||
context 'list content' do
|
||||
let!(:public_snippet) { create(:snippet, :public, author: user) }
|
||||
let!(:internal_snippet) { create(:snippet, :internal, author: user) }
|
||||
let!(:private_snippet) { create(:snippet, :private, author: user) }
|
||||
let!(:other_snippet) { create(:snippet, :public) }
|
||||
|
||||
it 'contains only internal and public snippets of a user when a user is logged in' do
|
||||
login_as(:user)
|
||||
visit user_path(user)
|
||||
page.within('.user-profile-nav') { click_link 'Snippets' }
|
||||
wait_for_ajax
|
||||
|
||||
expect(page).to have_selector('.snippet-row', count: 2)
|
||||
|
||||
expect(page).to have_content(public_snippet.title)
|
||||
expect(page).to have_content(internal_snippet.title)
|
||||
end
|
||||
|
||||
it 'contains only public snippets of a user when a user is not logged in' do
|
||||
visit user_path(user)
|
||||
page.within('.user-profile-nav') { click_link 'Snippets' }
|
||||
wait_for_ajax
|
||||
|
||||
expect(page).to have_selector('.snippet-row', count: 1)
|
||||
expect(page).to have_content(public_snippet.title)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,79 +8,145 @@ describe SnippetsFinder do
|
|||
let(:project1) { create(:empty_project, :public, group: group) }
|
||||
let(:project2) { create(:empty_project, :private, group: group) }
|
||||
|
||||
context ':all filter' do
|
||||
context 'all snippets visible to a user' do
|
||||
let!(:snippet1) { create(:personal_snippet, :private) }
|
||||
let!(:snippet2) { create(:personal_snippet, :internal) }
|
||||
let!(:snippet3) { create(:personal_snippet, :public) }
|
||||
let!(:project_snippet1) { create(:project_snippet, :private) }
|
||||
let!(:project_snippet2) { create(:project_snippet, :internal) }
|
||||
let!(:project_snippet3) { create(:project_snippet, :public) }
|
||||
|
||||
it "returns all private and internal snippets" do
|
||||
snippets = described_class.new.execute(user, filter: :all)
|
||||
expect(snippets).to include(snippet2, snippet3)
|
||||
expect(snippets).not_to include(snippet1)
|
||||
snippets = described_class.new(user, scope: :all).execute
|
||||
expect(snippets).to include(snippet2, snippet3, project_snippet2, project_snippet3)
|
||||
expect(snippets).not_to include(snippet1, project_snippet1)
|
||||
end
|
||||
|
||||
it "returns all public snippets" do
|
||||
snippets = described_class.new.execute(nil, filter: :all)
|
||||
expect(snippets).to include(snippet3)
|
||||
expect(snippets).not_to include(snippet1, snippet2)
|
||||
snippets = described_class.new(nil, scope: :all).execute
|
||||
expect(snippets).to include(snippet3, project_snippet3)
|
||||
expect(snippets).not_to include(snippet1, snippet2, project_snippet1, project_snippet2)
|
||||
end
|
||||
|
||||
it "returns all public and internal snippets for normal user" do
|
||||
snippets = SnippetsFinder.new(user).execute
|
||||
|
||||
expect(snippets).to include(snippet2, snippet3, project_snippet2, project_snippet3)
|
||||
expect(snippets).not_to include(snippet1, project_snippet1)
|
||||
end
|
||||
|
||||
it "returns all public snippets for non authorized user" do
|
||||
snippets = SnippetsFinder.new(nil).execute
|
||||
|
||||
expect(snippets).to include(snippet3, project_snippet3)
|
||||
expect(snippets).not_to include(snippet1, snippet2, project_snippet1, project_snippet2)
|
||||
end
|
||||
|
||||
it "returns all public and authored snippets for external user" do
|
||||
external_user = create(:user, :external)
|
||||
authored_snippet = create(:personal_snippet, :internal, author: external_user)
|
||||
|
||||
snippets = SnippetsFinder.new(external_user).execute
|
||||
|
||||
expect(snippets).to include(snippet3, project_snippet3, authored_snippet)
|
||||
expect(snippets).not_to include(snippet1, snippet2, project_snippet1, project_snippet2)
|
||||
end
|
||||
end
|
||||
|
||||
context ':public filter' do
|
||||
context 'filter by visibility' do
|
||||
let!(:snippet1) { create(:personal_snippet, :private) }
|
||||
let!(:snippet2) { create(:personal_snippet, :internal) }
|
||||
let!(:snippet3) { create(:personal_snippet, :public) }
|
||||
|
||||
it "returns public public snippets" do
|
||||
snippets = described_class.new.execute(nil, filter: :public)
|
||||
it "returns public snippets when visibility is PUBLIC" do
|
||||
snippets = SnippetsFinder.new(nil, visibility: Snippet::PUBLIC).execute
|
||||
|
||||
expect(snippets).to include(snippet3)
|
||||
expect(snippets).not_to include(snippet1, snippet2)
|
||||
end
|
||||
end
|
||||
|
||||
context ':by_user filter' do
|
||||
context 'filter by scope' do
|
||||
let!(:snippet1) { create(:personal_snippet, :private, author: user) }
|
||||
let!(:snippet2) { create(:personal_snippet, :internal, author: user) }
|
||||
let!(:snippet3) { create(:personal_snippet, :public, author: user) }
|
||||
|
||||
it "returns all snippets for 'all' scope" do
|
||||
snippets = SnippetsFinder.new(user, scope: :all).execute
|
||||
|
||||
expect(snippets).to include(snippet1, snippet2, snippet3)
|
||||
end
|
||||
|
||||
it "returns all snippets for 'are_private' scope" do
|
||||
snippets = SnippetsFinder.new(user, scope: :are_private).execute
|
||||
|
||||
expect(snippets).to include(snippet1)
|
||||
expect(snippets).not_to include(snippet2, snippet3)
|
||||
end
|
||||
|
||||
it "returns all snippets for 'are_interna;' scope" do
|
||||
snippets = SnippetsFinder.new(user, scope: :are_internal).execute
|
||||
|
||||
expect(snippets).to include(snippet2)
|
||||
expect(snippets).not_to include(snippet1, snippet3)
|
||||
end
|
||||
|
||||
it "returns all snippets for 'are_private' scope" do
|
||||
snippets = SnippetsFinder.new(user, scope: :are_public).execute
|
||||
|
||||
expect(snippets).to include(snippet3)
|
||||
expect(snippets).not_to include(snippet1, snippet2)
|
||||
end
|
||||
end
|
||||
|
||||
context 'filter by author' do
|
||||
let!(:snippet1) { create(:personal_snippet, :private, author: user) }
|
||||
let!(:snippet2) { create(:personal_snippet, :internal, author: user) }
|
||||
let!(:snippet3) { create(:personal_snippet, :public, author: user) }
|
||||
|
||||
it "returns all public and internal snippets" do
|
||||
snippets = described_class.new.execute(user1, filter: :by_user, user: user)
|
||||
snippets = SnippetsFinder.new(user1, author: user).execute
|
||||
|
||||
expect(snippets).to include(snippet2, snippet3)
|
||||
expect(snippets).not_to include(snippet1)
|
||||
end
|
||||
|
||||
it "returns internal snippets" do
|
||||
snippets = described_class.new.execute(user, filter: :by_user, user: user, scope: "are_internal")
|
||||
snippets = SnippetsFinder.new(user, author: user, visibility: Snippet::INTERNAL).execute
|
||||
|
||||
expect(snippets).to include(snippet2)
|
||||
expect(snippets).not_to include(snippet1, snippet3)
|
||||
end
|
||||
|
||||
it "returns private snippets" do
|
||||
snippets = described_class.new.execute(user, filter: :by_user, user: user, scope: "are_private")
|
||||
snippets = SnippetsFinder.new(user, author: user, visibility: Snippet::PRIVATE).execute
|
||||
|
||||
expect(snippets).to include(snippet1)
|
||||
expect(snippets).not_to include(snippet2, snippet3)
|
||||
end
|
||||
|
||||
it "returns public snippets" do
|
||||
snippets = described_class.new.execute(user, filter: :by_user, user: user, scope: "are_public")
|
||||
snippets = SnippetsFinder.new(user, author: user, visibility: Snippet::PUBLIC).execute
|
||||
|
||||
expect(snippets).to include(snippet3)
|
||||
expect(snippets).not_to include(snippet1, snippet2)
|
||||
end
|
||||
|
||||
it "returns all snippets" do
|
||||
snippets = described_class.new.execute(user, filter: :by_user, user: user)
|
||||
snippets = SnippetsFinder.new(user, author: user).execute
|
||||
|
||||
expect(snippets).to include(snippet1, snippet2, snippet3)
|
||||
end
|
||||
|
||||
it "returns only public snippets if unauthenticated user" do
|
||||
snippets = described_class.new.execute(nil, filter: :by_user, user: user)
|
||||
snippets = SnippetsFinder.new(nil, author: user).execute
|
||||
|
||||
expect(snippets).to include(snippet3)
|
||||
expect(snippets).not_to include(snippet2, snippet1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'by_project filter' do
|
||||
context 'filter by project' do
|
||||
before do
|
||||
@snippet1 = create(:project_snippet, :private, project: project1)
|
||||
@snippet2 = create(:project_snippet, :internal, project: project1)
|
||||
|
@ -88,43 +154,52 @@ describe SnippetsFinder do
|
|||
end
|
||||
|
||||
it "returns public snippets for unauthorized user" do
|
||||
snippets = described_class.new.execute(nil, filter: :by_project, project: project1)
|
||||
snippets = SnippetsFinder.new(nil, project: project1).execute
|
||||
|
||||
expect(snippets).to include(@snippet3)
|
||||
expect(snippets).not_to include(@snippet1, @snippet2)
|
||||
end
|
||||
|
||||
it "returns public and internal snippets for non project members" do
|
||||
snippets = described_class.new.execute(user, filter: :by_project, project: project1)
|
||||
snippets = SnippetsFinder.new(user, project: project1).execute
|
||||
|
||||
expect(snippets).to include(@snippet2, @snippet3)
|
||||
expect(snippets).not_to include(@snippet1)
|
||||
end
|
||||
|
||||
it "returns public snippets for non project members" do
|
||||
snippets = described_class.new.execute(user, filter: :by_project, project: project1, scope: "are_public")
|
||||
snippets = SnippetsFinder.new(user, project: project1, visibility: Snippet::PUBLIC).execute
|
||||
|
||||
expect(snippets).to include(@snippet3)
|
||||
expect(snippets).not_to include(@snippet1, @snippet2)
|
||||
end
|
||||
|
||||
it "returns internal snippets for non project members" do
|
||||
snippets = described_class.new.execute(user, filter: :by_project, project: project1, scope: "are_internal")
|
||||
snippets = SnippetsFinder.new(user, project: project1, visibility: Snippet::INTERNAL).execute
|
||||
|
||||
expect(snippets).to include(@snippet2)
|
||||
expect(snippets).not_to include(@snippet1, @snippet3)
|
||||
end
|
||||
|
||||
it "does not return private snippets for non project members" do
|
||||
snippets = described_class.new.execute(user, filter: :by_project, project: project1, scope: "are_private")
|
||||
snippets = SnippetsFinder.new(user, project: project1, visibility: Snippet::PRIVATE).execute
|
||||
|
||||
expect(snippets).not_to include(@snippet1, @snippet2, @snippet3)
|
||||
end
|
||||
|
||||
it "returns all snippets for project members" do
|
||||
project1.team << [user, :developer]
|
||||
snippets = described_class.new.execute(user, filter: :by_project, project: project1)
|
||||
|
||||
snippets = SnippetsFinder.new(user, project: project1).execute
|
||||
|
||||
expect(snippets).to include(@snippet1, @snippet2, @snippet3)
|
||||
end
|
||||
|
||||
it "returns private snippets for project members" do
|
||||
project1.team << [user, :developer]
|
||||
snippets = described_class.new.execute(user, filter: :by_project, project: project1, scope: "are_private")
|
||||
|
||||
snippets = SnippetsFinder.new(user, project: project1, visibility: Snippet::PRIVATE).execute
|
||||
|
||||
expect(snippets).to include(@snippet1)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -131,46 +131,6 @@ describe Snippet, models: true do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.accessible_to' do
|
||||
let(:author) { create(:author) }
|
||||
let(:project) { create(:empty_project) }
|
||||
|
||||
let!(:public_snippet) { create(:snippet, :public) }
|
||||
let!(:internal_snippet) { create(:snippet, :internal) }
|
||||
let!(:private_snippet) { create(:snippet, :private, author: author) }
|
||||
|
||||
let!(:project_public_snippet) { create(:snippet, :public, project: project) }
|
||||
let!(:project_internal_snippet) { create(:snippet, :internal, project: project) }
|
||||
let!(:project_private_snippet) { create(:snippet, :private, project: project) }
|
||||
|
||||
it 'returns only public snippets when user is blank' do
|
||||
expect(described_class.accessible_to(nil)).to match_array [public_snippet, project_public_snippet]
|
||||
end
|
||||
|
||||
it 'returns only public, and internal snippets for regular users' do
|
||||
user = create(:user)
|
||||
|
||||
expect(described_class.accessible_to(user)).to match_array [public_snippet, internal_snippet, project_public_snippet, project_internal_snippet]
|
||||
end
|
||||
|
||||
it 'returns public, internal snippets and project private snippets for project members' do
|
||||
member = create(:user)
|
||||
project.team << [member, :developer]
|
||||
|
||||
expect(described_class.accessible_to(member)).to match_array [public_snippet, internal_snippet, project_public_snippet, project_internal_snippet, project_private_snippet]
|
||||
end
|
||||
|
||||
it 'returns private snippets where the user is the author' do
|
||||
expect(described_class.accessible_to(author)).to match_array [public_snippet, internal_snippet, private_snippet, project_public_snippet, project_internal_snippet]
|
||||
end
|
||||
|
||||
it 'returns all snippets when for admins' do
|
||||
admin = create(:admin)
|
||||
|
||||
expect(described_class.accessible_to(admin)).to match_array [public_snippet, internal_snippet, private_snippet, project_public_snippet, project_internal_snippet, project_private_snippet]
|
||||
end
|
||||
end
|
||||
|
||||
describe '#participants' do
|
||||
let(:project) { create(:empty_project, :public) }
|
||||
let(:snippet) { create(:snippet, content: 'foo', project: project) }
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe ProjectSnippetPolicy, models: true do
|
||||
let(:current_user) { create(:user) }
|
||||
let(:regular_user) { create(:user) }
|
||||
let(:external_user) { create(:user, :external) }
|
||||
let(:project) { create(:empty_project) }
|
||||
|
||||
let(:author_permissions) do
|
||||
[
|
||||
|
@ -10,13 +12,15 @@ describe ProjectSnippetPolicy, models: true do
|
|||
]
|
||||
end
|
||||
|
||||
subject { described_class.abilities(current_user, project_snippet).to_set }
|
||||
def abilities(user, snippet_visibility)
|
||||
snippet = create(:project_snippet, snippet_visibility, project: project)
|
||||
|
||||
described_class.abilities(user, snippet).to_set
|
||||
end
|
||||
|
||||
context 'public snippet' do
|
||||
let(:project_snippet) { create(:project_snippet, :public) }
|
||||
|
||||
context 'no user' do
|
||||
let(:current_user) { nil }
|
||||
subject { abilities(nil, :public) }
|
||||
|
||||
it do
|
||||
is_expected.to include(:read_project_snippet)
|
||||
|
@ -25,6 +29,17 @@ describe ProjectSnippetPolicy, models: true do
|
|||
end
|
||||
|
||||
context 'regular user' do
|
||||
subject { abilities(regular_user, :public) }
|
||||
|
||||
it do
|
||||
is_expected.to include(:read_project_snippet)
|
||||
is_expected.not_to include(*author_permissions)
|
||||
end
|
||||
end
|
||||
|
||||
context 'external user' do
|
||||
subject { abilities(external_user, :public) }
|
||||
|
||||
it do
|
||||
is_expected.to include(:read_project_snippet)
|
||||
is_expected.not_to include(*author_permissions)
|
||||
|
@ -33,10 +48,8 @@ describe ProjectSnippetPolicy, models: true do
|
|||
end
|
||||
|
||||
context 'internal snippet' do
|
||||
let(:project_snippet) { create(:project_snippet, :internal) }
|
||||
|
||||
context 'no user' do
|
||||
let(:current_user) { nil }
|
||||
subject { abilities(nil, :internal) }
|
||||
|
||||
it do
|
||||
is_expected.not_to include(:read_project_snippet)
|
||||
|
@ -45,6 +58,28 @@ describe ProjectSnippetPolicy, models: true do
|
|||
end
|
||||
|
||||
context 'regular user' do
|
||||
subject { abilities(regular_user, :internal) }
|
||||
|
||||
it do
|
||||
is_expected.to include(:read_project_snippet)
|
||||
is_expected.not_to include(*author_permissions)
|
||||
end
|
||||
end
|
||||
|
||||
context 'external user' do
|
||||
subject { abilities(external_user, :internal) }
|
||||
|
||||
it do
|
||||
is_expected.not_to include(:read_project_snippet)
|
||||
is_expected.not_to include(*author_permissions)
|
||||
end
|
||||
end
|
||||
|
||||
context 'project team member external user' do
|
||||
subject { abilities(external_user, :internal) }
|
||||
|
||||
before { project.team << [external_user, :developer] }
|
||||
|
||||
it do
|
||||
is_expected.to include(:read_project_snippet)
|
||||
is_expected.not_to include(*author_permissions)
|
||||
|
@ -53,10 +88,8 @@ describe ProjectSnippetPolicy, models: true do
|
|||
end
|
||||
|
||||
context 'private snippet' do
|
||||
let(:project_snippet) { create(:project_snippet, :private) }
|
||||
|
||||
context 'no user' do
|
||||
let(:current_user) { nil }
|
||||
subject { abilities(nil, :private) }
|
||||
|
||||
it do
|
||||
is_expected.not_to include(:read_project_snippet)
|
||||
|
@ -65,6 +98,8 @@ describe ProjectSnippetPolicy, models: true do
|
|||
end
|
||||
|
||||
context 'regular user' do
|
||||
subject { abilities(regular_user, :private) }
|
||||
|
||||
it do
|
||||
is_expected.not_to include(:read_project_snippet)
|
||||
is_expected.not_to include(*author_permissions)
|
||||
|
@ -72,7 +107,9 @@ describe ProjectSnippetPolicy, models: true do
|
|||
end
|
||||
|
||||
context 'snippet author' do
|
||||
let(:project_snippet) { create(:project_snippet, :private, author: current_user) }
|
||||
let(:snippet) { create(:project_snippet, :private, author: regular_user) }
|
||||
|
||||
subject { described_class.abilities(regular_user, snippet).to_set }
|
||||
|
||||
it do
|
||||
is_expected.to include(:read_project_snippet)
|
||||
|
@ -80,8 +117,21 @@ describe ProjectSnippetPolicy, models: true do
|
|||
end
|
||||
end
|
||||
|
||||
context 'project team member' do
|
||||
before { project_snippet.project.team << [current_user, :developer] }
|
||||
context 'project team member normal user' do
|
||||
subject { abilities(regular_user, :private) }
|
||||
|
||||
before { project.team << [regular_user, :developer] }
|
||||
|
||||
it do
|
||||
is_expected.to include(:read_project_snippet)
|
||||
is_expected.not_to include(*author_permissions)
|
||||
end
|
||||
end
|
||||
|
||||
context 'project team member external user' do
|
||||
subject { abilities(external_user, :private) }
|
||||
|
||||
before { project.team << [external_user, :developer] }
|
||||
|
||||
it do
|
||||
is_expected.to include(:read_project_snippet)
|
||||
|
@ -90,7 +140,7 @@ describe ProjectSnippetPolicy, models: true do
|
|||
end
|
||||
|
||||
context 'admin user' do
|
||||
let(:current_user) { create(:admin) }
|
||||
subject { abilities(create(:admin), :private) }
|
||||
|
||||
it do
|
||||
is_expected.to include(:read_project_snippet)
|
||||
|
|
Loading…
Reference in a new issue