Skip to content

Commit bb3b369

Browse files
authored
Merge pull request #685 from code0-tech/copilot/restrict-query-users-admin
Restrict Query.users field to admin users and add Query.user field
2 parents 675fb3c + 367a282 commit bb3b369

File tree

6 files changed

+139
-0
lines changed

6 files changed

+139
-0
lines changed

app/graphql/types/query_type.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ class QueryType < Types::BaseObject
4242
argument :id, Types::GlobalIdType[::Namespace], required: true, description: 'GlobalID of the target namespace'
4343
end
4444

45+
field :user, Types::UserType, null: true, description: 'Find a user' do
46+
argument :id, Types::GlobalIdType[::User], required: true, description: 'GlobalID of the target user'
47+
end
48+
4549
field :users, Types::UserType.connection_type, null: false, description: 'Find users'
4650

4751
field :global_runtimes, Types::RuntimeType.connection_type, null: false, description: 'Find runtimes'
@@ -92,7 +96,13 @@ def namespace(id:)
9296
SagittariusSchema.object_from_id(id)
9397
end
9498

99+
def user(id:)
100+
SagittariusSchema.object_from_id(id)
101+
end
102+
95103
def users
104+
return User.none unless Ability.allowed?(context[:current_authentication], :list_users, :global)
105+
96106
User.all
97107
end
98108

app/policies/global_policy.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@ class GlobalPolicy < BasePolicy
2020
enable :update_runtime
2121
enable :delete_runtime
2222
enable :rotate_runtime_token
23+
enable :list_users
2324
end
2425
end

docs/graphql/object/query.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,13 @@ Returns [`Organization`](../object/organization.md).
6969
|------|------|-------------|
7070
| `id` | [`OrganizationID`](../scalar/organizationid.md) | GlobalID of the target organization |
7171
| `name` | [`String`](../scalar/string.md) | Name of the target organization |
72+
73+
### user
74+
75+
Find a user
76+
77+
Returns [`User`](../object/user.md).
78+
79+
| Name | Type | Description |
80+
|------|------|-------------|
81+
| `id` | [`UserID!`](../scalar/userid.md) | GlobalID of the target user |

spec/graphql/types/query_type_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
organization
1414
organizations
1515
users
16+
user
1617
global_runtimes
1718
namespace
1819
userAbilities
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# frozen_string_literal: true
2+
3+
require 'rails_helper'
4+
5+
RSpec.describe 'user Query' do
6+
include GraphqlHelpers
7+
8+
subject(:query!) { post_graphql query, current_user: current_user }
9+
10+
let(:target_user) { create(:user) }
11+
let(:query) do
12+
<<~QUERY
13+
query {
14+
user(id: "#{target_user.to_global_id}") {
15+
id
16+
username
17+
}
18+
}
19+
QUERY
20+
end
21+
22+
context 'when anonymous' do
23+
let(:current_user) { nil }
24+
25+
it 'returns nil due to read_user authorization on UserType' do
26+
query!
27+
28+
expect(graphql_data_at(:user)).to be_nil
29+
end
30+
end
31+
32+
context 'when logged in as regular user' do
33+
let(:current_user) { create(:user) }
34+
35+
it 'returns the user' do
36+
query!
37+
38+
expect(graphql_data_at(:user, :id)).to eq(target_user.to_global_id.to_s)
39+
expect(graphql_data_at(:user, :username)).to eq(target_user.username)
40+
end
41+
end
42+
43+
context 'when logged in as admin user' do
44+
let(:current_user) { create(:user, :admin) }
45+
46+
it 'returns the user' do
47+
query!
48+
49+
expect(graphql_data_at(:user, :id)).to eq(target_user.to_global_id.to_s)
50+
expect(graphql_data_at(:user, :username)).to eq(target_user.username)
51+
end
52+
end
53+
54+
context 'when querying self' do
55+
let(:current_user) { create(:user) }
56+
let(:target_user) { current_user }
57+
58+
it 'returns the user' do
59+
query!
60+
61+
expect(graphql_data_at(:user, :id)).to eq(current_user.to_global_id.to_s)
62+
expect(graphql_data_at(:user, :username)).to eq(current_user.username)
63+
end
64+
end
65+
end
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# frozen_string_literal: true
2+
3+
require 'rails_helper'
4+
5+
RSpec.describe 'users Query' do
6+
include GraphqlHelpers
7+
8+
let(:query) do
9+
<<~QUERY
10+
query {
11+
users {
12+
nodes {
13+
id
14+
username
15+
}
16+
}
17+
}
18+
QUERY
19+
end
20+
21+
before do
22+
create(:user)
23+
create(:user)
24+
create(:user)
25+
26+
post_graphql query, current_user: current_user
27+
end
28+
29+
context 'when anonymous' do
30+
let(:current_user) { nil }
31+
32+
it 'returns an error' do
33+
expect(graphql_data_at(:users, :nodes)).to be_empty
34+
end
35+
end
36+
37+
context 'when logged in as regular user' do
38+
let(:current_user) { create(:user) }
39+
40+
it 'returns an error' do
41+
expect(graphql_data_at(:users, :nodes)).to be_empty
42+
end
43+
end
44+
45+
context 'when logged in as admin user' do
46+
let(:current_user) { create(:user, :admin) }
47+
48+
it 'returns all users' do
49+
expect(graphql_data_at(:users, :nodes)).to have_attributes(length: 4)
50+
end
51+
end
52+
end

0 commit comments

Comments
 (0)