GODT-2119: Only show supported label IDs to clients

This commit is contained in:
James Houlahan
2022-11-21 17:12:31 +01:00
parent 294d1edfee
commit eb62056755
3 changed files with 61 additions and 23 deletions

View File

@ -28,7 +28,6 @@ import (
"github.com/ProtonMail/proton-bridge/v2/internal/logging" "github.com/ProtonMail/proton-bridge/v2/internal/logging"
"github.com/ProtonMail/proton-bridge/v2/internal/safe" "github.com/ProtonMail/proton-bridge/v2/internal/safe"
"github.com/ProtonMail/proton-bridge/v2/internal/vault" "github.com/ProtonMail/proton-bridge/v2/internal/vault"
"github.com/bradenaw/juniper/xslices"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"gitlab.protontech.ch/go/liteapi" "gitlab.protontech.ch/go/liteapi"
) )
@ -437,7 +436,7 @@ func (user *User) handleCreateMessageEvent(ctx context.Context, event liteapi.Me
}).Info("Handling message created event") }).Info("Handling message created event")
return withAddrKR(user.apiUser, user.apiAddrs[event.Message.AddressID], user.vault.KeyPass(), func(_, addrKR *crypto.KeyRing) error { return withAddrKR(user.apiUser, user.apiAddrs[event.Message.AddressID], user.vault.KeyPass(), func(_, addrKR *crypto.KeyRing) error {
buildRes, err := buildRFC822(full, addrKR) buildRes, err := buildRFC822(user.apiLabels, full, addrKR)
if err != nil { if err != nil {
return fmt.Errorf("failed to build RFC822 message: %w", err) return fmt.Errorf("failed to build RFC822 message: %w", err)
} }
@ -446,7 +445,7 @@ func (user *User) handleCreateMessageEvent(ctx context.Context, event liteapi.Me
return nil return nil
}) })
}, user.apiUserLock, user.apiAddrsLock, user.updateChLock) }, user.apiUserLock, user.apiAddrsLock, user.apiLabelsLock, user.updateChLock)
} }
func (user *User) handleUpdateMessageEvent(ctx context.Context, event liteapi.MessageEvent) error { //nolint:unparam func (user *User) handleUpdateMessageEvent(ctx context.Context, event liteapi.MessageEvent) error { //nolint:unparam
@ -458,13 +457,13 @@ func (user *User) handleUpdateMessageEvent(ctx context.Context, event liteapi.Me
user.updateCh[event.Message.AddressID].Enqueue(imap.NewMessageMailboxesUpdated( user.updateCh[event.Message.AddressID].Enqueue(imap.NewMessageMailboxesUpdated(
imap.MessageID(event.ID), imap.MessageID(event.ID),
mapTo[string, imap.MailboxID](xslices.Filter(event.Message.LabelIDs, wantLabelID)), mapTo[string, imap.MailboxID](wantLabels(user.apiLabels, event.Message.LabelIDs)),
event.Message.Seen(), event.Message.Seen(),
event.Message.Starred(), event.Message.Starred(),
)) ))
return nil return nil
}, user.updateChLock) }, user.apiLabelsLock, user.updateChLock)
} }
func (user *User) handleDeleteMessageEvent(ctx context.Context, event liteapi.MessageEvent) error { //nolint:unparam func (user *User) handleDeleteMessageEvent(ctx context.Context, event liteapi.MessageEvent) error { //nolint:unparam
@ -492,7 +491,7 @@ func (user *User) handleUpdateDraftEvent(ctx context.Context, event liteapi.Mess
} }
return withAddrKR(user.apiUser, user.apiAddrs[event.Message.AddressID], user.vault.KeyPass(), func(_, addrKR *crypto.KeyRing) error { return withAddrKR(user.apiUser, user.apiAddrs[event.Message.AddressID], user.vault.KeyPass(), func(_, addrKR *crypto.KeyRing) error {
buildRes, err := buildRFC822(full, addrKR) buildRes, err := buildRFC822(user.apiLabels, full, addrKR)
if err != nil { if err != nil {
return fmt.Errorf("failed to build RFC822 draft: %w", err) return fmt.Errorf("failed to build RFC822 draft: %w", err)
} }
@ -506,7 +505,7 @@ func (user *User) handleUpdateDraftEvent(ctx context.Context, event liteapi.Mess
return nil return nil
}) })
}, user.apiUserLock, user.apiAddrsLock, user.updateChLock) }, user.apiUserLock, user.apiAddrsLock, user.apiLabelsLock, user.updateChLock)
} }
func getMailboxName(label liteapi.Label) []string { func getMailboxName(label liteapi.Label) []string {

View File

@ -113,6 +113,7 @@ func (user *User) sync(ctx context.Context) error {
user.ID(), user.ID(),
user.client, user.client,
user.vault, user.vault,
user.apiLabels,
addrKRs, addrKRs,
user.updateCh, user.updateCh,
user.eventCh, user.eventCh,
@ -147,12 +148,14 @@ func syncLabels(ctx context.Context, apiLabels map[string]liteapi.Label, updateC
// Sync the user's labels. // Sync the user's labels.
for labelID, label := range apiLabels { for labelID, label := range apiLabels {
if !wantLabel(label) {
continue
}
switch label.Type { switch label.Type {
case liteapi.LabelTypeSystem: case liteapi.LabelTypeSystem:
if wantLabelID(labelID) { for _, updateCh := range updateCh {
for _, updateCh := range updateCh { updateCh.Enqueue(newSystemMailboxCreatedUpdate(imap.MailboxID(label.ID), label.Name))
updateCh.Enqueue(newSystemMailboxCreatedUpdate(imap.MailboxID(label.ID), label.Name))
}
} }
case liteapi.LabelTypeFolder, liteapi.LabelTypeLabel: case liteapi.LabelTypeFolder, liteapi.LabelTypeLabel:
@ -181,6 +184,7 @@ func syncMessages( //nolint:funlen
userID string, userID string,
client *liteapi.Client, client *liteapi.Client,
vault *vault.User, vault *vault.User,
apiLabels map[string]liteapi.Label,
addrKRs map[string]*crypto.KeyRing, addrKRs map[string]*crypto.KeyRing,
updateCh map[string]*queue.QueuedChannel[imap.Update], updateCh map[string]*queue.QueuedChannel[imap.Update],
eventCh *queue.QueuedChannel[events.Event], eventCh *queue.QueuedChannel[events.Event],
@ -196,7 +200,7 @@ func syncMessages( //nolint:funlen
buildCh := stream.Map( buildCh := stream.Map(
client.GetFullMessages(ctx, syncWorkers, syncBuffer, messageIDs...), client.GetFullMessages(ctx, syncWorkers, syncBuffer, messageIDs...),
func(_ context.Context, full liteapi.FullMessage) (*buildRes, error) { func(_ context.Context, full liteapi.FullMessage) (*buildRes, error) {
return buildRFC822(full, addrKRs[full.AddressID]) return buildRFC822(apiLabels, full, addrKRs[full.AddressID])
}, },
) )
@ -293,14 +297,46 @@ func newMailboxCreatedUpdate(labelID imap.MailboxID, labelName []string) *imap.M
}) })
} }
func wantLabelID(labelID string) bool { func wantLabel(label liteapi.Label) bool {
switch labelID { if label.Type != liteapi.LabelTypeSystem {
case liteapi.AllDraftsLabel, liteapi.AllSentLabel, liteapi.OutboxLabel:
return false
default:
return true return true
} }
// nolint:exhaustive
switch label.ID {
case liteapi.InboxLabel:
return true
case liteapi.TrashLabel:
return true
case liteapi.SpamLabel:
return true
case liteapi.AllMailLabel:
return true
case liteapi.ArchiveLabel:
return true
case liteapi.SentLabel:
return true
case liteapi.DraftsLabel:
return true
case liteapi.StarredLabel:
return true
default:
return false
}
}
func wantLabels(apiLabels map[string]liteapi.Label, labelIDs []string) []string {
return xslices.Filter(labelIDs, func(labelID string) bool {
return wantLabel(apiLabels[labelID])
})
} }
func forEach[T any](ctx context.Context, streamer stream.Stream[T], fn func(T) error) error { func forEach[T any](ctx context.Context, streamer stream.Stream[T], fn func(T) error) error {

View File

@ -23,7 +23,6 @@ import (
"github.com/ProtonMail/gluon/imap" "github.com/ProtonMail/gluon/imap"
"github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/ProtonMail/proton-bridge/v2/pkg/message" "github.com/ProtonMail/proton-bridge/v2/pkg/message"
"github.com/bradenaw/juniper/xslices"
"gitlab.protontech.ch/go/liteapi" "gitlab.protontech.ch/go/liteapi"
) )
@ -44,13 +43,13 @@ func defaultJobOpts() message.JobOptions {
} }
} }
func buildRFC822(full liteapi.FullMessage, addrKR *crypto.KeyRing) (*buildRes, error) { func buildRFC822(apiLabels map[string]liteapi.Label, full liteapi.FullMessage, addrKR *crypto.KeyRing) (*buildRes, error) {
literal, err := message.BuildRFC822(addrKR, full.Message, full.AttData, defaultJobOpts()) literal, err := message.BuildRFC822(addrKR, full.Message, full.AttData, defaultJobOpts())
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to build message %s: %w", full.ID, err) return nil, fmt.Errorf("failed to build message %s: %w", full.ID, err)
} }
update, err := newMessageCreatedUpdate(full.MessageMetadata, literal) update, err := newMessageCreatedUpdate(apiLabels, full.MessageMetadata, literal)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create IMAP update for message %s: %w", full.ID, err) return nil, fmt.Errorf("failed to create IMAP update for message %s: %w", full.ID, err)
} }
@ -62,7 +61,11 @@ func buildRFC822(full liteapi.FullMessage, addrKR *crypto.KeyRing) (*buildRes, e
}, nil }, nil
} }
func newMessageCreatedUpdate(message liteapi.MessageMetadata, literal []byte) (*imap.MessageCreated, error) { func newMessageCreatedUpdate(
apiLabels map[string]liteapi.Label,
message liteapi.MessageMetadata,
literal []byte,
) (*imap.MessageCreated, error) {
parsedMessage, err := imap.NewParsedMessage(literal) parsedMessage, err := imap.NewParsedMessage(literal)
if err != nil { if err != nil {
return nil, err return nil, err
@ -71,7 +74,7 @@ func newMessageCreatedUpdate(message liteapi.MessageMetadata, literal []byte) (*
return &imap.MessageCreated{ return &imap.MessageCreated{
Message: toIMAPMessage(message), Message: toIMAPMessage(message),
Literal: literal, Literal: literal,
MailboxIDs: mapTo[string, imap.MailboxID](xslices.Filter(message.LabelIDs, wantLabelID)), MailboxIDs: mapTo[string, imap.MailboxID](wantLabels(apiLabels, message.LabelIDs)),
ParsedMessage: parsedMessage, ParsedMessage: parsedMessage,
}, nil }, nil
} }