From 7657b858930b9255180d90dc3dc8142f3c97a16d Mon Sep 17 00:00:00 2001 From: Ibrahim Jarif Date: Tue, 27 Sep 2022 13:27:23 +0530 Subject: [PATCH 1/2] Add Support for CRUD operations on UserFlowAttributes This commit adds support for CRUD operations on UserFlowAttributes. API: https://learn.microsoft.com/en-us/graph/api/resources/identityuserflowattribute --- internal/test/testing.go | 1 + msgraph/models.go | 8 ++ msgraph/userflow_attributes.go | 171 ++++++++++++++++++++++++++++ msgraph/userflow_attributes_test.go | 79 +++++++++++++ 4 files changed, 259 insertions(+) create mode 100644 msgraph/userflow_attributes.go create mode 100644 msgraph/userflow_attributes_test.go diff --git a/internal/test/testing.go b/internal/test/testing.go index bb754e39..2ba38e7a 100644 --- a/internal/test/testing.go +++ b/internal/test/testing.go @@ -123,6 +123,7 @@ type Test struct { ServicePrincipalsClient *msgraph.ServicePrincipalsClient SignInReportsClient *msgraph.SignInReportsClient SynchronizationJobClient *msgraph.SynchronizationJobClient + UserFlowAttributesClient *msgraph.UserFlowAttributesClient UsersAppRoleAssignmentsClient *msgraph.AppRoleAssignmentsClient UsersClient *msgraph.UsersClient } diff --git a/msgraph/models.go b/msgraph/models.go index ed99f78a..cb0b48cd 100644 --- a/msgraph/models.go +++ b/msgraph/models.go @@ -1685,3 +1685,11 @@ type EmployeeOrgData struct { CostCenter *string `json:"costCenter,omitempty"` Division *string `json:"division,omitempty"` } + +type UserFlowAttribute struct { + ID *string `json:"id,omitempty"` + Description *string `json:"description,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + UserFlowAttributeType *string `json:"userFlowAttributeType,omitempty"` + DataType *string `json:"dataType,omitempty"` +} diff --git a/msgraph/userflow_attributes.go b/msgraph/userflow_attributes.go new file mode 100644 index 00000000..e086327d --- /dev/null +++ b/msgraph/userflow_attributes.go @@ -0,0 +1,171 @@ +package msgraph + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/manicminer/hamilton/odata" +) + +// UserFlowAttributesClient performs operations on UserFlowAttributes. +type UserFlowAttributesClient struct { + BaseClient Client +} + +// NewUserFlowAttributesClient returns a new UserFlowAttributesClient. +func NewUserFlowAttributesClient(tenantId string) *UserFlowAttributesClient { + return &UserFlowAttributesClient{ + BaseClient: NewClient(Version10, tenantId), + } +} + +// List returns a list of UserFlowAttributes, optionally queried using OData. +func (c *UserFlowAttributesClient) List(ctx context.Context, query odata.Query) (*[]UserFlowAttribute, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: "/identity/userFlowAttributes", + HasTenantId: true, + }, + }) + if err != nil { + return nil, status, fmt.Errorf("UserFlowAttributesClient.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 { + UserFlowAttributes []UserFlowAttribute `json:"value"` + } + if err := json.Unmarshal(respBody, &data); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &data.UserFlowAttributes, status, nil +} + +// Create creates a new UserFlowAttribute. +func (c *UserFlowAttributesClient) Create(ctx context.Context, userFlowAttribute UserFlowAttribute) (*UserFlowAttribute, int, error) { + var status int + + body, err := json.Marshal(userFlowAttribute) + 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: "/identity/userFlowAttributes", + HasTenantId: true, + }, + }) + if err != nil { + return nil, status, fmt.Errorf("UserFlowAttributesClient.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 newUserFlowAttribute UserFlowAttribute + if err := json.Unmarshal(respBody, &newUserFlowAttribute); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &newUserFlowAttribute, status, nil +} + +// Delete returns a UserFlowAttribute. +func (c *UserFlowAttributesClient) Get(ctx context.Context, id string, query odata.Query) (*UserFlowAttribute, int, error) { + resp, status, _, err := c.BaseClient.Get(ctx, GetHttpRequestInput{ + ConsistencyFailureFunc: RetryOn404ConsistencyFailureFunc, + OData: query, + ValidStatusCodes: []int{http.StatusOK}, + Uri: Uri{ + Entity: fmt.Sprintf("/identity/userFlowAttributes/%s", id), + HasTenantId: true, + }, + }) + if err != nil { + return nil, status, fmt.Errorf("UserFlowAttributesClient.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 userflowAttribute UserFlowAttribute + if err := json.Unmarshal(respBody, &userflowAttribute); err != nil { + return nil, status, fmt.Errorf("json.Unmarshal(): %v", err) + } + + return &userflowAttribute, status, nil +} + +// Update amends an existing UserFlowAttribute. +func (c *UserFlowAttributesClient) Update(ctx context.Context, userflowAttribute UserFlowAttribute) (int, error) { + var status int + if userflowAttribute.ID == nil { + return status, fmt.Errorf("cannot update userflowAttribute with nil ID") + } + + userflowID := *userflowAttribute.ID + userflowAttribute.ID = nil + + body, err := json.Marshal(userflowAttribute) + 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.StatusOK, + http.StatusNoContent, + }, + Uri: Uri{ + Entity: fmt.Sprintf("/identity/userFlowAttributes//%s", userflowID), + HasTenantId: true, + }, + }) + if err != nil { + return status, fmt.Errorf("UserFlowAttributesClient.BaseClient.Patch(): %v", err) + } + + return status, nil +} + +// Delete removes a UserFlowAttribute. +func (c *UserFlowAttributesClient) 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("/identity/userFlowAttributes/%s", id), + HasTenantId: true, + }, + }) + if err != nil { + return status, fmt.Errorf("UserFlowAttributesClient.BaseClient.Delete(): %v", err) + } + + return status, nil +} diff --git a/msgraph/userflow_attributes_test.go b/msgraph/userflow_attributes_test.go new file mode 100644 index 00000000..0c1831ec --- /dev/null +++ b/msgraph/userflow_attributes_test.go @@ -0,0 +1,79 @@ +package msgraph_test + +import ( + "testing" + + "github.com/manicminer/hamilton/internal/test" + "github.com/manicminer/hamilton/internal/utils" + "github.com/manicminer/hamilton/msgraph" + "github.com/manicminer/hamilton/odata" +) + +func TestUserFlowAttributesClient(t *testing.T) { + c := test.NewTest(t) + defer c.CancelFunc() + + userflowAttribute := testUserFlowAttributesClient_Create(t, c, msgraph.UserFlowAttribute{ + ID: utils.StringPtr("test attribute"), + DisplayName: utils.StringPtr("test attribute"), + UserFlowAttributeType: utils.StringPtr("custom"), + DataType: utils.StringPtr("string"), + }) + testUserFlowAttributesClient_Get(t, c, *userflowAttribute.ID) + userflowAttribute.DisplayName = utils.StringPtr("updated test attribute") + testUserFlowAttributesClient_Update(t, c, *userflowAttribute) + testUserFlowAttributesClient_List(t, c) + testGroupsClient_Delete(t, c, *userflowAttribute.ID) +} + +func testUserFlowAttributesClient_Create(t *testing.T, c *test.Test, u msgraph.UserFlowAttribute) *msgraph.UserFlowAttribute { + userflowAttribute, status, err := c.UserFlowAttributesClient.Create(c.Context, u) + if err != nil { + t.Fatalf("UserFlowAttributeclient.Create(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("UserFlowAttributesClient.Create(): invalid status: %d", status) + } + if userflowAttribute == nil { + t.Fatal("UserFlowAttributesClient.Create(): userflowAttribute was nil") + } + if userflowAttribute.ID == nil { + t.Fatal("UserFlowAttributesClient.Create(): userflowAttribute.ID was nil") + } + return userflowAttribute +} + +func testUserFlowAttributesClient_Get(t *testing.T, c *test.Test, id string) *msgraph.UserFlowAttribute { + userflowAttribute, status, err := c.UserFlowAttributesClient.Get(c.Context, id, odata.Query{}) + if err != nil { + t.Fatalf("UserFlowAttributesClient.Get(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("UserFlowAttributesClient.Get(): invalid status: %d", status) + } + if userflowAttribute == nil { + t.Fatal("UserFlowAttributesClient.Get(): userflowAttribute was nil") + } + return userflowAttribute +} + +func testUserFlowAttributesClient_List(t *testing.T, c *test.Test) *[]msgraph.UserFlowAttribute { + userflowAttributes, _, err := c.UserFlowAttributesClient.List(c.Context, odata.Query{Top: 10}) + if err != nil { + t.Fatalf("UserFlowAttributesClient.List(): %v", err) + } + if userflowAttributes == nil { + t.Fatal("UserFlowAttributesClient.List(): userflowAttributes was nil") + } + return userflowAttributes +} + +func testUserFlowAttributesClient_Update(t *testing.T, c *test.Test, u msgraph.UserFlowAttribute) { + status, err := c.UserFlowAttributesClient.Update(c.Context, u) + if err != nil { + t.Fatalf("UserFlowAttributesClient.Update(): %v", err) + } + if status < 200 || status >= 300 { + t.Fatalf("UserFlowAttributesClient.Update(): invalid status: %d", status) + } +} From 44848901e799dfbfc1ebd2a3eb42bca69bbbf79f Mon Sep 17 00:00:00 2001 From: Ibrahim Jarif Date: Wed, 28 Sep 2022 10:26:48 +0530 Subject: [PATCH 2/2] Add UserflowAttributeDataType --- msgraph/models.go | 10 +++++----- msgraph/valuetypes.go | 8 ++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/msgraph/models.go b/msgraph/models.go index cb0b48cd..8f496b14 100644 --- a/msgraph/models.go +++ b/msgraph/models.go @@ -1687,9 +1687,9 @@ type EmployeeOrgData struct { } type UserFlowAttribute struct { - ID *string `json:"id,omitempty"` - Description *string `json:"description,omitempty"` - DisplayName *string `json:"displayName,omitempty"` - UserFlowAttributeType *string `json:"userFlowAttributeType,omitempty"` - DataType *string `json:"dataType,omitempty"` + ID *string `json:"id,omitempty"` + Description *string `json:"description,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + UserFlowAttributeType *string `json:"userFlowAttributeType,omitempty"` + DataType *UserflowAttributeDataType `json:"dataType,omitempty"` } diff --git a/msgraph/valuetypes.go b/msgraph/valuetypes.go index cdf6cd3c..1c597756 100644 --- a/msgraph/valuetypes.go +++ b/msgraph/valuetypes.go @@ -627,3 +627,11 @@ const ( IncludedUserTypesMember IncludedUserTypes = "member" IncludedUserTypesGuest IncludedUserTypes = "guest" ) + +type UserflowAttributeDataType = string + +const ( + UserflowAttributeDataTypeString UserflowAttributeDataType = "string" + UserflowAttributeDataTypeBoolean UserflowAttributeDataType = "boolean" + UserflowAttributeDataTypeInt64 UserflowAttributeDataType = "int64" +)