forked from Silverfish/proton-bridge
GODT-1515: Do not crash when bridge users got disconnected.
This commit is contained in:
@ -345,6 +345,10 @@ func (u *User) GetAddressID(address string) (id string, err error) {
|
||||
return u.store.GetAddressID(address)
|
||||
}
|
||||
|
||||
if u.client == nil {
|
||||
return "", errors.New("bridge account is not fully connected to server")
|
||||
}
|
||||
|
||||
addresses := u.client.Addresses()
|
||||
pmapiAddress := addresses.ByEmail(address)
|
||||
if pmapiAddress != nil {
|
||||
@ -473,7 +477,9 @@ func (u *User) Logout() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := u.client.AuthDelete(context.Background()); err != nil {
|
||||
if u.client == nil {
|
||||
u.log.Warn("Failed to delete auth: no client")
|
||||
} else if err := u.client.AuthDelete(context.Background()); err != nil {
|
||||
u.log.WithError(err).Warn("Failed to delete auth")
|
||||
}
|
||||
|
||||
|
||||
@ -172,3 +172,7 @@ func (ctx *TestContext) MessagePreparationStarted(username string) {
|
||||
func (ctx *TestContext) MessagePreparationFinished(username string) {
|
||||
ctx.pmapiController.UnlockEvents(username)
|
||||
}
|
||||
|
||||
func (ctx *TestContext) CredentialsFailsOnWrite(shouldFail bool) {
|
||||
ctx.credStore.(*fakeCredStore).failOnWrite = shouldFail
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/users/credentials"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// bridgePassword is password to be used for IMAP or SMTP under tests.
|
||||
@ -28,6 +29,8 @@ const bridgePassword = "bridgepassword"
|
||||
|
||||
type fakeCredStore struct {
|
||||
credentials map[string]*credentials.Credentials
|
||||
|
||||
failOnWrite bool
|
||||
}
|
||||
|
||||
// newFakeCredStore returns a fake credentials store (optionally configured with the given credentials).
|
||||
@ -52,6 +55,9 @@ func (c *fakeCredStore) List() (userIDs []string, err error) {
|
||||
}
|
||||
|
||||
func (c *fakeCredStore) Add(userID, userName, uid, ref string, mailboxPassword []byte, emails []string) (*credentials.Credentials, error) {
|
||||
if c.failOnWrite {
|
||||
return nil, errors.New("An invalid attempt to change the owner of an item. (-25244)")
|
||||
}
|
||||
bridgePassword := bridgePassword
|
||||
if c, ok := c.credentials[userID]; ok {
|
||||
bridgePassword = c.BridgePassword
|
||||
@ -73,14 +79,23 @@ func (c *fakeCredStore) Get(userID string) (*credentials.Credentials, error) {
|
||||
}
|
||||
|
||||
func (c *fakeCredStore) SwitchAddressMode(userID string) (*credentials.Credentials, error) {
|
||||
if c.failOnWrite {
|
||||
return nil, errors.New("An invalid attempt to change the owner of an item. (-25244)")
|
||||
}
|
||||
return c.credentials[userID], nil
|
||||
}
|
||||
|
||||
func (c *fakeCredStore) UpdateEmails(userID string, emails []string) (*credentials.Credentials, error) {
|
||||
if c.failOnWrite {
|
||||
return nil, errors.New("An invalid attempt to change the owner of an item. (-25244)")
|
||||
}
|
||||
return c.credentials[userID], nil
|
||||
}
|
||||
|
||||
func (c *fakeCredStore) UpdatePassword(userID string, password []byte) (*credentials.Credentials, error) {
|
||||
if c.failOnWrite {
|
||||
return nil, errors.New("An invalid attempt to change the owner of an item. (-25244)")
|
||||
}
|
||||
creds, err := c.Get(userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -90,6 +105,9 @@ func (c *fakeCredStore) UpdatePassword(userID string, password []byte) (*credent
|
||||
}
|
||||
|
||||
func (c *fakeCredStore) UpdateToken(userID, uid, ref string) (*credentials.Credentials, error) {
|
||||
if c.failOnWrite {
|
||||
return nil, errors.New("An invalid attempt to change the owner of an item. (-25244)")
|
||||
}
|
||||
creds, err := c.Get(userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -99,12 +117,18 @@ func (c *fakeCredStore) UpdateToken(userID, uid, ref string) (*credentials.Crede
|
||||
}
|
||||
|
||||
func (c *fakeCredStore) Logout(userID string) (*credentials.Credentials, error) {
|
||||
if c.failOnWrite {
|
||||
return nil, errors.New("An invalid attempt to change the owner of an item. (-25244)")
|
||||
}
|
||||
c.credentials[userID].APIToken = ""
|
||||
c.credentials[userID].MailboxPassword = []byte{}
|
||||
return c.credentials[userID], nil
|
||||
}
|
||||
|
||||
func (c *fakeCredStore) Delete(userID string) error {
|
||||
if c.failOnWrite {
|
||||
return errors.New("An invalid attempt to change the owner of an item. (-25244)")
|
||||
}
|
||||
delete(c.credentials, userID)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -79,3 +79,12 @@ Feature: Start bridge
|
||||
And "user" does not have loaded store
|
||||
And "user" does not have running event loop
|
||||
And "user" has zero space
|
||||
|
||||
Scenario: Start with connected user, database file and internet connection, but no write access to credentials
|
||||
Given there is user "user" which just logged in
|
||||
And credentials are locked
|
||||
And there is database file for "user"
|
||||
When bridge starts
|
||||
Then "user" is connected
|
||||
When IMAP client authenticates "user"
|
||||
Then IMAP response is "NO"
|
||||
|
||||
@ -33,6 +33,7 @@ func UsersSetupFeatureContext(s *godog.ScenarioContext) {
|
||||
s.Step(`^there is database file for "([^"]*)"$`, thereIsDatabaseFileForUser)
|
||||
s.Step(`^there is no database file for "([^"]*)"$`, thereIsNoDatabaseFileForUser)
|
||||
s.Step(`^there is "([^"]*)" in "([^"]*)" address mode$`, thereIsUserWithAddressMode)
|
||||
s.Step(`^credentials? (?:are|is) locked$`, credentialsAreLocked)
|
||||
}
|
||||
|
||||
func thereIsUser(bddUserID string) error {
|
||||
@ -150,3 +151,8 @@ func thereIsUserWithAddressMode(bddUserID, wantAddressMode string) error {
|
||||
ctx.EventuallySyncIsFinishedForUsername(user.Username())
|
||||
return nil
|
||||
}
|
||||
|
||||
func credentialsAreLocked() error {
|
||||
ctx.CredentialsFailsOnWrite(true)
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user