add the groups resources service addition (#4053)
Adds groups to the m365 services api. Also adds a bit of touchups/cleanups on the side. --- #### Does this PR need a docs update or release note? - [x] ⛔ No #### Type of change - [x] 🌻 Feature #### Issue(s) * #3989 #### Test Plan - [x] ⚡ Unit test - [x] 💚 E2E
This commit is contained in:
parent
8d3fdeeb8d
commit
20675dbcf7
@ -223,11 +223,11 @@ func UnlicensedM365UserID(t *testing.T) string {
|
|||||||
|
|
||||||
// Teams
|
// Teams
|
||||||
|
|
||||||
// M365TeamsID returns a teamID string representing the m365TeamsID described
|
// M365TeamID returns a teamID string representing the m365TeamsID described
|
||||||
// by either the env var CORSO_M365_TEST_TEAM_ID, the corso_test.toml config
|
// by either the env var CORSO_M365_TEST_TEAM_ID, the corso_test.toml config
|
||||||
// file or the default value (in that order of priority). The default is a
|
// file or the default value (in that order of priority). The default is a
|
||||||
// last-attempt fallback that will only work on alcion's testing org.
|
// last-attempt fallback that will only work on alcion's testing org.
|
||||||
func M365TeamsID(t *testing.T) string {
|
func M365TeamID(t *testing.T) string {
|
||||||
cfg, err := ReadTestConfig()
|
cfg, err := ReadTestConfig()
|
||||||
require.NoError(t, err, "retrieving m365 team id from test configuration: %+v", clues.ToCore(err))
|
require.NoError(t, err, "retrieving m365 team id from test configuration: %+v", clues.ToCore(err))
|
||||||
|
|
||||||
|
|||||||
@ -49,24 +49,6 @@ func (c Groups) GetAll(
|
|||||||
return getGroups(ctx, errs, service)
|
return getGroups(ctx, errs, service)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTeams retrieves all Teams.
|
|
||||||
func (c Groups) GetTeams(
|
|
||||||
ctx context.Context,
|
|
||||||
errs *fault.Bus,
|
|
||||||
) ([]models.Groupable, error) {
|
|
||||||
service, err := c.Service()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
groups, err := getGroups(ctx, errs, service)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return OnlyTeams(ctx, groups), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAll retrieves all groups.
|
// GetAll retrieves all groups.
|
||||||
func getGroups(
|
func getGroups(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
@ -113,31 +95,6 @@ func getGroups(
|
|||||||
return groups, el.Failure()
|
return groups, el.Failure()
|
||||||
}
|
}
|
||||||
|
|
||||||
func OnlyTeams(ctx context.Context, groups []models.Groupable) []models.Groupable {
|
|
||||||
log := logger.Ctx(ctx)
|
|
||||||
|
|
||||||
var teams []models.Groupable
|
|
||||||
|
|
||||||
for _, g := range groups {
|
|
||||||
if g.GetAdditionalData()[ResourceProvisioningOptions] != nil {
|
|
||||||
val, _ := tform.AnyValueToT[[]any](ResourceProvisioningOptions, g.GetAdditionalData())
|
|
||||||
for _, v := range val {
|
|
||||||
s, err := str.AnyToString(v)
|
|
||||||
if err != nil {
|
|
||||||
log.Debug("could not be converted to string value: ", ResourceProvisioningOptions)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if s == teamsAdditionalDataLabel {
|
|
||||||
teams = append(teams, g)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return teams
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetID retrieves group by groupID.
|
// GetID retrieves group by groupID.
|
||||||
func (c Groups) GetByID(
|
func (c Groups) GetByID(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
@ -158,34 +115,6 @@ func (c Groups) GetByID(
|
|||||||
return resp, graph.Stack(ctx, err).OrNil()
|
return resp, graph.Stack(ctx, err).OrNil()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTeamByID retrieves group by groupID.
|
|
||||||
func (c Groups) GetTeamByID(
|
|
||||||
ctx context.Context,
|
|
||||||
identifier string,
|
|
||||||
) (models.Groupable, error) {
|
|
||||||
service, err := c.Service()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := service.Client().Groups().ByGroupId(identifier).Get(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
err := graph.Wrap(ctx, err, "getting group by id")
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
groups := []models.Groupable{resp}
|
|
||||||
|
|
||||||
if len(OnlyTeams(ctx, groups)) == 0 {
|
|
||||||
err := clues.New("given teamID is not related to any team")
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, graph.Stack(ctx, err).OrNil()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// helpers
|
// helpers
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@ -203,3 +132,38 @@ func ValidateGroup(item models.Groupable) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func OnlyTeams(ctx context.Context, groups []models.Groupable) []models.Groupable {
|
||||||
|
var teams []models.Groupable
|
||||||
|
|
||||||
|
for _, g := range groups {
|
||||||
|
if IsTeam(ctx, g) {
|
||||||
|
teams = append(teams, g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return teams
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsTeam(ctx context.Context, mg models.Groupable) bool {
|
||||||
|
log := logger.Ctx(ctx)
|
||||||
|
|
||||||
|
if mg.GetAdditionalData()[ResourceProvisioningOptions] == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val, _ := tform.AnyValueToT[[]any](ResourceProvisioningOptions, mg.GetAdditionalData())
|
||||||
|
for _, v := range val {
|
||||||
|
s, err := str.AnyToString(v)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("could not be converted to string value: ", ResourceProvisioningOptions)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if s == teamsAdditionalDataLabel {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
@ -97,7 +97,7 @@ func (suite *GroupsIntgSuite) SetupSuite() {
|
|||||||
suite.its = newIntegrationTesterSetup(suite.T())
|
suite.its = newIntegrationTesterSetup(suite.T())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *GroupsIntgSuite) TestGetAllGroups() {
|
func (suite *GroupsIntgSuite) TestGetAll() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
|
|
||||||
ctx, flush := tester.NewContext(t)
|
ctx, flush := tester.NewContext(t)
|
||||||
@ -107,100 +107,15 @@ func (suite *GroupsIntgSuite) TestGetAllGroups() {
|
|||||||
Groups().
|
Groups().
|
||||||
GetAll(ctx, fault.New(true))
|
GetAll(ctx, fault.New(true))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotZero(t, len(groups), "must have at least one group")
|
require.NotZero(t, len(groups), "must find at least one group")
|
||||||
}
|
|
||||||
|
|
||||||
func (suite *GroupsIntgSuite) TestGetAllTeams() {
|
|
||||||
t := suite.T()
|
|
||||||
|
|
||||||
ctx, flush := tester.NewContext(t)
|
|
||||||
defer flush()
|
|
||||||
|
|
||||||
teams, err := suite.its.ac.
|
|
||||||
Groups().
|
|
||||||
GetTeams(ctx, fault.New(true))
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotZero(t, len(teams), "must have at least one teams")
|
|
||||||
|
|
||||||
groups, err := suite.its.ac.
|
|
||||||
Groups().
|
|
||||||
GetAll(ctx, fault.New(true))
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotZero(t, len(groups), "must have at least one group")
|
|
||||||
|
|
||||||
var isTeam bool
|
|
||||||
|
|
||||||
if len(groups) > len(teams) {
|
|
||||||
isTeam = true
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.True(t, isTeam, "must only return teams")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (suite *GroupsIntgSuite) TestTeams_GetByID() {
|
|
||||||
var (
|
|
||||||
t = suite.T()
|
|
||||||
teamID = tconfig.M365TeamsID(t)
|
|
||||||
)
|
|
||||||
|
|
||||||
teamsAPI := suite.its.ac.Groups()
|
|
||||||
|
|
||||||
table := []struct {
|
|
||||||
name string
|
|
||||||
id string
|
|
||||||
expectErr func(*testing.T, error)
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "3 part id",
|
|
||||||
id: teamID,
|
|
||||||
expectErr: func(t *testing.T, err error) {
|
|
||||||
assert.NoError(t, err, clues.ToCore(err))
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "malformed id",
|
|
||||||
id: uuid.NewString(),
|
|
||||||
expectErr: func(t *testing.T, err error) {
|
|
||||||
assert.Error(t, err, clues.ToCore(err))
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "random id",
|
|
||||||
id: uuid.NewString() + "," + uuid.NewString(),
|
|
||||||
expectErr: func(t *testing.T, err error) {
|
|
||||||
assert.Error(t, err, clues.ToCore(err))
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: "malformed url",
|
|
||||||
id: "barunihlda",
|
|
||||||
expectErr: func(t *testing.T, err error) {
|
|
||||||
assert.Error(t, err, clues.ToCore(err))
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range table {
|
|
||||||
suite.Run(test.name, func() {
|
|
||||||
t := suite.T()
|
|
||||||
|
|
||||||
ctx, flush := tester.NewContext(t)
|
|
||||||
defer flush()
|
|
||||||
|
|
||||||
_, err := teamsAPI.GetTeamByID(ctx, test.id)
|
|
||||||
test.expectErr(t, err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *GroupsIntgSuite) TestGroups_GetByID() {
|
func (suite *GroupsIntgSuite) TestGroups_GetByID() {
|
||||||
var (
|
var (
|
||||||
t = suite.T()
|
groupID = suite.its.groupID
|
||||||
groupID = tconfig.M365GroupID(t)
|
groupsAPI = suite.its.ac.Groups()
|
||||||
)
|
)
|
||||||
|
|
||||||
groupsAPI := suite.its.ac.Groups()
|
|
||||||
|
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
id string
|
id string
|
||||||
|
|||||||
@ -83,7 +83,7 @@ type intgTesterSetup struct {
|
|||||||
siteID string
|
siteID string
|
||||||
siteDriveID string
|
siteDriveID string
|
||||||
siteDriveRootFolderID string
|
siteDriveRootFolderID string
|
||||||
teamID string
|
groupID string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newIntegrationTesterSetup(t *testing.T) intgTesterSetup {
|
func newIntegrationTesterSetup(t *testing.T) intgTesterSetup {
|
||||||
@ -132,13 +132,16 @@ func newIntegrationTesterSetup(t *testing.T) intgTesterSetup {
|
|||||||
|
|
||||||
its.siteDriveRootFolderID = ptr.Val(siteDriveRootFolder.GetId())
|
its.siteDriveRootFolderID = ptr.Val(siteDriveRootFolder.GetId())
|
||||||
|
|
||||||
// teams
|
// group
|
||||||
its.teamID = tconfig.M365TeamsID(t)
|
|
||||||
|
|
||||||
team, err := its.ac.Groups().GetTeamByID(ctx, its.teamID)
|
// use of the TeamID is intentional here, so that we are assured
|
||||||
|
// the group has full usage of the teams api.
|
||||||
|
its.groupID = tconfig.M365TeamID(t)
|
||||||
|
|
||||||
|
team, err := its.ac.Groups().GetByID(ctx, its.groupID)
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
its.teamID = ptr.Val(team.GetId())
|
its.groupID = ptr.Val(team.GetId())
|
||||||
|
|
||||||
return its
|
return its
|
||||||
}
|
}
|
||||||
|
|||||||
97
src/pkg/services/m365/groups.go
Normal file
97
src/pkg/services/m365/groups.go
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
package m365
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/alcionai/clues"
|
||||||
|
"github.com/microsoftgraph/msgraph-sdk-go/models"
|
||||||
|
|
||||||
|
"github.com/alcionai/corso/src/internal/common/ptr"
|
||||||
|
"github.com/alcionai/corso/src/pkg/account"
|
||||||
|
"github.com/alcionai/corso/src/pkg/fault"
|
||||||
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
|
"github.com/alcionai/corso/src/pkg/services/m365/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Group is the minimal information required to identify and display a M365 Group.
|
||||||
|
type Group struct {
|
||||||
|
ID string
|
||||||
|
|
||||||
|
// DisplayName is the human-readable name of the group. Normally the plaintext name that the
|
||||||
|
// user provided when they created the group, or the updated name if it was changed.
|
||||||
|
// Ex: displayName: "My Group"
|
||||||
|
DisplayName string
|
||||||
|
|
||||||
|
// IsTeam is true if the group qualifies as a Teams resource, and is able to backup and restore
|
||||||
|
// teams data.
|
||||||
|
IsTeam bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupsCompat returns a list of groups in the specified M365 tenant.
|
||||||
|
func GroupsCompat(ctx context.Context, acct account.Account) ([]*Group, error) {
|
||||||
|
errs := fault.New(true)
|
||||||
|
|
||||||
|
us, err := Groups(ctx, acct, errs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return us, errs.Failure()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Groups returns a list of groups in the specified M365 tenant
|
||||||
|
func Groups(
|
||||||
|
ctx context.Context,
|
||||||
|
acct account.Account,
|
||||||
|
errs *fault.Bus,
|
||||||
|
) ([]*Group, error) {
|
||||||
|
ac, err := makeAC(ctx, acct, path.GroupsService)
|
||||||
|
if err != nil {
|
||||||
|
return nil, clues.Stack(err).WithClues(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return getAllGroups(ctx, ac.Groups())
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAllGroups(
|
||||||
|
ctx context.Context,
|
||||||
|
ga getAller[models.Groupable],
|
||||||
|
) ([]*Group, error) {
|
||||||
|
groups, err := ga.GetAll(ctx, fault.New(true))
|
||||||
|
if err != nil {
|
||||||
|
return nil, clues.Wrap(err, "retrieving groups")
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := make([]*Group, 0, len(groups))
|
||||||
|
|
||||||
|
for _, g := range groups {
|
||||||
|
t, err := parseGroup(ctx, g)
|
||||||
|
if err != nil {
|
||||||
|
return nil, clues.Wrap(err, "parsing groups")
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// helpers
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// parseUser extracts information from `models.Groupable` we care about
|
||||||
|
func parseGroup(ctx context.Context, mg models.Groupable) (*Group, error) {
|
||||||
|
if mg.GetDisplayName() == nil {
|
||||||
|
return nil, clues.New("group missing display name").
|
||||||
|
With("group_id", ptr.Val(mg.GetId()))
|
||||||
|
}
|
||||||
|
|
||||||
|
u := &Group{
|
||||||
|
ID: ptr.Val(mg.GetId()),
|
||||||
|
DisplayName: ptr.Val(mg.GetDisplayName()),
|
||||||
|
IsTeam: api.IsTeam(ctx, mg),
|
||||||
|
}
|
||||||
|
|
||||||
|
return u, nil
|
||||||
|
}
|
||||||
108
src/pkg/services/m365/groups_test.go
Normal file
108
src/pkg/services/m365/groups_test.go
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
package m365_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/alcionai/clues"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
|
"github.com/alcionai/corso/src/internal/m365/graph"
|
||||||
|
"github.com/alcionai/corso/src/internal/tester"
|
||||||
|
"github.com/alcionai/corso/src/internal/tester/tconfig"
|
||||||
|
"github.com/alcionai/corso/src/pkg/account"
|
||||||
|
"github.com/alcionai/corso/src/pkg/credentials"
|
||||||
|
"github.com/alcionai/corso/src/pkg/fault"
|
||||||
|
"github.com/alcionai/corso/src/pkg/services/m365"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GroupsIntgSuite struct {
|
||||||
|
tester.Suite
|
||||||
|
acct account.Account
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGroupsIntgSuite(t *testing.T) {
|
||||||
|
suite.Run(t, &GroupsIntgSuite{
|
||||||
|
Suite: tester.NewIntegrationSuite(
|
||||||
|
t,
|
||||||
|
[][]string{tconfig.M365AcctCredEnvs}),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *GroupsIntgSuite) SetupSuite() {
|
||||||
|
t := suite.T()
|
||||||
|
|
||||||
|
ctx, flush := tester.NewContext(t)
|
||||||
|
defer flush()
|
||||||
|
|
||||||
|
graph.InitializeConcurrencyLimiter(ctx, true, 4)
|
||||||
|
|
||||||
|
suite.acct = tconfig.NewM365Account(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *GroupsIntgSuite) TestGroups() {
|
||||||
|
t := suite.T()
|
||||||
|
|
||||||
|
ctx, flush := tester.NewContext(t)
|
||||||
|
defer flush()
|
||||||
|
|
||||||
|
graph.InitializeConcurrencyLimiter(ctx, true, 4)
|
||||||
|
|
||||||
|
groups, err := m365.Groups(ctx, suite.acct, fault.New(true))
|
||||||
|
assert.NoError(t, err, clues.ToCore(err))
|
||||||
|
assert.NotEmpty(t, groups)
|
||||||
|
|
||||||
|
for _, group := range groups {
|
||||||
|
suite.Run("group_"+group.ID, func() {
|
||||||
|
t := suite.T()
|
||||||
|
|
||||||
|
assert.NotEmpty(t, group.ID)
|
||||||
|
assert.NotEmpty(t, group.DisplayName)
|
||||||
|
|
||||||
|
// at least one known group should be a team
|
||||||
|
if group.ID == tconfig.M365TeamID(t) {
|
||||||
|
assert.True(t, group.IsTeam)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *GroupsIntgSuite) TestGroups_InvalidCredentials() {
|
||||||
|
table := []struct {
|
||||||
|
name string
|
||||||
|
acct func(t *testing.T) account.Account
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Invalid Credentials",
|
||||||
|
acct: func(t *testing.T) account.Account {
|
||||||
|
a, err := account.NewAccount(
|
||||||
|
account.ProviderM365,
|
||||||
|
account.M365Config{
|
||||||
|
M365: credentials.M365{
|
||||||
|
AzureClientID: "Test",
|
||||||
|
AzureClientSecret: "without",
|
||||||
|
},
|
||||||
|
AzureTenantID: "data",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
|
return a
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range table {
|
||||||
|
suite.Run(test.name, func() {
|
||||||
|
t := suite.T()
|
||||||
|
|
||||||
|
ctx, flush := tester.NewContext(t)
|
||||||
|
defer flush()
|
||||||
|
|
||||||
|
groups, err := m365.Groups(ctx, test.acct(t), fault.New(true))
|
||||||
|
assert.Empty(t, groups, "returned no groups")
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -24,6 +24,10 @@ type getDefaultDriver interface {
|
|||||||
GetDefaultDrive(ctx context.Context, userID string) (models.Driveable, error)
|
GetDefaultDrive(ctx context.Context, userID string) (models.Driveable, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type getAller[T any] interface {
|
||||||
|
GetAll(ctx context.Context, errs *fault.Bus) ([]T, error)
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Users
|
// Users
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@ -253,12 +257,11 @@ func Sites(ctx context.Context, acct account.Account, errs *fault.Bus) ([]*Site,
|
|||||||
return getAllSites(ctx, ac.Sites())
|
return getAllSites(ctx, ac.Sites())
|
||||||
}
|
}
|
||||||
|
|
||||||
type getAllSiteser interface {
|
func getAllSites(
|
||||||
GetAll(ctx context.Context, errs *fault.Bus) ([]models.Siteable, error)
|
ctx context.Context,
|
||||||
}
|
ga getAller[models.Siteable],
|
||||||
|
) ([]*Site, error) {
|
||||||
func getAllSites(ctx context.Context, gas getAllSiteser) ([]*Site, error) {
|
sites, err := ga.GetAll(ctx, fault.New(true))
|
||||||
sites, err := gas.GetAll(ctx, fault.New(true))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if clues.HasLabel(err, graph.LabelsNoSharePointLicense) {
|
if clues.HasLabel(err, graph.LabelsNoSharePointLicense) {
|
||||||
return nil, clues.Stack(graph.ErrServiceNotEnabled, err)
|
return nil, clues.Stack(graph.ErrServiceNotEnabled, err)
|
||||||
|
|||||||
@ -276,25 +276,25 @@ func (suite *m365UnitSuite) TestCheckUserHasDrives() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockGAS struct {
|
type mockGASites struct {
|
||||||
response []models.Siteable
|
response []models.Siteable
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m mockGAS) GetAll(context.Context, *fault.Bus) ([]models.Siteable, error) {
|
func (m mockGASites) GetAll(context.Context, *fault.Bus) ([]models.Siteable, error) {
|
||||||
return m.response, m.err
|
return m.response, m.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *m365UnitSuite) TestGetAllSites() {
|
func (suite *m365UnitSuite) TestGetAllSites() {
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
mock func(context.Context) getAllSiteser
|
mock func(context.Context) getAller[models.Siteable]
|
||||||
expectErr func(*testing.T, error)
|
expectErr func(*testing.T, error)
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "ok",
|
name: "ok",
|
||||||
mock: func(ctx context.Context) getAllSiteser {
|
mock: func(ctx context.Context) getAller[models.Siteable] {
|
||||||
return mockGAS{[]models.Siteable{}, nil}
|
return mockGASites{[]models.Siteable{}, nil}
|
||||||
},
|
},
|
||||||
expectErr: func(t *testing.T, err error) {
|
expectErr: func(t *testing.T, err error) {
|
||||||
assert.NoError(t, err, clues.ToCore(err))
|
assert.NoError(t, err, clues.ToCore(err))
|
||||||
@ -302,14 +302,14 @@ func (suite *m365UnitSuite) TestGetAllSites() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no sharepoint license",
|
name: "no sharepoint license",
|
||||||
mock: func(ctx context.Context) getAllSiteser {
|
mock: func(ctx context.Context) getAller[models.Siteable] {
|
||||||
odErr := odataerrors.NewODataError()
|
odErr := odataerrors.NewODataError()
|
||||||
merr := odataerrors.NewMainError()
|
merr := odataerrors.NewMainError()
|
||||||
merr.SetCode(ptr.To("code"))
|
merr.SetCode(ptr.To("code"))
|
||||||
merr.SetMessage(ptr.To(string(graph.NoSPLicense)))
|
merr.SetMessage(ptr.To(string(graph.NoSPLicense)))
|
||||||
odErr.SetErrorEscaped(merr)
|
odErr.SetErrorEscaped(merr)
|
||||||
|
|
||||||
return mockGAS{nil, graph.Stack(ctx, odErr)}
|
return mockGASites{nil, graph.Stack(ctx, odErr)}
|
||||||
},
|
},
|
||||||
expectErr: func(t *testing.T, err error) {
|
expectErr: func(t *testing.T, err error) {
|
||||||
assert.ErrorIs(t, err, graph.ErrServiceNotEnabled, clues.ToCore(err))
|
assert.ErrorIs(t, err, graph.ErrServiceNotEnabled, clues.ToCore(err))
|
||||||
@ -317,14 +317,14 @@ func (suite *m365UnitSuite) TestGetAllSites() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "arbitrary error",
|
name: "arbitrary error",
|
||||||
mock: func(ctx context.Context) getAllSiteser {
|
mock: func(ctx context.Context) getAller[models.Siteable] {
|
||||||
odErr := odataerrors.NewODataError()
|
odErr := odataerrors.NewODataError()
|
||||||
merr := odataerrors.NewMainError()
|
merr := odataerrors.NewMainError()
|
||||||
merr.SetCode(ptr.To("code"))
|
merr.SetCode(ptr.To("code"))
|
||||||
merr.SetMessage(ptr.To("message"))
|
merr.SetMessage(ptr.To("message"))
|
||||||
odErr.SetErrorEscaped(merr)
|
odErr.SetErrorEscaped(merr)
|
||||||
|
|
||||||
return mockGAS{nil, graph.Stack(ctx, odErr)}
|
return mockGASites{nil, graph.Stack(ctx, odErr)}
|
||||||
},
|
},
|
||||||
expectErr: func(t *testing.T, err error) {
|
expectErr: func(t *testing.T, err error) {
|
||||||
assert.Error(t, err, clues.ToCore(err))
|
assert.Error(t, err, clues.ToCore(err))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user