feat(GODT-3122): added test, changed interface for accessing display name.

This commit is contained in:
Xavier Michelon
2023-11-16 09:52:44 +01:00
parent 36c5c37dac
commit 51229cbb68
5 changed files with 54 additions and 46 deletions

2
go.mod
View File

@ -7,7 +7,7 @@ require (
github.com/Masterminds/semver/v3 v3.2.0 github.com/Masterminds/semver/v3 v3.2.0
github.com/ProtonMail/gluon v0.17.1-0.20231114153341-2ecbdd2739f7 github.com/ProtonMail/gluon v0.17.1-0.20231114153341-2ecbdd2739f7
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a
github.com/ProtonMail/go-proton-api v0.4.1-0.20231115131212-0ea2258e7bbf github.com/ProtonMail/go-proton-api v0.4.1-0.20231116074655-c9bc6f71eef0
github.com/ProtonMail/gopenpgp/v2 v2.7.4-proton github.com/ProtonMail/gopenpgp/v2 v2.7.4-proton
github.com/PuerkitoBio/goquery v1.8.1 github.com/PuerkitoBio/goquery v1.8.1
github.com/abiosoft/ishell v2.0.0+incompatible github.com/abiosoft/ishell v2.0.0+incompatible

4
go.sum
View File

@ -36,8 +36,8 @@ github.com/ProtonMail/go-message v0.13.1-0.20230526094639-b62c999c85b7 h1:+j+Kd/
github.com/ProtonMail/go-message v0.13.1-0.20230526094639-b62c999c85b7/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4= github.com/ProtonMail/go-message v0.13.1-0.20230526094639-b62c999c85b7/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4=
github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f h1:tCbYj7/299ekTTXpdwKYF8eBlsYsDVoggDAuAjoK66k= github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f h1:tCbYj7/299ekTTXpdwKYF8eBlsYsDVoggDAuAjoK66k=
github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f/go.mod h1:gcr0kNtGBqin9zDW9GOHcVntrwnjrK+qdJ06mWYBybw= github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f/go.mod h1:gcr0kNtGBqin9zDW9GOHcVntrwnjrK+qdJ06mWYBybw=
github.com/ProtonMail/go-proton-api v0.4.1-0.20231115131212-0ea2258e7bbf h1:Zu1VnheQV2ybcrUyGd2wCzAZIwqEgBOpYrg/SKUEvYo= github.com/ProtonMail/go-proton-api v0.4.1-0.20231116074655-c9bc6f71eef0 h1:tUK7x2Vm2bnCdij/gKyXxgV9v1A680BdDOEQfBm1Rz0=
github.com/ProtonMail/go-proton-api v0.4.1-0.20231115131212-0ea2258e7bbf/go.mod h1:WEXJqj5DSc2YI77SgXdpMY0nk33Qy92Vu2r4tOEazA8= github.com/ProtonMail/go-proton-api v0.4.1-0.20231116074655-c9bc6f71eef0/go.mod h1:WEXJqj5DSc2YI77SgXdpMY0nk33Qy92Vu2r4tOEazA8=
github.com/ProtonMail/go-smtp v0.0.0-20231109081432-2b3d50599865 h1:EP1gnxLL5Z7xBSymE9nSTM27nRYINuvssAtDmG0suD8= github.com/ProtonMail/go-smtp v0.0.0-20231109081432-2b3d50599865 h1:EP1gnxLL5Z7xBSymE9nSTM27nRYINuvssAtDmG0suD8=
github.com/ProtonMail/go-smtp v0.0.0-20231109081432-2b3d50599865/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ= github.com/ProtonMail/go-smtp v0.0.0-20231109081432-2b3d50599865/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
github.com/ProtonMail/go-srp v0.0.7 h1:Sos3Qk+th4tQR64vsxGIxYpN3rdnG9Wf9K4ZloC1JrI= github.com/ProtonMail/go-srp v0.0.7 h1:Sos3Qk+th4tQR64vsxGIxYpN3rdnG9Wf9K4ZloC1JrI=

View File

@ -26,11 +26,9 @@ import (
"github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/constants"
"github.com/ProtonMail/proton-bridge/v3/internal/logging" "github.com/ProtonMail/proton-bridge/v3/internal/logging"
"github.com/ProtonMail/proton-bridge/v3/internal/safe" "github.com/ProtonMail/proton-bridge/v3/internal/safe"
userpkg "github.com/ProtonMail/proton-bridge/v3/internal/user"
"github.com/ProtonMail/proton-bridge/v3/internal/useragent" "github.com/ProtonMail/proton-bridge/v3/internal/useragent"
"github.com/ProtonMail/proton-bridge/v3/internal/vault" "github.com/ProtonMail/proton-bridge/v3/internal/vault"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/exp/slices"
) )
// ConfigureAppleMail configures Apple Mail for the given userID and address. // ConfigureAppleMail configures Apple Mail for the given userID and address.
@ -47,29 +45,26 @@ func (bridge *Bridge) ConfigureAppleMail(ctx context.Context, userID, address st
return ErrNoSuchUser return ErrNoSuchUser
} }
identities := user.Identities() emails := user.Emails()
if len(identities) == 0 { displayNames := user.DisplayNames()
return errors.New("could not retrieve user identities") if (len(emails) == 0) || (len(displayNames) == 0) {
return errors.New("could not retrieve user address info")
} }
if address == "" { if address == "" {
address = identities[0].Email address = emails[0]
} }
var username, displayName, addresses string var username, displayName, addresses string
if user.GetAddressMode() == vault.CombinedMode { if user.GetAddressMode() == vault.CombinedMode {
username = identities[0].Email username = address
displayName = identities[0].DisplayName displayName = displayNames[username]
addresses = strings.Join(user.Emails(), ",") addresses = strings.Join(emails, ",")
} else { } else {
username = address username = address
addresses = address addresses = address
index := slices.IndexFunc(identities, func(identity userpkg.Identity) bool { displayName = displayNames[address]
return strings.EqualFold(identity.Email, address) if len(displayName) == 0 {
})
if index >= 0 {
displayName = identities[index].DisplayName
} else {
displayName = address displayName = address
} }
} }

View File

@ -58,11 +58,6 @@ const (
SyncRetryCooldown = 20 * time.Second SyncRetryCooldown = 20 * time.Second
) )
type Identity struct {
DisplayName string
Email string
}
type User struct { type User struct {
id string id string
log *logrus.Entry log *logrus.Entry
@ -383,41 +378,32 @@ func (user *User) Match(query string) bool {
return false return false
} }
func (user *User) Identities() []Identity {
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Minute))
defer cancel()
apiAddresses, err := user.identityService.GetAddresses(ctx) // DisplayNames returns a map of the email addresses and their associated display names.
if err != nil { func (user *User) DisplayNames() map[string]string {
addresses := user.protonAddresses()
if addresses == nil {
return nil return nil
} }
addresses := xslices.Filter(maps.Values(apiAddresses), func(addr proton.Address) bool { result := make(map[string]string)
return addr.Status == proton.AddressStatusEnabled && addr.Type != proton.AddressTypeExternal for _, address := range addresses {
}) result[address.Email] = address.DisplayName
}
slices.SortFunc(addresses, func(a, b proton.Address) bool { return result
return a.Order < b.Order
})
return xslices.Map(addresses, func(addr proton.Address) Identity {
return Identity{
DisplayName: addr.DisplayName,
Email: addr.Email,
}
})
} }
// Emails returns all the user's active email addresses. // Emails returns all the user's active email addresses.
// It returns them in sorted order; the user's primary address is first. // It returns them in sorted order; the user's primary address is first.
func (user *User) Emails() []string { func (user *User) Emails() []string {
identities := user.Identities() addresses := user.protonAddresses()
if identities == nil { if addresses == nil {
return nil return nil
} }
return xslices.Map(identities, func(identity Identity) string { return xslices.Map(addresses, func(addr proton.Address) string {
return identity.Email return addr.Email
}) })
} }
@ -711,3 +697,23 @@ func (user *User) PauseEventLoopWithWaiter() *userevents.EventPollWaiter {
func (user *User) ResumeEventLoop() { func (user *User) ResumeEventLoop() {
user.eventService.Resume() user.eventService.Resume()
} }
func (user *User) protonAddresses() []proton.Address {
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Minute))
defer cancel()
apiAddrs, err := user.identityService.GetAddresses(ctx)
if err != nil {
return nil
}
addresses := xslices.Filter(maps.Values(apiAddrs), func(addr proton.Address) bool {
return addr.Status == proton.AddressStatusEnabled && addr.Type != proton.AddressTypeExternal
})
slices.SortFunc(addresses, func(a, b proton.Address) bool {
return a.Order < b.Order
})
return addresses
}

View File

@ -19,6 +19,7 @@ package user
import ( import (
"context" "context"
"reflect"
"testing" "testing"
"time" "time"
@ -58,8 +59,12 @@ func TestUser_Info(t *testing.T) {
// User's name should be correct. // User's name should be correct.
require.Equal(t, "username", user.Name()) require.Equal(t, "username", user.Name())
// User's email should be correct. // User's emails should be correct and their associated display names should be correct
require.ElementsMatch(t, []string{"username@" + s.GetDomain(), "alias@pm.me"}, user.Emails()) require.ElementsMatch(t, []string{"username@" + s.GetDomain(), "alias@pm.me"}, user.Emails())
require.True(t, reflect.DeepEqual(map[string]string{
"username@" + s.GetDomain(): "username" + " (Display Name)",
"alias@pm.me": "alias@pm.me (Display Name)",
}, user.DisplayNames()))
// By default, user should be in combined mode. // By default, user should be in combined mode.
require.Equal(t, vault.CombinedMode, user.GetAddressMode()) require.Equal(t, vault.CombinedMode, user.GetAddressMode())
@ -98,12 +103,14 @@ func withAPI(_ testing.TB, ctx context.Context, fn func(context.Context, *server
func withAccount(tb testing.TB, s *server.Server, username, password string, aliases []string, fn func(string, []string)) { //nolint:unparam func withAccount(tb testing.TB, s *server.Server, username, password string, aliases []string, fn func(string, []string)) { //nolint:unparam
userID, addrID, err := s.CreateUser(username, []byte(password)) userID, addrID, err := s.CreateUser(username, []byte(password))
require.NoError(tb, err) require.NoError(tb, err)
require.NoError(tb, s.ChangeAddressDisplayName(userID, addrID, username+" (Display Name)"))
addrIDs := []string{addrID} addrIDs := []string{addrID}
for _, email := range aliases { for _, email := range aliases {
addrID, err := s.CreateAddress(userID, email, []byte(password)) addrID, err := s.CreateAddress(userID, email, []byte(password))
require.NoError(tb, err) require.NoError(tb, err)
require.NoError(tb, s.ChangeAddressDisplayName(userID, addrID, email+" (Display Name)"))
addrIDs = append(addrIDs, addrID) addrIDs = append(addrIDs, addrID)
} }