feat: improve login flow

This commit is contained in:
James Houlahan
2020-04-02 16:41:49 +02:00
parent 941e09079c
commit 6e38a65bd8
41 changed files with 595 additions and 362 deletions

View File

@ -21,10 +21,8 @@ import (
"os"
"runtime"
"github.com/ProtonMail/proton-bridge/internal/bridge"
"github.com/ProtonMail/proton-bridge/internal/preferences"
"github.com/ProtonMail/proton-bridge/pkg/listener"
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
)
// GetBridge returns bridge instance.
@ -35,7 +33,10 @@ func (ctx *TestContext) GetBridge() *bridge.Bridge {
// withBridgeInstance creates a bridge instance for use in the test.
// Every TestContext has this by default and thus this doesn't need to be exported.
func (ctx *TestContext) withBridgeInstance() {
ctx.bridge = newBridgeInstance(ctx.t, ctx.cfg, ctx.credStore, ctx.listener, ctx.clientManager)
pmapiFactory := func(userID string) bridge.PMAPIProvider {
return ctx.pmapiController.GetClient(userID)
}
ctx.bridge = newBridgeInstance(ctx.t, ctx.cfg, ctx.credStore, ctx.listener, pmapiFactory)
ctx.addCleanupChecked(ctx.bridge.ClearData, "Cleaning bridge data")
}
@ -60,7 +61,7 @@ func newBridgeInstance(
cfg *fakeConfig,
credStore bridge.CredentialsStorer,
eventListener listener.Listener,
clientManager *pmapi.ClientManager,
pmapiFactory bridge.PMAPIProviderFactory,
) *bridge.Bridge {
version := os.Getenv("VERSION")
bridge.UpdateCurrentUserAgent(version, runtime.GOOS, "", "")
@ -68,7 +69,7 @@ func newBridgeInstance(
panicHandler := &panicHandler{t: t}
pref := preferences.New(cfg)
return bridge.New(cfg, pref, panicHandler, eventListener, version, clientManager, credStore)
return bridge.New(cfg, pref, panicHandler, eventListener, version, pmapiFactory, credStore)
}
// SetLastBridgeError sets the last error that occurred while executing a bridge action.

View File

@ -28,6 +28,7 @@ import (
type fakeConfig struct {
dir string
tm *pmapi.TokenManager
}
// newFakeConfig creates a temporary folder for files.
@ -40,6 +41,7 @@ func newFakeConfig() *fakeConfig {
return &fakeConfig{
dir: dir,
tm: pmapi.NewTokenManager(),
}
}
@ -51,6 +53,8 @@ func (c *fakeConfig) GetAPIConfig() *pmapi.ClientConfig {
AppVersion: "Bridge_" + os.Getenv("VERSION"),
ClientID: "bridge",
SentryDSN: "",
// TokenManager should not be required, but PMAPI still doesn't handle not-set cases everywhere.
TokenManager: c.tm,
}
}
func (c *fakeConfig) GetDBDir() string {

View File

@ -21,7 +21,6 @@ package context
import (
"github.com/ProtonMail/proton-bridge/internal/bridge"
"github.com/ProtonMail/proton-bridge/pkg/listener"
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
"github.com/ProtonMail/proton-bridge/test/accounts"
"github.com/ProtonMail/proton-bridge/test/mocks"
"github.com/sirupsen/logrus"
@ -58,9 +57,6 @@ type TestContext struct {
smtpClients map[string]*mocks.SMTPClient
smtpLastResponses map[string]*mocks.SMTPResponse
// PMAPI related variables.
clientManager *pmapi.ClientManager
// These are the cleanup steps executed when Cleanup() is called.
cleanupSteps []*Cleaner
@ -74,20 +70,17 @@ func New() *TestContext {
cfg := newFakeConfig()
cm := pmapi.NewClientManager(cfg.GetAPIConfig())
ctx := &TestContext{
t: &bddT{},
cfg: cfg,
listener: listener.New(),
pmapiController: newPMAPIController(cm),
pmapiController: newPMAPIController(),
testAccounts: newTestAccounts(),
credStore: newFakeCredStore(),
imapClients: make(map[string]*mocks.IMAPClient),
imapLastResponses: make(map[string]*mocks.IMAPResponse),
smtpClients: make(map[string]*mocks.SMTPClient),
smtpLastResponses: make(map[string]*mocks.SMTPResponse),
clientManager: cm,
logger: logrus.StandardLogger(),
}

View File

@ -81,6 +81,15 @@ func (c *fakeCredStore) UpdateEmails(userID string, emails []string) error {
return nil
}
func (c *fakeCredStore) UpdatePassword(userID, password string) error {
creds, err := c.Get(userID)
if err != nil {
return err
}
creds.MailboxPassword = password
return nil
}
func (c *fakeCredStore) UpdateToken(userID, apiToken string) error {
creds, err := c.Get(userID)
if err != nil {

View File

@ -40,12 +40,12 @@ type PMAPIController interface {
GetCalls(method, path string) [][]byte
}
func newPMAPIController(cm *pmapi.ClientManager) PMAPIController {
func newPMAPIController() PMAPIController {
switch os.Getenv(EnvName) {
case EnvFake:
return newFakePMAPIController()
case EnvLive:
return newLivePMAPIController(cm)
return newLivePMAPIController()
default:
panic("unknown env")
}
@ -67,8 +67,8 @@ func (s *fakePMAPIControllerWrap) GetClient(userID string) bridge.PMAPIProvider
return s.Controller.GetClient(userID)
}
func newLivePMAPIController(cm *pmapi.ClientManager) PMAPIController {
return newLiveAPIControllerWrap(liveapi.NewController(cm))
func newLivePMAPIController() PMAPIController {
return newLiveAPIControllerWrap(liveapi.NewController())
}
type liveAPIControllerWrap struct {

View File

@ -141,12 +141,13 @@ func (api *FakePMAPI) AuthRefresh(token string) (*pmapi.Auth, error) {
return auth, nil
}
func (api *FakePMAPI) Logout() {
func (api *FakePMAPI) Logout() error {
if err := api.checkAndRecordCall(DELETE, "/auth", nil); err != nil {
return
return err
}
// Logout will also emit change to auth channel
api.sendAuth(nil)
api.controller.deleteSession(api.uid)
api.unsetUser()
return nil
}

View File

@ -18,7 +18,9 @@
package liveapi
import (
"fmt"
"net/http"
"os"
"sync"
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
@ -30,31 +32,31 @@ type Controller struct {
calls []*fakeCall
pmapiByUsername map[string]*pmapi.Client
messageIDsByUsername map[string][]string
clientManager *pmapi.ClientManager
// State controlled by test.
noInternetConnection bool
}
func NewController(cm *pmapi.ClientManager) *Controller {
cntrl := &Controller{
func NewController() *Controller {
return &Controller{
lock: &sync.RWMutex{},
calls: []*fakeCall{},
pmapiByUsername: map[string]*pmapi.Client{},
messageIDsByUsername: map[string][]string{},
clientManager: cm,
noInternetConnection: false,
}
cntrl.clientManager.SetClientRoundTripper(&fakeTransport{
cntrl: cntrl,
transport: http.DefaultTransport,
})
return cntrl
}
func (cntrl *Controller) GetClient(userID string) *pmapi.Client {
return cntrl.clientManager.GetClient(userID)
cfg := &pmapi.ClientConfig{
AppVersion: fmt.Sprintf("Bridge_%s", os.Getenv("VERSION")),
ClientID: "bridge-test",
Transport: &fakeTransport{
cntrl: cntrl,
transport: http.DefaultTransport,
},
TokenManager: pmapi.NewTokenManager(),
}
return pmapi.NewClient(cfg, userID)
}

View File

@ -18,7 +18,9 @@
package liveapi
import (
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
"fmt"
"os"
"github.com/cucumber/godog"
"github.com/pkg/errors"
)
@ -28,7 +30,11 @@ func (cntrl *Controller) AddUser(user *pmapi.User, addresses *pmapi.AddressList,
return godog.ErrPending
}
client := cntrl.GetClient(user.ID)
client := pmapi.NewClient(&pmapi.ClientConfig{
AppVersion: fmt.Sprintf("Bridge_%s", os.Getenv("VERSION")),
ClientID: "bridge-cntrl",
TokenManager: pmapi.NewTokenManager(),
}, user.ID)
authInfo, err := client.AuthInfo(user.Name)
if err != nil {
@ -55,6 +61,5 @@ func (cntrl *Controller) AddUser(user *pmapi.User, addresses *pmapi.AddressList,
}
cntrl.pmapiByUsername[user.Name] = client
return nil
}