From 4205001ebbaf3e7c08dbc90eb50e6377643f0c66 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Fri, 19 Nov 2021 00:45:03 +0000 Subject: [PATCH] Support for Administrative Units --- .../cmd/test-cleanup/administrativeunits.go | 36 ++ internal/cmd/test-cleanup/main.go | 1 + internal/test/testing.go | 6 + msgraph/administrative_units.go | 441 ++++++++++++++++++ msgraph/administrative_units_test.go | 230 +++++++++ msgraph/models.go | 20 + msgraph/valuetypes.go | 10 + 7 files changed, 744 insertions(+) create mode 100644 internal/cmd/test-cleanup/administrativeunits.go create mode 100644 msgraph/administrative_units.go create mode 100644 msgraph/administrative_units_test.go diff --git a/internal/cmd/test-cleanup/administrativeunits.go b/internal/cmd/test-cleanup/administrativeunits.go new file mode 100644 index 00000000..cf9508b4 --- /dev/null +++ b/internal/cmd/test-cleanup/administrativeunits.go @@ -0,0 +1,36 @@ +package main + +import ( + "fmt" + "log" + + "github.com/manicminer/hamilton/msgraph" + "github.com/manicminer/hamilton/odata" +) + +func cleanupAdministrativeUnits() { + administrativeUnitsClient := msgraph.NewAdministrativeUnitsClient(tenantId) + administrativeUnitsClient.BaseClient.Authorizer = authorizer + + administrativeUnits, _, err := administrativeUnitsClient.List(ctx, odata.Query{Filter: fmt.Sprintf("startsWith(displayName, '%s')", displayNamePrefix)}) + if err != nil { + log.Println(err) + return + } + if administrativeUnits == nil { + log.Println("bad API response, nil administrativeUnits result received") + return + } + for _, au := range *administrativeUnits { + if au.ID == nil || au.DisplayName == nil { + log.Println("Group returned with nil ID or DisplayName") + continue + } + + log.Printf("Deleting administrative unit %q (DisplayName: %q)\n", *au.ID, *au.DisplayName) + _, err := administrativeUnitsClient.Delete(ctx, *au.ID) + if err != nil { + log.Printf("Error when deleting administrative group %q: %v\n", *au.ID, err) + } + } +} diff --git a/internal/cmd/test-cleanup/main.go b/internal/cmd/test-cleanup/main.go index 1075954f..86f5768b 100644 --- a/internal/cmd/test-cleanup/main.go +++ b/internal/cmd/test-cleanup/main.go @@ -50,6 +50,7 @@ func init() { func main() { log.Println("Starting test cleanup...") + cleanupAdministrativeUnits() cleanupConditionalAccessPolicies() cleanupNamedLocations() cleanupServicePrincipals() diff --git a/internal/test/testing.go b/internal/test/testing.go index cad44037..1c3dcf67 100644 --- a/internal/test/testing.go +++ b/internal/test/testing.go @@ -91,6 +91,7 @@ type Test struct { AccessPackageResourceClient *msgraph.AccessPackageResourceClient AccessPackageResourceRequestClient *msgraph.AccessPackageResourceRequestClient AccessPackageResourceRoleScopeClient *msgraph.AccessPackageResourceRoleScopeClient + AdministrativeUnitsClient *msgraph.AdministrativeUnitsClient ApplicationTemplatesClient *msgraph.ApplicationTemplatesClient ApplicationsClient *msgraph.ApplicationsClient AppRoleAssignedToClient *msgraph.AppRoleAssignedToClient @@ -179,6 +180,11 @@ func NewTest(t *testing.T) (c *Test) { c.AccessPackageResourceRoleScopeClient.BaseClient.Endpoint = c.Connection.AuthConfig.Environment.MsGraph.Endpoint c.AccessPackageResourceRoleScopeClient.BaseClient.RetryableClient.RetryMax = retry + c.AdministrativeUnitsClient = msgraph.NewAdministrativeUnitsClient(c.Connection.AuthConfig.TenantID) + c.AdministrativeUnitsClient.BaseClient.Authorizer = c.Connection.Authorizer + c.AdministrativeUnitsClient.BaseClient.Endpoint = c.Connection.AuthConfig.Environment.MsGraph.Endpoint + c.AdministrativeUnitsClient.BaseClient.RetryableClient.RetryMax = retry + c.ApplicationTemplatesClient = msgraph.NewApplicationTemplatesClient(c.Connection.AuthConfig.TenantID) c.ApplicationTemplatesClient.BaseClient.Authorizer = c.Connection.Authorizer c.ApplicationTemplatesClient.BaseClient.Endpoint = c.Connection.AuthConfig.Environment.MsGraph.Endpoint diff --git a/msgraph/administrative_units.go b/msgraph/administrative_units.go new file mode 100644 index 00000000..04b5b300 --- /dev/null +++ b/msgraph/administrative_units.go @@ -0,0 +1,441 @@ +package msgraph + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/manicminer/hamilton/odata" +) + +// AdministrativeUnitsClient performs operations on Administrative Units +type AdministrativeUnitsClient struct { + BaseClient Client +} + +// NewAdministrativeUnitsClient returns a new AdministrativeUnitsClient. +func NewAdministrativeUnitsClient(tenantId string) *AdministrativeUnitsClient { + return &AdministrativeUnitsClient{ + BaseClient: NewClient(VersionBeta, tenantId), + } +} + +// List returns a list of AdministrativeUnits, optionally queried using OData. +func (c *AdministrativeUnitsClient) List(ctx context.Context, query odata.Query) (*[]AdministrativeUnit, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + DisablePaging: query.Top > 0, + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: "/administrativeUnits", + HasTenantId: true, + }, + }) + if err != nil { + return nil, status, fmt.Errorf("AdministrativeUnitsClient.BaseClient.Get(): %v", err) + } + + defer resp.Body.Close() + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, status, fmt.Errorf("io.ReadAll(): %v", err) + } + + var data struct { + AdministrativeUnits []AdministrativeUnit `json:"value"` + } + if err := json.Unmarshal(respBody, &data); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &data.AdministrativeUnits, status, nil +} + +// Create creates a new AdministrativeUnit. +func (c *AdministrativeUnitsClient) Create(ctx context.Context, administrativeUnit AdministrativeUnit) (*AdministrativeUnit, int, error) { + var status int + + body, err := json.Marshal(administrativeUnit) + if err != nil { + return nil, status, fmt.Errorf("json.Marshal(): %v", err) + } + + resp, status, _, err := c.BaseClient.Post(ctx, PostHttpRequestInput{ + Body: body, + OData: odata.Query{ + Metadata: odata.MetadataFull, + }, + ValidStatusCodes: []int{http.StatusCreated}, + Uri: Uri{ + Entity: "/administrativeUnits", + HasTenantId: true, + }, + }) + if err != nil { + return nil, status, fmt.Errorf("AdministrativeUnitsClient.BaseClient.Post(): %v", err) + } + + defer resp.Body.Close() + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, status, fmt.Errorf("io.ReadAll(): %v", err) + } + + var newAdministrativeUnit AdministrativeUnit + if err := json.Unmarshal(respBody, &newAdministrativeUnit); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &newAdministrativeUnit, status, nil +} + +// Get retrieves an AdministrativeUnit +func (c *AdministrativeUnitsClient) Get(ctx context.Context, id string, query odata.Query) (*AdministrativeUnit, int, error) { + query.Metadata = odata.MetadataFull + + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/administrativeUnits/%s", id), + HasTenantId: true, + }, + }) + if err != nil { + return nil, status, fmt.Errorf("AdministrativeUnitsClient.BaseClient.Get(): %v", err) + } + + defer resp.Body.Close() + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, status, fmt.Errorf("io.ReadAll(): %v", err) + } + + var administrativeUnit AdministrativeUnit + if err := json.Unmarshal(respBody, &administrativeUnit); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &administrativeUnit, status, nil +} + +// Update amends an existing AdministrativeUnit. +func (c *AdministrativeUnitsClient) Update(ctx context.Context, administrativeUnit AdministrativeUnit) (int, error) { + var status int + + body, err := json.Marshal(administrativeUnit) + if err != nil { + return status, fmt.Errorf("json.Marshal(): %v", err) + } + + _, status, _, err = c.BaseClient.Patch(ctx, PatchHttpRequestInput{ + Body: body, + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + ValidStatusCodes: []int{http.StatusNoContent}, + Uri: Uri{ + Entity: fmt.Sprintf("/administrativeUnits/%s", *administrativeUnit.ID), + HasTenantId: true, + }, + }) + if err != nil { + return status, fmt.Errorf("AdministrativeUnitsClient.BaseClient.Patch(): %v", err) + } + + return status, nil +} + +// Delete removes a AdministrativeUnit. +func (c *AdministrativeUnitsClient) Delete(ctx context.Context, id string) (int, error) { + _, status, _, err := c.BaseClient.Delete(ctx, DeleteHttpRequestInput{ + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + ValidStatusCodes: []int{http.StatusNoContent}, + Uri: Uri{ + Entity: fmt.Sprintf("/administrativeUnits/%s", id), + HasTenantId: true, + }, + }) + if err != nil { + return status, fmt.Errorf("AdministrativeUnits.BaseClient.Get(): %v", err) + } + + return status, nil +} + +// ListMembers retrieves the members of the specified AdministrativeUnit. +func (c *AdministrativeUnitsClient) ListMembers(ctx context.Context, administrativeUnitId string) (*[]string, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + OData: odata.Query{ + Select: []string{"id"}, + }, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/administrativeUnits/%s/members", administrativeUnitId), + HasTenantId: true, + }, + }) + if err != nil { + return nil, status, fmt.Errorf("AdministrativeUnitsClient.BaseClient.Get(): %v", err) + } + + defer resp.Body.Close() + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, status, fmt.Errorf("io.ReadAll(): %v", err) + } + + var data struct { + Members []struct { + Type string `json:"@odata.type"` + Id string `json:"id"` + } `json:"value"` + } + if err := json.Unmarshal(respBody, &data); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + ret := make([]string, len(data.Members)) + for i, v := range data.Members { + ret[i] = v.Id + } + + return &ret, status, nil +} + +// GetMember retrieves a single member of the specified AdministrativeUnit. +func (c *AdministrativeUnitsClient) GetMember(ctx context.Context, administrativeUnitId, memberId string) (*string, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + OData: odata.Query{ + Select: []string{"id", "url"}, + }, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/administrativeUnits/%s/members/%s/$ref", administrativeUnitId, memberId), + HasTenantId: true, + }, + }) + if err != nil { + return nil, status, fmt.Errorf("AdministrativeUnitsClient.BaseClient.Get(): %v", err) + } + + defer resp.Body.Close() + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, status, fmt.Errorf("io.ReadAll(): %v", err) + } + + var data struct { + Context string `json:"@odata.context"` + Type string `json:"@odata.type"` + Id string `json:"id"` + Url string `json:"url"` + } + if err := json.Unmarshal(respBody, &data); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &data.Id, status, nil +} + +// AddMembers adds new members to a AdministrativeUnit. +func (c *AdministrativeUnitsClient) AddMembers(ctx context.Context, administrativeUnitId string, members *Members) (int, error) { + var status int + + if members == nil || len(*members) == 0 { + return status, fmt.Errorf("no members specified") + } + + for _, member := range *members { + // don't fail if a member already exists + checkMemberAlreadyExists := func(resp *http.Response, o *odata.OData) bool { + if resp != nil && resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { + return o.Error.Match(odata.ErrorAddedObjectReferencesAlreadyExist) + } + return false + } + + body, err := json.Marshal(DirectoryObject{ODataId: member.ODataId}) + if err != nil { + return status, fmt.Errorf("json.Marshal(): %v", err) + } + + _, status, _, err = c.BaseClient.Post(ctx, PostHttpRequestInput{ + Body: body, + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + ValidStatusCodes: []int{http.StatusNoContent}, + ValidStatusFunc: checkMemberAlreadyExists, + Uri: Uri{ + Entity: fmt.Sprintf("/administrativeUnits/%s/members/$ref", administrativeUnitId), + HasTenantId: true, + }, + }) + if err != nil { + return status, fmt.Errorf("AdministrativeUnitsClient.BaseClient.Post(): %v", err) + } + } + + return status, nil +} + +// RemoveMembers removes members from a AdministrativeUnit. +func (c *AdministrativeUnitsClient) RemoveMembers(ctx context.Context, administrativeUnitId string, memberIds *[]string) (int, error) { + var status int + + if memberIds == nil || len(*memberIds) == 0 { + return status, fmt.Errorf("no members specified") + } + + for _, memberId := range *memberIds { + // check for membership before attempting deletion + if _, status, err := c.GetMember(ctx, administrativeUnitId, memberId); err != nil { + if status == http.StatusNotFound { + continue + } + return status, err + } + + // despite the above check, sometimes members are just gone + checkMemberGone := func(resp *http.Response, o *odata.OData) bool { + if resp != nil && resp.StatusCode == http.StatusBadRequest && o != nil && o.Error != nil { + return o.Error.Match(odata.ErrorRemovedObjectReferencesDoNotExist) + } + return false + } + + var err error + _, status, _, err = c.BaseClient.Delete(ctx, DeleteHttpRequestInput{ + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + ValidStatusCodes: []int{http.StatusNoContent}, + ValidStatusFunc: checkMemberGone, + Uri: Uri{ + Entity: fmt.Sprintf("/administrativeUnits/%s/members/%s/$ref", administrativeUnitId, memberId), + HasTenantId: true, + }, + }) + if err != nil { + return status, fmt.Errorf("AdministrativeUnitsClient.BaseClient.Delete(): %v", err) + } + } + + return status, nil +} + +// ListScopedRoleMembers retrieves the members of the specified AdministrativeUnit. +func (c *AdministrativeUnitsClient) ListScopedRoleMembers(ctx context.Context, administrativeUnitId string, query odata.Query) (*[]ScopedRoleMembership, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/administrativeUnits/%s/scopedRoleMembers", administrativeUnitId), + HasTenantId: true, + }, + }) + if err != nil { + return nil, status, fmt.Errorf("AdministrativeUnitsClient.BaseClient.Get(): %v", err) + } + + defer resp.Body.Close() + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, status, fmt.Errorf("io.ReadAll(): %v", err) + } + + var data struct { + ScopedRoleMembers []ScopedRoleMembership `json:"value"` + } + if err := json.Unmarshal(respBody, &data); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &data.ScopedRoleMembers, status, nil +} + +// GetScopedRoleMember retrieves a single member of the specified AdministrativeUnit. +func (c *AdministrativeUnitsClient) GetScopedRoleMember(ctx context.Context, administrativeUnitId, scopedRoleMembershipId string, query odata.Query) (*ScopedRoleMembership, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/administrativeUnits/%s/scopedRoleMembers/%s", administrativeUnitId, scopedRoleMembershipId), + HasTenantId: true, + }, + }) + if err != nil { + return nil, status, fmt.Errorf("AdministrativeUnitsClient.BaseClient.Get(): %v", err) + } + + defer resp.Body.Close() + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, status, fmt.Errorf("io.ReadAll(): %v", err) + } + + var data ScopedRoleMembership + if err := json.Unmarshal(respBody, &data); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &data, status, nil +} + +// AddScopedRoleMember adds a new scoped role membership for a AdministrativeUnit. +func (c *AdministrativeUnitsClient) AddScopedRoleMember(ctx context.Context, administrativeUnitId string, scopedRoleMembership ScopedRoleMembership) (*ScopedRoleMembership, int, error) { + var status int + + body, err := json.Marshal(scopedRoleMembership) + if err != nil { + return nil, status, fmt.Errorf("json.Marshal(): %v", err) + } + + resp, status, _, err := c.BaseClient.Post(ctx, PostHttpRequestInput{ + Body: body, + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + ValidStatusCodes: []int{http.StatusCreated}, + Uri: Uri{ + Entity: fmt.Sprintf("/administrativeUnits/%s/scopedRoleMembers", administrativeUnitId), + HasTenantId: true, + }, + }) + if err != nil { + return nil, status, fmt.Errorf("AdministrativeUnitsClient.BaseClient.Post(): %v", err) + } + + defer resp.Body.Close() + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, status, fmt.Errorf("io.ReadAll(): %v", err) + } + + var data ScopedRoleMembership + if err := json.Unmarshal(respBody, &data); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &data, status, nil +} + +// RemoveScopedRoleMembers removes members from a AdministrativeUnit. +func (c *AdministrativeUnitsClient) RemoveScopedRoleMembers(ctx context.Context, administrativeUnitId, scopedRoleMembershipId string) (int, error) { + var status int + + var err error + _, status, _, err = c.BaseClient.Delete(ctx, DeleteHttpRequestInput{ + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + ValidStatusCodes: []int{http.StatusNoContent}, + Uri: Uri{ + Entity: fmt.Sprintf("/administrativeUnits/%s/scopedRoleMembers/%s", administrativeUnitId, scopedRoleMembershipId), + HasTenantId: true, + }, + }) + if err != nil { + return status, fmt.Errorf("AdministrativeUnitsClient.BaseClient.Delete(): %v", err) + } + + return status, nil +} diff --git a/msgraph/administrative_units_test.go b/msgraph/administrative_units_test.go new file mode 100644 index 00000000..8a36fb06 --- /dev/null +++ b/msgraph/administrative_units_test.go @@ -0,0 +1,230 @@ +package msgraph_test + +import ( + "fmt" + "strings" + "testing" + + "github.com/manicminer/hamilton/internal/test" + "github.com/manicminer/hamilton/internal/utils" + "github.com/manicminer/hamilton/msgraph" + "github.com/manicminer/hamilton/odata" +) + +func TestAdministrativeUnitsClient(t *testing.T) { + c := test.NewTest(t) + defer c.CancelFunc() + + newAdministrativeUnit := msgraph.AdministrativeUnit{ + DisplayName: utils.StringPtr("test-administrativeUnit"), + Description: msgraph.NullableString("test-administrativeUnit-description"), + } + administrativeUnit := testAdministrativeUnitsClient_Create(t, c, newAdministrativeUnit) + testAdministrativeUnitsClient_Get(t, c, *administrativeUnit.ID) + + administrativeUnit.DisplayName = utils.StringPtr(fmt.Sprintf("test-updated-administrativeUnit-%s", c.RandomString)) + administrativeUnit.Description = msgraph.NullableString("") + testAdministrativeUnitsClient_Update(t, c, *administrativeUnit) + + user := testUsersClient_Create(t, c, msgraph.User{ + AccountEnabled: utils.BoolPtr(true), + DisplayName: utils.StringPtr("test-user"), + MailNickname: utils.StringPtr(fmt.Sprintf("test-user-%s", c.RandomString)), + UserPrincipalName: utils.StringPtr(fmt.Sprintf("test-user-%s@%s", c.RandomString, c.Connection.DomainName)), + PasswordProfile: &msgraph.UserPasswordProfile{ + Password: utils.StringPtr(fmt.Sprintf("IrPa55w0rd%s", c.RandomString)), + }, + }) + + testAdministrativeUnitsClient_AddMembers(t, c, *administrativeUnit.ID, &msgraph.Members{user.DirectoryObject}) + testAdministrativeUnitsClient_ListMembers(t, c, *administrativeUnit.ID) + testAdministrativeUnitsClient_GetMember(t, c, *administrativeUnit.ID, *user.ID) + testAdministrativeUnitsClient_RemoveMembers(t, c, *administrativeUnit.ID, &([]string{*user.ID})) + + directoryRoleTemplates := testDirectoryRoleTemplatesClient_List(t, c) + var helpdeskAdministratorRoleId string + for _, template := range *directoryRoleTemplates { + if strings.EqualFold(*template.DisplayName, "Helpdesk administrator") { + helpdeskAdministratorRoleId = *template.ID + } + } + testDirectoryRolesClient_Activate(t, c, helpdeskAdministratorRoleId) + directoryRole := testDirectoryRolesClient_GetByTemplateId(t, c, helpdeskAdministratorRoleId) + + membership := testAdministrativeUnitsClient_AddScopedRoleMember(t, c, *administrativeUnit.ID, msgraph.ScopedRoleMembership{ + RoleId: directoryRole.ID, + RoleMemberInfo: &msgraph.Identity{Id: user.ID}, + }) + testAdministrativeUnitsClient_ListScopedRoleMembers(t, c, *administrativeUnit.ID) + testAdministrativeUnitsClient_GetRoleScopedMember(t, c, *administrativeUnit.ID, *membership.Id) + testAdministrativeUnitsClient_RemoveScopedRoleMember(t, c, *administrativeUnit.ID, *membership.Id) + + testAdministrativeUnitsClient_List(t, c) + testAdministrativeUnitsClient_Delete(t, c, *administrativeUnit.ID) + testUsersClient_Delete(t, c, *user.ID) +} + +func testAdministrativeUnitsClient_Create(t *testing.T, c *test.Test, g msgraph.AdministrativeUnit) (administrativeUnit *msgraph.AdministrativeUnit) { + administrativeUnit, status, err := c.AdministrativeUnitsClient.Create(c.Context, g) + if err != nil { + t.Fatalf("AdministrativeUnitsClient.Create(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("AdministrativeUnitsClient.Create(): invalid status: %d", status) + } + if administrativeUnit == nil { + t.Fatal("AdministrativeUnitsClient.Create(): administrativeUnit was nil") + } + if administrativeUnit.ID == nil { + t.Fatal("AdministrativeUnitsClient.Create(): administrativeUnit.ID was nil") + } + return +} + +func testAdministrativeUnitsClient_Update(t *testing.T, c *test.Test, g msgraph.AdministrativeUnit) { + status, err := c.AdministrativeUnitsClient.Update(c.Context, g) + if err != nil { + t.Fatalf("AdministrativeUnitsClient.Update(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("AdministrativeUnitsClient.Update(): invalid status: %d", status) + } +} + +func testAdministrativeUnitsClient_List(t *testing.T, c *test.Test) (administrativeUnits *[]msgraph.AdministrativeUnit) { + administrativeUnits, _, err := c.AdministrativeUnitsClient.List(c.Context, odata.Query{Top: 10}) + if err != nil { + t.Fatalf("AdministrativeUnitsClient.List(): %v", err) + } + if administrativeUnits == nil { + t.Fatal("AdministrativeUnitsClient.List(): administrativeUnits was nil") + } + return +} + +func testAdministrativeUnitsClient_Get(t *testing.T, c *test.Test, id string) (administrativeUnit *msgraph.AdministrativeUnit) { + administrativeUnit, status, err := c.AdministrativeUnitsClient.Get(c.Context, id, odata.Query{}) + if err != nil { + t.Fatalf("AdministrativeUnitsClient.Get(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("AdministrativeUnitsClient.Get(): invalid status: %d", status) + } + if administrativeUnit == nil { + t.Fatal("AdministrativeUnitsClient.Get(): administrativeUnit was nil") + } + return +} + +func testAdministrativeUnitsClient_Delete(t *testing.T, c *test.Test, id string) { + status, err := c.AdministrativeUnitsClient.Delete(c.Context, id) + if err != nil { + t.Fatalf("AdministrativeUnitsClient.Delete(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("AdministrativeUnitsClient.Delete(): invalid status: %d", status) + } +} + +func testAdministrativeUnitsClient_ListMembers(t *testing.T, c *test.Test, administrativeUnitId string) (members *[]string) { + members, status, err := c.AdministrativeUnitsClient.ListMembers(c.Context, administrativeUnitId) + if err != nil { + t.Fatalf("AdministrativeUnitsClient.ListMembers(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("AdministrativeUnitsClient.ListMembers(): invalid status: %d", status) + } + if members == nil { + t.Fatal("AdministrativeUnitsClient.ListMembers(): members was nil") + } + if len(*members) == 0 { + t.Fatal("AdministrativeUnitsClient.ListMembers(): members was empty") + } + return +} + +func testAdministrativeUnitsClient_GetMember(t *testing.T, c *test.Test, administrativeUnitId string, memberId string) (member *string) { + member, status, err := c.AdministrativeUnitsClient.GetMember(c.Context, administrativeUnitId, memberId) + if err != nil { + t.Fatalf("AdministrativeUnitsClient.GetMember(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("AdministrativeUnitsClient.GetMember(): invalid status: %d", status) + } + if member == nil { + t.Fatal("AdministrativeUnitsClient.GetMember(): member was nil") + } + return +} + +func testAdministrativeUnitsClient_AddMembers(t *testing.T, c *test.Test, administrativeUnitId string, members *msgraph.Members) { + status, err := c.AdministrativeUnitsClient.AddMembers(c.Context, administrativeUnitId, members) + if err != nil { + t.Fatalf("AdministrativeUnitsClient.AddMembers(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("AdministrativeUnitsClient.AddMembers(): invalid status: %d", status) + } +} + +func testAdministrativeUnitsClient_RemoveMembers(t *testing.T, c *test.Test, administrativeUnitId string, memberIds *[]string) { + status, err := c.AdministrativeUnitsClient.RemoveMembers(c.Context, administrativeUnitId, memberIds) + if err != nil { + t.Fatalf("AdministrativeUnitsClient.RemoveMembers(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("AdministrativeUnitsClient.RemoveMembers(): invalid status: %d", status) + } +} + +func testAdministrativeUnitsClient_ListScopedRoleMembers(t *testing.T, c *test.Test, administrativeUnitId string) (memberships *[]msgraph.ScopedRoleMembership) { + memberships, status, err := c.AdministrativeUnitsClient.ListScopedRoleMembers(c.Context, administrativeUnitId, odata.Query{}) + if err != nil { + t.Fatalf("AdministrativeUnitsClient.ListScopedRoleMembers(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("AdministrativeUnitsClient.ListScopedRoleMembers(): invalid status: %d", status) + } + if memberships == nil { + t.Fatal("AdministrativeUnitsClient.ListScopedRoleMembers(): members was nil") + } + if len(*memberships) == 0 { + t.Fatal("AdministrativeUnitsClient.ListScopedRoleMembers(): members was empty") + } + return +} + +func testAdministrativeUnitsClient_GetRoleScopedMember(t *testing.T, c *test.Test, administrativeUnitId string, memberId string) (membership *msgraph.ScopedRoleMembership) { + member, status, err := c.AdministrativeUnitsClient.GetScopedRoleMember(c.Context, administrativeUnitId, memberId, odata.Query{}) + if err != nil { + t.Fatalf("AdministrativeUnitsClient.GetScopedRoleMember(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("AdministrativeUnitsClient.GetScopedRoleMember(): invalid status: %d", status) + } + if member == nil { + t.Fatal("AdministrativeUnitsClient.GetScopedRoleMember(): member was nil") + } + return +} + +func testAdministrativeUnitsClient_AddScopedRoleMember(t *testing.T, c *test.Test, administrativeUnitId string, member msgraph.ScopedRoleMembership) (membership *msgraph.ScopedRoleMembership) { + membership, status, err := c.AdministrativeUnitsClient.AddScopedRoleMember(c.Context, administrativeUnitId, member) + if err != nil { + t.Fatalf("AdministrativeUnitsClient.AddScopedRoleMember(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("AdministrativeUnitsClient.AddScopedRoleMember(): invalid status: %d", status) + } + return +} + +func testAdministrativeUnitsClient_RemoveScopedRoleMember(t *testing.T, c *test.Test, administrativeUnitId string, membershipId string) { + status, err := c.AdministrativeUnitsClient.RemoveScopedRoleMembers(c.Context, administrativeUnitId, membershipId) + if err != nil { + t.Fatalf("AdministrativeUnitsClient.RemoveScopedRoleMembers(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("AdministrativeUnitsClient.RemoveScopedRoleMembers(): invalid status: %d", status) + } +} diff --git a/msgraph/models.go b/msgraph/models.go index 3f5eae8d..c4d298af 100644 --- a/msgraph/models.go +++ b/msgraph/models.go @@ -157,6 +157,13 @@ type AddInKeyValue struct { Value *string `json:"value,omitempty"` } +type AdministrativeUnit struct { + Description *StringNullWhenEmpty `json:"description,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + ID *string `json:"id,omitempty"` + Visibility *AdministrativeUnitVisibility `json:"visibility,omitempty"` +} + type ApiPreAuthorizedApplication struct { AppId *string `json:"appId,omitempty"` PermissionIds *[]string `json:"permissionIds,omitempty"` @@ -862,6 +869,12 @@ type GroupOnPremisesProvisioningError struct { Value *string `json:"value,omitempty"` } +type Identity struct { + DisplayName *string `json:"displayName,omitempty"` + Id *string `json:"id,omitempty"` + TenantId *string `json:"tenantId,omitempty"` +} + type IdentityProvider struct { ODataType *odata.Type `json:"@odata.type,omitempty"` ID *string `json:"id,omitempty"` @@ -1129,6 +1142,13 @@ func (se SchemaExtensionData) MarshalJSON() ([]byte, error) { return json.Marshal(in) } +type ScopedRoleMembership struct { + AdministrativeUnitId *string `json:"administrativeUnitId,omitempty"` + Id *string `json:"id,omitempty"` + RoleId *string `json:"roleId,omitempty"` + RoleMemberInfo *Identity `json:"roleMemberInfo"` +} + // ServicePrincipal describes a Service Principal object. type ServicePrincipal struct { DirectoryObject diff --git a/msgraph/valuetypes.go b/msgraph/valuetypes.go index eb33cb5b..e8b00dcc 100644 --- a/msgraph/valuetypes.go +++ b/msgraph/valuetypes.go @@ -7,6 +7,9 @@ import ( "github.com/manicminer/hamilton/odata" ) +// NullableString returns a pointer to a StringNullWhenEmpty for use in model structs +func NullableString(s StringNullWhenEmpty) *StringNullWhenEmpty { return &s } + // StringNullWhenEmpty is a string type that marshals its JSON representation as null when set to its zero value. // Can be used with a pointer reference with the `omitempty` tag to omit a field when the pointer is nil, but send a // JSON null value when the string is empty. @@ -60,6 +63,13 @@ const ( AccessPackageResourceTypeSharePointOnlineSite AccessPackageResourceType = "SharePoint Online Site" ) +type AdministrativeUnitVisibility = string + +const ( + AdministrativeUnitVisibilityHiddenMembership AdministrativeUnitVisibility = "HiddenMembership" + AdministrativeUnitVisibilityPublic AdministrativeUnitVisibility = "Public" +) + type AgeGroup = StringNullWhenEmpty const (