mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 16:51:55 +00:00
azuredevops: Add client method ListAuthorizedUserOrganizations (#48572)
This commit is contained in:
parent
4549d045cb
commit
7d2d2a0094
129
enterprise/internal/batches/sources/mocks_test.go
generated
129
enterprise/internal/batches/sources/mocks_test.go
generated
@ -5728,6 +5728,10 @@ type MockAzureDevOpsClient struct {
|
||||
// IsAzureDevOpsServicesFunc is an instance of a mock function object
|
||||
// controlling the behavior of the method IsAzureDevOpsServices.
|
||||
IsAzureDevOpsServicesFunc *AzureDevOpsClientIsAzureDevOpsServicesFunc
|
||||
// ListAuthorizedUserOrganizationsFunc is an instance of a mock function
|
||||
// object controlling the behavior of the method
|
||||
// ListAuthorizedUserOrganizations.
|
||||
ListAuthorizedUserOrganizationsFunc *AzureDevOpsClientListAuthorizedUserOrganizationsFunc
|
||||
// ListRepositoriesByProjectOrOrgFunc is an instance of a mock function
|
||||
// object controlling the behavior of the method
|
||||
// ListRepositoriesByProjectOrOrg.
|
||||
@ -5814,6 +5818,11 @@ func NewMockAzureDevOpsClient() *MockAzureDevOpsClient {
|
||||
return
|
||||
},
|
||||
},
|
||||
ListAuthorizedUserOrganizationsFunc: &AzureDevOpsClientListAuthorizedUserOrganizationsFunc{
|
||||
defaultHook: func(context.Context, azuredevops.Profile) (r0 []azuredevops.Org, r1 error) {
|
||||
return
|
||||
},
|
||||
},
|
||||
ListRepositoriesByProjectOrOrgFunc: &AzureDevOpsClientListRepositoriesByProjectOrOrgFunc{
|
||||
defaultHook: func(context.Context, azuredevops.ListRepositoriesByProjectOrOrgArgs) (r0 []azuredevops.Repository, r1 error) {
|
||||
return
|
||||
@ -5906,6 +5915,11 @@ func NewStrictMockAzureDevOpsClient() *MockAzureDevOpsClient {
|
||||
panic("unexpected invocation of MockAzureDevOpsClient.IsAzureDevOpsServices")
|
||||
},
|
||||
},
|
||||
ListAuthorizedUserOrganizationsFunc: &AzureDevOpsClientListAuthorizedUserOrganizationsFunc{
|
||||
defaultHook: func(context.Context, azuredevops.Profile) ([]azuredevops.Org, error) {
|
||||
panic("unexpected invocation of MockAzureDevOpsClient.ListAuthorizedUserOrganizations")
|
||||
},
|
||||
},
|
||||
ListRepositoriesByProjectOrOrgFunc: &AzureDevOpsClientListRepositoriesByProjectOrOrgFunc{
|
||||
defaultHook: func(context.Context, azuredevops.ListRepositoriesByProjectOrOrgArgs) ([]azuredevops.Repository, error) {
|
||||
panic("unexpected invocation of MockAzureDevOpsClient.ListRepositoriesByProjectOrOrg")
|
||||
@ -5971,6 +5985,9 @@ func NewMockAzureDevOpsClientFrom(i azuredevops.Client) *MockAzureDevOpsClient {
|
||||
IsAzureDevOpsServicesFunc: &AzureDevOpsClientIsAzureDevOpsServicesFunc{
|
||||
defaultHook: i.IsAzureDevOpsServices,
|
||||
},
|
||||
ListAuthorizedUserOrganizationsFunc: &AzureDevOpsClientListAuthorizedUserOrganizationsFunc{
|
||||
defaultHook: i.ListAuthorizedUserOrganizations,
|
||||
},
|
||||
ListRepositoriesByProjectOrOrgFunc: &AzureDevOpsClientListRepositoriesByProjectOrOrgFunc{
|
||||
defaultHook: i.ListRepositoriesByProjectOrOrg,
|
||||
},
|
||||
@ -7522,6 +7539,118 @@ func (c AzureDevOpsClientIsAzureDevOpsServicesFuncCall) Results() []interface{}
|
||||
return []interface{}{c.Result0}
|
||||
}
|
||||
|
||||
// AzureDevOpsClientListAuthorizedUserOrganizationsFunc describes the
|
||||
// behavior when the ListAuthorizedUserOrganizations method of the parent
|
||||
// MockAzureDevOpsClient instance is invoked.
|
||||
type AzureDevOpsClientListAuthorizedUserOrganizationsFunc struct {
|
||||
defaultHook func(context.Context, azuredevops.Profile) ([]azuredevops.Org, error)
|
||||
hooks []func(context.Context, azuredevops.Profile) ([]azuredevops.Org, error)
|
||||
history []AzureDevOpsClientListAuthorizedUserOrganizationsFuncCall
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
// ListAuthorizedUserOrganizations delegates to the next hook function in
|
||||
// the queue and stores the parameter and result values of this invocation.
|
||||
func (m *MockAzureDevOpsClient) ListAuthorizedUserOrganizations(v0 context.Context, v1 azuredevops.Profile) ([]azuredevops.Org, error) {
|
||||
r0, r1 := m.ListAuthorizedUserOrganizationsFunc.nextHook()(v0, v1)
|
||||
m.ListAuthorizedUserOrganizationsFunc.appendCall(AzureDevOpsClientListAuthorizedUserOrganizationsFuncCall{v0, v1, r0, r1})
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SetDefaultHook sets function that is called when the
|
||||
// ListAuthorizedUserOrganizations method of the parent
|
||||
// MockAzureDevOpsClient instance is invoked and the hook queue is empty.
|
||||
func (f *AzureDevOpsClientListAuthorizedUserOrganizationsFunc) SetDefaultHook(hook func(context.Context, azuredevops.Profile) ([]azuredevops.Org, error)) {
|
||||
f.defaultHook = hook
|
||||
}
|
||||
|
||||
// PushHook adds a function to the end of hook queue. Each invocation of the
|
||||
// ListAuthorizedUserOrganizations method of the parent
|
||||
// MockAzureDevOpsClient instance invokes the hook at the front of the queue
|
||||
// and discards it. After the queue is empty, the default hook function is
|
||||
// invoked for any future action.
|
||||
func (f *AzureDevOpsClientListAuthorizedUserOrganizationsFunc) PushHook(hook func(context.Context, azuredevops.Profile) ([]azuredevops.Org, error)) {
|
||||
f.mutex.Lock()
|
||||
f.hooks = append(f.hooks, hook)
|
||||
f.mutex.Unlock()
|
||||
}
|
||||
|
||||
// SetDefaultReturn calls SetDefaultHook with a function that returns the
|
||||
// given values.
|
||||
func (f *AzureDevOpsClientListAuthorizedUserOrganizationsFunc) SetDefaultReturn(r0 []azuredevops.Org, r1 error) {
|
||||
f.SetDefaultHook(func(context.Context, azuredevops.Profile) ([]azuredevops.Org, error) {
|
||||
return r0, r1
|
||||
})
|
||||
}
|
||||
|
||||
// PushReturn calls PushHook with a function that returns the given values.
|
||||
func (f *AzureDevOpsClientListAuthorizedUserOrganizationsFunc) PushReturn(r0 []azuredevops.Org, r1 error) {
|
||||
f.PushHook(func(context.Context, azuredevops.Profile) ([]azuredevops.Org, error) {
|
||||
return r0, r1
|
||||
})
|
||||
}
|
||||
|
||||
func (f *AzureDevOpsClientListAuthorizedUserOrganizationsFunc) nextHook() func(context.Context, azuredevops.Profile) ([]azuredevops.Org, error) {
|
||||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
|
||||
if len(f.hooks) == 0 {
|
||||
return f.defaultHook
|
||||
}
|
||||
|
||||
hook := f.hooks[0]
|
||||
f.hooks = f.hooks[1:]
|
||||
return hook
|
||||
}
|
||||
|
||||
func (f *AzureDevOpsClientListAuthorizedUserOrganizationsFunc) appendCall(r0 AzureDevOpsClientListAuthorizedUserOrganizationsFuncCall) {
|
||||
f.mutex.Lock()
|
||||
f.history = append(f.history, r0)
|
||||
f.mutex.Unlock()
|
||||
}
|
||||
|
||||
// History returns a sequence of
|
||||
// AzureDevOpsClientListAuthorizedUserOrganizationsFuncCall objects
|
||||
// describing the invocations of this function.
|
||||
func (f *AzureDevOpsClientListAuthorizedUserOrganizationsFunc) History() []AzureDevOpsClientListAuthorizedUserOrganizationsFuncCall {
|
||||
f.mutex.Lock()
|
||||
history := make([]AzureDevOpsClientListAuthorizedUserOrganizationsFuncCall, len(f.history))
|
||||
copy(history, f.history)
|
||||
f.mutex.Unlock()
|
||||
|
||||
return history
|
||||
}
|
||||
|
||||
// AzureDevOpsClientListAuthorizedUserOrganizationsFuncCall is an object
|
||||
// that describes an invocation of method ListAuthorizedUserOrganizations on
|
||||
// an instance of MockAzureDevOpsClient.
|
||||
type AzureDevOpsClientListAuthorizedUserOrganizationsFuncCall struct {
|
||||
// Arg0 is the value of the 1st argument passed to this method
|
||||
// invocation.
|
||||
Arg0 context.Context
|
||||
// Arg1 is the value of the 2nd argument passed to this method
|
||||
// invocation.
|
||||
Arg1 azuredevops.Profile
|
||||
// Result0 is the value of the 1st result returned from this method
|
||||
// invocation.
|
||||
Result0 []azuredevops.Org
|
||||
// Result1 is the value of the 2nd result returned from this method
|
||||
// invocation.
|
||||
Result1 error
|
||||
}
|
||||
|
||||
// Args returns an interface slice containing the arguments of this
|
||||
// invocation.
|
||||
func (c AzureDevOpsClientListAuthorizedUserOrganizationsFuncCall) Args() []interface{} {
|
||||
return []interface{}{c.Arg0, c.Arg1}
|
||||
}
|
||||
|
||||
// Results returns an interface slice containing the results of this
|
||||
// invocation.
|
||||
func (c AzureDevOpsClientListAuthorizedUserOrganizationsFuncCall) Results() []interface{} {
|
||||
return []interface{}{c.Result0, c.Result1}
|
||||
}
|
||||
|
||||
// AzureDevOpsClientListRepositoriesByProjectOrOrgFunc describes the
|
||||
// behavior when the ListRepositoriesByProjectOrOrg method of the parent
|
||||
// MockAzureDevOpsClient instance is invoked.
|
||||
|
||||
@ -46,6 +46,7 @@ type Client interface {
|
||||
GetRepositoryBranch(ctx context.Context, args OrgProjectRepoArgs, branchName string) (Ref, error)
|
||||
GetProject(ctx context.Context, org, project string) (Project, error)
|
||||
GetAuthorizedProfile(ctx context.Context) (Profile, error)
|
||||
ListAuthorizedUserOrganizations(ctx context.Context, profile Profile) ([]Org, error)
|
||||
}
|
||||
|
||||
type client struct {
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"flag"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
@ -33,7 +34,15 @@ func NewTestClient(t testing.TB, name string, update bool) (Client, func()) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cli, err := NewClient("urn", "https://dev.azure.com", &auth.BasicAuth{Username: "testuser", Password: "testtoken"}, hc)
|
||||
cli, err := NewClient(
|
||||
"urn",
|
||||
AzureDevOpsAPIURL,
|
||||
&auth.BasicAuth{
|
||||
Username: os.Getenv("AZURE_DEV_OPS_USERNAME"),
|
||||
Password: os.Getenv("AZURE_DEV_OPS_TOKEN"),
|
||||
},
|
||||
hc,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
22
internal/extsvc/azuredevops/testdata/golden/ListAuthorizedUserOrganizations.json
vendored
Normal file
22
internal/extsvc/azuredevops/testdata/golden/ListAuthorizedUserOrganizations.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"accountId": "3b958f8e-017e-4f06-95ce-1b6cdd242b36",
|
||||
"accountUri": "https://vssps.dev.azure.com:443/sgtestazure/",
|
||||
"accountName": "sgtestazure"
|
||||
},
|
||||
{
|
||||
"accountId": "65fd1acc-c89e-43e5-9069-395214eb0c25",
|
||||
"accountUri": "https://vssps.dev.azure.com:443/repo-management/",
|
||||
"accountName": "repo-management"
|
||||
},
|
||||
{
|
||||
"accountId": "e8899f60-b66c-4106-8176-8c75b1710c97",
|
||||
"accountUri": "https://vssps.dev.azure.com:443/indra-foobar/",
|
||||
"accountName": "indra-foobar"
|
||||
},
|
||||
{
|
||||
"accountId": "0b807719-5c78-49cd-a851-b24b694db41c",
|
||||
"accountUri": "https://vssps.dev.azure.com:443/sgtestazure2/",
|
||||
"accountName": "sgtestazure2"
|
||||
}
|
||||
]
|
||||
113
internal/extsvc/azuredevops/testdata/vcr/ListAuthorizedUserOrganizations.yaml
vendored
Normal file
113
internal/extsvc/azuredevops/testdata/vcr/ListAuthorizedUserOrganizations.yaml
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
---
|
||||
version: 1
|
||||
interactions:
|
||||
- request:
|
||||
body: ""
|
||||
form: {}
|
||||
headers: {}
|
||||
url: https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=7.0
|
||||
method: GET
|
||||
response:
|
||||
body: '{"displayName":"idan.varsano","publicAlias":"473dec3e-03d7-6147-b106-0b0a7f766a92","emailAddress":"idan.varsano@sourcegraph.com","coreRevision":411938451,"timeStamp":"2023-01-20T19:20:51.6433333+00:00","id":"473dec3e-03d7-6147-b106-0b0a7f766a92","revision":411938451}'
|
||||
headers:
|
||||
Access-Control-Expose-Headers:
|
||||
- Request-Context
|
||||
Activityid:
|
||||
- d2cf0ab4-6956-4880-bffa-eebdf9f92550
|
||||
Cache-Control:
|
||||
- no-cache, no-store, must-revalidate
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8; api-version=7.0
|
||||
Date:
|
||||
- Thu, 02 Mar 2023 18:36:45 GMT
|
||||
Etag:
|
||||
- '"0"'
|
||||
Expires:
|
||||
- "-1"
|
||||
Last-Modified:
|
||||
- Fri, 20 Jan 2023 19:20:51 GMT
|
||||
P3p:
|
||||
- CP="CAO DSP COR ADMa DEV CONo TELo CUR PSA PSD TAI IVDo OUR SAMi BUS DEM NAV
|
||||
STA UNI COM INT PHY ONL FIN PUR LOC CNT"
|
||||
Pragma:
|
||||
- no-cache
|
||||
Request-Context:
|
||||
- appId=cid-v1:20b3930f-73dc-453a-b660-e3891d782eef
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
X-Cache:
|
||||
- CONFIG_NOCACHE
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Frame-Options:
|
||||
- SAMEORIGIN
|
||||
X-Msedge-Ref:
|
||||
- 'Ref A: 5C3F7F96F5674231B1EC5F1F62DC3144 Ref B: MAA01EDGE1111 Ref C: 2023-03-02T18:36:45Z'
|
||||
X-Tfs-Processid:
|
||||
- 820ab1ae-fa5e-4b54-bcd3-c19228bd810b
|
||||
X-Tfs-Session:
|
||||
- d2cf0ab4-6956-4880-bffa-eebdf9f92550
|
||||
X-Vss-E2eid:
|
||||
- d2cf0ab4-6956-4880-bffa-eebdf9f92550
|
||||
X-Vss-Senderdeploymentid:
|
||||
- a5ca35eb-148e-4ccd-bbb3-d31576d75958
|
||||
X-Vss-Userdata:
|
||||
- 473dec3e-03d7-6147-b106-0b0a7f766a92:idan.varsano@sourcegraph.com
|
||||
status: 200 OK
|
||||
code: 200
|
||||
duration: ""
|
||||
- request:
|
||||
body: ""
|
||||
form: {}
|
||||
headers: {}
|
||||
url: https://app.vssps.visualstudio.com/_apis/accounts?api-version=7.0&memberId=473dec3e-03d7-6147-b106-0b0a7f766a92
|
||||
method: GET
|
||||
response:
|
||||
body: '{"count":4,"value":[{"accountId":"3b958f8e-017e-4f06-95ce-1b6cdd242b36","accountUri":"https://vssps.dev.azure.com:443/sgtestazure/","accountName":"sgtestazure","properties":{}},{"accountId":"65fd1acc-c89e-43e5-9069-395214eb0c25","accountUri":"https://vssps.dev.azure.com:443/repo-management/","accountName":"repo-management","properties":{}},{"accountId":"e8899f60-b66c-4106-8176-8c75b1710c97","accountUri":"https://vssps.dev.azure.com:443/indra-foobar/","accountName":"indra-foobar","properties":{}},{"accountId":"0b807719-5c78-49cd-a851-b24b694db41c","accountUri":"https://vssps.dev.azure.com:443/sgtestazure2/","accountName":"sgtestazure2","properties":{}}]}'
|
||||
headers:
|
||||
Access-Control-Expose-Headers:
|
||||
- Request-Context
|
||||
Activityid:
|
||||
- e2fa6c27-6b16-4f2d-83e4-bfc6a8cbcc87
|
||||
Cache-Control:
|
||||
- no-cache, no-store, must-revalidate
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8; api-version=7.0
|
||||
Date:
|
||||
- Thu, 02 Mar 2023 18:36:45 GMT
|
||||
Expires:
|
||||
- "-1"
|
||||
P3p:
|
||||
- CP="CAO DSP COR ADMa DEV CONo TELo CUR PSA PSD TAI IVDo OUR SAMi BUS DEM NAV
|
||||
STA UNI COM INT PHY ONL FIN PUR LOC CNT"
|
||||
Pragma:
|
||||
- no-cache
|
||||
Request-Context:
|
||||
- appId=cid-v1:20b3930f-73dc-453a-b660-e3891d782eef
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
X-Cache:
|
||||
- CONFIG_NOCACHE
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Frame-Options:
|
||||
- SAMEORIGIN
|
||||
X-Msedge-Ref:
|
||||
- 'Ref A: BB7D52F5D4D94054936DD2D1686AD864 Ref B: MAA01EDGE1111 Ref C: 2023-03-02T18:36:45Z'
|
||||
X-Tfs-Processid:
|
||||
- 7079e5b3-fcdc-4e60-bc32-c76d7829ecec
|
||||
X-Tfs-Session:
|
||||
- e2fa6c27-6b16-4f2d-83e4-bfc6a8cbcc87
|
||||
X-Vss-E2eid:
|
||||
- e2fa6c27-6b16-4f2d-83e4-bfc6a8cbcc87
|
||||
X-Vss-Senderdeploymentid:
|
||||
- a5ca35eb-148e-4ccd-bbb3-d31576d75958
|
||||
X-Vss-Userdata:
|
||||
- 473dec3e-03d7-6147-b106-0b0a7f766a92:idan.varsano@sourcegraph.com
|
||||
status: 200 OK
|
||||
code: 200
|
||||
duration: ""
|
||||
@ -28,6 +28,17 @@ var (
|
||||
PullRequestMergeStrategyNoFastForward PullRequestMergeStrategy = "notFastForward"
|
||||
)
|
||||
|
||||
type Org struct {
|
||||
ID string `json:"accountId"`
|
||||
URI string `json:"accountUri"`
|
||||
Name string `json:"accountName"`
|
||||
}
|
||||
|
||||
type ListAuthorizedUserOrgsResponse struct {
|
||||
Count int `json:"count"`
|
||||
Value []Org `json:"value"`
|
||||
}
|
||||
|
||||
type OrgProjectRepoArgs struct {
|
||||
Org string
|
||||
Project string
|
||||
|
||||
@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/sourcegraph/sourcegraph/internal/encryption"
|
||||
"github.com/sourcegraph/sourcegraph/internal/extsvc"
|
||||
"github.com/sourcegraph/sourcegraph/lib/errors"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
@ -41,6 +42,35 @@ func (c *client) GetAuthorizedProfile(ctx context.Context) (Profile, error) {
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (c *client) ListAuthorizedUserOrganizations(ctx context.Context, profile Profile) ([]Org, error) {
|
||||
if MockVisualStudioAppURL == "" && !c.IsAzureDevOpsServices() {
|
||||
return nil, errors.New("ListAuthorizedUserOrganizations can only be used with Azure DevOps Services")
|
||||
}
|
||||
|
||||
reqURL := url.URL{Path: "_apis/accounts"}
|
||||
|
||||
req, err := http.NewRequest("GET", reqURL.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
queryParams := req.URL.Query()
|
||||
queryParams.Set("memberId", profile.PublicAlias)
|
||||
req.URL.RawQuery = queryParams.Encode()
|
||||
|
||||
apiURL := VisualStudioAppURL
|
||||
if MockVisualStudioAppURL != "" {
|
||||
apiURL = MockVisualStudioAppURL
|
||||
}
|
||||
|
||||
response := ListAuthorizedUserOrgsResponse{}
|
||||
if _, err := c.do(ctx, req, apiURL, &response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response.Value, nil
|
||||
}
|
||||
|
||||
// SetExternalAccountData sets the user and token into the external account data blob.
|
||||
func SetExternalAccountData(data *extsvc.AccountData, user *Profile, token *oauth2.Token) error {
|
||||
serializedUser, err := json.Marshal(user)
|
||||
|
||||
@ -18,3 +18,29 @@ func TestClient_AzureServicesProfile(t *testing.T) {
|
||||
|
||||
testutil.AssertGolden(t, "testdata/golden/AzureServicesProfile.json", *update, resp)
|
||||
}
|
||||
|
||||
// To update this test run:
|
||||
// 1. Set the env AZURE_DEV_OPS_USERNAME and AZURE_DEV_OPS_TOKEN (the secrets can be found in 1Password if you search for Azure test credentials)
|
||||
// 2. Run the test with the -update flag:
|
||||
// `go test -run='TestClient_ListAuthorizedUserOrganizations' -update=true`
|
||||
func TestClient_ListAuthorizedUserOrganizations(t *testing.T) {
|
||||
cli, save := NewTestClient(
|
||||
t,
|
||||
"ListAuthorizedUserOrganizations",
|
||||
*update,
|
||||
)
|
||||
t.Cleanup(save)
|
||||
|
||||
ctx := context.Background()
|
||||
profile, err := cli.GetAuthorizedProfile(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get authorized profile: %v", err)
|
||||
}
|
||||
|
||||
orgs, err := cli.ListAuthorizedUserOrganizations(ctx, profile)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to list authorized user origanizations: %v", err)
|
||||
}
|
||||
|
||||
testutil.AssertGolden(t, "testdata/golden/ListAuthorizedUserOrganizations.json", *update, orgs)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user