diff --git a/src/cli/backup/teamschats.go b/src/cli/backup/teamschats.go index d324deead..e4318bdbf 100644 --- a/src/cli/backup/teamschats.go +++ b/src/cli/backup/teamschats.go @@ -213,7 +213,6 @@ func runDetailsTeamsChatsCmd(cmd *cobra.Command) error { opts := utils.MakeTeamsChatsOpts(cmd) sel := utils.IncludeTeamsChatsRestoreDataSelectors(ctx, opts) - sel.Configure(selectors.Config{OnlyMatchItemNames: true}) utils.FilterTeamsChatsRestoreInfoSelectors(sel, opts) ds, err := genericDetailsCommand(cmd, flags.BackupIDFV, sel.Selector) diff --git a/src/cli/utils/teamschats.go b/src/cli/utils/teamschats.go index 1467949a3..f91609bbc 100644 --- a/src/cli/utils/teamschats.go +++ b/src/cli/utils/teamschats.go @@ -89,7 +89,10 @@ func IncludeTeamsChatsRestoreDataSelectors(ctx context.Context, opts TeamsChatsO users = selectors.Any() } - return selectors.NewTeamsChatsRestore(users) + sel := selectors.NewTeamsChatsRestore(users) + sel.Include(sel.Chats(selectors.Any())) + + return sel } // FilterTeamsChatsRestoreInfoSelectors builds the common info-selector filters. diff --git a/src/internal/m365/collection/teamsChats/backup.go b/src/internal/m365/collection/teamsChats/backup.go index 2a464d322..0155383b6 100644 --- a/src/internal/m365/collection/teamsChats/backup.go +++ b/src/internal/m365/collection/teamsChats/backup.go @@ -115,11 +115,8 @@ func populateCollection[I chatsItemer]( ) ctx = clues.AddLabelCounter(ctx, cl.PlainAdder()) - cc := api.CallConfig{ - CanMakeDeltaQueries: false, - } - items, err := bh.getItemIDs(ctx, cc) + items, err := bh.getItemIDs(ctx) if err != nil { errs.AddRecoverable(ctx, clues.Stack(err)) return collection, clues.Stack(errs.Failure()).OrNil() diff --git a/src/internal/m365/collection/teamsChats/backup_test.go b/src/internal/m365/collection/teamsChats/backup_test.go index 9ca745b55..3bf22a776 100644 --- a/src/internal/m365/collection/teamsChats/backup_test.go +++ b/src/internal/m365/collection/teamsChats/backup_test.go @@ -49,14 +49,6 @@ type mockBackupHandler struct { doNotInclude bool } -//lint:ignore U1000 false linter issue due to generics -func (bh mockBackupHandler) augmentItemInfo( - *details.TeamsChatsInfo, - models.Chatable, -) { - // no-op -} - func (bh mockBackupHandler) container() container[models.Chatable] { return chatContainer() } @@ -71,7 +63,6 @@ func (bh mockBackupHandler) getContainer( func (bh mockBackupHandler) getItemIDs( _ context.Context, - _ api.CallConfig, ) ([]models.Chatable, error) { return bh.chats, bh.chatsErr } diff --git a/src/internal/m365/collection/teamsChats/chat_handler.go b/src/internal/m365/collection/teamsChats/chat_handler.go index b87f4dd1b..121068655 100644 --- a/src/internal/m365/collection/teamsChats/chat_handler.go +++ b/src/internal/m365/collection/teamsChats/chat_handler.go @@ -46,8 +46,11 @@ func (bh usersChatsBackupHandler) getContainer( //lint:ignore U1000 required for interface compliance func (bh usersChatsBackupHandler) getItemIDs( ctx context.Context, - cc api.CallConfig, ) ([]models.Chatable, error) { + cc := api.CallConfig{ + Expand: []string{"lastMessagePreview"}, + } + return bh.ac.GetChats( ctx, bh.protectedResourceID, @@ -89,11 +92,7 @@ func (bh usersChatsBackupHandler) getItem( chatID := ptr.Val(chat.GetId()) - cc := api.CallConfig{ - Expand: []string{"lastMessagePreview"}, - } - - msgs, err := bh.ac.GetChatMessages(ctx, chatID, cc) + msgs, err := bh.ac.GetChatMessages(ctx, chatID, api.CallConfig{}) if err != nil { return nil, nil, clues.Stack(err) } @@ -103,14 +102,6 @@ func (bh usersChatsBackupHandler) getItem( return chat, api.TeamsChatInfo(chat), nil } -//lint:ignore U1000 false linter issue due to generics -func (bh usersChatsBackupHandler) augmentItemInfo( - dgi *details.TeamsChatsInfo, - c models.Chatable, -) { - // no-op -} - func chatContainer() container[models.Chatable] { return container[models.Chatable]{ storageDirFolders: path.Elements{}, diff --git a/src/internal/m365/collection/teamsChats/collection.go b/src/internal/m365/collection/teamsChats/collection.go index 6c32bd5cd..e2fe532db 100644 --- a/src/internal/m365/collection/teamsChats/collection.go +++ b/src/internal/m365/collection/teamsChats/collection.go @@ -66,7 +66,7 @@ func updateStatus( // or notMoved (if they match). func NewCollection[I chatsItemer]( baseCol data.BaseCollection, - getAndAugment getItemAndAugmentInfoer[I], + getter getItemer[I], protectedResource string, items []I, contains container[I], @@ -76,7 +76,7 @@ func NewCollection[I chatsItemer]( BaseCollection: baseCol, items: items, contains: contains, - getAndAugment: getAndAugment, + getter: getter, statusUpdater: statusUpdater, stream: make(chan data.Item, collectionChannelBufferSize), protectedResource: protectedResource, @@ -96,7 +96,7 @@ type lazyFetchCollection[I chatsItemer] struct { items []I - getAndAugment getItemAndAugmentInfoer[I] + getter getItemer[I] statusUpdater support.StatusUpdater } @@ -167,13 +167,13 @@ func (col *lazyFetchCollection[I]) streamItems(ctx context.Context, errs *fault. col.stream <- data.NewLazyItemWithInfo( ictx, &lazyItemGetter[I]{ - modTime: modTime, - getAndAugment: col.getAndAugment, - resourceID: col.protectedResource, - item: item, - containerIDs: col.FullPath().Folders(), - contains: col.contains, - parentPath: col.LocationPath().String(), + modTime: modTime, + getter: col.getter, + resourceID: col.protectedResource, + item: item, + containerIDs: col.FullPath().Folders(), + contains: col.contains, + parentPath: col.LocationPath().String(), }, itemID, modTime, @@ -192,13 +192,13 @@ func (col *lazyFetchCollection[I]) streamItems(ctx context.Context, errs *fault. } type lazyItemGetter[I chatsItemer] struct { - getAndAugment getItemAndAugmentInfoer[I] - resourceID string - item I - parentPath string - containerIDs path.Elements - modTime time.Time - contains container[I] + getter getItemer[I] + resourceID string + item I + parentPath string + containerIDs path.Elements + modTime time.Time + contains container[I] } func (lig *lazyItemGetter[I]) GetData( @@ -208,7 +208,7 @@ func (lig *lazyItemGetter[I]) GetData( writer := kjson.NewJsonSerializationWriter() defer writer.Close() - item, info, err := lig.getAndAugment.getItem( + item, info, err := lig.getter.getItem( ctx, lig.resourceID, lig.item) @@ -229,8 +229,6 @@ func (lig *lazyItemGetter[I]) GetData( return nil, nil, false, err } - lig.getAndAugment.augmentItemInfo(info, lig.contains.container) - if err := writer.WriteObjectValue("", item); err != nil { err = clues.WrapWC(ctx, err, "writing item to serializer").Label(fault.LabelForceNoBackupCreation) errs.AddRecoverable(ctx, err) diff --git a/src/internal/m365/collection/teamsChats/collection_test.go b/src/internal/m365/collection/teamsChats/collection_test.go index 1eb8a237c..b1296e40f 100644 --- a/src/internal/m365/collection/teamsChats/collection_test.go +++ b/src/internal/m365/collection/teamsChats/collection_test.go @@ -163,11 +163,6 @@ func (m getAndAugmentChat) getItem( return chat, &details.TeamsChatsInfo{}, m.err } -//lint:ignore U1000 false linter issue due to generics -func (getAndAugmentChat) augmentItemInfo(*details.TeamsChatsInfo, models.Chatable) { - // no-op -} - func (suite *CollectionUnitSuite) TestLazyFetchCollection_Items_LazyFetch() { var ( t = suite.T() @@ -225,7 +220,7 @@ func (suite *CollectionUnitSuite) TestLazyFetchCollection_Items_LazyFetch() { count.New()), items: test.items, contains: container[models.Chatable]{}, - getAndAugment: getterAugmenter, + getter: getterAugmenter, stream: make(chan data.Item), statusUpdater: statusUpdater, } @@ -285,11 +280,11 @@ func (suite *CollectionUnitSuite) TestLazyItem_GetDataErrors() { li := data.NewLazyItemWithInfo( ctx, &lazyItemGetter[models.Chatable]{ - resourceID: "resourceID", - item: chat, - getAndAugment: &m, - modTime: now, - parentPath: parentPath, + resourceID: "resourceID", + item: chat, + getter: &m, + modTime: now, + parentPath: parentPath, }, ptr.Val(chat.GetId()), now, @@ -329,11 +324,11 @@ func (suite *CollectionUnitSuite) TestLazyItem_ReturnsEmptyReaderOnDeletedInFlig li := data.NewLazyItemWithInfo( ctx, &lazyItemGetter[models.Chatable]{ - resourceID: "resourceID", - item: chat, - getAndAugment: &m, - modTime: now, - parentPath: parentPath, + resourceID: "resourceID", + item: chat, + getter: &m, + modTime: now, + parentPath: parentPath, }, ptr.Val(chat.GetId()), now, @@ -368,11 +363,11 @@ func (suite *CollectionUnitSuite) TestLazyItem() { li := data.NewLazyItemWithInfo( ctx, &lazyItemGetter[models.Chatable]{ - resourceID: "resourceID", - item: chat, - getAndAugment: &m, - modTime: now, - parentPath: parentPath, + resourceID: "resourceID", + item: chat, + getter: &m, + modTime: now, + parentPath: parentPath, }, ptr.Val(chat.GetId()), now, diff --git a/src/internal/m365/collection/teamsChats/handlers.go b/src/internal/m365/collection/teamsChats/handlers.go index 2763f8704..7865de489 100644 --- a/src/internal/m365/collection/teamsChats/handlers.go +++ b/src/internal/m365/collection/teamsChats/handlers.go @@ -22,7 +22,7 @@ type chatsItemer interface { type backupHandler[I chatsItemer] interface { getContainerer[I] - getItemAndAugmentInfoer[I] + getItemer[I] getItemer[I] getItemIDser[I] includeItemer[I] @@ -39,22 +39,10 @@ type getContainerer[I chatsItemer] interface { ) (container[I], error) } -type getItemAndAugmentInfoer[I chatsItemer] interface { - getItemer[I] - augmentItemInfoer[I] -} - -type augmentItemInfoer[I chatsItemer] interface { - // augmentItemInfo completes the teamChatsInfo population with any data - // owned by the container and not accessible to the item. - augmentItemInfo(*details.TeamsChatsInfo, I) -} - // gets all item IDs in the container type getItemIDser[I chatsItemer] interface { getItemIDs( ctx context.Context, - cc api.CallConfig, ) ([]I, error) } diff --git a/src/pkg/backup/details/entry.go b/src/pkg/backup/details/entry.go index 0d040eb67..d33cb6051 100644 --- a/src/pkg/backup/details/entry.go +++ b/src/pkg/backup/details/entry.go @@ -141,26 +141,23 @@ func (de Entry) MinimumPrintable() any { // Headers returns the human-readable names of properties in a DetailsEntry // for printing out to a terminal in a columnar display. func (de Entry) Headers(skipID bool) []string { - hs := []string{} + var hs []string - if de.ItemInfo.Folder != nil { + switch { + case de.ItemInfo.Folder != nil: hs = de.ItemInfo.Folder.Headers() - } - - if de.ItemInfo.Exchange != nil { + case de.ItemInfo.Exchange != nil: hs = de.ItemInfo.Exchange.Headers() - } - - if de.ItemInfo.SharePoint != nil { + case de.ItemInfo.SharePoint != nil: hs = de.ItemInfo.SharePoint.Headers() - } - - if de.ItemInfo.OneDrive != nil { + case de.ItemInfo.OneDrive != nil: hs = de.ItemInfo.OneDrive.Headers() - } - - if de.ItemInfo.Groups != nil { + case de.ItemInfo.Groups != nil: hs = de.ItemInfo.Groups.Headers() + case de.ItemInfo.TeamsChats != nil: + hs = de.ItemInfo.TeamsChats.Headers() + default: + hs = []string{"ERROR - Service not recognized"} } if skipID { @@ -172,26 +169,23 @@ func (de Entry) Headers(skipID bool) []string { // Values returns the values matching the Headers list. func (de Entry) Values(skipID bool) []string { - vs := []string{} + var vs []string - if de.ItemInfo.Folder != nil { + switch { + case de.ItemInfo.Folder != nil: vs = de.ItemInfo.Folder.Values() - } - - if de.ItemInfo.Exchange != nil { + case de.ItemInfo.Exchange != nil: vs = de.ItemInfo.Exchange.Values() - } - - if de.ItemInfo.SharePoint != nil { + case de.ItemInfo.SharePoint != nil: vs = de.ItemInfo.SharePoint.Values() - } - - if de.ItemInfo.OneDrive != nil { + case de.ItemInfo.OneDrive != nil: vs = de.ItemInfo.OneDrive.Values() - } - - if de.ItemInfo.Groups != nil { + case de.ItemInfo.Groups != nil: vs = de.ItemInfo.Groups.Values() + case de.ItemInfo.TeamsChats != nil: + vs = de.ItemInfo.TeamsChats.Values() + default: + vs = []string{"ERROR - Service not recognized"} } if skipID { diff --git a/src/pkg/backup/details/iteminfo.go b/src/pkg/backup/details/iteminfo.go index 22391d2d8..656d7d92a 100644 --- a/src/pkg/backup/details/iteminfo.go +++ b/src/pkg/backup/details/iteminfo.go @@ -91,19 +91,14 @@ func (i ItemInfo) infoType() ItemType { switch { case i.Folder != nil: return i.Folder.ItemType - case i.Exchange != nil: return i.Exchange.ItemType - case i.SharePoint != nil: return i.SharePoint.ItemType - case i.OneDrive != nil: return i.OneDrive.ItemType - case i.Groups != nil: return i.Groups.ItemType - case i.TeamsChats != nil: return i.TeamsChats.ItemType } @@ -115,19 +110,14 @@ func (i ItemInfo) size() int64 { switch { case i.Exchange != nil: return i.Exchange.Size - case i.OneDrive != nil: return i.OneDrive.Size - case i.SharePoint != nil: return i.SharePoint.Size - case i.Groups != nil: return i.Groups.Size - case i.Folder != nil: return i.Folder.Size - case i.TeamsChats != nil: return int64(i.TeamsChats.Chat.MessageCount) } @@ -139,19 +129,14 @@ func (i ItemInfo) Modified() time.Time { switch { case i.Exchange != nil: return i.Exchange.Modified - case i.OneDrive != nil: return i.OneDrive.Modified - case i.SharePoint != nil: return i.SharePoint.Modified - case i.Groups != nil: return i.Groups.Modified - case i.Folder != nil: return i.Folder.Modified - case i.TeamsChats != nil: return i.TeamsChats.Modified } @@ -163,19 +148,14 @@ func (i ItemInfo) uniqueLocation(baseLoc *path.Builder) (*uniqueLoc, error) { switch { case i.Exchange != nil: return i.Exchange.uniqueLocation(baseLoc) - case i.OneDrive != nil: return i.OneDrive.uniqueLocation(baseLoc) - case i.SharePoint != nil: return i.SharePoint.uniqueLocation(baseLoc) - case i.Groups != nil: return i.Groups.uniqueLocation(baseLoc) - case i.TeamsChats != nil: return i.TeamsChats.uniqueLocation(baseLoc) - default: return nil, clues.New("unsupported type") } @@ -185,19 +165,14 @@ func (i ItemInfo) updateFolder(f *FolderInfo) error { switch { case i.Exchange != nil: return i.Exchange.updateFolder(f) - case i.OneDrive != nil: return i.OneDrive.updateFolder(f) - case i.SharePoint != nil: return i.SharePoint.updateFolder(f) - case i.Groups != nil: return i.Groups.updateFolder(f) - case i.TeamsChats != nil: return i.TeamsChats.updateFolder(f) - default: return clues.New("unsupported type") } diff --git a/src/pkg/backup/details/teamsChats.go b/src/pkg/backup/details/teamsChats.go index 04e2d61a7..e5c411593 100644 --- a/src/pkg/backup/details/teamsChats.go +++ b/src/pkg/backup/details/teamsChats.go @@ -44,7 +44,7 @@ type ChatInfo struct { LastMessagePreview string `json:"preview,omitempty"` Members []string `json:"members,omitempty"` MessageCount int `json:"size,omitempty"` - Name string `json:"name,omitempty"` + Topic string `json:"topic,omitempty"` } // Headers returns the human-readable names of properties in a ChatsInfo @@ -52,7 +52,7 @@ type ChatInfo struct { func (i TeamsChatsInfo) Headers() []string { switch i.ItemType { case TeamsChat: - return []string{"Name", "Last message", "Last message at", "Message count", "Created", "Members"} + return []string{"Topic", "Last message", "Last message at", "Message count", "Created", "Members"} } return []string{} @@ -75,7 +75,7 @@ func (i TeamsChatsInfo) Values() []string { } return []string{ - i.Chat.Name, + i.Chat.Topic, i.Chat.LastMessagePreview, dttm.FormatToTabularDisplay(i.Chat.LastMessageAt), strconv.Itoa(i.Chat.MessageCount), diff --git a/src/pkg/backup/details/teamsChats_test.go b/src/pkg/backup/details/teamsChats_test.go index 476a32341..d3f646f1d 100644 --- a/src/pkg/backup/details/teamsChats_test.go +++ b/src/pkg/backup/details/teamsChats_test.go @@ -42,7 +42,7 @@ func (suite *ChatsUnitSuite) TestChatsPrintable() { LastMessagePreview: "last message preview", Members: []string{"foo@bar.baz", "fnords@smarf.zoomba"}, MessageCount: 42, - Name: "chat name", + Topic: "chat name", }, }, expectHs: []string{"Name", "Last message", "Last message at", "Message count", "Created", "Members"}, diff --git a/src/pkg/selectors/teamsChats.go b/src/pkg/selectors/teamsChats.go index 18ca26e39..c22b1dd02 100644 --- a/src/pkg/selectors/teamsChats.go +++ b/src/pkg/selectors/teamsChats.go @@ -506,7 +506,7 @@ func (s TeamsChatsScope) matchesInfo(dii details.ItemInfo) bool { case TeamsChatsInfoChatMember: i = strings.Join(info.Chat.Members, ",") case TeamsChatsInfoChatName: - i = info.Chat.Name + i = info.Chat.Topic } return s.Matches(infoCat, i) diff --git a/src/pkg/selectors/teamsChats_test.go b/src/pkg/selectors/teamsChats_test.go index f3b695494..990450e79 100644 --- a/src/pkg/selectors/teamsChats_test.go +++ b/src/pkg/selectors/teamsChats_test.go @@ -273,7 +273,7 @@ func (suite *TeamsChatsSelectorSuite) TestTeamsChatsScope_MatchesInfo() { LastMessagePreview: "preview", Members: []string{member}, MessageCount: 1, - Name: name, + Topic: name, }, }, } diff --git a/src/pkg/services/m365/api/teamsChats.go b/src/pkg/services/m365/api/teamsChats.go index 3aca53c40..04e1b7459 100644 --- a/src/pkg/services/m365/api/teamsChats.go +++ b/src/pkg/services/m365/api/teamsChats.go @@ -103,7 +103,7 @@ func TeamsChatInfo(chat models.Chatable) *details.TeamsChatsInfo { LastMessagePreview: preview, Members: memberNames, MessageCount: len(msgs), - Name: ptr.Val(chat.GetTopic()), + Topic: ptr.Val(chat.GetTopic()), }, } } diff --git a/src/pkg/services/m365/api/teamsChats_test.go b/src/pkg/services/m365/api/teamsChats_test.go index 9d2c762f8..2f17cff92 100644 --- a/src/pkg/services/m365/api/teamsChats_test.go +++ b/src/pkg/services/m365/api/teamsChats_test.go @@ -64,7 +64,7 @@ func (suite *ChatsAPIUnitSuite) TestChatsInfo() { ItemType: details.TeamsChat, Modified: then, Chat: details.ChatInfo{ - Name: "Hello world", + Topic: "Hello world", LastMessageAt: then, LastMessagePreview: id, Members: []string{}, @@ -92,7 +92,7 @@ func (suite *ChatsAPIUnitSuite) TestChatsInfo() { ItemType: details.TeamsChat, Modified: then, Chat: details.ChatInfo{ - Name: "Hello world", + Topic: "Hello world", LastMessageAt: then, LastMessagePreview: id, Members: []string{}, @@ -120,7 +120,7 @@ func (suite *ChatsAPIUnitSuite) TestChatsInfo() { ItemType: details.TeamsChat, Modified: then, Chat: details.ChatInfo{ - Name: "Hello world", + Topic: "Hello world", LastMessageAt: time.Time{}, LastMessagePreview: "", Members: []string{}, @@ -138,7 +138,7 @@ func (suite *ChatsAPIUnitSuite) TestChatsInfo() { chat, expected := test.expected() result := TeamsChatInfo(chat) - assert.Equal(t, expected.Chat.Name, result.Chat.Name) + assert.Equal(t, expected.Chat.Topic, result.Chat.Topic) expectCreated := chat.GetCreatedDateTime() if expectCreated != nil {