From 51229cbb68eea7052de0dd3637de7e07c077d3f8 Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Thu, 16 Nov 2023 09:52:44 +0100 Subject: [PATCH] feat(GODT-3122): added test, changed interface for accessing display name. --- go.mod | 2 +- go.sum | 4 +-- internal/bridge/configure.go | 25 ++++++--------- internal/user/user.go | 60 ++++++++++++++++++++---------------- internal/user/user_test.go | 9 +++++- 5 files changed, 54 insertions(+), 46 deletions(-) diff --git a/go.mod b/go.mod index c00e0e21..e71607e3 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.0 github.com/ProtonMail/gluon v0.17.1-0.20231114153341-2ecbdd2739f7 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/PuerkitoBio/goquery v1.8.1 github.com/abiosoft/ishell v2.0.0+incompatible diff --git a/go.sum b/go.sum index 2effaff8..65817bb4 100644 --- a/go.sum +++ b/go.sum @@ -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-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-proton-api v0.4.1-0.20231115131212-0ea2258e7bbf h1:Zu1VnheQV2ybcrUyGd2wCzAZIwqEgBOpYrg/SKUEvYo= -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 h1:tUK7x2Vm2bnCdij/gKyXxgV9v1A680BdDOEQfBm1Rz0= +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/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ= github.com/ProtonMail/go-srp v0.0.7 h1:Sos3Qk+th4tQR64vsxGIxYpN3rdnG9Wf9K4ZloC1JrI= diff --git a/internal/bridge/configure.go b/internal/bridge/configure.go index c2673903..98946b69 100644 --- a/internal/bridge/configure.go +++ b/internal/bridge/configure.go @@ -26,11 +26,9 @@ import ( "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/logging" "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/vault" "github.com/sirupsen/logrus" - "golang.org/x/exp/slices" ) // 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 } - identities := user.Identities() - if len(identities) == 0 { - return errors.New("could not retrieve user identities") + emails := user.Emails() + displayNames := user.DisplayNames() + if (len(emails) == 0) || (len(displayNames) == 0) { + return errors.New("could not retrieve user address info") } if address == "" { - address = identities[0].Email + address = emails[0] } var username, displayName, addresses string if user.GetAddressMode() == vault.CombinedMode { - username = identities[0].Email - displayName = identities[0].DisplayName - addresses = strings.Join(user.Emails(), ",") + username = address + displayName = displayNames[username] + addresses = strings.Join(emails, ",") } else { username = address addresses = address - index := slices.IndexFunc(identities, func(identity userpkg.Identity) bool { - return strings.EqualFold(identity.Email, address) - }) - if index >= 0 { - displayName = identities[index].DisplayName - } else { + displayName = displayNames[address] + if len(displayName) == 0 { displayName = address } } diff --git a/internal/user/user.go b/internal/user/user.go index e18d226a..3566877c 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -58,11 +58,6 @@ const ( SyncRetryCooldown = 20 * time.Second ) -type Identity struct { - DisplayName string - Email string -} - type User struct { id string log *logrus.Entry @@ -383,41 +378,32 @@ func (user *User) Match(query string) bool { 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) - if err != nil { +// DisplayNames returns a map of the email addresses and their associated display names. +func (user *User) DisplayNames() map[string]string { + addresses := user.protonAddresses() + if addresses == nil { return nil } - addresses := xslices.Filter(maps.Values(apiAddresses), func(addr proton.Address) bool { - return addr.Status == proton.AddressStatusEnabled && addr.Type != proton.AddressTypeExternal - }) + result := make(map[string]string) + for _, address := range addresses { + result[address.Email] = address.DisplayName + } - slices.SortFunc(addresses, func(a, b proton.Address) bool { - return a.Order < b.Order - }) - - return xslices.Map(addresses, func(addr proton.Address) Identity { - return Identity{ - DisplayName: addr.DisplayName, - Email: addr.Email, - } - }) + return result } // Emails returns all the user's active email addresses. // It returns them in sorted order; the user's primary address is first. func (user *User) Emails() []string { - identities := user.Identities() - if identities == nil { + addresses := user.protonAddresses() + if addresses == nil { return nil } - return xslices.Map(identities, func(identity Identity) string { - return identity.Email + return xslices.Map(addresses, func(addr proton.Address) string { + return addr.Email }) } @@ -711,3 +697,23 @@ func (user *User) PauseEventLoopWithWaiter() *userevents.EventPollWaiter { func (user *User) ResumeEventLoop() { 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 +} diff --git a/internal/user/user_test.go b/internal/user/user_test.go index a6503402..cb7dc03b 100644 --- a/internal/user/user_test.go +++ b/internal/user/user_test.go @@ -19,6 +19,7 @@ package user import ( "context" + "reflect" "testing" "time" @@ -58,8 +59,12 @@ func TestUser_Info(t *testing.T) { // User's name should be correct. 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.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. 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 userID, addrID, err := s.CreateUser(username, []byte(password)) require.NoError(tb, err) + require.NoError(tb, s.ChangeAddressDisplayName(userID, addrID, username+" (Display Name)")) addrIDs := []string{addrID} for _, email := range aliases { addrID, err := s.CreateAddress(userID, email, []byte(password)) require.NoError(tb, err) + require.NoError(tb, s.ChangeAddressDisplayName(userID, addrID, email+" (Display Name)")) addrIDs = append(addrIDs, addrID) }