add teamschat boilerplate to m365/service

This commit is contained in:
ryanfkeepers 2024-01-22 17:19:42 -07:00
parent 8344fe60be
commit db14816ac8
8 changed files with 267 additions and 4 deletions

View File

@ -139,7 +139,7 @@ func populateCollection[I chatsItemer](
cl.Add(count.ItemsAdded, int64(len(includedItems))) cl.Add(count.ItemsAdded, int64(len(includedItems)))
cl.Add(count.ItemsRemoved, 0) cl.Add(count.ItemsRemoved, 0)
p, err := bh.canonicalPath() p, err := bh.CanonicalPath()
if err != nil { if err != nil {
err = clues.StackWC(ctx, err).Label(count.BadCollPath) err = clues.StackWC(ctx, err).Label(count.BadCollPath)
errs.AddRecoverable(ctx, err) errs.AddRecoverable(ctx, err)

View File

@ -84,7 +84,7 @@ func (bh mockBackupHandler) includeItem(
return !bh.doNotInclude return !bh.doNotInclude
} }
func (bh mockBackupHandler) canonicalPath() (path.Path, error) { func (bh mockBackupHandler) CanonicalPath() (path.Path, error) {
return path.BuildPrefix( return path.BuildPrefix(
"tenant", "tenant",
"protectedResource", "protectedResource",

View File

@ -61,7 +61,7 @@ func (bh usersChatsBackupHandler) includeItem(
return scope.Matches(selectors.TeamsChatsChat, ptr.Val(ch.GetTopic())) return scope.Matches(selectors.TeamsChatsChat, ptr.Val(ch.GetTopic()))
} }
func (bh usersChatsBackupHandler) canonicalPath() (path.Path, error) { func (bh usersChatsBackupHandler) CanonicalPath() (path.Path, error) {
return path.BuildPrefix( return path.BuildPrefix(
bh.tenantID, bh.tenantID,
bh.protectedResourceID, bh.protectedResourceID,

View File

@ -79,7 +79,7 @@ type includeItemer[I chatsItemer] interface {
// the given builder. The tenantID and protectedResourceID are assumed // the given builder. The tenantID and protectedResourceID are assumed
// to be stored in the handler already. // to be stored in the handler already.
type canonicalPather interface { type canonicalPather interface {
canonicalPath() (path.Path, error) CanonicalPath() (path.Path, error)
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -0,0 +1,162 @@
package groups
import (
"context"
"github.com/alcionai/clues"
"github.com/alcionai/corso/src/internal/common/idname"
"github.com/alcionai/corso/src/internal/common/prefixmatcher"
"github.com/alcionai/corso/src/internal/data"
"github.com/alcionai/corso/src/internal/m365/collection/teamschats"
"github.com/alcionai/corso/src/internal/m365/support"
"github.com/alcionai/corso/src/internal/observe"
"github.com/alcionai/corso/src/internal/operations/inject"
"github.com/alcionai/corso/src/pkg/account"
"github.com/alcionai/corso/src/pkg/count"
"github.com/alcionai/corso/src/pkg/fault"
"github.com/alcionai/corso/src/pkg/logger"
"github.com/alcionai/corso/src/pkg/path"
"github.com/alcionai/corso/src/pkg/selectors"
"github.com/alcionai/corso/src/pkg/services/m365/api"
"github.com/alcionai/corso/src/pkg/services/m365/api/graph"
)
func ProduceBackupCollections(
ctx context.Context,
bpc inject.BackupProducerConfig,
ac api.Client,
creds account.M365Config,
su support.StatusUpdater,
counter *count.Bus,
errs *fault.Bus,
) ([]data.BackupCollection, *prefixmatcher.StringSetMatcher, error) {
b, err := bpc.Selector.ToTeamsChatsBackup()
if err != nil {
return nil, nil, clues.WrapWC(ctx, err, "parsing selector")
}
var (
el = errs.Local()
collections = []data.BackupCollection{}
categories = map[path.CategoryType]struct{}{}
)
ctx = clues.Add(
ctx,
"user_id", clues.Hide(bpc.ProtectedResource.ID()),
"user_name", clues.Hide(bpc.ProtectedResource.Name()))
bc := backupCommon{
apiCli: ac,
producerConfig: bpc,
creds: creds,
user: bpc.ProtectedResource,
statusUpdater: su,
}
for _, scope := range b.Scopes() {
if el.Failure() != nil {
break
}
cl := counter.Local()
ictx := clues.AddLabelCounter(ctx, cl.PlainAdder())
ictx = clues.Add(ictx, "category", scope.Category().PathType())
var colls []data.BackupCollection
switch scope.Category().PathType() {
case path.ChatsCategory:
colls, err = backupChats(
ictx,
bc,
scope,
cl,
el)
}
if err != nil {
el.AddRecoverable(ctx, clues.Stack(err))
continue
}
collections = append(collections, colls...)
categories[scope.Category().PathType()] = struct{}{}
}
if len(collections) > 0 {
baseCols, err := graph.BaseCollections(
ctx,
collections,
creds.AzureTenantID,
bpc.ProtectedResource.ID(),
path.TeamsChatsService,
categories,
su,
counter,
errs)
if err != nil {
return nil, nil, err
}
collections = append(collections, baseCols...)
}
counter.Add(count.Collections, int64(len(collections)))
logger.Ctx(ctx).Infow("produced collections", "stats", counter.Values())
return collections, nil, clues.Stack(el.Failure()).OrNil()
}
type backupCommon struct {
apiCli api.Client
producerConfig inject.BackupProducerConfig
creds account.M365Config
user idname.Provider
statusUpdater support.StatusUpdater
}
func backupChats(
ctx context.Context,
bc backupCommon,
scope selectors.TeamsChatsScope,
counter *count.Bus,
errs *fault.Bus,
) ([]data.BackupCollection, error) {
var (
colls []data.BackupCollection
)
progressMessage := observe.MessageWithCompletion(
ctx,
observe.ProgressCfg{
Indent: 1,
CompletionMessage: func() string { return "(done)" },
},
scope.Category().PathType().HumanString())
defer close(progressMessage)
bh := teamschats.NewUsersChatsBackupHandler(
bc.creds.AzureTenantID,
bc.producerConfig.ProtectedResource.ID(),
bc.apiCli.Chats())
// Always disable lazy reader for channels until #4321 support is added
useLazyReader := false
colls, _, err := teamschats.CreateCollections(
ctx,
bc.producerConfig,
bh,
bc.creds.AzureTenantID,
scope,
bc.statusUpdater,
useLazyReader,
counter,
errs)
return colls, clues.Stack(err).OrNil()
}

View File

@ -0,0 +1,18 @@
package groups
import (
"context"
"github.com/alcionai/clues"
"github.com/microsoftgraph/msgraph-sdk-go/models"
"github.com/alcionai/corso/src/pkg/services/m365/api"
)
func IsServiceEnabled(
ctx context.Context,
gbi api.GetByIDer[models.Userable],
resource string,
) (bool, error) {
return true, clues.New("needs implementation")
}

View File

@ -0,0 +1,69 @@
package groups
import (
"context"
"testing"
"github.com/alcionai/clues"
"github.com/microsoftgraph/msgraph-sdk-go/models"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"github.com/alcionai/corso/src/internal/tester"
"github.com/alcionai/corso/src/pkg/services/m365/api"
)
type EnabledUnitSuite struct {
tester.Suite
}
func TestEnabledUnitSuite(t *testing.T) {
suite.Run(t, &EnabledUnitSuite{Suite: tester.NewUnitSuite(t)})
}
var _ api.GetByIDer[models.Userable] = mockGU{}
type mockGU struct {
user models.Userable
err error
}
func (m mockGU) GetByID(
ctx context.Context,
identifier string,
_ api.CallConfig,
) (models.Userable, error) {
return m.user, m.err
}
func (suite *EnabledUnitSuite) TestIsServiceEnabled() {
table := []struct {
name string
mock func(context.Context) api.GetByIDer[models.Userable]
expect assert.BoolAssertionFunc
expectErr assert.ErrorAssertionFunc
}{
{
name: "ok",
mock: func(ctx context.Context) api.GetByIDer[models.Userable] {
return mockGU{}
},
expect: assert.True,
expectErr: assert.Error,
},
}
for _, test := range table {
suite.Run(test.name, func() {
t := suite.T()
ctx, flush := tester.NewContext(t)
defer flush()
gu := test.mock(ctx)
ok, err := IsServiceEnabled(ctx, gu, "resource_id")
test.expect(t, ok, "has mailbox flag")
test.expectErr(t, err, clues.ToCore(err))
})
}
}

View File

@ -0,0 +1,14 @@
package stub
import (
"github.com/alcionai/corso/src/pkg/backup/details"
)
func ItemInfo() details.ItemInfo {
return details.ItemInfo{
TeamsChats: &details.TeamsChatsInfo{
ItemType: details.TeamsChat,
Chat: details.ChatInfo{},
},
}
}