github.com/google/go-github/v49@v49.1.0/github/scim_test.go (about)

     1  // Copyright 2021 The go-github AUTHORS. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package github
     7  
     8  import (
     9  	"context"
    10  	"net/http"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/google/go-cmp/cmp"
    15  )
    16  
    17  func TestSCIMService_ListSCIMProvisionedIdentities(t *testing.T) {
    18  	client, mux, _, teardown := setup()
    19  	defer teardown()
    20  
    21  	mux.HandleFunc("/scim/v2/organizations/o/Users", func(w http.ResponseWriter, r *http.Request) {
    22  		testMethod(t, r, "GET")
    23  		w.WriteHeader(http.StatusOK)
    24  		_, _ = w.Write([]byte(`{
    25  			"schemas": [
    26  			  "urn:ietf:params:scim:api:messages:2.0:ListResponse"
    27  			],
    28  			"totalResults": 1,
    29  			"itemsPerPage": 1,
    30  			"startIndex": 1,
    31  			"Resources": [
    32  			  {
    33  				"schemas": [
    34  				  "urn:ietf:params:scim:schemas:core:2.0:User"
    35  				],
    36  				"id": "5fc0c238-1112-11e8-8e45-920c87bdbd75",
    37  				"externalId": "00u1dhhb1fkIGP7RL1d8",
    38  				"userName": "octocat@github.com",
    39  				"displayName": "Mona Octocat",
    40  				"name": {
    41  				  "givenName": "Mona",
    42  				  "familyName": "Octocat",
    43  				  "formatted": "Mona Octocat"
    44  				},
    45  				"emails": [
    46  				  {
    47  					"value": "octocat@github.com",
    48  					"primary": true
    49  				  }
    50  				],
    51  				"active": true,
    52  				"meta": {
    53  				  "resourceType": "User",
    54  				  "created": "2018-02-13T15:05:24.000-00:00",
    55  				  "lastModified": "2018-02-13T15:05:24.000-00:00",
    56  				  "location": "https://api.github.com/scim/v2/organizations/octo-org/Users/5fc0c238-1112-11e8-8e45-920c87bdbd75"
    57  				}
    58  			  }
    59  			]
    60  		  }`))
    61  	})
    62  
    63  	ctx := context.Background()
    64  	opts := &ListSCIMProvisionedIdentitiesOptions{}
    65  	identities, _, err := client.SCIM.ListSCIMProvisionedIdentities(ctx, "o", opts)
    66  	if err != nil {
    67  		t.Errorf("SCIM.ListSCIMProvisionedIdentities returned error: %v", err)
    68  	}
    69  
    70  	date := Timestamp{time.Date(2018, time.February, 13, 15, 5, 24, 0, time.UTC)}
    71  	want := SCIMProvisionedIdentities{
    72  		Schemas:      []string{"urn:ietf:params:scim:api:messages:2.0:ListResponse"},
    73  		TotalResults: Int(1),
    74  		ItemsPerPage: Int(1),
    75  		StartIndex:   Int(1),
    76  		Resources: []*SCIMUserAttributes{
    77  			{
    78  				ID: String("5fc0c238-1112-11e8-8e45-920c87bdbd75"),
    79  				Meta: &SCIMMeta{
    80  					ResourceType: String("User"),
    81  					Created:      &date,
    82  					LastModified: &date,
    83  					Location:     String("https://api.github.com/scim/v2/organizations/octo-org/Users/5fc0c238-1112-11e8-8e45-920c87bdbd75"),
    84  				},
    85  				UserName: "octocat@github.com",
    86  				Name: SCIMUserName{
    87  					GivenName:  "Mona",
    88  					FamilyName: "Octocat",
    89  					Formatted:  String("Mona Octocat"),
    90  				},
    91  				DisplayName: String("Mona Octocat"),
    92  				Emails: []*SCIMUserEmail{
    93  					{
    94  						Value:   "octocat@github.com",
    95  						Primary: Bool(true),
    96  					},
    97  				},
    98  				Schemas:    []string{"urn:ietf:params:scim:schemas:core:2.0:User"},
    99  				ExternalID: String("00u1dhhb1fkIGP7RL1d8"),
   100  				Groups:     nil,
   101  				Active:     Bool(true),
   102  			},
   103  		},
   104  	}
   105  
   106  	if !cmp.Equal(identities, &want) {
   107  		diff := cmp.Diff(identities, want)
   108  		t.Errorf("SCIM.ListSCIMProvisionedIdentities returned %+v, want %+v: diff %+v", identities, want, diff)
   109  	}
   110  
   111  	const methodName = "ListSCIMProvisionedIdentities"
   112  	testBadOptions(t, methodName, func() (err error) {
   113  		_, _, err = client.SCIM.ListSCIMProvisionedIdentities(ctx, "\n", opts)
   114  		return err
   115  	})
   116  
   117  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   118  		_, r, err := client.SCIM.ListSCIMProvisionedIdentities(ctx, "o", opts)
   119  		return r, err
   120  	})
   121  }
   122  
   123  func TestSCIMService_ProvisionAndInviteSCIMUser(t *testing.T) {
   124  	client, mux, _, teardown := setup()
   125  	defer teardown()
   126  
   127  	mux.HandleFunc("/scim/v2/organizations/o/Users", func(w http.ResponseWriter, r *http.Request) {
   128  		testMethod(t, r, "POST")
   129  		w.WriteHeader(http.StatusOK)
   130  	})
   131  
   132  	ctx := context.Background()
   133  	opts := &SCIMUserAttributes{
   134  		UserName: "userName",
   135  		Name: SCIMUserName{
   136  			GivenName:  "givenName",
   137  			FamilyName: "familyName",
   138  		},
   139  		Emails: []*SCIMUserEmail{
   140  			{
   141  				Value: "octocat@github.com",
   142  			},
   143  		},
   144  	}
   145  	_, err := client.SCIM.ProvisionAndInviteSCIMUser(ctx, "o", opts)
   146  	if err != nil {
   147  		t.Errorf("SCIM.ListSCIMProvisionedIdentities returned error: %v", err)
   148  	}
   149  
   150  	const methodName = "ProvisionAndInviteSCIMUser"
   151  	testBadOptions(t, methodName, func() (err error) {
   152  		_, err = client.SCIM.ProvisionAndInviteSCIMUser(ctx, "\n", opts)
   153  		return err
   154  	})
   155  
   156  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   157  		return client.SCIM.ProvisionAndInviteSCIMUser(ctx, "o", opts)
   158  	})
   159  }
   160  
   161  func TestSCIMService_GetSCIMProvisioningInfoForUser(t *testing.T) {
   162  	client, mux, _, teardown := setup()
   163  	defer teardown()
   164  
   165  	mux.HandleFunc("/scim/v2/organizations/o/Users/123", func(w http.ResponseWriter, r *http.Request) {
   166  		testMethod(t, r, "GET")
   167  		w.WriteHeader(http.StatusOK)
   168  		_, _ = w.Write([]byte(`{
   169  			"schemas": [
   170  			  "urn:ietf:params:scim:schemas:core:2.0:User"
   171  			],
   172  			"id": "edefdfedf-050c-11e7-8d32",
   173  			"externalId": "a7d0f98382",
   174  			"userName": "mona.octocat@okta.example.com",
   175  			"displayName": "Mona Octocat",
   176  			"name": {
   177  			  "givenName": "Mona",
   178  			  "familyName": "Octocat",
   179  			  "formatted": "Mona Octocat"
   180  			},
   181  			"emails": [
   182  			  {
   183  				"value": "mona.octocat@okta.example.com",
   184  				"primary": true
   185  			  },
   186  			  {
   187  				"value": "mona@octocat.github.com"
   188  			  }
   189  			],
   190  			"active": true,
   191  			"meta": {
   192  			  "resourceType": "User",
   193  			  "created": "2017-03-09T16:11:13-00:00",
   194  			  "lastModified": "2017-03-09T16:11:13-00:00",
   195  			  "location": "https://api.github.com/scim/v2/organizations/octo-org/Users/edefdfedf-050c-11e7-8d32"
   196  			}
   197  		  }`))
   198  	})
   199  
   200  	ctx := context.Background()
   201  	user, _, err := client.SCIM.GetSCIMProvisioningInfoForUser(ctx, "o", "123")
   202  	if err != nil {
   203  		t.Errorf("SCIM.GetSCIMProvisioningInfoForUser returned error: %v", err)
   204  	}
   205  
   206  	date := Timestamp{time.Date(2017, time.March, 9, 16, 11, 13, 0, time.UTC)}
   207  	want := SCIMUserAttributes{
   208  		ID: String("edefdfedf-050c-11e7-8d32"),
   209  		Meta: &SCIMMeta{
   210  			ResourceType: String("User"),
   211  			Created:      &date,
   212  			LastModified: &date,
   213  			Location:     String("https://api.github.com/scim/v2/organizations/octo-org/Users/edefdfedf-050c-11e7-8d32"),
   214  		},
   215  		UserName: "mona.octocat@okta.example.com",
   216  		Name: SCIMUserName{
   217  			GivenName:  "Mona",
   218  			FamilyName: "Octocat",
   219  			Formatted:  String("Mona Octocat"),
   220  		},
   221  		DisplayName: String("Mona Octocat"),
   222  		Emails: []*SCIMUserEmail{
   223  			{
   224  				Value:   "mona.octocat@okta.example.com",
   225  				Primary: Bool(true),
   226  			},
   227  			{
   228  				Value: "mona@octocat.github.com",
   229  			},
   230  		},
   231  		Schemas:    []string{"urn:ietf:params:scim:schemas:core:2.0:User"},
   232  		ExternalID: String("a7d0f98382"),
   233  		Groups:     nil,
   234  		Active:     Bool(true),
   235  	}
   236  
   237  	if !cmp.Equal(user, &want) {
   238  		diff := cmp.Diff(user, want)
   239  		t.Errorf("SCIM.ListSCIMProvisionedIdentities returned %+v, want %+v: diff %+v", user, want, diff)
   240  	}
   241  
   242  	const methodName = "GetSCIMProvisioningInfoForUser"
   243  	testBadOptions(t, methodName, func() error {
   244  		_, _, err := client.SCIM.GetSCIMProvisioningInfoForUser(ctx, "\n", "123")
   245  		return err
   246  	})
   247  
   248  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   249  		_, r, err := client.SCIM.GetSCIMProvisioningInfoForUser(ctx, "o", "123")
   250  		return r, err
   251  	})
   252  }
   253  
   254  func TestSCIMService_UpdateProvisionedOrgMembership(t *testing.T) {
   255  	client, mux, _, teardown := setup()
   256  	defer teardown()
   257  
   258  	mux.HandleFunc("/scim/v2/organizations/o/Users/123", func(w http.ResponseWriter, r *http.Request) {
   259  		testMethod(t, r, "PUT")
   260  		w.WriteHeader(http.StatusOK)
   261  	})
   262  
   263  	ctx := context.Background()
   264  	opts := &SCIMUserAttributes{
   265  		UserName: "userName",
   266  		Name: SCIMUserName{
   267  			GivenName:  "givenName",
   268  			FamilyName: "familyName",
   269  		},
   270  		Emails: []*SCIMUserEmail{
   271  			{
   272  				Value: "octocat@github.com",
   273  			},
   274  		},
   275  	}
   276  	_, err := client.SCIM.UpdateProvisionedOrgMembership(ctx, "o", "123", opts)
   277  	if err != nil {
   278  		t.Errorf("SCIM.UpdateProvisionedOrgMembership returned error: %v", err)
   279  	}
   280  
   281  	const methodName = "UpdateProvisionedOrgMembership"
   282  	testBadOptions(t, methodName, func() error {
   283  		_, err := client.SCIM.UpdateProvisionedOrgMembership(ctx, "\n", "123", opts)
   284  		return err
   285  	})
   286  
   287  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   288  		return client.SCIM.UpdateProvisionedOrgMembership(ctx, "o", "123", opts)
   289  	})
   290  }
   291  
   292  func TestSCIMService_UpdateAttributeForSCIMUser(t *testing.T) {
   293  	client, mux, _, teardown := setup()
   294  	defer teardown()
   295  
   296  	mux.HandleFunc("/scim/v2/organizations/o/Users/123", func(w http.ResponseWriter, r *http.Request) {
   297  		testMethod(t, r, "PATCH")
   298  		w.WriteHeader(http.StatusNoContent)
   299  	})
   300  
   301  	ctx := context.Background()
   302  	opts := &UpdateAttributeForSCIMUserOptions{}
   303  	_, err := client.SCIM.UpdateAttributeForSCIMUser(ctx, "o", "123", opts)
   304  	if err != nil {
   305  		t.Errorf("SCIM.UpdateAttributeForSCIMUser returned error: %v", err)
   306  	}
   307  
   308  	const methodName = "UpdateAttributeForSCIMUser"
   309  	testBadOptions(t, methodName, func() error {
   310  		_, err := client.SCIM.UpdateAttributeForSCIMUser(ctx, "\n", "123", opts)
   311  		return err
   312  	})
   313  
   314  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   315  		return client.SCIM.UpdateAttributeForSCIMUser(ctx, "o", "123", opts)
   316  	})
   317  }
   318  
   319  func TestSCIMService_DeleteSCIMUserFromOrg(t *testing.T) {
   320  	client, mux, _, teardown := setup()
   321  	defer teardown()
   322  
   323  	mux.HandleFunc("/scim/v2/organizations/o/Users/123", func(w http.ResponseWriter, r *http.Request) {
   324  		testMethod(t, r, "DELETE")
   325  		w.WriteHeader(http.StatusNoContent)
   326  	})
   327  
   328  	ctx := context.Background()
   329  	_, err := client.SCIM.DeleteSCIMUserFromOrg(ctx, "o", "123")
   330  	if err != nil {
   331  		t.Errorf("SCIM.DeleteSCIMUserFromOrg returned error: %v", err)
   332  	}
   333  
   334  	const methodName = "DeleteSCIMUserFromOrg"
   335  	testBadOptions(t, methodName, func() error {
   336  		_, err := client.SCIM.DeleteSCIMUserFromOrg(ctx, "\n", "")
   337  		return err
   338  	})
   339  
   340  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   341  		return client.SCIM.DeleteSCIMUserFromOrg(ctx, "o", "123")
   342  	})
   343  }
   344  
   345  func TestSCIMUserAttributes_Marshal(t *testing.T) {
   346  	testJSONMarshal(t, &SCIMUserAttributes{}, `{
   347  		"userName":"","name":{"givenName":"","familyName":""},"emails":null
   348  	}`)
   349  
   350  	u := &SCIMUserAttributes{
   351  		UserName: "userName1",
   352  		Name: SCIMUserName{
   353  			GivenName:  "Name1",
   354  			FamilyName: "Fname",
   355  			Formatted:  String("formatted name"),
   356  		},
   357  		DisplayName: String("Name"),
   358  		Emails: []*SCIMUserEmail{
   359  			{
   360  				Value:   "value",
   361  				Primary: Bool(false),
   362  				Type:    String("type"),
   363  			},
   364  		},
   365  		Schemas:    []string{"schema1"},
   366  		ExternalID: String("id"),
   367  		Groups:     []string{"group1"},
   368  		Active:     Bool(true),
   369  	}
   370  
   371  	want := `{
   372  		"userName": "userName1",
   373  		"name": {
   374  			"givenName": "Name1",
   375  			"familyName": "Fname",
   376  			"formatted": "formatted name"
   377  		},
   378  		"displayName": "Name",
   379  		"emails": [{
   380  			"value": "value",
   381  			"primary": false,
   382  			"type": "type"
   383  		}],
   384  		"schemas": ["schema1"],
   385  		"externalId": "id",
   386  		"groups": ["group1"],
   387  		"active": true
   388  	}`
   389  
   390  	testJSONMarshal(t, u, want)
   391  }
   392  
   393  func TestUpdateAttributeForSCIMUserOperations_Marshal(t *testing.T) {
   394  	testJSONMarshal(t, &UpdateAttributeForSCIMUserOperations{}, `{}`)
   395  
   396  	u := &UpdateAttributeForSCIMUserOperations{
   397  		Op:   "TestOp",
   398  		Path: String("path"),
   399  	}
   400  
   401  	want := `{
   402  		"op": "TestOp",
   403  		"path": "path"
   404  	}`
   405  
   406  	testJSONMarshal(t, u, want)
   407  }
   408  
   409  func TestUpdateAttributeForSCIMUserOptions_Marshal(t *testing.T) {
   410  	testJSONMarshal(t, &UpdateAttributeForSCIMUserOptions{}, `{}`)
   411  
   412  	u := &UpdateAttributeForSCIMUserOptions{
   413  		Schemas: []string{"test", "schema"},
   414  		Operations: UpdateAttributeForSCIMUserOperations{
   415  			Op:   "TestOp",
   416  			Path: String("path"),
   417  		},
   418  	}
   419  
   420  	want := `{
   421  		"schemas": ["test", "schema"],
   422  		"operations": {
   423  			"op": "TestOp",
   424  			"path": "path"
   425  		}
   426  	}`
   427  
   428  	testJSONMarshal(t, u, want)
   429  }
   430  
   431  func TestListSCIMProvisionedIdentitiesOptions_Marshal(t *testing.T) {
   432  	testJSONMarshal(t, &ListSCIMProvisionedIdentitiesOptions{}, `{}`)
   433  
   434  	u := &ListSCIMProvisionedIdentitiesOptions{
   435  		StartIndex: Int(1),
   436  		Count:      Int(10),
   437  		Filter:     String("test"),
   438  	}
   439  
   440  	want := `{
   441  		"startIndex": 1,
   442  		"count": 10,
   443  	 	"filter": "test"
   444  	}`
   445  
   446  	testJSONMarshal(t, u, want)
   447  }
   448  
   449  func TestSCIMUserName_Marshal(t *testing.T) {
   450  	testJSONMarshal(t, &SCIMUserName{}, `{
   451  		"givenName":"","familyName":""
   452  	}`)
   453  
   454  	u := &SCIMUserName{
   455  		GivenName:  "Name1",
   456  		FamilyName: "Fname",
   457  		Formatted:  String("formatted name"),
   458  	}
   459  
   460  	want := `{
   461  			"givenName": "Name1",
   462  			"familyName": "Fname",
   463  			"formatted": "formatted name"	
   464  	}`
   465  	testJSONMarshal(t, u, want)
   466  }
   467  
   468  func TestSCIMMeta_Marshal(t *testing.T) {
   469  	testJSONMarshal(t, &SCIMMeta{}, `{}`)
   470  
   471  	u := &SCIMMeta{
   472  		ResourceType: String("test"),
   473  		Location:     String("test"),
   474  	}
   475  
   476  	want := `{
   477  		"resourceType": "test",
   478  		"location": "test"
   479  	}`
   480  
   481  	testJSONMarshal(t, u, want)
   482  }
   483  
   484  func TestSCIMProvisionedIdentities_Marshal(t *testing.T) {
   485  	testJSONMarshal(t, &SCIMProvisionedIdentities{}, `{}`)
   486  
   487  	u := &SCIMProvisionedIdentities{
   488  		Schemas:      []string{"test", "schema"},
   489  		TotalResults: Int(1),
   490  		ItemsPerPage: Int(2),
   491  		StartIndex:   Int(1),
   492  		Resources: []*SCIMUserAttributes{
   493  			{
   494  				UserName: "SCIM",
   495  				Name: SCIMUserName{
   496  					GivenName:  "scim",
   497  					FamilyName: "test",
   498  					Formatted:  String("SCIM"),
   499  				},
   500  				DisplayName: String("Test SCIM"),
   501  				Emails: []*SCIMUserEmail{
   502  					{
   503  						Value:   "test",
   504  						Primary: Bool(true),
   505  						Type:    String("test"),
   506  					},
   507  				},
   508  				Schemas:    []string{"schema1"},
   509  				ExternalID: String("id"),
   510  				Groups:     []string{"group1"},
   511  				Active:     Bool(true),
   512  			},
   513  		},
   514  	}
   515  
   516  	want := `{
   517  		"schemas": ["test", "schema"],
   518  		"totalResults": 1,
   519  		"itemsPerPage": 2,
   520  		"startIndex": 1,
   521  		"Resources": [{
   522  			"userName": "SCIM",
   523  			"name": {
   524  				"givenName": "scim",
   525  				"familyName": "test",
   526  				"formatted": "SCIM"
   527  			},
   528  			"displayName": "Test SCIM",
   529  			"emails": [{
   530  				"value": "test",
   531  				"primary": true,
   532  				"type": "test"
   533  			}],
   534  			"schemas": ["schema1"],
   535  			"externalId": "id",
   536  			"groups": ["group1"],
   537  			"active": true
   538  		}]
   539  	}`
   540  
   541  	testJSONMarshal(t, u, want)
   542  }