From aa7d4e651ea1609835d6421f88b89484714ded47 Mon Sep 17 00:00:00 2001 From: Jio Castillo Date: Tue, 13 Jun 2023 19:28:34 -0700 Subject: [PATCH 1/3] Add API endpoint to get single SAML/SCIM identity Changelog: added EE: true --- doc/api/saml.md | 35 +++++++++++++++++-- doc/api/scim.md | 32 ++++++++++++++++- ee/lib/api/provider_identity.rb | 15 ++++++++ .../requests/api/provider_identity_spec.rb | 34 ++++++++++++++++++ 4 files changed, 112 insertions(+), 4 deletions(-) diff --git a/doc/api/saml.md b/doc/api/saml.md index 6b2e7cffaabe9d..dc2d14d3ffc87c 100644 --- a/doc/api/saml.md +++ b/doc/api/saml.md @@ -22,7 +22,7 @@ Supported attributes: | Attribute | Type | Required | Description | |:------------------|:--------|:---------|:----------------------| -| `id` | integer | Yes | Group ID for the group to return SAML identities. | +| `id` | integer/string | yes | The ID or [URL-encoded path of the group](rest/index.md#namespaced-path-encoding) | If successful, returns [`200`](rest/index.md#status-codes) and the following response attributes: @@ -49,6 +49,34 @@ Example response: ] ``` +## Get a single SAML identity + +```plaintext +GET /groups/:id/saml/:uid +``` + +Supported attributes: + +| Attribute | Type | Required | Description | +| --------- | -------------- | -------- | ------------------------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the group](rest/index.md#namespaced-path-encoding) | +| `uid` | string | yes | External UID of the user. | + +Example request: + +```shell +curl --location --request GET "https://gitlab.example.com/api/v4/groups/33/saml/sydney_jones" --header "" +``` + +Example response: + +```json +{ + "extern_uid": "4", + "user_id": 48 +} +``` + ## Update `extern_uid` field for a SAML identity Update `extern_uid` field for a SAML identity: @@ -58,13 +86,14 @@ Update `extern_uid` field for a SAML identity: | `id/externalId` | `extern_uid` | ```plaintext -PATCH groups/:groups_id/saml/:uid +PATCH /groups/:id/saml/:uid ``` -Parameters: +Supported attributes: | Attribute | Type | Required | Description | | --------- | ------ | -------- | ------------------------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the group](rest/index.md#namespaced-path-encoding) | | `uid` | string | yes | External UID of the user. | Example request: diff --git a/doc/api/scim.md b/doc/api/scim.md index 6e022afb2f5efc..a200e7165d525e 100644 --- a/doc/api/scim.md +++ b/doc/api/scim.md @@ -28,7 +28,7 @@ Supported attributes: | Attribute | Type | Required | Description | |:------------------|:--------|:---------|:----------------------| -| `id` | integer | Yes | Return SCIM identities for the given group ID. | +| `id` | integer/string | Yes | The ID or [URL-encoded path of the group](rest/index.md#namespaced-path-encoding) | If successful, returns [`200`](rest/index.md#status-codes) and the following response attributes: @@ -58,6 +58,35 @@ curl --location --request GET "https://gitlab.example.com/api/v4/groups/33/scim/ --header "PRIVATE-TOKEN: " ``` +## Get a single SCIM identity + +```plaintext +GET /groups/:id/scim/:uid +``` + +Supported attributes: + +| Attribute | Type | Required | Description | +| --------- | ------- | -------- | ------------------------- | +| `id` | integer | yes | The ID or [URL-encoded path of the group](rest/index.md#namespaced-path-encoding) | +| `uid` | string | yes | External UID of the user. | + +Example request: + +```shell +curl --location --request GET "https://gitlab.example.com/api/v4/groups/33/scim/sydney_jones" --header "" +``` + +Example response: + +```json +{ + "extern_uid": "4", + "user_id": 48, + "active": true +} +``` + ## Update `extern_uid` field for a SCIM identity > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227841) in GitLab 15.5. @@ -76,6 +105,7 @@ Parameters: | Attribute | Type | Required | Description | | --------- | ------ | -------- | ------------------------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the group](rest/index.md#namespaced-path-encoding) | | `uid` | string | yes | External UID of the user. | Example request: diff --git a/ee/lib/api/provider_identity.rb b/ee/lib/api/provider_identity.rb index 42f7494ac9a7df..ad208961e783e2 100644 --- a/ee/lib/api/provider_identity.rb +++ b/ee/lib/api/provider_identity.rb @@ -31,6 +31,21 @@ class ProviderIdentity < ::API::Base end end + desc 'Get a single identity for a user' do + success EE::API::Entities::IdentityDetail + end + params do + requires :uid, type: String, desc: 'External UID of the user' + end + get ':uid', format: false, requirements: { uid: API::NO_SLASH_URL_PART_REGEX } do + group = find_group(params[:id]) + identity = find_provider_identity(provider_type, params[:uid], group) + + not_found!('Identity') unless identity + + present identity, with: EE::API::Entities::IdentityDetail + end + desc 'Update extern_uid for the user' do success EE::API::Entities::IdentityDetail end diff --git a/ee/spec/requests/api/provider_identity_spec.rb b/ee/spec/requests/api/provider_identity_spec.rb index a8c4fdacc59177..5d0e9a0a2c6cc9 100644 --- a/ee/spec/requests/api/provider_identity_spec.rb +++ b/ee/spec/requests/api/provider_identity_spec.rb @@ -101,6 +101,40 @@ end end + context "when GET identity" do + subject(:get_identity) do + get api("/groups/#{group.id}/#{provider_type}/#{provider_extern_uid_1}", current_user) + end + + context "when user is not a group owner" do + let(:current_user) { guest_user_1 } + + it "throws unauthorized error" do + get_identity + + expect(response).to have_gitlab_http_status(:forbidden) + end + end + + context "when user is group owner" do + let(:current_user) { owner } + + it "returns the identity" do + get_identity + + if identity_type == ScimIdentity + expect(json_response).to match( + a_hash_including("extern_uid" => provider_extern_uid_1, "user_id" => guest_user_1.id, "active" => true) + ) + else + expect(json_response).to match( + a_hash_including("extern_uid" => provider_extern_uid_1, "user_id" => guest_user_1.id) + ) + end + end + end + end + context "when PATCH uid" do subject(:patch_identities) do patch api("/groups/#{group.id}/#{provider_type}/#{uid}", current_user), -- GitLab From ebbdfe9380f72dd6c9803d965fe612cfc23c1475 Mon Sep 17 00:00:00 2001 From: Jio Castillo Date: Wed, 14 Jun 2023 12:17:03 -0700 Subject: [PATCH 2/3] Apply suggestion to tests --- ee/spec/requests/api/provider_identity_spec.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ee/spec/requests/api/provider_identity_spec.rb b/ee/spec/requests/api/provider_identity_spec.rb index 5d0e9a0a2c6cc9..61c2c1683b193c 100644 --- a/ee/spec/requests/api/provider_identity_spec.rb +++ b/ee/spec/requests/api/provider_identity_spec.rb @@ -6,6 +6,7 @@ include ApiHelpers let_it_be(:owner) { create(:user) } + let_it_be(:maintainer) { create(:user) } let_it_be(:guest_user_1) { create(:user) } let_it_be(:guest_user_2) { create(:user) } let(:current_user) { nil } @@ -14,6 +15,7 @@ group = create(:group) group.add_guest(guest_user_1) group.add_guest(guest_user_2) + group.add_maintainer(maintainer) group.add_owner(owner) group end @@ -61,7 +63,7 @@ subject(:get_identities) { get api("/groups/#{group.id}/#{provider_type}/identities", current_user) } context "when user is not a group owner" do - let(:current_user) { guest_user_1 } + let(:current_user) { maintainer } it "throws unauthorized error" do get_identities @@ -107,7 +109,7 @@ end context "when user is not a group owner" do - let(:current_user) { guest_user_1 } + let(:current_user) { maintainer } it "throws unauthorized error" do get_identity @@ -143,7 +145,7 @@ context "when user is not a group owner" do let(:uid) { provider_extern_uid_1 } - let(:current_user) { guest_user_1 } + let(:current_user) { maintainer } let(:extern_uid) { 'updated_uid' } it "throws forbidden error" do -- GitLab From aa51df5ccc6b33a5e294fdb7d5c3f9bf669977ef Mon Sep 17 00:00:00 2001 From: Jio Castillo Date: Wed, 14 Jun 2023 12:19:18 -0700 Subject: [PATCH 3/3] Add version history item --- doc/api/saml.md | 2 ++ doc/api/scim.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/doc/api/saml.md b/doc/api/saml.md index dc2d14d3ffc87c..b1d7692fbaf6d6 100644 --- a/doc/api/saml.md +++ b/doc/api/saml.md @@ -51,6 +51,8 @@ Example response: ## Get a single SAML identity +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/123591) in GitLab 16.1. + ```plaintext GET /groups/:id/saml/:uid ``` diff --git a/doc/api/scim.md b/doc/api/scim.md index a200e7165d525e..df0d90756d26d0 100644 --- a/doc/api/scim.md +++ b/doc/api/scim.md @@ -60,6 +60,8 @@ curl --location --request GET "https://gitlab.example.com/api/v4/groups/33/scim/ ## Get a single SCIM identity +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/123591) in GitLab 16.1. + ```plaintext GET /groups/:id/scim/:uid ``` -- GitLab