mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-11 05:06:51 +00:00
Other: Switch from liteapi to go-proton-api
This commit is contained in:
@ -23,18 +23,18 @@ import (
|
||||
|
||||
"github.com/ProtonMail/gluon/imap"
|
||||
"github.com/ProtonMail/gluon/queue"
|
||||
"github.com/ProtonMail/go-proton-api"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/events"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/logging"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/safe"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/vault"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
)
|
||||
|
||||
// handleAPIEvent handles the given liteapi.Event.
|
||||
func (user *User) handleAPIEvent(ctx context.Context, event liteapi.Event) error {
|
||||
if event.Refresh&liteapi.RefreshMail != 0 {
|
||||
// handleAPIEvent handles the given proton.Event.
|
||||
func (user *User) handleAPIEvent(ctx context.Context, event proton.Event) error {
|
||||
if event.Refresh&proton.RefreshMail != 0 {
|
||||
return user.handleRefreshEvent(ctx, event.Refresh, event.EventID)
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ func (user *User) handleAPIEvent(ctx context.Context, event liteapi.Event) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (user *User) handleRefreshEvent(ctx context.Context, refresh liteapi.RefreshFlag, eventID string) error {
|
||||
func (user *User) handleRefreshEvent(ctx context.Context, refresh proton.RefreshFlag, eventID string) error {
|
||||
l := user.log.WithFields(logrus.Fields{
|
||||
"eventID": eventID,
|
||||
"refresh": refresh,
|
||||
@ -100,15 +100,15 @@ func (user *User) handleRefreshEvent(ctx context.Context, refresh liteapi.Refres
|
||||
}
|
||||
|
||||
// Fetch latest label info.
|
||||
apiLabels, err := user.client.GetLabels(ctx, liteapi.LabelTypeSystem, liteapi.LabelTypeFolder, liteapi.LabelTypeLabel)
|
||||
apiLabels, err := user.client.GetLabels(ctx, proton.LabelTypeSystem, proton.LabelTypeFolder, proton.LabelTypeLabel)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get labels: %w", err)
|
||||
}
|
||||
|
||||
// Update the API info in the user.
|
||||
user.apiUser = apiUser
|
||||
user.apiAddrs = groupBy(apiAddrs, func(addr liteapi.Address) string { return addr.ID })
|
||||
user.apiLabels = groupBy(apiLabels, func(label liteapi.Label) string { return label.ID })
|
||||
user.apiAddrs = groupBy(apiAddrs, func(addr proton.Address) string { return addr.ID })
|
||||
user.apiLabels = groupBy(apiLabels, func(label proton.Label) string { return label.ID })
|
||||
|
||||
// Reinitialize the update channels.
|
||||
user.initUpdateCh(user.vault.AddressMode())
|
||||
@ -128,7 +128,7 @@ func (user *User) handleRefreshEvent(ctx context.Context, refresh liteapi.Refres
|
||||
}
|
||||
|
||||
// handleUserEvent handles the given user event.
|
||||
func (user *User) handleUserEvent(_ context.Context, userEvent liteapi.User) error {
|
||||
func (user *User) handleUserEvent(_ context.Context, userEvent proton.User) error {
|
||||
return safe.LockRet(func() error {
|
||||
user.log.WithFields(logrus.Fields{
|
||||
"userID": userEvent.ID,
|
||||
@ -147,20 +147,20 @@ func (user *User) handleUserEvent(_ context.Context, userEvent liteapi.User) err
|
||||
|
||||
// handleAddressEvents handles the given address events.
|
||||
// GODT-1945: If split address mode, need to signal back to bridge to update the addresses.
|
||||
func (user *User) handleAddressEvents(ctx context.Context, addressEvents []liteapi.AddressEvent) error {
|
||||
func (user *User) handleAddressEvents(ctx context.Context, addressEvents []proton.AddressEvent) error {
|
||||
for _, event := range addressEvents {
|
||||
switch event.Action {
|
||||
case liteapi.EventCreate:
|
||||
case proton.EventCreate:
|
||||
if err := user.handleCreateAddressEvent(ctx, event); err != nil {
|
||||
return fmt.Errorf("failed to handle create address event: %w", err)
|
||||
}
|
||||
|
||||
case liteapi.EventUpdate, liteapi.EventUpdateFlags:
|
||||
case proton.EventUpdate, proton.EventUpdateFlags:
|
||||
if err := user.handleUpdateAddressEvent(ctx, event); err != nil {
|
||||
return fmt.Errorf("failed to handle update address event: %w", err)
|
||||
}
|
||||
|
||||
case liteapi.EventDelete:
|
||||
case proton.EventDelete:
|
||||
if err := user.handleDeleteAddressEvent(ctx, event); err != nil {
|
||||
return fmt.Errorf("failed to delete address: %w", err)
|
||||
}
|
||||
@ -170,7 +170,7 @@ func (user *User) handleAddressEvents(ctx context.Context, addressEvents []litea
|
||||
return nil
|
||||
}
|
||||
|
||||
func (user *User) handleCreateAddressEvent(ctx context.Context, event liteapi.AddressEvent) error {
|
||||
func (user *User) handleCreateAddressEvent(ctx context.Context, event proton.AddressEvent) error {
|
||||
if err := safe.LockRet(func() error {
|
||||
user.log.WithFields(logrus.Fields{
|
||||
"addressID": event.ID,
|
||||
@ -219,7 +219,7 @@ func (user *User) handleCreateAddressEvent(ctx context.Context, event liteapi.Ad
|
||||
}, user.apiAddrsLock, user.apiLabelsLock, user.updateChLock)
|
||||
}
|
||||
|
||||
func (user *User) handleUpdateAddressEvent(_ context.Context, event liteapi.AddressEvent) error { //nolint:unparam
|
||||
func (user *User) handleUpdateAddressEvent(_ context.Context, event proton.AddressEvent) error { //nolint:unparam
|
||||
return safe.LockRet(func() error {
|
||||
user.log.WithFields(logrus.Fields{
|
||||
"addressID": event.ID,
|
||||
@ -242,7 +242,7 @@ func (user *User) handleUpdateAddressEvent(_ context.Context, event liteapi.Addr
|
||||
}, user.apiAddrsLock)
|
||||
}
|
||||
|
||||
func (user *User) handleDeleteAddressEvent(_ context.Context, event liteapi.AddressEvent) error {
|
||||
func (user *User) handleDeleteAddressEvent(_ context.Context, event proton.AddressEvent) error {
|
||||
return safe.LockRet(func() error {
|
||||
user.log.WithField("addressID", event.ID).Info("Handling address deleted event")
|
||||
|
||||
@ -269,20 +269,20 @@ func (user *User) handleDeleteAddressEvent(_ context.Context, event liteapi.Addr
|
||||
}
|
||||
|
||||
// handleLabelEvents handles the given label events.
|
||||
func (user *User) handleLabelEvents(ctx context.Context, labelEvents []liteapi.LabelEvent) error {
|
||||
func (user *User) handleLabelEvents(ctx context.Context, labelEvents []proton.LabelEvent) error {
|
||||
for _, event := range labelEvents {
|
||||
switch event.Action {
|
||||
case liteapi.EventCreate:
|
||||
case proton.EventCreate:
|
||||
if err := user.handleCreateLabelEvent(ctx, event); err != nil {
|
||||
return fmt.Errorf("failed to handle create label event: %w", err)
|
||||
}
|
||||
|
||||
case liteapi.EventUpdate, liteapi.EventUpdateFlags:
|
||||
case proton.EventUpdate, proton.EventUpdateFlags:
|
||||
if err := user.handleUpdateLabelEvent(ctx, event); err != nil {
|
||||
return fmt.Errorf("failed to handle update label event: %w", err)
|
||||
}
|
||||
|
||||
case liteapi.EventDelete:
|
||||
case proton.EventDelete:
|
||||
if err := user.handleDeleteLabelEvent(ctx, event); err != nil {
|
||||
return fmt.Errorf("failed to handle delete label event: %w", err)
|
||||
}
|
||||
@ -292,7 +292,7 @@ func (user *User) handleLabelEvents(ctx context.Context, labelEvents []liteapi.L
|
||||
return nil
|
||||
}
|
||||
|
||||
func (user *User) handleCreateLabelEvent(_ context.Context, event liteapi.LabelEvent) error { //nolint:unparam
|
||||
func (user *User) handleCreateLabelEvent(_ context.Context, event proton.LabelEvent) error { //nolint:unparam
|
||||
return safe.LockRet(func() error {
|
||||
user.log.WithFields(logrus.Fields{
|
||||
"labelID": event.ID,
|
||||
@ -319,7 +319,7 @@ func (user *User) handleCreateLabelEvent(_ context.Context, event liteapi.LabelE
|
||||
}, user.apiLabelsLock, user.updateChLock)
|
||||
}
|
||||
|
||||
func (user *User) handleUpdateLabelEvent(_ context.Context, event liteapi.LabelEvent) error { //nolint:unparam
|
||||
func (user *User) handleUpdateLabelEvent(_ context.Context, event proton.LabelEvent) error { //nolint:unparam
|
||||
return safe.LockRet(func() error {
|
||||
user.log.WithFields(logrus.Fields{
|
||||
"labelID": event.ID,
|
||||
@ -349,7 +349,7 @@ func (user *User) handleUpdateLabelEvent(_ context.Context, event liteapi.LabelE
|
||||
}, user.apiLabelsLock, user.updateChLock)
|
||||
}
|
||||
|
||||
func (user *User) handleDeleteLabelEvent(_ context.Context, event liteapi.LabelEvent) error { //nolint:unparam
|
||||
func (user *User) handleDeleteLabelEvent(_ context.Context, event proton.LabelEvent) error { //nolint:unparam
|
||||
return safe.LockRet(func() error {
|
||||
user.log.WithField("labelID", event.ID).Info("Handling label deleted event")
|
||||
|
||||
@ -375,12 +375,12 @@ func (user *User) handleDeleteLabelEvent(_ context.Context, event liteapi.LabelE
|
||||
}
|
||||
|
||||
// handleMessageEvents handles the given message events.
|
||||
func (user *User) handleMessageEvents(ctx context.Context, messageEvents []liteapi.MessageEvent) error {
|
||||
func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proton.MessageEvent) error {
|
||||
for _, event := range messageEvents {
|
||||
ctx = logging.WithLogrusField(ctx, "messageID", event.ID)
|
||||
|
||||
switch event.Action {
|
||||
case liteapi.EventCreate:
|
||||
case proton.EventCreate:
|
||||
if err := user.handleCreateMessageEvent(
|
||||
logging.WithLogrusField(ctx, "action", "create message"),
|
||||
event,
|
||||
@ -388,9 +388,9 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []litea
|
||||
return fmt.Errorf("failed to handle create message event: %w", err)
|
||||
}
|
||||
|
||||
case liteapi.EventUpdate, liteapi.EventUpdateFlags:
|
||||
case proton.EventUpdate, proton.EventUpdateFlags:
|
||||
// GODT-2028 - Use better events here. It should be possible to have 3 separate events that refrain to
|
||||
// whether the flags, labels or read only data (header+body) has been changed. This requires fixing liteapi
|
||||
// whether the flags, labels or read only data (header+body) has been changed. This requires fixing proton
|
||||
// first so that it correctly reports those cases.
|
||||
// Issue regular update to handle mailboxes and flag changes.
|
||||
if err := user.handleUpdateMessageEvent(
|
||||
@ -410,7 +410,7 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []litea
|
||||
}
|
||||
}
|
||||
|
||||
case liteapi.EventDelete:
|
||||
case proton.EventDelete:
|
||||
if err := user.handleDeleteMessageEvent(
|
||||
logging.WithLogrusField(ctx, "action", "delete message"),
|
||||
event,
|
||||
@ -423,7 +423,7 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []litea
|
||||
return nil
|
||||
}
|
||||
|
||||
func (user *User) handleCreateMessageEvent(ctx context.Context, event liteapi.MessageEvent) error {
|
||||
func (user *User) handleCreateMessageEvent(ctx context.Context, event proton.MessageEvent) error {
|
||||
full, err := user.client.GetFullMessage(ctx, event.Message.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get full message: %w", err)
|
||||
@ -448,7 +448,7 @@ func (user *User) handleCreateMessageEvent(ctx context.Context, event liteapi.Me
|
||||
}, 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 proton.MessageEvent) error { //nolint:unparam
|
||||
return safe.RLockRet(func() error {
|
||||
user.log.WithFields(logrus.Fields{
|
||||
"messageID": event.ID,
|
||||
@ -466,7 +466,7 @@ func (user *User) handleUpdateMessageEvent(ctx context.Context, event liteapi.Me
|
||||
}, 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 proton.MessageEvent) error { //nolint:unparam
|
||||
return safe.RLockRet(func() error {
|
||||
user.log.WithField("messageID", event.ID).Info("Handling message deleted event")
|
||||
|
||||
@ -478,7 +478,7 @@ func (user *User) handleDeleteMessageEvent(ctx context.Context, event liteapi.Me
|
||||
}, user.updateChLock)
|
||||
}
|
||||
|
||||
func (user *User) handleUpdateDraftEvent(ctx context.Context, event liteapi.MessageEvent) error { //nolint:unparam
|
||||
func (user *User) handleUpdateDraftEvent(ctx context.Context, event proton.MessageEvent) error { //nolint:unparam
|
||||
return safe.RLockRet(func() error {
|
||||
user.log.WithFields(logrus.Fields{
|
||||
"messageID": event.ID,
|
||||
@ -508,19 +508,19 @@ func (user *User) handleUpdateDraftEvent(ctx context.Context, event liteapi.Mess
|
||||
}, user.apiUserLock, user.apiAddrsLock, user.apiLabelsLock, user.updateChLock)
|
||||
}
|
||||
|
||||
func getMailboxName(label liteapi.Label) []string {
|
||||
func getMailboxName(label proton.Label) []string {
|
||||
var name []string
|
||||
|
||||
switch label.Type {
|
||||
case liteapi.LabelTypeFolder:
|
||||
case proton.LabelTypeFolder:
|
||||
name = append([]string{folderPrefix}, label.Path...)
|
||||
|
||||
case liteapi.LabelTypeLabel:
|
||||
case proton.LabelTypeLabel:
|
||||
name = append([]string{labelPrefix}, label.Path...)
|
||||
|
||||
case liteapi.LabelTypeContactGroup:
|
||||
case proton.LabelTypeContactGroup:
|
||||
fallthrough
|
||||
case liteapi.LabelTypeSystem:
|
||||
case proton.LabelTypeSystem:
|
||||
fallthrough
|
||||
default:
|
||||
name = label.Path
|
||||
|
||||
@ -26,13 +26,13 @@ import (
|
||||
"github.com/ProtonMail/gluon/connector"
|
||||
"github.com/ProtonMail/gluon/imap"
|
||||
"github.com/ProtonMail/gluon/rfc822"
|
||||
"github.com/ProtonMail/go-proton-api"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/safe"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/vault"
|
||||
"github.com/ProtonMail/proton-bridge/v2/pkg/message"
|
||||
"github.com/bradenaw/juniper/stream"
|
||||
"github.com/bradenaw/juniper/xslices"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
@ -109,10 +109,10 @@ func (conn *imapConnector) createLabel(ctx context.Context, name []string) (imap
|
||||
return imap.Mailbox{}, fmt.Errorf("a label cannot have children")
|
||||
}
|
||||
|
||||
label, err := conn.client.CreateLabel(ctx, liteapi.CreateLabelReq{
|
||||
label, err := conn.client.CreateLabel(ctx, proton.CreateLabelReq{
|
||||
Name: name[0],
|
||||
Color: "#f66",
|
||||
Type: liteapi.LabelTypeLabel,
|
||||
Type: proton.LabelTypeLabel,
|
||||
})
|
||||
if err != nil {
|
||||
return imap.Mailbox{}, err
|
||||
@ -141,10 +141,10 @@ func (conn *imapConnector) createFolder(ctx context.Context, name []string) (ima
|
||||
}
|
||||
}
|
||||
|
||||
label, err := conn.client.CreateLabel(ctx, liteapi.CreateLabelReq{
|
||||
label, err := conn.client.CreateLabel(ctx, proton.CreateLabelReq{
|
||||
Name: name[len(name)-1],
|
||||
Color: "#f66",
|
||||
Type: liteapi.LabelTypeFolder,
|
||||
Type: proton.LabelTypeFolder,
|
||||
ParentID: parentID,
|
||||
})
|
||||
if err != nil {
|
||||
@ -180,12 +180,12 @@ func (conn *imapConnector) updateLabel(ctx context.Context, labelID imap.Mailbox
|
||||
return fmt.Errorf("a label cannot have children")
|
||||
}
|
||||
|
||||
label, err := conn.client.GetLabel(ctx, string(labelID), liteapi.LabelTypeLabel)
|
||||
label, err := conn.client.GetLabel(ctx, string(labelID), proton.LabelTypeLabel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := conn.client.UpdateLabel(ctx, label.ID, liteapi.UpdateLabelReq{
|
||||
if _, err := conn.client.UpdateLabel(ctx, label.ID, proton.UpdateLabelReq{
|
||||
Name: name[0],
|
||||
Color: label.Color,
|
||||
}); err != nil {
|
||||
@ -215,12 +215,12 @@ func (conn *imapConnector) updateFolder(ctx context.Context, labelID imap.Mailbo
|
||||
}
|
||||
}
|
||||
|
||||
label, err := conn.client.GetLabel(ctx, string(labelID), liteapi.LabelTypeFolder)
|
||||
label, err := conn.client.GetLabel(ctx, string(labelID), proton.LabelTypeFolder)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := conn.client.UpdateLabel(ctx, string(labelID), liteapi.UpdateLabelReq{
|
||||
if _, err := conn.client.UpdateLabel(ctx, string(labelID), proton.UpdateLabelReq{
|
||||
Name: name[len(name)-1],
|
||||
Color: label.Color,
|
||||
ParentID: parentID,
|
||||
@ -274,38 +274,38 @@ func (conn *imapConnector) CreateMessage(
|
||||
wantLabelIDs := []string{string(mailboxID)}
|
||||
|
||||
if flags.Contains(imap.FlagFlagged) {
|
||||
wantLabelIDs = append(wantLabelIDs, liteapi.StarredLabel)
|
||||
wantLabelIDs = append(wantLabelIDs, proton.StarredLabel)
|
||||
}
|
||||
|
||||
var wantFlags liteapi.MessageFlag
|
||||
var wantFlags proton.MessageFlag
|
||||
|
||||
unread := !flags.Contains(imap.FlagSeen)
|
||||
|
||||
if mailboxID != liteapi.DraftsLabel {
|
||||
if mailboxID != proton.DraftsLabel {
|
||||
header, err := rfc822.Parse(literal).ParseHeader()
|
||||
if err != nil {
|
||||
return imap.Message{}, nil, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case mailboxID == liteapi.InboxLabel:
|
||||
wantFlags = wantFlags.Add(liteapi.MessageFlagReceived)
|
||||
case mailboxID == proton.InboxLabel:
|
||||
wantFlags = wantFlags.Add(proton.MessageFlagReceived)
|
||||
|
||||
case mailboxID == liteapi.SentLabel:
|
||||
wantFlags = wantFlags.Add(liteapi.MessageFlagSent)
|
||||
case mailboxID == proton.SentLabel:
|
||||
wantFlags = wantFlags.Add(proton.MessageFlagSent)
|
||||
|
||||
case header.Has("Received"):
|
||||
wantFlags = wantFlags.Add(liteapi.MessageFlagReceived)
|
||||
wantFlags = wantFlags.Add(proton.MessageFlagReceived)
|
||||
|
||||
default:
|
||||
wantFlags = wantFlags.Add(liteapi.MessageFlagSent)
|
||||
wantFlags = wantFlags.Add(proton.MessageFlagSent)
|
||||
}
|
||||
} else {
|
||||
unread = false
|
||||
}
|
||||
|
||||
if flags.Contains(imap.FlagAnswered) {
|
||||
wantFlags = wantFlags.Add(liteapi.MessageFlagReplied)
|
||||
wantFlags = wantFlags.Add(proton.MessageFlagReplied)
|
||||
}
|
||||
|
||||
return conn.importMessage(ctx, literal, wantLabelIDs, wantFlags, unread)
|
||||
@ -326,13 +326,13 @@ func (conn *imapConnector) RemoveMessagesFromMailbox(ctx context.Context, messag
|
||||
return err
|
||||
}
|
||||
|
||||
if mailboxID == liteapi.SpamLabel || mailboxID == liteapi.TrashLabel || mailboxID == liteapi.DraftsLabel {
|
||||
var metadata []liteapi.MessageMetadata
|
||||
if mailboxID == proton.SpamLabel || mailboxID == proton.TrashLabel || mailboxID == proton.DraftsLabel {
|
||||
var metadata []proton.MessageMetadata
|
||||
|
||||
// There's currently no limit on how many IDs we can filter on,
|
||||
// but to be nice to API, let's chunk it by 150.
|
||||
for _, messageIDs := range xslices.Chunk(messageIDs, 150) {
|
||||
m, err := conn.client.GetMessageMetadata(ctx, liteapi.MessageFilter{
|
||||
m, err := conn.client.GetMessageMetadata(ctx, proton.MessageFilter{
|
||||
ID: mapTo[imap.MessageID, string](messageIDs),
|
||||
})
|
||||
if err != nil {
|
||||
@ -341,9 +341,9 @@ func (conn *imapConnector) RemoveMessagesFromMailbox(ctx context.Context, messag
|
||||
|
||||
// If a message is not preset in any other label other than AllMail, AllDrafts and AllSent, it can be
|
||||
// permanently deleted.
|
||||
m = xslices.Filter(m, func(m liteapi.MessageMetadata) bool {
|
||||
m = xslices.Filter(m, func(m proton.MessageMetadata) bool {
|
||||
labelsThatMatter := xslices.Filter(m.LabelIDs, func(id string) bool {
|
||||
return id != liteapi.AllDraftsLabel && id != liteapi.AllMailLabel && id != liteapi.AllSentLabel
|
||||
return id != proton.AllDraftsLabel && id != proton.AllMailLabel && id != proton.AllSentLabel
|
||||
})
|
||||
return len(labelsThatMatter) == 0
|
||||
})
|
||||
@ -351,7 +351,7 @@ func (conn *imapConnector) RemoveMessagesFromMailbox(ctx context.Context, messag
|
||||
metadata = append(metadata, m...)
|
||||
}
|
||||
|
||||
if err := conn.client.DeleteMessage(ctx, xslices.Map(metadata, func(m liteapi.MessageMetadata) string {
|
||||
if err := conn.client.DeleteMessage(ctx, xslices.Map(metadata, func(m proton.MessageMetadata) string {
|
||||
return m.ID
|
||||
})...); err != nil {
|
||||
return err
|
||||
@ -392,10 +392,10 @@ func (conn *imapConnector) MarkMessagesFlagged(ctx context.Context, messageIDs [
|
||||
defer conn.goPollAPIEvents(false)
|
||||
|
||||
if flagged {
|
||||
return conn.client.LabelMessages(ctx, mapTo[imap.MessageID, string](messageIDs), liteapi.StarredLabel)
|
||||
return conn.client.LabelMessages(ctx, mapTo[imap.MessageID, string](messageIDs), proton.StarredLabel)
|
||||
}
|
||||
|
||||
return conn.client.UnlabelMessages(ctx, mapTo[imap.MessageID, string](messageIDs), liteapi.StarredLabel)
|
||||
return conn.client.UnlabelMessages(ctx, mapTo[imap.MessageID, string](messageIDs), proton.StarredLabel)
|
||||
}
|
||||
|
||||
// GetUpdates returns a stream of updates that the gluon server should apply.
|
||||
@ -418,7 +418,7 @@ func (conn *imapConnector) SetUIDValidity(validity imap.UID) error {
|
||||
|
||||
// IsMailboxVisible returns whether this mailbox should be visible over IMAP.
|
||||
func (conn *imapConnector) IsMailboxVisible(_ context.Context, mailboxID imap.MailboxID) bool {
|
||||
return atomic.LoadUint32(&conn.showAllMail) != 0 || mailboxID != liteapi.AllMailLabel
|
||||
return atomic.LoadUint32(&conn.showAllMail) != 0 || mailboxID != proton.AllMailLabel
|
||||
}
|
||||
|
||||
// Close the connector will no longer be used and all resources should be closed/released.
|
||||
@ -430,18 +430,18 @@ func (conn *imapConnector) importMessage(
|
||||
ctx context.Context,
|
||||
literal []byte,
|
||||
labelIDs []string,
|
||||
flags liteapi.MessageFlag,
|
||||
flags proton.MessageFlag,
|
||||
unread bool,
|
||||
) (imap.Message, []byte, error) {
|
||||
var full liteapi.FullMessage
|
||||
var full proton.FullMessage
|
||||
|
||||
if err := safe.RLockRet(func() error {
|
||||
return withAddrKR(conn.apiUser, conn.apiAddrs[conn.addrID], conn.vault.KeyPass(), func(_, addrKR *crypto.KeyRing) error {
|
||||
res, err := stream.Collect(ctx, conn.client.ImportMessages(ctx, addrKR, 1, 1, []liteapi.ImportReq{{
|
||||
Metadata: liteapi.ImportMetadata{
|
||||
res, err := stream.Collect(ctx, conn.client.ImportMessages(ctx, addrKR, 1, 1, []proton.ImportReq{{
|
||||
Metadata: proton.ImportMetadata{
|
||||
AddressID: conn.addrID,
|
||||
LabelIDs: labelIDs,
|
||||
Unread: liteapi.Bool(unread),
|
||||
Unread: proton.Bool(unread),
|
||||
Flags: flags,
|
||||
},
|
||||
Message: literal,
|
||||
@ -467,18 +467,18 @@ func (conn *imapConnector) importMessage(
|
||||
return toIMAPMessage(full.MessageMetadata), literal, nil
|
||||
}
|
||||
|
||||
func toIMAPMessage(message liteapi.MessageMetadata) imap.Message {
|
||||
func toIMAPMessage(message proton.MessageMetadata) imap.Message {
|
||||
flags := imap.NewFlagSet()
|
||||
|
||||
if !message.Unread {
|
||||
flags = flags.Add(imap.FlagSeen)
|
||||
}
|
||||
|
||||
if slices.Contains(message.LabelIDs, liteapi.StarredLabel) {
|
||||
if slices.Contains(message.LabelIDs, proton.StarredLabel) {
|
||||
flags = flags.Add(imap.FlagFlagged)
|
||||
}
|
||||
|
||||
if slices.Contains(message.LabelIDs, liteapi.DraftsLabel) {
|
||||
if slices.Contains(message.LabelIDs, proton.DraftsLabel) {
|
||||
flags = flags.Add(imap.FlagDraft)
|
||||
}
|
||||
|
||||
@ -497,10 +497,10 @@ func toIMAPMessage(message liteapi.MessageMetadata) imap.Message {
|
||||
}
|
||||
}
|
||||
|
||||
func toIMAPMailbox(label liteapi.Label, flags, permFlags, attrs imap.FlagSet) imap.Mailbox {
|
||||
if label.Type == liteapi.LabelTypeLabel {
|
||||
func toIMAPMailbox(label proton.Label, flags, permFlags, attrs imap.FlagSet) imap.Mailbox {
|
||||
if label.Type == proton.LabelTypeLabel {
|
||||
label.Path = append([]string{labelPrefix}, label.Path...)
|
||||
} else if label.Type == liteapi.LabelTypeFolder {
|
||||
} else if label.Type == proton.LabelTypeFolder {
|
||||
label.Path = append([]string{folderPrefix}, label.Path...)
|
||||
}
|
||||
|
||||
|
||||
@ -20,12 +20,12 @@ package user
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ProtonMail/go-proton-api"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
)
|
||||
|
||||
func withAddrKR(apiUser liteapi.User, apiAddr liteapi.Address, keyPass []byte, fn func(userKR, addrKR *crypto.KeyRing) error) error {
|
||||
func withAddrKR(apiUser proton.User, apiAddr proton.Address, keyPass []byte, fn func(userKR, addrKR *crypto.KeyRing) error) error {
|
||||
userKR, err := apiUser.Keys.Unlock(keyPass, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unlock user keys: %w", err)
|
||||
@ -41,7 +41,7 @@ func withAddrKR(apiUser liteapi.User, apiAddr liteapi.Address, keyPass []byte, f
|
||||
return fn(userKR, addrKR)
|
||||
}
|
||||
|
||||
func withAddrKRs(apiUser liteapi.User, apiAddr map[string]liteapi.Address, keyPass []byte, fn func(*crypto.KeyRing, map[string]*crypto.KeyRing) error) error {
|
||||
func withAddrKRs(apiUser proton.User, apiAddr map[string]proton.Address, keyPass []byte, fn func(*crypto.KeyRing, map[string]*crypto.KeyRing) error) error {
|
||||
userKR, err := apiUser.Keys.Unlock(keyPass, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unlock user keys: %w", err)
|
||||
|
||||
@ -21,16 +21,16 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/ProtonMail/go-proton-api"
|
||||
"github.com/ProtonMail/go-proton-api/server"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
"gitlab.protontech.ch/go/liteapi/server"
|
||||
)
|
||||
|
||||
func BenchmarkAddrKeyRing(b *testing.B) {
|
||||
b.StopTimer()
|
||||
|
||||
withAPI(b, context.Background(), func(ctx context.Context, s *server.Server, m *liteapi.Manager) {
|
||||
withAPI(b, context.Background(), func(ctx context.Context, s *server.Server, m *proton.Manager) {
|
||||
withAccount(b, s, "username", "password", []string{"email@pm.me"}, func(userID string, addrIDs []string) {
|
||||
withUser(b, ctx, s, m, "username", "password", func(user *User) {
|
||||
b.StartTimer()
|
||||
|
||||
@ -29,6 +29,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/gluon/rfc822"
|
||||
"github.com/ProtonMail/go-proton-api"
|
||||
"github.com/ProtonMail/go-rfc5322"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/logging"
|
||||
@ -39,7 +40,6 @@ import (
|
||||
"github.com/bradenaw/juniper/parallel"
|
||||
"github.com/bradenaw/juniper/xslices"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
@ -56,7 +56,7 @@ func (user *User) sendMail(authID string, from string, to []string, r io.Reader)
|
||||
return ErrInvalidReturnPath
|
||||
}
|
||||
|
||||
emails := xslices.Map(maps.Values(user.apiAddrs), func(addr liteapi.Address) string {
|
||||
emails := xslices.Map(maps.Values(user.apiAddrs), func(addr proton.Address) string {
|
||||
return addr.Email
|
||||
})
|
||||
|
||||
@ -113,7 +113,7 @@ func (user *User) sendMail(authID string, from string, to []string, r io.Reader)
|
||||
}
|
||||
|
||||
// If we have to attach the public key, do it now.
|
||||
if settings.AttachPublicKey == liteapi.AttachPublicKeyEnabled {
|
||||
if settings.AttachPublicKey == proton.AttachPublicKeyEnabled {
|
||||
key, err := addrKR.GetKey(0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get sending key: %w", err)
|
||||
@ -159,19 +159,19 @@ func (user *User) sendMail(authID string, from string, to []string, r io.Reader)
|
||||
// sendWithKey sends the message with the given address key.
|
||||
func sendWithKey( //nolint:funlen
|
||||
ctx context.Context,
|
||||
client *liteapi.Client,
|
||||
client *proton.Client,
|
||||
authAddrID string,
|
||||
addrMode vault.AddressMode,
|
||||
settings liteapi.MailSettings,
|
||||
settings proton.MailSettings,
|
||||
userKR, addrKR *crypto.KeyRing,
|
||||
emails []string,
|
||||
from string,
|
||||
to []string,
|
||||
message message.Message,
|
||||
) (liteapi.Message, error) {
|
||||
) (proton.Message, error) {
|
||||
parentID, err := getParentID(ctx, client, authAddrID, addrMode, message.References)
|
||||
if err != nil {
|
||||
return liteapi.Message{}, fmt.Errorf("failed to get parent ID: %w", err)
|
||||
return proton.Message{}, fmt.Errorf("failed to get parent ID: %w", err)
|
||||
}
|
||||
|
||||
var decBody string
|
||||
@ -185,20 +185,20 @@ func sendWithKey( //nolint:funlen
|
||||
decBody = string(message.PlainBody)
|
||||
|
||||
default:
|
||||
return liteapi.Message{}, fmt.Errorf("unsupported MIME type: %v", message.MIMEType)
|
||||
return proton.Message{}, fmt.Errorf("unsupported MIME type: %v", message.MIMEType)
|
||||
}
|
||||
|
||||
encBody, err := addrKR.Encrypt(crypto.NewPlainMessageFromString(decBody), nil)
|
||||
if err != nil {
|
||||
return liteapi.Message{}, fmt.Errorf("failed to encrypt message body: %w", err)
|
||||
return proton.Message{}, fmt.Errorf("failed to encrypt message body: %w", err)
|
||||
}
|
||||
|
||||
armBody, err := encBody.GetArmored()
|
||||
if err != nil {
|
||||
return liteapi.Message{}, fmt.Errorf("failed to get armored message body: %w", err)
|
||||
return proton.Message{}, fmt.Errorf("failed to get armored message body: %w", err)
|
||||
}
|
||||
|
||||
draft, err := createDraft(ctx, client, emails, from, to, parentID, message.InReplyTo, liteapi.DraftTemplate{
|
||||
draft, err := createDraft(ctx, client, emails, from, to, parentID, message.InReplyTo, proton.DraftTemplate{
|
||||
Subject: message.Subject,
|
||||
Body: armBody,
|
||||
MIMEType: message.MIMEType,
|
||||
@ -211,27 +211,27 @@ func sendWithKey( //nolint:funlen
|
||||
ExternalID: message.ExternalID,
|
||||
})
|
||||
if err != nil {
|
||||
return liteapi.Message{}, fmt.Errorf("failed to create attachments: %w", err)
|
||||
return proton.Message{}, fmt.Errorf("failed to create attachments: %w", err)
|
||||
}
|
||||
|
||||
attKeys, err := createAttachments(ctx, client, addrKR, draft.ID, message.Attachments)
|
||||
if err != nil {
|
||||
return liteapi.Message{}, fmt.Errorf("failed to create attachments: %w", err)
|
||||
return proton.Message{}, fmt.Errorf("failed to create attachments: %w", err)
|
||||
}
|
||||
|
||||
recipients, err := getRecipients(ctx, client, userKR, settings, draft)
|
||||
if err != nil {
|
||||
return liteapi.Message{}, fmt.Errorf("failed to get recipients: %w", err)
|
||||
return proton.Message{}, fmt.Errorf("failed to get recipients: %w", err)
|
||||
}
|
||||
|
||||
req, err := createSendReq(addrKR, message.MIMEBody, message.RichBody, message.PlainBody, recipients, attKeys)
|
||||
if err != nil {
|
||||
return liteapi.Message{}, fmt.Errorf("failed to create packages: %w", err)
|
||||
return proton.Message{}, fmt.Errorf("failed to create packages: %w", err)
|
||||
}
|
||||
|
||||
res, err := client.SendDraft(ctx, draft.ID, req)
|
||||
if err != nil {
|
||||
return liteapi.Message{}, fmt.Errorf("failed to send draft: %w", err)
|
||||
return proton.Message{}, fmt.Errorf("failed to send draft: %w", err)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
@ -239,7 +239,7 @@ func sendWithKey( //nolint:funlen
|
||||
|
||||
func getParentID( //nolint:funlen
|
||||
ctx context.Context,
|
||||
client *liteapi.Client,
|
||||
client *proton.Client,
|
||||
authAddrID string,
|
||||
addrMode vault.AddressMode,
|
||||
references []string,
|
||||
@ -267,7 +267,7 @@ func getParentID( //nolint:funlen
|
||||
addrID = authAddrID
|
||||
}
|
||||
|
||||
metadata, err := client.GetMessageMetadata(ctx, liteapi.MessageFilter{
|
||||
metadata, err := client.GetMessageMetadata(ctx, proton.MessageFilter{
|
||||
ID: []string{internal},
|
||||
AddressID: addrID,
|
||||
})
|
||||
@ -293,7 +293,7 @@ func getParentID( //nolint:funlen
|
||||
addrID = authAddrID
|
||||
}
|
||||
|
||||
metadata, err := client.GetMessageMetadata(ctx, liteapi.MessageFilter{
|
||||
metadata, err := client.GetMessageMetadata(ctx, proton.MessageFilter{
|
||||
ExternalID: external[len(external)-1],
|
||||
AddressID: addrID,
|
||||
})
|
||||
@ -311,14 +311,14 @@ func getParentID( //nolint:funlen
|
||||
|
||||
func createDraft(
|
||||
ctx context.Context,
|
||||
client *liteapi.Client,
|
||||
client *proton.Client,
|
||||
emails []string,
|
||||
from string,
|
||||
to []string,
|
||||
parentID string,
|
||||
replyToID string,
|
||||
template liteapi.DraftTemplate,
|
||||
) (liteapi.Message, error) {
|
||||
template proton.DraftTemplate,
|
||||
) (proton.Message, error) {
|
||||
// Check sender: set the sender if it's missing.
|
||||
if template.Sender == nil {
|
||||
template.Sender = &mail.Address{Address: from}
|
||||
@ -330,7 +330,7 @@ func createDraft(
|
||||
if idx := xslices.IndexFunc(emails, func(email string) bool {
|
||||
return strings.EqualFold(email, sanitizeEmail(template.Sender.Address))
|
||||
}); idx < 0 {
|
||||
return liteapi.Message{}, fmt.Errorf("address %q is not owned by user", template.Sender.Address)
|
||||
return proton.Message{}, fmt.Errorf("address %q is not owned by user", template.Sender.Address)
|
||||
} else { //nolint:revive
|
||||
template.Sender.Address = constructEmail(template.Sender.Address, emails[idx])
|
||||
}
|
||||
@ -349,15 +349,15 @@ func createDraft(
|
||||
}
|
||||
}
|
||||
|
||||
var action liteapi.CreateDraftAction
|
||||
var action proton.CreateDraftAction
|
||||
|
||||
if len(replyToID) > 0 {
|
||||
action = liteapi.ReplyAction
|
||||
action = proton.ReplyAction
|
||||
} else {
|
||||
action = liteapi.ForwardAction
|
||||
action = proton.ForwardAction
|
||||
}
|
||||
|
||||
return client.CreateDraft(ctx, liteapi.CreateDraftReq{
|
||||
return client.CreateDraft(ctx, proton.CreateDraftReq{
|
||||
Message: template,
|
||||
ParentID: parentID,
|
||||
Action: action,
|
||||
@ -367,7 +367,7 @@ func createDraft(
|
||||
// nolint:funlen
|
||||
func createAttachments(
|
||||
ctx context.Context,
|
||||
client *liteapi.Client,
|
||||
client *proton.Client,
|
||||
addrKR *crypto.KeyRing,
|
||||
draftID string,
|
||||
attachments []message.Attachment,
|
||||
@ -387,15 +387,15 @@ func createAttachments(
|
||||
|
||||
// Some clients use inline disposition but don't set a content ID. Our API doesn't support this.
|
||||
// We could generate our own content ID, but for simplicity, we just set the disposition to attachment.
|
||||
if att.Disposition == string(liteapi.InlineDisposition) && att.ContentID == "" {
|
||||
att.Disposition = string(liteapi.AttachmentDisposition)
|
||||
if att.Disposition == string(proton.InlineDisposition) && att.ContentID == "" {
|
||||
att.Disposition = string(proton.AttachmentDisposition)
|
||||
}
|
||||
|
||||
attachment, err := client.UploadAttachment(ctx, addrKR, liteapi.CreateAttachmentReq{
|
||||
attachment, err := client.UploadAttachment(ctx, addrKR, proton.CreateAttachmentReq{
|
||||
Filename: att.Name,
|
||||
MessageID: draftID,
|
||||
MIMEType: rfc822.MIMEType(att.MIMEType),
|
||||
Disposition: liteapi.Disposition(att.Disposition),
|
||||
Disposition: proton.Disposition(att.Disposition),
|
||||
ContentID: att.ContentID,
|
||||
Body: att.Data,
|
||||
})
|
||||
@ -430,27 +430,27 @@ func createAttachments(
|
||||
|
||||
func getRecipients(
|
||||
ctx context.Context,
|
||||
client *liteapi.Client,
|
||||
client *proton.Client,
|
||||
userKR *crypto.KeyRing,
|
||||
settings liteapi.MailSettings,
|
||||
draft liteapi.Message,
|
||||
settings proton.MailSettings,
|
||||
draft proton.Message,
|
||||
) (recipients, error) {
|
||||
addresses := xslices.Map(xslices.Join(draft.ToList, draft.CCList, draft.BCCList), func(addr *mail.Address) string {
|
||||
return addr.Address
|
||||
})
|
||||
|
||||
prefs, err := parallel.MapContext(ctx, runtime.NumCPU(), addresses, func(ctx context.Context, recipient string) (liteapi.SendPreferences, error) {
|
||||
prefs, err := parallel.MapContext(ctx, runtime.NumCPU(), addresses, func(ctx context.Context, recipient string) (proton.SendPreferences, error) {
|
||||
pubKeys, recType, err := client.GetPublicKeys(ctx, recipient)
|
||||
if err != nil {
|
||||
return liteapi.SendPreferences{}, fmt.Errorf("failed to get public keys: %w", err)
|
||||
return proton.SendPreferences{}, fmt.Errorf("failed to get public keys: %w", err)
|
||||
}
|
||||
|
||||
contactSettings, err := getContactSettings(ctx, client, userKR, recipient)
|
||||
if err != nil {
|
||||
return liteapi.SendPreferences{}, fmt.Errorf("failed to get contact settings: %w", err)
|
||||
return proton.SendPreferences{}, fmt.Errorf("failed to get contact settings: %w", err)
|
||||
}
|
||||
|
||||
return buildSendPrefs(contactSettings, settings, pubKeys, draft.MIMEType, recType == liteapi.RecipientTypeInternal)
|
||||
return buildSendPrefs(contactSettings, settings, pubKeys, draft.MIMEType, recType == proton.RecipientTypeInternal)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get send preferences: %w", err)
|
||||
@ -467,26 +467,26 @@ func getRecipients(
|
||||
|
||||
func getContactSettings(
|
||||
ctx context.Context,
|
||||
client *liteapi.Client,
|
||||
client *proton.Client,
|
||||
userKR *crypto.KeyRing,
|
||||
recipient string,
|
||||
) (liteapi.ContactSettings, error) {
|
||||
) (proton.ContactSettings, error) {
|
||||
contacts, err := client.GetAllContactEmails(ctx, recipient)
|
||||
if err != nil {
|
||||
return liteapi.ContactSettings{}, fmt.Errorf("failed to get contact data: %w", err)
|
||||
return proton.ContactSettings{}, fmt.Errorf("failed to get contact data: %w", err)
|
||||
}
|
||||
|
||||
idx := xslices.IndexFunc(contacts, func(contact liteapi.ContactEmail) bool {
|
||||
idx := xslices.IndexFunc(contacts, func(contact proton.ContactEmail) bool {
|
||||
return contact.Email == recipient
|
||||
})
|
||||
|
||||
if idx < 0 {
|
||||
return liteapi.ContactSettings{}, nil
|
||||
return proton.ContactSettings{}, nil
|
||||
}
|
||||
|
||||
contact, err := client.GetContact(ctx, contacts[idx].ContactID)
|
||||
if err != nil {
|
||||
return liteapi.ContactSettings{}, fmt.Errorf("failed to get contact: %w", err)
|
||||
return proton.ContactSettings{}, fmt.Errorf("failed to get contact: %w", err)
|
||||
}
|
||||
|
||||
return contact.GetSettings(userKR, recipient)
|
||||
|
||||
@ -19,10 +19,10 @@ package user
|
||||
|
||||
import (
|
||||
"github.com/ProtonMail/gluon/rfc822"
|
||||
"github.com/ProtonMail/go-proton-api"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/v2/pkg/message"
|
||||
"github.com/bradenaw/juniper/xslices"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
@ -33,25 +33,25 @@ func createSendReq(
|
||||
richBody, plainBody message.Body,
|
||||
recipients recipients,
|
||||
attKeys map[string]*crypto.SessionKey,
|
||||
) (liteapi.SendDraftReq, error) {
|
||||
var req liteapi.SendDraftReq
|
||||
) (proton.SendDraftReq, error) {
|
||||
var req proton.SendDraftReq
|
||||
|
||||
if recs := recipients.scheme(liteapi.PGPMIMEScheme, liteapi.ClearMIMEScheme); len(recs) > 0 {
|
||||
if recs := recipients.scheme(proton.PGPMIMEScheme, proton.ClearMIMEScheme); len(recs) > 0 {
|
||||
if err := req.AddMIMEPackage(kr, string(mimeBody), recs); err != nil {
|
||||
return liteapi.SendDraftReq{}, err
|
||||
return proton.SendDraftReq{}, err
|
||||
}
|
||||
}
|
||||
|
||||
if recs := recipients.scheme(liteapi.InternalScheme, liteapi.ClearScheme, liteapi.PGPInlineScheme); len(recs) > 0 {
|
||||
if recs := recipients.scheme(proton.InternalScheme, proton.ClearScheme, proton.PGPInlineScheme); len(recs) > 0 {
|
||||
if recs := recs.content(rfc822.TextHTML); len(recs) > 0 {
|
||||
if err := req.AddTextPackage(kr, string(richBody), rfc822.TextHTML, recs, attKeys); err != nil {
|
||||
return liteapi.SendDraftReq{}, err
|
||||
return proton.SendDraftReq{}, err
|
||||
}
|
||||
}
|
||||
|
||||
if recs := recs.content(rfc822.TextPlain); len(recs) > 0 {
|
||||
if err := req.AddTextPackage(kr, string(plainBody), rfc822.TextPlain, recs, attKeys); err != nil {
|
||||
return liteapi.SendDraftReq{}, err
|
||||
return proton.SendDraftReq{}, err
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -59,9 +59,9 @@ func createSendReq(
|
||||
return req, nil
|
||||
}
|
||||
|
||||
type recipients map[string]liteapi.SendPreferences
|
||||
type recipients map[string]proton.SendPreferences
|
||||
|
||||
func (r recipients) scheme(scheme ...liteapi.EncryptionScheme) recipients {
|
||||
func (r recipients) scheme(scheme ...proton.EncryptionScheme) recipients {
|
||||
res := make(recipients)
|
||||
|
||||
for _, addr := range xslices.Filter(maps.Keys(r), func(addr string) bool {
|
||||
|
||||
@ -21,9 +21,9 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ProtonMail/gluon/rfc822"
|
||||
"github.com/ProtonMail/go-proton-api"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/pkg/errors"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -44,7 +44,7 @@ type contactSettings struct {
|
||||
|
||||
// newContactSettings converts the API settings into our local settings.
|
||||
// This is due to the legacy send preferences code.
|
||||
func newContactSettings(settings liteapi.ContactSettings) *contactSettings {
|
||||
func newContactSettings(settings proton.ContactSettings) *contactSettings {
|
||||
metadata := &contactSettings{}
|
||||
|
||||
if settings.MIMEType != nil {
|
||||
@ -62,10 +62,10 @@ func newContactSettings(settings liteapi.ContactSettings) *contactSettings {
|
||||
|
||||
if settings.Scheme != nil {
|
||||
switch *settings.Scheme { // nolint:exhaustive
|
||||
case liteapi.PGPMIMEScheme:
|
||||
case proton.PGPMIMEScheme:
|
||||
metadata.Scheme = pgpMIME
|
||||
|
||||
case liteapi.PGPInlineScheme:
|
||||
case proton.PGPInlineScheme:
|
||||
metadata.Scheme = pgpInline
|
||||
|
||||
default:
|
||||
@ -88,16 +88,16 @@ func newContactSettings(settings liteapi.ContactSettings) *contactSettings {
|
||||
}
|
||||
|
||||
func buildSendPrefs(
|
||||
contactSettings liteapi.ContactSettings,
|
||||
mailSettings liteapi.MailSettings,
|
||||
pubKeys []liteapi.PublicKey,
|
||||
contactSettings proton.ContactSettings,
|
||||
mailSettings proton.MailSettings,
|
||||
pubKeys []proton.PublicKey,
|
||||
mimeType rfc822.MIMEType,
|
||||
isInternal bool,
|
||||
) (liteapi.SendPreferences, error) {
|
||||
) (proton.SendPreferences, error) {
|
||||
builder := &sendPrefsBuilder{}
|
||||
|
||||
if err := builder.setPGPSettings(newContactSettings(contactSettings), pubKeys, isInternal); err != nil {
|
||||
return liteapi.SendPreferences{}, fmt.Errorf("failed to set PGP settings: %w", err)
|
||||
return proton.SendPreferences{}, fmt.Errorf("failed to set PGP settings: %w", err)
|
||||
}
|
||||
|
||||
builder.setEncryptionPreferences(mailSettings)
|
||||
@ -222,37 +222,37 @@ func (b *sendPrefsBuilder) withPublicKey(v *crypto.KeyRing) {
|
||||
// mimeType: 'text/html' | 'text/plain' | 'multipart/mixed',
|
||||
// publicKey: OpenPGPKey | undefined/null
|
||||
// }.
|
||||
func (b *sendPrefsBuilder) build() (p liteapi.SendPreferences) {
|
||||
func (b *sendPrefsBuilder) build() (p proton.SendPreferences) {
|
||||
p.Encrypt = b.shouldEncrypt()
|
||||
p.MIMEType = b.getMIMEType()
|
||||
p.PubKey = b.publicKey
|
||||
|
||||
if b.shouldSign() {
|
||||
p.SignatureType = liteapi.DetachedSignature
|
||||
p.SignatureType = proton.DetachedSignature
|
||||
} else {
|
||||
p.SignatureType = liteapi.NoSignature
|
||||
p.SignatureType = proton.NoSignature
|
||||
}
|
||||
|
||||
switch {
|
||||
case b.isInternal():
|
||||
p.EncryptionScheme = liteapi.InternalScheme
|
||||
p.EncryptionScheme = proton.InternalScheme
|
||||
|
||||
case b.shouldSign() && b.shouldEncrypt():
|
||||
if b.getScheme() == pgpInline {
|
||||
p.EncryptionScheme = liteapi.PGPInlineScheme
|
||||
p.EncryptionScheme = proton.PGPInlineScheme
|
||||
} else {
|
||||
p.EncryptionScheme = liteapi.PGPMIMEScheme
|
||||
p.EncryptionScheme = proton.PGPMIMEScheme
|
||||
}
|
||||
|
||||
case b.shouldSign() && !b.shouldEncrypt():
|
||||
if b.getScheme() == pgpInline {
|
||||
p.EncryptionScheme = liteapi.ClearScheme
|
||||
p.EncryptionScheme = proton.ClearScheme
|
||||
} else {
|
||||
p.EncryptionScheme = liteapi.ClearMIMEScheme
|
||||
p.EncryptionScheme = proton.ClearMIMEScheme
|
||||
}
|
||||
|
||||
default:
|
||||
p.EncryptionScheme = liteapi.ClearScheme
|
||||
p.EncryptionScheme = proton.ClearScheme
|
||||
}
|
||||
|
||||
return p
|
||||
@ -272,7 +272,7 @@ func (b *sendPrefsBuilder) build() (p liteapi.SendPreferences) {
|
||||
// key info retrieved from the API via the GET KEYS route.
|
||||
func (b *sendPrefsBuilder) setPGPSettings(
|
||||
vCardData *contactSettings,
|
||||
apiKeys []liteapi.PublicKey,
|
||||
apiKeys []proton.PublicKey,
|
||||
isInternal bool,
|
||||
) (err error) {
|
||||
// If there is no contact metadata, we can just use a default constructed one.
|
||||
@ -304,7 +304,7 @@ func (b *sendPrefsBuilder) setPGPSettings(
|
||||
// registered with proton.
|
||||
func (b *sendPrefsBuilder) setInternalPGPSettings(
|
||||
vCardData *contactSettings,
|
||||
apiKeys []liteapi.PublicKey,
|
||||
apiKeys []proton.PublicKey,
|
||||
) (err error) {
|
||||
// We're guaranteed to get at least one valid (i.e. not expired, revoked or
|
||||
// marked as verification-only) public key from the server.
|
||||
@ -349,7 +349,7 @@ func (b *sendPrefsBuilder) setInternalPGPSettings(
|
||||
// 3. If there are no pinned keys, then the client should encrypt with the
|
||||
// first valid key served by the API (in principle the server already
|
||||
// validates the keys and the first one provided should be valid).
|
||||
func pickSendingKey(vCardData *contactSettings, rawAPIKeys []liteapi.PublicKey) (kr *crypto.KeyRing, err error) {
|
||||
func pickSendingKey(vCardData *contactSettings, rawAPIKeys []proton.PublicKey) (kr *crypto.KeyRing, err error) {
|
||||
contactKeys := make([]*crypto.Key, len(vCardData.Keys))
|
||||
apiKeys := make([]*crypto.Key, len(rawAPIKeys))
|
||||
|
||||
@ -415,7 +415,7 @@ func matchFingerprints(a, b []*crypto.Key) (res []*crypto.Key) {
|
||||
|
||||
func (b *sendPrefsBuilder) setExternalPGPSettingsWithWKDKeys(
|
||||
vCardData *contactSettings,
|
||||
apiKeys []liteapi.PublicKey,
|
||||
apiKeys []proton.PublicKey,
|
||||
) (err error) {
|
||||
// We're guaranteed to get at least one valid (i.e. not expired, revoked or
|
||||
// marked as verification-only) public key from the server.
|
||||
@ -520,7 +520,7 @@ func (b *sendPrefsBuilder) setExternalPGPSettingsWithoutWKDKeys(
|
||||
//
|
||||
// The public key can still be undefined as we do not need it if the outgoing
|
||||
// email is not encrypted.
|
||||
func (b *sendPrefsBuilder) setEncryptionPreferences(mailSettings liteapi.MailSettings) {
|
||||
func (b *sendPrefsBuilder) setEncryptionPreferences(mailSettings proton.MailSettings) {
|
||||
// For internal addresses or external ones with WKD keys, this flag should
|
||||
// always be true. For external ones, an undefined flag defaults to false.
|
||||
b.withEncryptDefault(false)
|
||||
@ -541,11 +541,11 @@ func (b *sendPrefsBuilder) setEncryptionPreferences(mailSettings liteapi.MailSet
|
||||
// If undefined, default to the user mail setting "Default PGP scheme".
|
||||
// Otherwise keep the defined value.
|
||||
switch mailSettings.PGPScheme {
|
||||
case liteapi.PGPInlineScheme:
|
||||
case proton.PGPInlineScheme:
|
||||
b.withSchemeDefault(pgpInline)
|
||||
case liteapi.PGPMIMEScheme:
|
||||
case proton.PGPMIMEScheme:
|
||||
b.withSchemeDefault(pgpMIME)
|
||||
case liteapi.ClearMIMEScheme, liteapi.ClearScheme, liteapi.EncryptedOutsideScheme, liteapi.InternalScheme:
|
||||
case proton.ClearMIMEScheme, proton.ClearScheme, proton.EncryptedOutsideScheme, proton.InternalScheme:
|
||||
// nothing to set
|
||||
}
|
||||
|
||||
|
||||
@ -21,10 +21,10 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ProtonMail/gluon/rfc822"
|
||||
"github.com/ProtonMail/go-proton-api"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
)
|
||||
|
||||
func TestPreferencesBuilder(t *testing.T) {
|
||||
@ -35,14 +35,14 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name string
|
||||
|
||||
contactMeta *contactSettings
|
||||
receivedKeys []liteapi.PublicKey
|
||||
receivedKeys []proton.PublicKey
|
||||
isInternal bool
|
||||
mailSettings liteapi.MailSettings
|
||||
mailSettings proton.MailSettings
|
||||
composerMIMEType string
|
||||
|
||||
wantEncrypt bool
|
||||
wantSign liteapi.SignatureType
|
||||
wantScheme liteapi.EncryptionScheme
|
||||
wantSign proton.SignatureType
|
||||
wantScheme proton.EncryptionScheme
|
||||
wantMIMEType rfc822.MIMEType
|
||||
wantPublicKey string
|
||||
}{
|
||||
@ -50,13 +50,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "internal",
|
||||
|
||||
contactMeta: &contactSettings{},
|
||||
receivedKeys: []liteapi.PublicKey{{PublicKey: testPublicKey}},
|
||||
receivedKeys: []proton.PublicKey{{PublicKey: testPublicKey}},
|
||||
isInternal: true,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: true,
|
||||
wantSign: liteapi.DetachedSignature,
|
||||
wantScheme: liteapi.InternalScheme,
|
||||
wantSign: proton.DetachedSignature,
|
||||
wantScheme: proton.InternalScheme,
|
||||
wantMIMEType: "text/html",
|
||||
wantPublicKey: testPublicKey,
|
||||
},
|
||||
@ -65,13 +65,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "internal with contact-specific email format",
|
||||
|
||||
contactMeta: &contactSettings{MIMEType: "text/plain"},
|
||||
receivedKeys: []liteapi.PublicKey{{PublicKey: testPublicKey}},
|
||||
receivedKeys: []proton.PublicKey{{PublicKey: testPublicKey}},
|
||||
isInternal: true,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: true,
|
||||
wantSign: liteapi.DetachedSignature,
|
||||
wantScheme: liteapi.InternalScheme,
|
||||
wantSign: proton.DetachedSignature,
|
||||
wantScheme: proton.InternalScheme,
|
||||
wantMIMEType: "text/plain",
|
||||
wantPublicKey: testPublicKey,
|
||||
},
|
||||
@ -80,13 +80,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "internal with pinned contact public key",
|
||||
|
||||
contactMeta: &contactSettings{Keys: []string{testContactKey}},
|
||||
receivedKeys: []liteapi.PublicKey{{PublicKey: testPublicKey}},
|
||||
receivedKeys: []proton.PublicKey{{PublicKey: testPublicKey}},
|
||||
isInternal: true,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: true,
|
||||
wantSign: liteapi.DetachedSignature,
|
||||
wantScheme: liteapi.InternalScheme,
|
||||
wantSign: proton.DetachedSignature,
|
||||
wantScheme: proton.InternalScheme,
|
||||
wantMIMEType: "text/html",
|
||||
wantPublicKey: testPublicKey,
|
||||
},
|
||||
@ -96,13 +96,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "internal with conflicting contact public key",
|
||||
|
||||
contactMeta: &contactSettings{Keys: []string{testOtherContactKey}},
|
||||
receivedKeys: []liteapi.PublicKey{{PublicKey: testPublicKey}},
|
||||
receivedKeys: []proton.PublicKey{{PublicKey: testPublicKey}},
|
||||
isInternal: true,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: true,
|
||||
wantSign: liteapi.DetachedSignature,
|
||||
wantScheme: liteapi.InternalScheme,
|
||||
wantSign: proton.DetachedSignature,
|
||||
wantScheme: proton.InternalScheme,
|
||||
wantMIMEType: "text/html",
|
||||
wantPublicKey: testPublicKey,
|
||||
},
|
||||
@ -111,13 +111,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "wkd-external",
|
||||
|
||||
contactMeta: &contactSettings{},
|
||||
receivedKeys: []liteapi.PublicKey{{PublicKey: testPublicKey}},
|
||||
receivedKeys: []proton.PublicKey{{PublicKey: testPublicKey}},
|
||||
isInternal: false,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: true,
|
||||
wantSign: liteapi.DetachedSignature,
|
||||
wantScheme: liteapi.PGPMIMEScheme,
|
||||
wantSign: proton.DetachedSignature,
|
||||
wantScheme: proton.PGPMIMEScheme,
|
||||
wantMIMEType: "multipart/mixed",
|
||||
wantPublicKey: testPublicKey,
|
||||
},
|
||||
@ -126,13 +126,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "wkd-external with contact-specific email format",
|
||||
|
||||
contactMeta: &contactSettings{MIMEType: "text/plain"},
|
||||
receivedKeys: []liteapi.PublicKey{{PublicKey: testPublicKey}},
|
||||
receivedKeys: []proton.PublicKey{{PublicKey: testPublicKey}},
|
||||
isInternal: false,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: true,
|
||||
wantSign: liteapi.DetachedSignature,
|
||||
wantScheme: liteapi.PGPMIMEScheme,
|
||||
wantSign: proton.DetachedSignature,
|
||||
wantScheme: proton.PGPMIMEScheme,
|
||||
wantMIMEType: "multipart/mixed",
|
||||
wantPublicKey: testPublicKey,
|
||||
},
|
||||
@ -141,13 +141,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "wkd-external with global pgp-inline scheme",
|
||||
|
||||
contactMeta: &contactSettings{},
|
||||
receivedKeys: []liteapi.PublicKey{{PublicKey: testPublicKey}},
|
||||
receivedKeys: []proton.PublicKey{{PublicKey: testPublicKey}},
|
||||
isInternal: false,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPInlineScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPInlineScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: true,
|
||||
wantSign: liteapi.DetachedSignature,
|
||||
wantScheme: liteapi.PGPInlineScheme,
|
||||
wantSign: proton.DetachedSignature,
|
||||
wantScheme: proton.PGPInlineScheme,
|
||||
wantMIMEType: "text/plain",
|
||||
wantPublicKey: testPublicKey,
|
||||
},
|
||||
@ -156,13 +156,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "wkd-external with contact-specific pgp-inline scheme overriding global pgp-mime setting",
|
||||
|
||||
contactMeta: &contactSettings{Scheme: pgpInline},
|
||||
receivedKeys: []liteapi.PublicKey{{PublicKey: testPublicKey}},
|
||||
receivedKeys: []proton.PublicKey{{PublicKey: testPublicKey}},
|
||||
isInternal: false,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: true,
|
||||
wantSign: liteapi.DetachedSignature,
|
||||
wantScheme: liteapi.PGPInlineScheme,
|
||||
wantSign: proton.DetachedSignature,
|
||||
wantScheme: proton.PGPInlineScheme,
|
||||
wantMIMEType: "text/plain",
|
||||
wantPublicKey: testPublicKey,
|
||||
},
|
||||
@ -171,13 +171,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "wkd-external with contact-specific pgp-mime scheme overriding global pgp-inline setting",
|
||||
|
||||
contactMeta: &contactSettings{Scheme: pgpMIME},
|
||||
receivedKeys: []liteapi.PublicKey{{PublicKey: testPublicKey}},
|
||||
receivedKeys: []proton.PublicKey{{PublicKey: testPublicKey}},
|
||||
isInternal: false,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPInlineScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPInlineScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: true,
|
||||
wantSign: liteapi.DetachedSignature,
|
||||
wantScheme: liteapi.PGPMIMEScheme,
|
||||
wantSign: proton.DetachedSignature,
|
||||
wantScheme: proton.PGPMIMEScheme,
|
||||
wantMIMEType: "multipart/mixed",
|
||||
wantPublicKey: testPublicKey,
|
||||
},
|
||||
@ -186,13 +186,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "wkd-external with additional pinned contact public key",
|
||||
|
||||
contactMeta: &contactSettings{Keys: []string{testContactKey}},
|
||||
receivedKeys: []liteapi.PublicKey{{PublicKey: testPublicKey}},
|
||||
receivedKeys: []proton.PublicKey{{PublicKey: testPublicKey}},
|
||||
isInternal: false,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: true,
|
||||
wantSign: liteapi.DetachedSignature,
|
||||
wantScheme: liteapi.PGPMIMEScheme,
|
||||
wantSign: proton.DetachedSignature,
|
||||
wantScheme: proton.PGPMIMEScheme,
|
||||
wantMIMEType: "multipart/mixed",
|
||||
wantPublicKey: testPublicKey,
|
||||
},
|
||||
@ -202,13 +202,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "wkd-external with additional conflicting contact public key",
|
||||
|
||||
contactMeta: &contactSettings{Keys: []string{testOtherContactKey}},
|
||||
receivedKeys: []liteapi.PublicKey{{PublicKey: testPublicKey}},
|
||||
receivedKeys: []proton.PublicKey{{PublicKey: testPublicKey}},
|
||||
isInternal: false,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: true,
|
||||
wantSign: liteapi.DetachedSignature,
|
||||
wantScheme: liteapi.PGPMIMEScheme,
|
||||
wantSign: proton.DetachedSignature,
|
||||
wantScheme: proton.PGPMIMEScheme,
|
||||
wantMIMEType: "multipart/mixed",
|
||||
wantPublicKey: testPublicKey,
|
||||
},
|
||||
@ -217,13 +217,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "external",
|
||||
|
||||
contactMeta: &contactSettings{},
|
||||
receivedKeys: []liteapi.PublicKey{},
|
||||
receivedKeys: []proton.PublicKey{},
|
||||
isInternal: false,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: false,
|
||||
wantSign: liteapi.NoSignature,
|
||||
wantScheme: liteapi.ClearScheme,
|
||||
wantSign: proton.NoSignature,
|
||||
wantScheme: proton.ClearScheme,
|
||||
wantMIMEType: "text/html",
|
||||
},
|
||||
|
||||
@ -231,13 +231,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "external with contact-specific email format",
|
||||
|
||||
contactMeta: &contactSettings{MIMEType: "text/plain"},
|
||||
receivedKeys: []liteapi.PublicKey{},
|
||||
receivedKeys: []proton.PublicKey{},
|
||||
isInternal: false,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: false,
|
||||
wantSign: liteapi.NoSignature,
|
||||
wantScheme: liteapi.ClearScheme,
|
||||
wantSign: proton.NoSignature,
|
||||
wantScheme: proton.ClearScheme,
|
||||
wantMIMEType: "text/plain",
|
||||
},
|
||||
|
||||
@ -245,13 +245,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "external with sign enabled",
|
||||
|
||||
contactMeta: &contactSettings{Sign: true, SignIsSet: true},
|
||||
receivedKeys: []liteapi.PublicKey{},
|
||||
receivedKeys: []proton.PublicKey{},
|
||||
isInternal: false,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: false,
|
||||
wantSign: liteapi.DetachedSignature,
|
||||
wantScheme: liteapi.ClearMIMEScheme,
|
||||
wantSign: proton.DetachedSignature,
|
||||
wantScheme: proton.ClearMIMEScheme,
|
||||
wantMIMEType: "multipart/mixed",
|
||||
},
|
||||
|
||||
@ -259,13 +259,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "external with contact sign enabled and plain text",
|
||||
|
||||
contactMeta: &contactSettings{MIMEType: "text/plain", Scheme: pgpInline, Sign: true, SignIsSet: true},
|
||||
receivedKeys: []liteapi.PublicKey{},
|
||||
receivedKeys: []proton.PublicKey{},
|
||||
isInternal: false,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: false,
|
||||
wantSign: liteapi.DetachedSignature,
|
||||
wantScheme: liteapi.ClearScheme,
|
||||
wantSign: proton.DetachedSignature,
|
||||
wantScheme: proton.ClearScheme,
|
||||
wantMIMEType: "text/plain",
|
||||
},
|
||||
|
||||
@ -273,13 +273,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "external with sign enabled, sending plaintext, should still send as ClearMIME",
|
||||
|
||||
contactMeta: &contactSettings{Sign: true, SignIsSet: true},
|
||||
receivedKeys: []liteapi.PublicKey{},
|
||||
receivedKeys: []proton.PublicKey{},
|
||||
isInternal: false,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPMIMEScheme, DraftMIMEType: "text/plain"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPMIMEScheme, DraftMIMEType: "text/plain"},
|
||||
|
||||
wantEncrypt: false,
|
||||
wantSign: liteapi.DetachedSignature,
|
||||
wantScheme: liteapi.ClearMIMEScheme,
|
||||
wantSign: proton.DetachedSignature,
|
||||
wantScheme: proton.ClearMIMEScheme,
|
||||
wantMIMEType: "multipart/mixed",
|
||||
},
|
||||
|
||||
@ -287,13 +287,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "external with pinned contact public key but no intention to encrypt/sign",
|
||||
|
||||
contactMeta: &contactSettings{Keys: []string{testContactKey}},
|
||||
receivedKeys: []liteapi.PublicKey{},
|
||||
receivedKeys: []proton.PublicKey{},
|
||||
isInternal: false,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: false,
|
||||
wantSign: liteapi.NoSignature,
|
||||
wantScheme: liteapi.ClearScheme,
|
||||
wantSign: proton.NoSignature,
|
||||
wantScheme: proton.ClearScheme,
|
||||
wantMIMEType: "text/html",
|
||||
wantPublicKey: testPublicKey,
|
||||
},
|
||||
@ -302,13 +302,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "external with pinned contact public key, encrypted and signed",
|
||||
|
||||
contactMeta: &contactSettings{Keys: []string{testContactKey}, Encrypt: true, Sign: true, SignIsSet: true},
|
||||
receivedKeys: []liteapi.PublicKey{},
|
||||
receivedKeys: []proton.PublicKey{},
|
||||
isInternal: false,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: true,
|
||||
wantSign: liteapi.DetachedSignature,
|
||||
wantScheme: liteapi.PGPMIMEScheme,
|
||||
wantSign: proton.DetachedSignature,
|
||||
wantScheme: proton.PGPMIMEScheme,
|
||||
wantMIMEType: "multipart/mixed",
|
||||
wantPublicKey: testPublicKey,
|
||||
},
|
||||
@ -317,13 +317,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "external with pinned contact public key, encrypted and signed using contact-specific pgp-inline",
|
||||
|
||||
contactMeta: &contactSettings{Keys: []string{testContactKey}, Encrypt: true, Sign: true, Scheme: pgpInline, SignIsSet: true},
|
||||
receivedKeys: []liteapi.PublicKey{},
|
||||
receivedKeys: []proton.PublicKey{},
|
||||
isInternal: false,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPMIMEScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: true,
|
||||
wantSign: liteapi.DetachedSignature,
|
||||
wantScheme: liteapi.PGPInlineScheme,
|
||||
wantSign: proton.DetachedSignature,
|
||||
wantScheme: proton.PGPInlineScheme,
|
||||
wantMIMEType: "text/plain",
|
||||
wantPublicKey: testPublicKey,
|
||||
},
|
||||
@ -332,13 +332,13 @@ func TestPreferencesBuilder(t *testing.T) {
|
||||
name: "external with pinned contact public key, encrypted and signed using global pgp-inline",
|
||||
|
||||
contactMeta: &contactSettings{Keys: []string{testContactKey}, Encrypt: true, Sign: true, SignIsSet: true},
|
||||
receivedKeys: []liteapi.PublicKey{},
|
||||
receivedKeys: []proton.PublicKey{},
|
||||
isInternal: false,
|
||||
mailSettings: liteapi.MailSettings{PGPScheme: liteapi.PGPInlineScheme, DraftMIMEType: "text/html"},
|
||||
mailSettings: proton.MailSettings{PGPScheme: proton.PGPInlineScheme, DraftMIMEType: "text/html"},
|
||||
|
||||
wantEncrypt: true,
|
||||
wantSign: liteapi.DetachedSignature,
|
||||
wantScheme: liteapi.PGPInlineScheme,
|
||||
wantSign: proton.DetachedSignature,
|
||||
wantScheme: proton.PGPInlineScheme,
|
||||
wantMIMEType: "text/plain",
|
||||
wantPublicKey: testPublicKey,
|
||||
},
|
||||
|
||||
@ -26,6 +26,7 @@ import (
|
||||
|
||||
"github.com/ProtonMail/gluon/imap"
|
||||
"github.com/ProtonMail/gluon/queue"
|
||||
"github.com/ProtonMail/go-proton-api"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/events"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/safe"
|
||||
@ -34,7 +35,6 @@ import (
|
||||
"github.com/bradenaw/juniper/xslices"
|
||||
"github.com/google/uuid"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
"golang.org/x/exp/maps"
|
||||
)
|
||||
|
||||
@ -138,7 +138,7 @@ func (user *User) sync(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// nolint:exhaustive
|
||||
func syncLabels(ctx context.Context, apiLabels map[string]liteapi.Label, updateCh ...*queue.QueuedChannel[imap.Update]) error {
|
||||
func syncLabels(ctx context.Context, apiLabels map[string]proton.Label, updateCh ...*queue.QueuedChannel[imap.Update]) error {
|
||||
// Create placeholder Folders/Labels mailboxes with a random ID and with the \Noselect attribute.
|
||||
for _, prefix := range []string{folderPrefix, labelPrefix} {
|
||||
for _, updateCh := range updateCh {
|
||||
@ -153,12 +153,12 @@ func syncLabels(ctx context.Context, apiLabels map[string]liteapi.Label, updateC
|
||||
}
|
||||
|
||||
switch label.Type {
|
||||
case liteapi.LabelTypeSystem:
|
||||
case proton.LabelTypeSystem:
|
||||
for _, updateCh := range updateCh {
|
||||
updateCh.Enqueue(newSystemMailboxCreatedUpdate(imap.MailboxID(label.ID), label.Name))
|
||||
}
|
||||
|
||||
case liteapi.LabelTypeFolder, liteapi.LabelTypeLabel:
|
||||
case proton.LabelTypeFolder, proton.LabelTypeLabel:
|
||||
for _, updateCh := range updateCh {
|
||||
updateCh.Enqueue(newMailboxCreatedUpdate(imap.MailboxID(labelID), getMailboxName(label)))
|
||||
}
|
||||
@ -183,9 +183,9 @@ func syncLabels(ctx context.Context, apiLabels map[string]liteapi.Label, updateC
|
||||
func syncMessages(
|
||||
ctx context.Context,
|
||||
userID string,
|
||||
client *liteapi.Client,
|
||||
client *proton.Client,
|
||||
vault *vault.User,
|
||||
apiLabels map[string]liteapi.Label,
|
||||
apiLabels map[string]proton.Label,
|
||||
addrKRs map[string]*crypto.KeyRing,
|
||||
updateCh map[string]*queue.QueuedChannel[imap.Update],
|
||||
eventCh *queue.QueuedChannel[events.Event],
|
||||
@ -261,7 +261,6 @@ func syncMessages(
|
||||
|
||||
return buildRFC822(apiLabels, msg, addrKRs[msg.AddressID])
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
errorCh <- err
|
||||
return
|
||||
@ -328,25 +327,25 @@ func newSystemMailboxCreatedUpdate(labelID imap.MailboxID, labelName string) *im
|
||||
attrs := imap.NewFlagSet(imap.AttrNoInferiors)
|
||||
|
||||
switch labelID {
|
||||
case liteapi.TrashLabel:
|
||||
case proton.TrashLabel:
|
||||
attrs = attrs.Add(imap.AttrTrash)
|
||||
|
||||
case liteapi.SpamLabel:
|
||||
case proton.SpamLabel:
|
||||
attrs = attrs.Add(imap.AttrJunk)
|
||||
|
||||
case liteapi.AllMailLabel:
|
||||
case proton.AllMailLabel:
|
||||
attrs = attrs.Add(imap.AttrAll)
|
||||
|
||||
case liteapi.ArchiveLabel:
|
||||
case proton.ArchiveLabel:
|
||||
attrs = attrs.Add(imap.AttrArchive)
|
||||
|
||||
case liteapi.SentLabel:
|
||||
case proton.SentLabel:
|
||||
attrs = attrs.Add(imap.AttrSent)
|
||||
|
||||
case liteapi.DraftsLabel:
|
||||
case proton.DraftsLabel:
|
||||
attrs = attrs.Add(imap.AttrDrafts)
|
||||
|
||||
case liteapi.StarredLabel:
|
||||
case proton.StarredLabel:
|
||||
attrs = attrs.Add(imap.AttrFlagged)
|
||||
}
|
||||
|
||||
@ -379,35 +378,35 @@ func newMailboxCreatedUpdate(labelID imap.MailboxID, labelName []string) *imap.M
|
||||
})
|
||||
}
|
||||
|
||||
func wantLabel(label liteapi.Label) bool {
|
||||
if label.Type != liteapi.LabelTypeSystem {
|
||||
func wantLabel(label proton.Label) bool {
|
||||
if label.Type != proton.LabelTypeSystem {
|
||||
return true
|
||||
}
|
||||
|
||||
// nolint:exhaustive
|
||||
switch label.ID {
|
||||
case liteapi.InboxLabel:
|
||||
case proton.InboxLabel:
|
||||
return true
|
||||
|
||||
case liteapi.TrashLabel:
|
||||
case proton.TrashLabel:
|
||||
return true
|
||||
|
||||
case liteapi.SpamLabel:
|
||||
case proton.SpamLabel:
|
||||
return true
|
||||
|
||||
case liteapi.AllMailLabel:
|
||||
case proton.AllMailLabel:
|
||||
return true
|
||||
|
||||
case liteapi.ArchiveLabel:
|
||||
case proton.ArchiveLabel:
|
||||
return true
|
||||
|
||||
case liteapi.SentLabel:
|
||||
case proton.SentLabel:
|
||||
return true
|
||||
|
||||
case liteapi.DraftsLabel:
|
||||
case proton.DraftsLabel:
|
||||
return true
|
||||
|
||||
case liteapi.StarredLabel:
|
||||
case proton.StarredLabel:
|
||||
return true
|
||||
|
||||
default:
|
||||
@ -415,7 +414,7 @@ func wantLabel(label liteapi.Label) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func wantLabels(apiLabels map[string]liteapi.Label, labelIDs []string) []string {
|
||||
func wantLabels(apiLabels map[string]proton.Label, labelIDs []string) []string {
|
||||
return xslices.Filter(labelIDs, func(labelID string) bool {
|
||||
return wantLabel(apiLabels[labelID])
|
||||
})
|
||||
|
||||
@ -21,9 +21,9 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ProtonMail/gluon/imap"
|
||||
"github.com/ProtonMail/go-proton-api"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/v2/pkg/message"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
)
|
||||
|
||||
type buildRes struct {
|
||||
@ -43,7 +43,7 @@ func defaultJobOpts() message.JobOptions {
|
||||
}
|
||||
}
|
||||
|
||||
func buildRFC822(apiLabels map[string]liteapi.Label, full liteapi.FullMessage, addrKR *crypto.KeyRing) (*buildRes, error) {
|
||||
func buildRFC822(apiLabels map[string]proton.Label, full proton.FullMessage, addrKR *crypto.KeyRing) (*buildRes, error) {
|
||||
literal, err := message.BuildRFC822(addrKR, full.Message, full.AttData, defaultJobOpts())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to build message %s: %w", full.ID, err)
|
||||
@ -62,8 +62,8 @@ func buildRFC822(apiLabels map[string]liteapi.Label, full liteapi.FullMessage, a
|
||||
}
|
||||
|
||||
func newMessageCreatedUpdate(
|
||||
apiLabels map[string]liteapi.Label,
|
||||
message liteapi.MessageMetadata,
|
||||
apiLabels map[string]proton.Label,
|
||||
message proton.MessageMetadata,
|
||||
literal []byte,
|
||||
) (*imap.MessageCreated, error) {
|
||||
parsedMessage, err := imap.NewParsedMessage(literal)
|
||||
|
||||
@ -23,7 +23,7 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
"github.com/ProtonMail/go-proton-api"
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
@ -80,7 +80,7 @@ func b64Decode(b []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
// getAddrID returns the address ID for the given email address.
|
||||
func getAddrID(apiAddrs map[string]liteapi.Address, email string) (string, error) {
|
||||
func getAddrID(apiAddrs map[string]proton.Address, email string) (string, error) {
|
||||
for _, addr := range apiAddrs {
|
||||
if strings.EqualFold(addr.Email, sanitizeEmail(email)) {
|
||||
return addr.ID, nil
|
||||
@ -91,13 +91,13 @@ func getAddrID(apiAddrs map[string]liteapi.Address, email string) (string, error
|
||||
}
|
||||
|
||||
// getAddrIdx returns the address with the given index.
|
||||
func getAddrIdx(apiAddrs map[string]liteapi.Address, idx int) (liteapi.Address, error) {
|
||||
sorted := sortSlice(maps.Values(apiAddrs), func(a, b liteapi.Address) bool {
|
||||
func getAddrIdx(apiAddrs map[string]proton.Address, idx int) (proton.Address, error) {
|
||||
sorted := sortSlice(maps.Values(apiAddrs), func(a, b proton.Address) bool {
|
||||
return a.Order < b.Order
|
||||
})
|
||||
|
||||
if idx < 0 || idx >= len(sorted) {
|
||||
return liteapi.Address{}, fmt.Errorf("address index %d out of range", idx)
|
||||
return proton.Address{}, fmt.Errorf("address index %d out of range", idx)
|
||||
}
|
||||
|
||||
return sorted[idx], nil
|
||||
|
||||
@ -30,6 +30,7 @@ import (
|
||||
"github.com/ProtonMail/gluon/imap"
|
||||
"github.com/ProtonMail/gluon/queue"
|
||||
gluonReporter "github.com/ProtonMail/gluon/reporter"
|
||||
"github.com/ProtonMail/go-proton-api"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/async"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/events"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/logging"
|
||||
@ -38,7 +39,6 @@ import (
|
||||
"github.com/bradenaw/juniper/xslices"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
@ -56,17 +56,17 @@ type User struct {
|
||||
log *logrus.Entry
|
||||
|
||||
vault *vault.User
|
||||
client *liteapi.Client
|
||||
client *proton.Client
|
||||
eventCh *queue.QueuedChannel[events.Event]
|
||||
sendHash *sendRecorder
|
||||
|
||||
apiUser liteapi.User
|
||||
apiUser proton.User
|
||||
apiUserLock safe.RWMutex
|
||||
|
||||
apiAddrs map[string]liteapi.Address
|
||||
apiAddrs map[string]proton.Address
|
||||
apiAddrsLock safe.RWMutex
|
||||
|
||||
apiLabels map[string]liteapi.Label
|
||||
apiLabels map[string]proton.Label
|
||||
apiLabelsLock safe.RWMutex
|
||||
|
||||
updateCh map[string]*queue.QueuedChannel[imap.Update]
|
||||
@ -91,8 +91,8 @@ type User struct {
|
||||
func New(
|
||||
ctx context.Context,
|
||||
encVault *vault.User,
|
||||
client *liteapi.Client,
|
||||
apiUser liteapi.User,
|
||||
client *proton.Client,
|
||||
apiUser proton.User,
|
||||
crashHandler async.PanicHandler,
|
||||
reporter gluonReporter.Reporter,
|
||||
syncWorkers int,
|
||||
@ -107,7 +107,7 @@ func New(
|
||||
}
|
||||
|
||||
// Get the user's API labels.
|
||||
apiLabels, err := client.GetLabels(ctx, liteapi.LabelTypeSystem, liteapi.LabelTypeFolder, liteapi.LabelTypeLabel)
|
||||
apiLabels, err := client.GetLabels(ctx, proton.LabelTypeSystem, proton.LabelTypeFolder, proton.LabelTypeLabel)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get labels: %w", err)
|
||||
}
|
||||
@ -124,10 +124,10 @@ func New(
|
||||
apiUser: apiUser,
|
||||
apiUserLock: safe.NewRWMutex(),
|
||||
|
||||
apiAddrs: groupBy(apiAddrs, func(addr liteapi.Address) string { return addr.ID }),
|
||||
apiAddrs: groupBy(apiAddrs, func(addr proton.Address) string { return addr.ID }),
|
||||
apiAddrsLock: safe.NewRWMutex(),
|
||||
|
||||
apiLabels: groupBy(apiLabels, func(label liteapi.Label) string { return label.ID }),
|
||||
apiLabels: groupBy(apiLabels, func(label proton.Label) string { return label.ID }),
|
||||
apiLabelsLock: safe.NewRWMutex(),
|
||||
|
||||
updateCh: make(map[string]*queue.QueuedChannel[imap.Update]),
|
||||
@ -147,7 +147,7 @@ func New(
|
||||
|
||||
// When we receive an auth object, we update it in the vault.
|
||||
// This will be used to authorize the user on the next run.
|
||||
user.client.AddAuthHandler(func(auth liteapi.Auth) {
|
||||
user.client.AddAuthHandler(func(auth proton.Auth) {
|
||||
if err := user.vault.SetAuth(auth.UID, auth.RefreshToken); err != nil {
|
||||
user.log.WithError(err).Error("Failed to update auth in vault")
|
||||
}
|
||||
@ -172,7 +172,7 @@ func New(
|
||||
// When we receive an API event, we attempt to handle it.
|
||||
// If successful, we update the event ID in the vault.
|
||||
user.tasks.Once(func(ctx context.Context) {
|
||||
ticker := liteapi.NewTicker(EventPeriod, EventJitter)
|
||||
ticker := proton.NewTicker(EventPeriod, EventJitter)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
@ -271,11 +271,11 @@ func (user *User) Emails() []string {
|
||||
return safe.RLockRet(func() []string {
|
||||
addresses := maps.Values(user.apiAddrs)
|
||||
|
||||
slices.SortFunc(addresses, func(a, b liteapi.Address) bool {
|
||||
slices.SortFunc(addresses, func(a, b proton.Address) bool {
|
||||
return a.Order < b.Order
|
||||
})
|
||||
|
||||
return xslices.Map(addresses, func(addr liteapi.Address) string {
|
||||
return xslices.Map(addresses, func(addr proton.Address) string {
|
||||
return addr.Email
|
||||
})
|
||||
}, user.apiAddrsLock)
|
||||
|
||||
@ -23,6 +23,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/gluon/connector"
|
||||
"github.com/ProtonMail/go-proton-api"
|
||||
"github.com/ProtonMail/go-proton-api/server"
|
||||
"github.com/ProtonMail/go-proton-api/server/backend"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/bridge/mocks"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/certs"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/events"
|
||||
@ -30,9 +33,6 @@ import (
|
||||
"github.com/ProtonMail/proton-bridge/v2/tests"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
"gitlab.protontech.ch/go/liteapi/server"
|
||||
"gitlab.protontech.ch/go/liteapi/server/backend"
|
||||
"go.uber.org/goleak"
|
||||
)
|
||||
|
||||
@ -48,7 +48,7 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
|
||||
func TestUser_Info(t *testing.T) {
|
||||
withAPI(t, context.Background(), func(ctx context.Context, s *server.Server, m *liteapi.Manager) {
|
||||
withAPI(t, context.Background(), func(ctx context.Context, s *server.Server, m *proton.Manager) {
|
||||
withAccount(t, s, "username", "password", []string{"email@pm.me", "alias@pm.me"}, func(userID string, _ []string) {
|
||||
withUser(t, ctx, s, m, "username", "password", func(user *User) {
|
||||
// User's ID should be correct.
|
||||
@ -71,7 +71,7 @@ func TestUser_Info(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUser_Sync(t *testing.T) {
|
||||
withAPI(t, context.Background(), func(ctx context.Context, s *server.Server, m *liteapi.Manager) {
|
||||
withAPI(t, context.Background(), func(ctx context.Context, s *server.Server, m *proton.Manager) {
|
||||
withAccount(t, s, "username", "password", []string{"email@pm.me"}, func(string, []string) {
|
||||
withUser(t, ctx, s, m, "username", "password", func(user *User) {
|
||||
// User starts a sync at startup.
|
||||
@ -88,7 +88,7 @@ func TestUser_Sync(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUser_AddressMode(t *testing.T) {
|
||||
withAPI(t, context.Background(), func(ctx context.Context, s *server.Server, m *liteapi.Manager) {
|
||||
withAPI(t, context.Background(), func(ctx context.Context, s *server.Server, m *proton.Manager) {
|
||||
withAccount(t, s, "username", "password", []string{"email@pm.me", "alias@pm.me"}, func(string, []string) {
|
||||
withUser(t, ctx, s, m, "username", "password", func(user *User) {
|
||||
// User finishes syncing at startup.
|
||||
@ -125,7 +125,7 @@ func TestUser_AddressMode(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUser_Deauth(t *testing.T) {
|
||||
withAPI(t, context.Background(), func(ctx context.Context, s *server.Server, m *liteapi.Manager) {
|
||||
withAPI(t, context.Background(), func(ctx context.Context, s *server.Server, m *proton.Manager) {
|
||||
withAccount(t, s, "username", "password", []string{"email@pm.me"}, func(string, []string) {
|
||||
withUser(t, ctx, s, m, "username", "password", func(user *User) {
|
||||
require.IsType(t, events.SyncStarted{}, <-user.GetEventCh())
|
||||
@ -146,7 +146,7 @@ func TestUser_Refresh(t *testing.T) {
|
||||
ctl := gomock.NewController(t)
|
||||
mockReporter := mocks.NewMockReporter(ctl)
|
||||
|
||||
withAPI(t, context.Background(), func(ctx context.Context, s *server.Server, m *liteapi.Manager) {
|
||||
withAPI(t, context.Background(), func(ctx context.Context, s *server.Server, m *proton.Manager) {
|
||||
withAccount(t, s, "username", "password", []string{"email@pm.me"}, func(string, []string) {
|
||||
withUser(t, ctx, s, m, "username", "password", func(user *User) {
|
||||
require.IsType(t, events.SyncStarted{}, <-user.GetEventCh())
|
||||
@ -157,11 +157,11 @@ func TestUser_Refresh(t *testing.T) {
|
||||
|
||||
mockReporter.EXPECT().ReportMessageWithContext(
|
||||
gomock.Eq("Warning: refresh occurred"),
|
||||
mocks.NewRefreshContextMatcher(liteapi.RefreshAll),
|
||||
mocks.NewRefreshContextMatcher(proton.RefreshAll),
|
||||
).Return(nil)
|
||||
|
||||
// Send refresh event
|
||||
require.NoError(t, s.RefreshUser(user.ID(), liteapi.RefreshAll))
|
||||
require.NoError(t, s.RefreshUser(user.ID(), proton.RefreshAll))
|
||||
|
||||
// The user should eventually be re-synced.
|
||||
require.Eventually(t, func() bool { _, ok := (<-user.GetEventCh()).(events.UserRefreshed); return ok }, 5*time.Second, 100*time.Millisecond)
|
||||
@ -170,13 +170,13 @@ func TestUser_Refresh(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func withAPI(_ testing.TB, ctx context.Context, fn func(context.Context, *server.Server, *liteapi.Manager)) { //nolint:revive
|
||||
func withAPI(_ testing.TB, ctx context.Context, fn func(context.Context, *server.Server, *proton.Manager)) { //nolint:revive
|
||||
server := server.New()
|
||||
defer server.Close()
|
||||
|
||||
fn(ctx, server, liteapi.New(
|
||||
liteapi.WithHostURL(server.GetHostURL()),
|
||||
liteapi.WithTransport(liteapi.InsecureTransport()),
|
||||
fn(ctx, server, proton.New(
|
||||
proton.WithHostURL(server.GetHostURL()),
|
||||
proton.WithTransport(proton.InsecureTransport()),
|
||||
))
|
||||
}
|
||||
|
||||
@ -198,7 +198,7 @@ func withAccount(tb testing.TB, s *server.Server, username, password string, ema
|
||||
fn(userID, addrIDs)
|
||||
}
|
||||
|
||||
func withUser(tb testing.TB, ctx context.Context, _ *server.Server, m *liteapi.Manager, username, password string, fn func(*User)) { //nolint:unparam,revive
|
||||
func withUser(tb testing.TB, ctx context.Context, _ *server.Server, m *proton.Manager, username, password string, fn func(*User)) { //nolint:unparam,revive
|
||||
client, apiAuth, err := m.NewClientWithLogin(ctx, username, []byte(password))
|
||||
require.NoError(tb, err)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user