GODT-35: New pmapi client and manager using resty

This commit is contained in:
James Houlahan
2021-02-22 18:23:51 +01:00
committed by Jakub
parent 1d538e8540
commit 2284e9ede1
163 changed files with 3333 additions and 8124 deletions

View File

@ -26,6 +26,7 @@ import (
"github.com/ProtonMail/proton-bridge/internal/sentry"
"github.com/ProtonMail/proton-bridge/internal/users"
"github.com/ProtonMail/proton-bridge/pkg/listener"
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
)
// GetBridge returns bridge instance.
@ -52,7 +53,6 @@ func (ctx *TestContext) RestartBridge() error {
_ = user.GetStore().Close()
}
ctx.bridge.StopWatchers()
time.Sleep(50 * time.Millisecond)
ctx.withBridgeInstance()
@ -68,7 +68,7 @@ func newBridgeInstance(
settings *fakeSettings,
credStore users.CredentialsStorer,
eventListener listener.Listener,
clientManager users.ClientManager,
clientManager pmapi.Manager,
) *bridge.Bridge {
sentryReporter := sentry.NewReporter("bridge", constants.Version, useragent.New())
panicHandler := &panicHandler{t: t}

View File

@ -23,7 +23,6 @@ import (
"github.com/ProtonMail/proton-bridge/internal/bridge"
"github.com/ProtonMail/proton-bridge/internal/config/useragent"
"github.com/ProtonMail/proton-bridge/internal/constants"
"github.com/ProtonMail/proton-bridge/internal/importexport"
"github.com/ProtonMail/proton-bridge/internal/transfer"
"github.com/ProtonMail/proton-bridge/internal/users"
@ -53,7 +52,7 @@ type TestContext struct {
// pmapiController is used to control real or fake pmapi clients.
// The clients are created by the clientManager.
pmapiController PMAPIController
clientManager *pmapi.ClientManager
clientManager pmapi.Manager
// Core related variables.
bridge *bridge.Bridge
@ -99,10 +98,7 @@ func New(app string) *TestContext {
userAgent := useragent.New()
cm := pmapi.NewClientManager(
pmapi.GetAPIConfig(getConfigName(app), constants.Version),
userAgent,
)
pmapiController, clientManager := newPMAPIController()
ctx := &TestContext{
t: &bddT{},
@ -111,8 +107,8 @@ func New(app string) *TestContext {
settings: newFakeSettings(),
listener: listener.New(),
userAgent: userAgent,
pmapiController: newPMAPIController(cm),
clientManager: cm,
pmapiController: pmapiController,
clientManager: clientManager,
testAccounts: newTestAccounts(),
credStore: newFakeCredStore(),
imapClients: make(map[string]*mocks.IMAPClient),
@ -164,7 +160,7 @@ func (ctx *TestContext) GetPMAPIController() PMAPIController {
}
// GetClientManager returns client manager being used for testing.
func (ctx *TestContext) GetClientManager() *pmapi.ClientManager {
func (ctx *TestContext) GetClientManager() pmapi.Manager {
return ctx.clientManager
}

View File

@ -51,7 +51,7 @@ func (c *fakeCredStore) List() (userIDs []string, err error) {
return keys, nil
}
func (c *fakeCredStore) Add(userID, userName, apiToken, mailboxPassword string, emails []string) (*credentials.Credentials, error) {
func (c *fakeCredStore) Add(userID, userName, uid, ref, mailboxPassword string, emails []string) (*credentials.Credentials, error) {
bridgePassword := bridgePassword
if c, ok := c.credentials[userID]; ok {
bridgePassword = c.BridgePassword
@ -60,7 +60,7 @@ func (c *fakeCredStore) Add(userID, userName, apiToken, mailboxPassword string,
UserID: userID,
Name: userName,
Emails: strings.Join(emails, ";"),
APIToken: apiToken,
APIToken: uid + ":" + ref,
MailboxPassword: mailboxPassword,
BridgePassword: bridgePassword,
IsCombinedAddressMode: true, // otherwise by default starts in split mode
@ -73,36 +73,38 @@ func (c *fakeCredStore) Get(userID string) (*credentials.Credentials, error) {
return c.credentials[userID], nil
}
func (c *fakeCredStore) SwitchAddressMode(userID string) error {
return nil
func (c *fakeCredStore) SwitchAddressMode(userID string) (*credentials.Credentials, error) {
// FIXME(conman): Why is this empty?
return c.credentials[userID], nil
}
func (c *fakeCredStore) UpdateEmails(userID string, emails []string) error {
return nil
func (c *fakeCredStore) UpdateEmails(userID string, emails []string) (*credentials.Credentials, error) {
// FIXME(conman): Why is this empty?
return c.credentials[userID], nil
}
func (c *fakeCredStore) UpdatePassword(userID, password string) error {
func (c *fakeCredStore) UpdatePassword(userID, password string) (*credentials.Credentials, error) {
creds, err := c.Get(userID)
if err != nil {
return err
return nil, err
}
creds.MailboxPassword = password
return nil
return creds, nil
}
func (c *fakeCredStore) UpdateToken(userID, apiToken string) error {
func (c *fakeCredStore) UpdateToken(userID, uid, ref string) (*credentials.Credentials, error) {
creds, err := c.Get(userID)
if err != nil {
return err
return nil, err
}
creds.APIToken = apiToken
return nil
creds.APIToken = uid + ":" + ref
return creds, nil
}
func (c *fakeCredStore) Logout(userID string) error {
func (c *fakeCredStore) Logout(userID string) (*credentials.Credentials, error) {
c.credentials[userID].APIToken = ""
c.credentials[userID].MailboxPassword = ""
return nil
return c.credentials[userID], nil
}
func (c *fakeCredStore) Delete(userID string) error {

View File

@ -21,6 +21,7 @@ import (
"github.com/ProtonMail/proton-bridge/internal/importexport"
"github.com/ProtonMail/proton-bridge/internal/users"
"github.com/ProtonMail/proton-bridge/pkg/listener"
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
)
// GetImportExport returns import-export instance.
@ -42,7 +43,7 @@ func newImportExportInstance(
cache importexport.Cacher,
credStore users.CredentialsStorer,
eventListener listener.Listener,
clientManager users.ClientManager,
clientManager pmapi.Manager,
) *importexport.ImportExport {
panicHandler := &panicHandler{t: t}
return importexport.New(locations, cache, panicHandler, eventListener, clientManager, credStore)

View File

@ -39,37 +39,15 @@ type PMAPIController interface {
GetCalls(method, path string) [][]byte
}
func newPMAPIController(cm *pmapi.ClientManager) PMAPIController {
func newPMAPIController() (PMAPIController, pmapi.Manager) {
switch os.Getenv(EnvName) {
case EnvFake:
return newFakePMAPIController(cm)
return fakeapi.NewController()
case EnvLive:
return newLivePMAPIController(cm)
return liveapi.NewController()
default:
panic("unknown env")
}
}
func newFakePMAPIController(cm *pmapi.ClientManager) PMAPIController {
return newFakePMAPIControllerWrap(fakeapi.NewController(cm))
}
type fakePMAPIControllerWrap struct {
*fakeapi.Controller
}
func newFakePMAPIControllerWrap(controller *fakeapi.Controller) PMAPIController {
return &fakePMAPIControllerWrap{Controller: controller}
}
func newLivePMAPIController(cm *pmapi.ClientManager) PMAPIController {
return newLiveAPIControllerWrap(liveapi.NewController(cm))
}
type liveAPIControllerWrap struct {
*liveapi.Controller
}
func newLiveAPIControllerWrap(controller *liveapi.Controller) PMAPIController {
return &liveAPIControllerWrap{Controller: controller}
}

View File

@ -0,0 +1,65 @@
package context
import (
"context"
"net/http"
"time"
"github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
"github.com/go-resty/resty/v2"
)
func newLivePMAPIManager() pmapi.Manager {
return pmapi.New(pmapi.DefaultConfig)
}
func newFakePMAPIManager() pmapi.Manager {
return &fakePMAPIManager{}
}
type fakePMAPIManager struct{}
func (*fakePMAPIManager) NewClient(string, string, string, time.Time) pmapi.Client {
panic("TODO")
}
func (*fakePMAPIManager) NewClientWithRefresh(context.Context, string, string) (pmapi.Client, *pmapi.Auth, error) {
panic("TODO")
}
func (*fakePMAPIManager) NewClientWithLogin(context.Context, string, string) (pmapi.Client, *pmapi.Auth, error) {
panic("TODO")
}
func (*fakePMAPIManager) DownloadAndVerify(kr *crypto.KeyRing, url, sig string) ([]byte, error) {
panic("TODO")
}
func (*fakePMAPIManager) ReportBug(context.Context, pmapi.ReportBugReq) error {
panic("TODO")
}
func (*fakePMAPIManager) SendSimpleMetric(context.Context, string, string, string) error {
panic("TODO")
}
func (*fakePMAPIManager) SetLogger(resty.Logger) {
panic("TODO")
}
func (*fakePMAPIManager) SetTransport(http.RoundTripper) {
panic("TODO")
}
func (*fakePMAPIManager) SetCookieJar(http.CookieJar) {
panic("TODO")
}
func (*fakePMAPIManager) SetRetryCount(int) {
panic("TODO")
}
func (*fakePMAPIManager) AddConnectionObserver(pmapi.ConnectionObserver) {
panic("TODO")
}

View File

@ -18,6 +18,7 @@
package context
import (
"context"
"fmt"
"math/rand"
"path/filepath"
@ -25,6 +26,7 @@ import (
"github.com/ProtonMail/proton-bridge/internal/store"
"github.com/ProtonMail/proton-bridge/internal/users"
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
"github.com/ProtonMail/proton-bridge/pkg/srp"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
@ -36,7 +38,7 @@ func (ctx *TestContext) GetUsers() *users.Users {
}
// LoginUser logs in the user with the given username, password, and mailbox password.
func (ctx *TestContext) LoginUser(username, password, mailboxPassword string) (err error) {
func (ctx *TestContext) LoginUser(username, password, mailboxPassword string) error {
srp.RandReader = rand.New(rand.NewSource(42)) //nolint[gosec] It is OK to use weaker random number generator here
client, auth, err := ctx.users.Login(username, password)
@ -44,8 +46,8 @@ func (ctx *TestContext) LoginUser(username, password, mailboxPassword string) (e
return errors.Wrap(err, "failed to login")
}
if auth.HasTwoFactor() {
if err := client.Auth2FA("2fa code", auth); err != nil {
if auth.TwoFA.Enabled == pmapi.TOTPEnabled {
if err := client.Auth2FA(context.TODO(), pmapi.Auth2FAReq{TwoFactorCode: "2fa code"}); err != nil {
return errors.Wrap(err, "failed to login with 2FA")
}
}
@ -57,7 +59,7 @@ func (ctx *TestContext) LoginUser(username, password, mailboxPassword string) (e
ctx.addCleanupChecked(user.Logout, "Logging out user")
return
return nil
}
// GetUser retrieves the bridge user matching the given query string.