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
require 'spec_helper'
RSpec.describe Types::Ci::JobBaseField, feature_category: :runner_fleet do
describe 'authorized?' do
let_it_be(:current_user) { create(:user) }
let(:object) { double }
let(:ctx) { { current_user: current_user, current_field: current_field } }
let(:current_field) { instance_double(described_class, original_name: current_field_name.to_sym) }
let(:args) { {} }
subject(:field) do
described_class.new(name: current_field_name, type: GraphQL::Types::String, null: true, **args)
end
context 'when :job_field_authorization is specified' do
let(:ctx) { { current_user: current_user, current_field: current_field, job_field_authorization: :foo } }
context 'with public field' do
using RSpec::Parameterized::TableSyntax
where(:current_field_name) do
%i[allow_failure duration id kind status created_at finished_at queued_at queued_duration updated_at runner]
end
with_them do
it 'returns true without authorizing' do
is_expected.to be_authorized(object, nil, ctx)
end
end
end
context 'with private field' do
let(:current_field_name) { 'short_sha' }
context 'when permission is not allowed' do
it 'returns false' do
expect(Ability).to receive(:allowed?).with(current_user, :foo, object).and_return(false)
is_expected.not_to be_authorized(object, nil, ctx)
end
end
context 'when permission is allowed' do
it 'returns true' do
expect(Ability).to receive(:allowed?).with(current_user, :foo, object).and_return(true)
is_expected.to be_authorized(object, nil, ctx)
end
end
end
end
context 'when :job_field_authorization is not specified' do
let(:current_field_name) { 'status' }
it 'defaults to true' do
is_expected.to be_authorized(object, nil, ctx)
end
context 'when field is authorized' do
let(:args) { { authorize: :foo } }
it 'tests the field authorization' do
expect(Ability).to receive(:allowed?).with(current_user, :foo, object).and_return(false)
expect(field).not_to be_authorized(object, nil, ctx)
end
it 'tests the field authorization, if provided, when it succeeds' do
expect(Ability).to receive(:allowed?).with(current_user, :foo, object).and_return(true)
expect(field).to be_authorized(object, nil, ctx)
end
end
context 'with field resolver' do
let(:resolver) { Class.new }
let(:args) { { resolver_class: resolver } }
it 'only tests the resolver authorization if it authorizes_object?' do
is_expected.to be_authorized(object, nil, ctx)
end
context 'when resolver authorizes object' do
let(:resolver) do
Class.new do
include Gitlab::Graphql::Authorize::AuthorizeResource
authorizes_object!
end
end
it 'tests the resolver authorization, if provided' do
expect(resolver).to receive(:authorized?).with(object, ctx).and_return(false)
expect(field).not_to be_authorized(object, nil, ctx)
end
context 'when field is authorized' do
let(:args) { { authorize: :foo, resolver_class: resolver } }
it 'tests field authorization before resolver authorization, when field auth fails' do
expect(Ability).to receive(:allowed?).with(current_user, :foo, object).and_return(false)
expect(resolver).not_to receive(:authorized?)
expect(field).not_to be_authorized(object, nil, ctx)
end
it 'tests field authorization before resolver authorization, when field auth succeeds' do
expect(Ability).to receive(:allowed?).with(current_user, :foo, object).and_return(true)
expect(resolver).to receive(:authorized?).with(object, ctx).and_return(false)
expect(field).not_to be_authorized(object, nil, ctx)
end
end
end
end
end
end
describe '#resolve' do
context 'when late_extensions is given' do
it 'registers the late extensions after the regular extensions' do
extension_class = Class.new(GraphQL::Schema::Field::ConnectionExtension)
field = described_class.new(name: 'private_field', type: GraphQL::Types::String.connection_type,
null: true, late_extensions: [extension_class])
expect(field.extensions.last.class).to be(extension_class)
end
end
end
include_examples 'Gitlab-style deprecations' do
def subject(args = {})
base_args = { name: 'private_field', type: GraphQL::Types::String, null: true }
described_class.new(**base_args.merge(args))
end
end
end
|