From b093334dcef67c470e9fa15e273d3c084f6edb6a Mon Sep 17 00:00:00 2001 From: jules <130390278+juleslasarte@users.noreply.github.com> Date: Tue, 10 Oct 2023 16:31:42 -0700 Subject: [PATCH] many incidents --- src/internal/m365/onedrive_test.go | 18 ++++---- src/internal/operations/test/onedrive_test.go | 2 +- src/pkg/services/m365/api/users.go | 35 ++++++++++++++-- src/pkg/services/m365/users.go | 42 ++++++++++++++++++- src/pkg/services/m365/users_test.go | 26 ++++++++++++ 5 files changed, 108 insertions(+), 15 deletions(-) diff --git a/src/internal/m365/onedrive_test.go b/src/internal/m365/onedrive_test.go index 6617f1bfa..9b393f32b 100644 --- a/src/internal/m365/onedrive_test.go +++ b/src/internal/m365/onedrive_test.go @@ -186,15 +186,15 @@ func (suite *SharePointIntegrationSuite) SetupSuite() { si := NewSuiteInfoImpl(suite.T(), ctx, tconfig.M365SiteID(suite.T()), path.SharePointService) // users needed for permissions - user, err := si.controller.AC.Users().GetByID(ctx, si.user) + user, err := si.controller.AC.Users().IsLicenseReconciliationNeeded(ctx, si.user) require.NoError(t, err, "fetching user", si.user, clues.ToCore(err)) si.userID = ptr.Val(user.GetId()) - secondaryUser, err := si.controller.AC.Users().GetByID(ctx, si.secondaryUser) + secondaryUser, err := si.controller.AC.Users().IsLicenseReconciliationNeeded(ctx, si.secondaryUser) require.NoError(t, err, "fetching user", si.secondaryUser, clues.ToCore(err)) si.secondaryUserID = ptr.Val(secondaryUser.GetId()) - tertiaryUser, err := si.controller.AC.Users().GetByID(ctx, si.tertiaryUser) + tertiaryUser, err := si.controller.AC.Users().IsLicenseReconciliationNeeded(ctx, si.tertiaryUser) require.NoError(t, err, "fetching user", si.tertiaryUser, clues.ToCore(err)) si.tertiaryUserID = ptr.Val(tertiaryUser.GetId()) @@ -255,15 +255,15 @@ func (suite *OneDriveIntegrationSuite) SetupSuite() { si := NewSuiteInfoImpl(t, ctx, tconfig.M365UserID(t), path.OneDriveService) - user, err := si.controller.AC.Users().GetByID(ctx, si.user) + user, err := si.controller.AC.Users().IsLicenseReconciliationNeeded(ctx, si.user) require.NoError(t, err, "fetching user", si.user, clues.ToCore(err)) si.userID = ptr.Val(user.GetId()) - secondaryUser, err := si.controller.AC.Users().GetByID(ctx, si.secondaryUser) + secondaryUser, err := si.controller.AC.Users().IsLicenseReconciliationNeeded(ctx, si.secondaryUser) require.NoError(t, err, "fetching user", si.secondaryUser, clues.ToCore(err)) si.secondaryUserID = ptr.Val(secondaryUser.GetId()) - tertiaryUser, err := si.controller.AC.Users().GetByID(ctx, si.tertiaryUser) + tertiaryUser, err := si.controller.AC.Users().IsLicenseReconciliationNeeded(ctx, si.tertiaryUser) require.NoError(t, err, "fetching user", si.tertiaryUser, clues.ToCore(err)) si.tertiaryUserID = ptr.Val(tertiaryUser.GetId()) @@ -319,15 +319,15 @@ func (suite *OneDriveNightlySuite) SetupSuite() { si := NewSuiteInfoImpl(t, ctx, tconfig.M365UserID(t), path.OneDriveService) - user, err := si.controller.AC.Users().GetByID(ctx, si.user) + user, err := si.controller.AC.Users().IsLicenseReconciliationNeeded(ctx, si.user) require.NoError(t, err, "fetching user", si.user, clues.ToCore(err)) si.userID = ptr.Val(user.GetId()) - secondaryUser, err := si.controller.AC.Users().GetByID(ctx, si.secondaryUser) + secondaryUser, err := si.controller.AC.Users().IsLicenseReconciliationNeeded(ctx, si.secondaryUser) require.NoError(t, err, "fetching user", si.secondaryUser, clues.ToCore(err)) si.secondaryUserID = ptr.Val(secondaryUser.GetId()) - tertiaryUser, err := si.controller.AC.Users().GetByID(ctx, si.tertiaryUser) + tertiaryUser, err := si.controller.AC.Users().IsLicenseReconciliationNeeded(ctx, si.tertiaryUser) require.NoError(t, err, "fetching user", si.tertiaryUser, clues.ToCore(err)) si.tertiaryUserID = ptr.Val(tertiaryUser.GetId()) diff --git a/src/internal/operations/test/onedrive_test.go b/src/internal/operations/test/onedrive_test.go index 3343adae8..483971698 100644 --- a/src/internal/operations/test/onedrive_test.go +++ b/src/internal/operations/test/onedrive_test.go @@ -832,7 +832,7 @@ func (suite *OneDriveBackupIntgSuite) TestBackup_Run_oneDriveOwnerMigration() { control.DefaultOptions()) require.NoError(t, err, clues.ToCore(err)) - userable, err := ctrl.AC.Users().GetByID(ctx, suite.its.user.ID) + userable, err := ctrl.AC.Users().IsLicenseReconciliationNeeded(ctx, suite.its.user.ID) require.NoError(t, err, clues.ToCore(err)) uid := ptr.Val(userable.GetId()) diff --git a/src/pkg/services/m365/api/users.go b/src/pkg/services/m365/api/users.go index ccd3f22af..cab471338 100644 --- a/src/pkg/services/m365/api/users.go +++ b/src/pkg/services/m365/api/users.go @@ -112,15 +112,42 @@ func (c Users) GetAll( return us, el.Failure() } -// GetByID looks up the user matching the given identifier. The identifier can be either a +// IsLicenseReconciliationNeeded looks up the user matching the given identifier. The identifier can be either a // canonical user id or a princpalName. -func (c Users) GetByID(ctx context.Context, identifier string) (models.Userable, error) { +func (c Users) IsLicenseReconciliationNeeded(ctx context.Context, identifier string) (models.Userable, error) { var ( resp models.Userable err error ) - resp, err = c.Stable.Client().Users().ByUserId(identifier).Get(ctx, nil) + options := &users.UserItemRequestBuilderGetRequestConfiguration{ + QueryParameters: &users.UserItemRequestBuilderGetQueryParameters{}, + } + + options.QueryParameters.Select = []string{"isLicenseReconciliationNeeded"} + + resp, err = c.Stable.Client().Users().ByUserId(identifier).Get(ctx, options) + + if err != nil { + return nil, graph.Wrap(ctx, err, "getting user") + } + + return resp, err +} + +func (c Users) AssignedPlans(ctx context.Context, identifier string) (models.Userable, error) { + var ( + resp models.Userable + err error + ) + + options := &users.UserItemRequestBuilderGetRequestConfiguration{ + QueryParameters: &users.UserItemRequestBuilderGetQueryParameters{}, + } + + options.QueryParameters.Select = []string{"assignedPlans"} + + resp, err = c.Stable.Client().Users().ByUserId(identifier).Get(ctx, options) if err != nil { return nil, graph.Wrap(ctx, err, "getting user") @@ -136,7 +163,7 @@ func (c Users) GetIDAndName( userID string, _ CallConfig, // not currently supported ) (string, string, error) { - u, err := c.GetByID(ctx, userID) + u, err := c.IsLicenseReconciliationNeeded(ctx, userID) if err != nil { return "", "", err } diff --git a/src/pkg/services/m365/users.go b/src/pkg/services/m365/users.go index 19f16b67d..38000eb86 100644 --- a/src/pkg/services/m365/users.go +++ b/src/pkg/services/m365/users.go @@ -7,6 +7,7 @@ import ( "github.com/microsoftgraph/msgraph-sdk-go/models" "github.com/alcionai/corso/src/internal/common/ptr" + "github.com/alcionai/corso/src/internal/common/tform" "github.com/alcionai/corso/src/internal/m365/service/exchange" "github.com/alcionai/corso/src/internal/m365/service/onedrive" "github.com/alcionai/corso/src/pkg/account" @@ -104,13 +105,52 @@ func usersNoInfo(ctx context.Context, acct account.Account, errs *fault.Bus) ([] return ret, nil } +func UserIsLicenseReconciliationNeeded(ctx context.Context, acct account.Account, userID string) (bool, error) { + ac, err := makeAC(ctx, acct, path.UnknownService) + if err != nil { + return false, clues.Stack(err).WithClues(ctx) + } + + us, err := ac.Users().IsLicenseReconciliationNeeded(ctx, userID) + if err != nil { + return false, err + } + + if _, ok := us.GetAdditionalData()["isLicenseReconciliationNeeded"]; ok { + licenseReconciliationStatus, err := tform.AnyValueToT[*bool]("isLicenseReconciliationNeeded", us.GetAdditionalData()) + if err != nil { + return false, err + } + return *licenseReconciliationStatus, nil + } + + return false, clues.New("user missing license information") +} + +func UserAssignedPlansCount(ctx context.Context, acct account.Account, userID string) (int, error) { + ac, err := makeAC(ctx, acct, path.UnknownService) + if err != nil { + return 0, clues.Stack(err).WithClues(ctx) + } + + us, err := ac.Users().AssignedPlans(ctx, userID) + if err != nil { + return 0, err + } + + if us.GetAssignedPlans() != nil { + return len(us.GetAssignedPlans()), nil + } + + return 0, clues.New("user missing assigned plans") +} + // parseUser extracts information from `models.Userable` we care about func parseUser(item models.Userable) (*UserNoInfo, error) { if item.GetUserPrincipalName() == nil { return nil, clues.New("user missing principal name"). With("user_id", ptr.Val(item.GetId())) } - u := &UserNoInfo{ PrincipalName: ptr.Val(item.GetUserPrincipalName()), ID: ptr.Val(item.GetId()), diff --git a/src/pkg/services/m365/users_test.go b/src/pkg/services/m365/users_test.go index 5e793f89e..c8b30ae1b 100644 --- a/src/pkg/services/m365/users_test.go +++ b/src/pkg/services/m365/users_test.go @@ -1,6 +1,7 @@ package m365 import ( + "fmt" "testing" "github.com/alcionai/clues" @@ -202,6 +203,31 @@ func (suite *userIntegrationSuite) TestUserGetMailboxInfo() { } } +func (suite *userIntegrationSuite) TestUser_GetByID() { + t := suite.T() + + ctx, flush := tester.NewContext(t) + defer flush() + + acct := tconfig.NewM365Account(t) + + users, err := UsersCompatNoInfo(ctx, acct) + assert.NoError(t, err, clues.ToCore(err)) + assert.NotEmpty(t, users) + + for _, s := range users { + suite.Run("user_"+s.ID, func() { + t := suite.T() + reconciliationNeeded, err := UserIsLicenseReconciliationNeeded(ctx, acct, s.ID) + assert.NoError(t, err, clues.ToCore(err)) + plans, err := UserAssignedPlansCount(ctx, acct, s.ID) + assert.NoError(t, err, clues.ToCore(err)) + fmt.Printf("user: %v \n", reconciliationNeeded) + fmt.Printf("user: %v \n", plans) + }) + } +} + func (suite *userIntegrationSuite) TestUsers_InvalidCredentials() { table := []struct { name string