// Copyright 2021 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "context" "fmt" "net/http" "testing" "time" "github.com/google/go-cmp/cmp" ) func TestSCIMService_ListSCIMProvisionedIdentities(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/scim/v2/organizations/o/Users", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(`{ "schemas": [ "urn:ietf:params:scim:api:messages:2.0:ListResponse" ], "totalResults": 1, "itemsPerPage": 1, "startIndex": 1, "Resources": [ { "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:User" ], "id": "5fc0c238-1112-11e8-8e45-920c87bdbd75", "externalId": "00u1dhhb1fkIGP7RL1d8", "userName": "octocat@github.com", "displayName": "Mona Octocat", "name": { "givenName": "Mona", "familyName": "Octocat", "formatted": "Mona Octocat" }, "emails": [ { "value": "octocat@github.com", "primary": true } ], "active": true, "meta": { "resourceType": "User", "created": "2018-02-13T15:05:24.000-00:00", "lastModified": "2018-02-13T15:05:24.000-00:00", "location": "https://api.github.com/scim/v2/organizations/octo-org/Users/5fc0c238-1112-11e8-8e45-920c87bdbd75" } } ] }`)) }) ctx := context.Background() opts := &ListSCIMProvisionedIdentitiesOptions{} identities, _, err := client.SCIM.ListSCIMProvisionedIdentities(ctx, "o", opts) if err != nil { t.Errorf("SCIM.ListSCIMProvisionedIdentities returned error: %v", err) } date := Timestamp{time.Date(2018, time.February, 13, 15, 5, 24, 0, time.UTC)} want := SCIMProvisionedIdentities{ Schemas: []string{"urn:ietf:params:scim:api:messages:2.0:ListResponse"}, TotalResults: Int(1), ItemsPerPage: Int(1), StartIndex: Int(1), Resources: []*SCIMUserAttributes{ { ID: String("5fc0c238-1112-11e8-8e45-920c87bdbd75"), Meta: &SCIMMeta{ ResourceType: String("User"), Created: &date, LastModified: &date, Location: String("https://api.github.com/scim/v2/organizations/octo-org/Users/5fc0c238-1112-11e8-8e45-920c87bdbd75"), }, UserName: "octocat@github.com", Name: SCIMUserName{ GivenName: "Mona", FamilyName: "Octocat", Formatted: String("Mona Octocat"), }, DisplayName: String("Mona Octocat"), Emails: []*SCIMUserEmail{ { Value: "octocat@github.com", Primary: Bool(true), }, }, Schemas: []string{"urn:ietf:params:scim:schemas:core:2.0:User"}, ExternalID: String("00u1dhhb1fkIGP7RL1d8"), Groups: nil, Active: Bool(true), }, }, } if !cmp.Equal(identities, &want) { diff := cmp.Diff(identities, want) t.Errorf("SCIM.ListSCIMProvisionedIdentities returned %+v, want %+v: diff %+v", identities, want, diff) } const methodName = "ListSCIMProvisionedIdentities" testBadOptions(t, methodName, func() (err error) { _, _, err = client.SCIM.ListSCIMProvisionedIdentities(ctx, "\n", opts) return err }) testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { _, r, err := client.SCIM.ListSCIMProvisionedIdentities(ctx, "o", opts) return r, err }) } func TestSCIMService_ProvisionAndInviteSCIMUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/scim/v2/organizations/o/Users", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") w.WriteHeader(http.StatusOK) }) ctx := context.Background() opts := &SCIMUserAttributes{ UserName: "userName", Name: SCIMUserName{ GivenName: "givenName", FamilyName: "familyName", }, Emails: []*SCIMUserEmail{ { Value: "octocat@github.com", }, }, } _, err := client.SCIM.ProvisionAndInviteSCIMUser(ctx, "o", opts) if err != nil { t.Errorf("SCIM.ListSCIMProvisionedIdentities returned error: %v", err) } const methodName = "ProvisionAndInviteSCIMUser" testBadOptions(t, methodName, func() (err error) { _, err = client.SCIM.ProvisionAndInviteSCIMUser(ctx, "\n", opts) return err }) testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { return client.SCIM.ProvisionAndInviteSCIMUser(ctx, "o", opts) }) } func TestSCIMService_GetSCIMProvisioningInfoForUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/scim/v2/organizations/o/Users/123", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(`{ "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:User" ], "id": "edefdfedf-050c-11e7-8d32", "externalId": "a7d0f98382", "userName": "mona.octocat@okta.example.com", "displayName": "Mona Octocat", "name": { "givenName": "Mona", "familyName": "Octocat", "formatted": "Mona Octocat" }, "emails": [ { "value": "mona.octocat@okta.example.com", "primary": true }, { "value": "mona@octocat.github.com" } ], "active": true, "meta": { "resourceType": "User", "created": "2017-03-09T16:11:13-00:00", "lastModified": "2017-03-09T16:11:13-00:00", "location": "https://api.github.com/scim/v2/organizations/octo-org/Users/edefdfedf-050c-11e7-8d32" } }`)) }) ctx := context.Background() user, _, err := client.SCIM.GetSCIMProvisioningInfoForUser(ctx, "o", "123") if err != nil { t.Errorf("SCIM.GetSCIMProvisioningInfoForUser returned error: %v", err) } date := Timestamp{time.Date(2017, time.March, 9, 16, 11, 13, 0, time.UTC)} want := SCIMUserAttributes{ ID: String("edefdfedf-050c-11e7-8d32"), Meta: &SCIMMeta{ ResourceType: String("User"), Created: &date, LastModified: &date, Location: String("https://api.github.com/scim/v2/organizations/octo-org/Users/edefdfedf-050c-11e7-8d32"), }, UserName: "mona.octocat@okta.example.com", Name: SCIMUserName{ GivenName: "Mona", FamilyName: "Octocat", Formatted: String("Mona Octocat"), }, DisplayName: String("Mona Octocat"), Emails: []*SCIMUserEmail{ { Value: "mona.octocat@okta.example.com", Primary: Bool(true), }, { Value: "mona@octocat.github.com", }, }, Schemas: []string{"urn:ietf:params:scim:schemas:core:2.0:User"}, ExternalID: String("a7d0f98382"), Groups: nil, Active: Bool(true), } if !cmp.Equal(user, &want) { diff := cmp.Diff(user, want) t.Errorf("SCIM.ListSCIMProvisionedIdentities returned %+v, want %+v: diff %+v", user, want, diff) } const methodName = "GetSCIMProvisioningInfoForUser" testBadOptions(t, methodName, func() error { _, _, err := client.SCIM.GetSCIMProvisioningInfoForUser(ctx, "\n", "123") return err }) testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { _, r, err := client.SCIM.GetSCIMProvisioningInfoForUser(ctx, "o", "123") return r, err }) } func TestSCIMService_UpdateProvisionedOrgMembership(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/scim/v2/organizations/o/Users/123", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") w.WriteHeader(http.StatusOK) }) ctx := context.Background() opts := &SCIMUserAttributes{ UserName: "userName", Name: SCIMUserName{ GivenName: "givenName", FamilyName: "familyName", }, Emails: []*SCIMUserEmail{ { Value: "octocat@github.com", }, }, } _, err := client.SCIM.UpdateProvisionedOrgMembership(ctx, "o", "123", opts) if err != nil { t.Errorf("SCIM.UpdateProvisionedOrgMembership returned error: %v", err) } const methodName = "UpdateProvisionedOrgMembership" testBadOptions(t, methodName, func() error { _, err := client.SCIM.UpdateProvisionedOrgMembership(ctx, "\n", "123", opts) return err }) testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { return client.SCIM.UpdateProvisionedOrgMembership(ctx, "o", "123", opts) }) } func TestSCIMService_UpdateAttributeForSCIMUser(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/scim/v2/organizations/o/Users/123", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PATCH") w.WriteHeader(http.StatusNoContent) }) ctx := context.Background() opts := &UpdateAttributeForSCIMUserOptions{} _, err := client.SCIM.UpdateAttributeForSCIMUser(ctx, "o", "123", opts) if err != nil { t.Errorf("SCIM.UpdateAttributeForSCIMUser returned error: %v", err) } const methodName = "UpdateAttributeForSCIMUser" testBadOptions(t, methodName, func() error { _, err := client.SCIM.UpdateAttributeForSCIMUser(ctx, "\n", "123", opts) return err }) testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { return client.SCIM.UpdateAttributeForSCIMUser(ctx, "o", "123", opts) }) } func TestSCIMService_DeleteSCIMUserFromOrg(t *testing.T) { client, mux, _, teardown := setup() defer teardown() mux.HandleFunc("/scim/v2/organizations/o/Users/123", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") w.WriteHeader(http.StatusNoContent) }) ctx := context.Background() _, err := client.SCIM.DeleteSCIMUserFromOrg(ctx, "o", "123") if err != nil { t.Errorf("SCIM.DeleteSCIMUserFromOrg returned error: %v", err) } const methodName = "DeleteSCIMUserFromOrg" testBadOptions(t, methodName, func() error { _, err := client.SCIM.DeleteSCIMUserFromOrg(ctx, "\n", "") return err }) testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { return client.SCIM.DeleteSCIMUserFromOrg(ctx, "o", "123") }) } func TestSCIMUserAttributes_Marshal(t *testing.T) { testJSONMarshal(t, &SCIMUserAttributes{}, `{ "userName":"","name":{"givenName":"","familyName":""},"emails":null }`) u := &SCIMUserAttributes{ UserName: "userName1", Name: SCIMUserName{ GivenName: "Name1", FamilyName: "Fname", Formatted: String("formatted name"), }, DisplayName: String("Name"), Emails: []*SCIMUserEmail{ { Value: "value", Primary: Bool(false), Type: String("type"), }, }, Schemas: []string{"schema1"}, ExternalID: String("id"), Groups: []string{"group1"}, Active: Bool(true), } want := `{ "userName": "userName1", "name": { "givenName": "Name1", "familyName": "Fname", "formatted": "formatted name" }, "displayName": "Name", "emails": [{ "value": "value", "primary": false, "type": "type" }], "schemas": ["schema1"], "externalId": "id", "groups": ["group1"], "active": true }` testJSONMarshal(t, u, want) } func TestUpdateAttributeForSCIMUserOperations_Marshal(t *testing.T) { testJSONMarshal(t, &UpdateAttributeForSCIMUserOperations{}, `{}`) u := &UpdateAttributeForSCIMUserOperations{ Op: "TestOp", Path: String("path"), } want := `{ "op": "TestOp", "path": "path" }` testJSONMarshal(t, u, want) } func TestUpdateAttributeForSCIMUserOptions_Marshal(t *testing.T) { testJSONMarshal(t, &UpdateAttributeForSCIMUserOptions{}, `{}`) u := &UpdateAttributeForSCIMUserOptions{ Schemas: []string{"test", "schema"}, Operations: UpdateAttributeForSCIMUserOperations{ Op: "TestOp", Path: String("path"), }, } want := `{ "schemas": ["test", "schema"], "operations": { "op": "TestOp", "path": "path" } }` testJSONMarshal(t, u, want) } func TestListSCIMProvisionedIdentitiesOptions_addOptions(t *testing.T) { testJSONMarshal(t, &ListSCIMProvisionedIdentitiesOptions{}, `{ "StartIndex": null, "Count": null, "Filter": null }`) url := "some/path" testAddURLOptions(t, url, &ListSCIMProvisionedIdentitiesOptions{}, url) testAddURLOptions( t, url, &ListSCIMProvisionedIdentitiesOptions{ StartIndex: Int(1), Count: Int(10), }, fmt.Sprintf("%s?count=10&startIndex=1", url), ) testAddURLOptions( t, url, &ListSCIMProvisionedIdentitiesOptions{ StartIndex: Int(1), Count: Int(10), Filter: String("test"), }, fmt.Sprintf("%s?count=10&filter=test&startIndex=1", url), ) } func TestSCIMUserName_Marshal(t *testing.T) { testJSONMarshal(t, &SCIMUserName{}, `{ "givenName":"","familyName":"" }`) u := &SCIMUserName{ GivenName: "Name1", FamilyName: "Fname", Formatted: String("formatted name"), } want := `{ "givenName": "Name1", "familyName": "Fname", "formatted": "formatted name" }` testJSONMarshal(t, u, want) } func TestSCIMMeta_Marshal(t *testing.T) { testJSONMarshal(t, &SCIMMeta{}, `{}`) u := &SCIMMeta{ ResourceType: String("test"), Location: String("test"), } want := `{ "resourceType": "test", "location": "test" }` testJSONMarshal(t, u, want) } func TestSCIMProvisionedIdentities_Marshal(t *testing.T) { testJSONMarshal(t, &SCIMProvisionedIdentities{}, `{}`) u := &SCIMProvisionedIdentities{ Schemas: []string{"test", "schema"}, TotalResults: Int(1), ItemsPerPage: Int(2), StartIndex: Int(1), Resources: []*SCIMUserAttributes{ { UserName: "SCIM", Name: SCIMUserName{ GivenName: "scim", FamilyName: "test", Formatted: String("SCIM"), }, DisplayName: String("Test SCIM"), Emails: []*SCIMUserEmail{ { Value: "test", Primary: Bool(true), Type: String("test"), }, }, Schemas: []string{"schema1"}, ExternalID: String("id"), Groups: []string{"group1"}, Active: Bool(true), }, }, } want := `{ "schemas": ["test", "schema"], "totalResults": 1, "itemsPerPage": 2, "startIndex": 1, "Resources": [{ "userName": "SCIM", "name": { "givenName": "scim", "familyName": "test", "formatted": "SCIM" }, "displayName": "Test SCIM", "emails": [{ "value": "test", "primary": true, "type": "test" }], "schemas": ["schema1"], "externalId": "id", "groups": ["group1"], "active": true }] }` testJSONMarshal(t, u, want) }