diff --git a/src/pkg/path/resource_path.go b/src/pkg/path/resource_path.go index 88f025371..c2702faed 100644 --- a/src/pkg/path/resource_path.go +++ b/src/pkg/path/resource_path.go @@ -30,8 +30,8 @@ const ( ExchangeMetadataService // exchangeMetadata OneDriveMetadataService // onedriveMetadata SharePointMetadataService // sharepointMetadata - TeamsService // teams - TeamsMetadataService // teamsMetadata + GroupsService // groups + GroupsMetadataService // groupsMetadata ) func toServiceType(service string) ServiceType { diff --git a/src/pkg/path/servicetype_string.go b/src/pkg/path/servicetype_string.go index 6d6b960d8..6fa499364 100644 --- a/src/pkg/path/servicetype_string.go +++ b/src/pkg/path/servicetype_string.go @@ -15,11 +15,13 @@ func _() { _ = x[ExchangeMetadataService-4] _ = x[OneDriveMetadataService-5] _ = x[SharePointMetadataService-6] + _ = x[GroupsService-7] + _ = x[GroupsMetadataService-8] } -const _ServiceType_name = "UnknownServiceexchangeonedrivesharepointexchangeMetadataonedriveMetadatasharepointMetadata" +const _ServiceType_name = "UnknownServiceexchangeonedrivesharepointexchangeMetadataonedriveMetadatasharepointMetadatagroupsgroupsMetadata" -var _ServiceType_index = [...]uint8{0, 14, 22, 30, 40, 56, 72, 90} +var _ServiceType_index = [...]uint8{0, 14, 22, 30, 40, 56, 72, 90, 96, 110} func (i ServiceType) String() string { if i < 0 || i >= ServiceType(len(_ServiceType_index)-1) { diff --git a/src/pkg/services/m365/api/teams.go b/src/pkg/services/m365/api/groups.go similarity index 72% rename from src/pkg/services/m365/api/teams.go rename to src/pkg/services/m365/api/groups.go index 8eef3fba3..589da1a45 100644 --- a/src/pkg/services/m365/api/teams.go +++ b/src/pkg/services/m365/api/groups.go @@ -23,21 +23,21 @@ const ( // controller // --------------------------------------------------------------------------- -func (c Client) Teams() Teams { - return Teams{c} +func (c Client) Groups() Groups { + return Groups{c} } // On creation of each Teams team a corrsponding group gets created. // The group acts as the protected resource, and all teams data like events, // drive and mail messages are owned by that group. -// Teams is an interface-compliant provider of the client. -type Teams struct { +// Groups is an interface-compliant provider of the client. +type Groups struct { Client } -// GetAllTeams retrieves all groups. -func (c Teams) GetAll( +// GetAllGroups retrieves all groups. +func (c Groups) GetAll( ctx context.Context, errs *fault.Bus, ) ([]models.Groupable, error) { @@ -46,13 +46,26 @@ func (c Teams) GetAll( return nil, err } - return getGroups(ctx, true, errs, service) + return getGroups(ctx, func(ctx context.Context, g models.Groupable) bool { return true }, 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 + } + + return getGroups(ctx, FetchOnlyTeams, errs, service) } // GetAll retrieves all groups. func getGroups( ctx context.Context, - getOnlyTeams bool, + filterGroupsData func(ctx context.Context, g models.Groupable) bool, errs *fault.Bus, service graph.Servicer, ) ([]models.Groupable, error) { @@ -64,7 +77,7 @@ func getGroups( iter, err := msgraphgocore.NewPageIterator[models.Groupable]( resp, service.Adapter(), - models.CreateTeamCollectionResponseFromDiscriminatorValue) + models.CreateGroupCollectionResponseFromDiscriminatorValue) if err != nil { return nil, graph.Wrap(ctx, err, "creating groups iterator") } @@ -83,8 +96,7 @@ func getGroups( if err != nil { el.AddRecoverable(ctx, graph.Wrap(ctx, err, "validating groups")) } else { - isTeam := IsTeam(ctx, item) - if !getOnlyTeams || isTeam { + if filterGroupsData(ctx, item) { groups = append(groups, item) } } @@ -99,7 +111,7 @@ func getGroups( return groups, el.Failure() } -func IsTeam(ctx context.Context, g models.Groupable) bool { +func FetchOnlyTeams(ctx context.Context, g models.Groupable) bool { log := logger.Ctx(ctx) if g.GetAdditionalData()[ResourceProvisioningOptions] != nil { @@ -120,8 +132,8 @@ func IsTeam(ctx context.Context, g models.Groupable) bool { return false } -// GetID retrieves team by groupID/teamID. -func (c Teams) GetByID( +// GetID retrieves group by groupID. +func (c Groups) GetByID( ctx context.Context, identifier string, ) (models.Groupable, error) { @@ -137,7 +149,27 @@ func (c Teams) GetByID( return nil, err } - if !IsTeam(ctx, resp) { + 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 + } + + if !FetchOnlyTeams(ctx, resp) { err := clues.New("given teamID is not related to any team") return nil, err diff --git a/src/pkg/services/m365/api/teams_test.go b/src/pkg/services/m365/api/groups_test.go similarity index 53% rename from src/pkg/services/m365/api/teams_test.go rename to src/pkg/services/m365/api/groups_test.go index dcb039dc5..5d43ea08d 100644 --- a/src/pkg/services/m365/api/teams_test.go +++ b/src/pkg/services/m365/api/groups_test.go @@ -17,18 +17,18 @@ import ( "github.com/alcionai/corso/src/pkg/services/m365/api" ) -type TeamsUnitSuite struct { +type GroupUnitSuite struct { tester.Suite } -func TestTeamsUnitSuite(t *testing.T) { - suite.Run(t, &TeamsUnitSuite{Suite: tester.NewUnitSuite(t)}) +func TestGroupsUnitSuite(t *testing.T) { + suite.Run(t, &GroupUnitSuite{Suite: tester.NewUnitSuite(t)}) } -func (suite *TeamsUnitSuite) TestValidateGroup() { - team := models.NewTeam() - team.SetDisplayName(ptr.To("testgroup")) - team.SetId(ptr.To("testID")) +func (suite *GroupUnitSuite) TestValidateGroup() { + group := models.NewGroup() + group.SetDisplayName(ptr.To("testgroup")) + group.SetId(ptr.To("testID")) tests := []struct { name string @@ -41,7 +41,7 @@ func (suite *TeamsUnitSuite) TestValidateGroup() { args: func() *models.Group { s := models.NewGroup() s.SetId(ptr.To("id")) - s.SetDisplayName(ptr.To("testTeam")) + s.SetDisplayName(ptr.To("testgroup")) return s }(), errCheck: assert.NoError, @@ -59,7 +59,7 @@ func (suite *TeamsUnitSuite) TestValidateGroup() { name: "No ID", args: func() *models.Group { s := models.NewGroup() - s.SetDisplayName(ptr.To("testTeam")) + s.SetDisplayName(ptr.To("testgroup")) return s }(), errCheck: assert.Error, @@ -80,47 +80,60 @@ func (suite *TeamsUnitSuite) TestValidateGroup() { } } -type TeamsIntgSuite struct { +type GroupsIntgSuite struct { tester.Suite its intgTesterSetup } -func TestTeamsIntgSuite(t *testing.T) { - suite.Run(t, &TeamsIntgSuite{ +func TestGroupsIntgSuite(t *testing.T) { + suite.Run(t, &GroupsIntgSuite{ Suite: tester.NewIntegrationSuite( t, [][]string{tconfig.M365AcctCredEnvs}), }) } -func (suite *TeamsIntgSuite) SetupSuite() { +func (suite *GroupsIntgSuite) SetupSuite() { suite.its = newIntegrationTesterSetup(suite.T()) } -func (suite *TeamsIntgSuite) TestGetAllTeams() { +func (suite *GroupsIntgSuite) TestGetAllGroups() { t := suite.T() ctx, flush := tester.NewContext(t) defer flush() - teams, err := suite.its.ac. - Teams(). + groups, err := suite.its.ac. + Groups(). GetAll(ctx, fault.New(true)) require.NoError(t, err) - require.NotZero(t, len(teams), "must have at least one team") + require.NotZero(t, len(groups), "must have at least one group") +} - for _, team := range teams { - assert.True(t, api.IsTeam(ctx, team), "must not return non teams groups") +func (suite *GroupsIntgSuite) TestGetAllTeams() { + t := suite.T() + + ctx, flush := tester.NewContext(t) + defer flush() + + groups, err := suite.its.ac. + Groups(). + GetTeams(ctx, fault.New(true)) + require.NoError(t, err) + require.NotZero(t, len(groups), "must have at least one group") + + for _, team := range groups { + assert.True(t, api.FetchOnlyTeams(ctx, team), "must not return non groups groups") } } -func (suite *TeamsIntgSuite) TestTeams_GetByID() { +func (suite *GroupsIntgSuite) TestTeams_GetByID() { var ( t = suite.T() teamID = tconfig.M365TeamsID(t) ) - teamsAPI := suite.its.ac.Teams() + teamsAPI := suite.its.ac.Groups() table := []struct { name string @@ -164,7 +177,63 @@ func (suite *TeamsIntgSuite) TestTeams_GetByID() { ctx, flush := tester.NewContext(t) defer flush() - _, err := teamsAPI.GetByID(ctx, test.id) + _, err := teamsAPI.GetTeamByID(ctx, test.id) + test.expectErr(t, err) + }) + } +} + +func (suite *GroupsIntgSuite) TestGroups_GetByID() { + var ( + t = suite.T() + groupID = tconfig.M365GroupID(t) + ) + + groupsAPI := suite.its.ac.Groups() + + table := []struct { + name string + id string + expectErr func(*testing.T, error) + }{ + { + name: "3 part id", + id: groupID, + 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 := groupsAPI.GetByID(ctx, test.id) test.expectErr(t, err) }) } diff --git a/src/pkg/services/m365/api/helper_test.go b/src/pkg/services/m365/api/helper_test.go index fb5138350..cf61c0277 100644 --- a/src/pkg/services/m365/api/helper_test.go +++ b/src/pkg/services/m365/api/helper_test.go @@ -135,7 +135,7 @@ func newIntegrationTesterSetup(t *testing.T) intgTesterSetup { // teams its.teamID = tconfig.M365TeamsID(t) - team, err := its.ac.Teams().GetByID(ctx, its.teamID) + team, err := its.ac.Groups().GetTeamByID(ctx, its.teamID) require.NoError(t, err, clues.ToCore(err)) its.teamID = ptr.Val(team.GetId())