Commit 583ef945 authored by Hassan Zamani's avatar Hassan Zamani Committed by Markus Koller

Add groups to OpenID Connect claims

parent bfb32b46
...@@ -564,7 +564,7 @@ class User < ActiveRecord::Base ...@@ -564,7 +564,7 @@ class User < ActiveRecord::Base
gpg_keys.each(&:update_invalid_gpg_signatures) gpg_keys.each(&:update_invalid_gpg_signatures)
end end
# Returns the groups a user has access to # Returns the groups a user has access to, either through a membership or a project authorization
def authorized_groups def authorized_groups
union = Gitlab::SQL::Union union = Gitlab::SQL::Union
.new([groups.select(:id), authorized_projects.select(:namespace_id)]) .new([groups.select(:id), authorized_projects.select(:namespace_id)])
...@@ -572,6 +572,11 @@ class User < ActiveRecord::Base ...@@ -572,6 +572,11 @@ class User < ActiveRecord::Base
Group.where("namespaces.id IN (#{union.to_sql})") # rubocop:disable GitlabSecurity/SqlInjection Group.where("namespaces.id IN (#{union.to_sql})") # rubocop:disable GitlabSecurity/SqlInjection
end end
# Returns the groups a user is a member of, either directly or through a parent group
def membership_groups
Gitlab::GroupHierarchy.new(groups).base_and_descendants
end
# Returns a relation of groups the user has access to, including their parent # Returns a relation of groups the user has access to, including their parent
# and child groups (recursively). # and child groups (recursively).
def all_expanded_groups def all_expanded_groups
......
---
title: Add groups to OpenID Connect claims
merge_request: 16929
author: Hassan Zamani
...@@ -31,6 +31,7 @@ Doorkeeper::OpenidConnect.configure do ...@@ -31,6 +31,7 @@ Doorkeeper::OpenidConnect.configure do
o.claim(:website) { |user| user.full_website_url if user.website_url? } o.claim(:website) { |user| user.full_website_url if user.website_url? }
o.claim(:profile) { |user| Gitlab::Routing.url_helpers.user_url user } o.claim(:profile) { |user| Gitlab::Routing.url_helpers.user_url user }
o.claim(:picture) { |user| user.avatar_url(only_path: false) } o.claim(:picture) { |user| user.avatar_url(only_path: false) }
o.claim(:groups) { |user| user.membership_groups.map(&:full_path) }
end end
end end
end end
...@@ -68,7 +68,7 @@ en: ...@@ -68,7 +68,7 @@ en:
read_user: read_user:
Read-only access to the user's profile information, like username, public email and full name Read-only access to the user's profile information, like username, public email and full name
openid: openid:
The ability to authenticate using GitLab, and read-only access to the user's profile information The ability to authenticate using GitLab, and read-only access to the user's profile information and group memberships
sudo: sudo:
Access to the Sudo feature, to perform API actions as any user in the system (only available for admins) Access to the Sudo feature, to perform API actions as any user in the system (only available for admins)
flash: flash:
......
...@@ -39,6 +39,7 @@ Currently the following user information is shared with clients: ...@@ -39,6 +39,7 @@ Currently the following user information is shared with clients:
| `website` | `string` | URL for the user's website | `website` | `string` | URL for the user's website
| `profile` | `string` | URL for the user's GitLab profile | `profile` | `string` | URL for the user's GitLab profile
| `picture` | `string` | URL for the user's GitLab avatar | `picture` | `string` | URL for the user's GitLab avatar
| `groups` | `array` | Names of the groups the user is a member of
[OpenID Connect]: http://openid.net/connect/ "OpenID Connect website" [OpenID Connect]: http://openid.net/connect/ "OpenID Connect website"
[doorkeeper-openid_connect]: https://github.com/doorkeeper-gem/doorkeeper-openid_connect "Doorkeeper::OpenidConnect website" [doorkeeper-openid_connect]: https://github.com/doorkeeper-gem/doorkeeper-openid_connect "Doorkeeper::OpenidConnect website"
......
...@@ -1557,14 +1557,37 @@ describe User do ...@@ -1557,14 +1557,37 @@ describe User do
describe '#authorized_groups' do describe '#authorized_groups' do
let!(:user) { create(:user) } let!(:user) { create(:user) }
let!(:private_group) { create(:group) } let!(:private_group) { create(:group) }
let!(:child_group) { create(:group, parent: private_group) }
let!(:project_group) { create(:group) }
let!(:project) { create(:project, group: project_group) }
before do before do
private_group.add_user(user, Gitlab::Access::MASTER) private_group.add_user(user, Gitlab::Access::MASTER)
project.add_master(user)
end end
subject { user.authorized_groups } subject { user.authorized_groups }
it { is_expected.to eq([private_group]) } it { is_expected.to contain_exactly private_group, project_group }
end
describe '#membership_groups' do
let!(:user) { create(:user) }
let!(:parent_group) { create(:group) }
let!(:child_group) { create(:group, parent: parent_group) }
before do
parent_group.add_user(user, Gitlab::Access::MASTER)
end
subject { user.membership_groups }
if Group.supports_nested_groups?
it { is_expected.to contain_exactly parent_group, child_group }
else
it { is_expected.to contain_exactly parent_group }
end
end end
describe '#authorized_projects', :delete do describe '#authorized_projects', :delete do
......
...@@ -65,10 +65,20 @@ describe 'OpenID Connect requests' do ...@@ -65,10 +65,20 @@ describe 'OpenID Connect requests' do
) )
end end
let(:public_email) { build :email, email: 'public@example.com' } let!(:public_email) { build :email, email: 'public@example.com' }
let(:private_email) { build :email, email: 'private@example.com' } let!(:private_email) { build :email, email: 'private@example.com' }
it 'includes all user information' do let!(:group1) { create :group, path: 'group1' }
let!(:group2) { create :group, path: 'group2' }
let!(:group3) { create :group, path: 'group3', parent: group2 }
let!(:group4) { create :group, path: 'group4', parent: group3 }
before do
group1.add_user(user, GroupMember::OWNER)
group3.add_user(user, Gitlab::Access::DEVELOPER)
end
it 'includes all user information and group memberships' do
request_user_info request_user_info
expect(json_response).to eq({ expect(json_response).to eq({
...@@ -79,7 +89,13 @@ describe 'OpenID Connect requests' do ...@@ -79,7 +89,13 @@ describe 'OpenID Connect requests' do
'email_verified' => true, 'email_verified' => true,
'website' => 'https://example.com', 'website' => 'https://example.com',
'profile' => 'http://localhost/alice', 'profile' => 'http://localhost/alice',
'picture' => "http://localhost/uploads/-/system/user/avatar/#{user.id}/dk.png" 'picture' => "http://localhost/uploads/-/system/user/avatar/#{user.id}/dk.png",
'groups' =>
if Group.supports_nested_groups?
['group1', 'group2/group3', 'group2/group3/group4']
else
['group1', 'group2/group3']
end
}) })
end 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