blob: 116b523bd99705960d5a2f882402f5650dab5ef1 (
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
|
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe FinderWithCrossProjectAccess do
let(:finder_class) do
Class.new do
prepend FinderWithCrossProjectAccess
include FinderMethods
requires_cross_project_access if: -> { requires_access? }
attr_reader :current_user
def initialize(user)
@current_user = user
end
def execute
Issue.all
end
end
end
let(:user) { create(:user) }
subject(:finder) { finder_class.new(user) }
let!(:result) { create(:issue) }
before do
result.project.add_maintainer(user)
end
def expect_access_check_on_result
expect(finder).not_to receive(:requires_access?)
expect(Ability).to receive(:allowed?).with(user, :read_issue, result).and_call_original
end
context 'when the user cannot read cross project' do
before do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?).with(user, :read_cross_project)
.and_return(false)
end
describe '#execute' do
it 'returns a issue if the check is disabled' do
expect(finder).to receive(:requires_access?).and_return(false)
expect(finder.execute).to include(result)
end
it 'returns an empty relation when the check is enabled' do
expect(finder).to receive(:requires_access?).and_return(true)
expect(finder.execute).to be_empty
end
it 'only queries once when check is enabled' do
expect(finder).to receive(:requires_access?).and_return(true)
expect { finder.execute }.not_to exceed_query_limit(1)
end
it 'only queries once when check is disabled' do
expect(finder).to receive(:requires_access?).and_return(false)
expect { finder.execute }.not_to exceed_query_limit(1)
end
end
describe '#find' do
it 'checks the accessibility of the subject directly' do
expect_access_check_on_result
finder.find(result.id)
end
it 'returns the issue' do
expect(finder.find(result.id)).to eq(result)
end
end
describe '#find_by' do
it 'checks the accessibility of the subject directly' do
expect_access_check_on_result
finder.find_by(id: result.id)
end
end
describe '#find_by!' do
it 'checks the accessibility of the subject directly' do
expect_access_check_on_result
finder.find_by!(id: result.id)
end
it 're-enables the check after the find failed' do
finder.find_by!(id: non_existing_record_id) rescue ActiveRecord::RecordNotFound
expect(finder.instance_variable_get(:@should_skip_cross_project_check))
.to eq(false)
end
end
end
context 'when the user can read cross project' do
before do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?).with(user, :read_cross_project)
.and_return(true)
end
it 'returns the result' do
expect(finder).not_to receive(:requires_access?)
expect(finder.execute).to include(result)
end
end
context 'when specifying a model' do
let(:finder_class) do
Class.new do
prepend FinderWithCrossProjectAccess
requires_cross_project_access model: Project
end
end
describe '.finder_model' do
it 'is set correctly' do
expect(finder_class.finder_model).to eq(Project)
end
end
end
end
|