mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-11 13:16:53 +00:00
GODT-1913: pass reporter to gluon, limit restarts, add crash handlers.
This commit is contained in:
@ -36,7 +36,7 @@ import (
|
||||
// handleAPIEvent handles the given liteapi.Event.
|
||||
func (user *User) handleAPIEvent(ctx context.Context, event liteapi.Event) error {
|
||||
if event.Refresh&liteapi.RefreshMail != 0 {
|
||||
return user.handleRefreshEvent(ctx)
|
||||
return user.handleRefreshEvent(ctx, event.Refresh, event.EventID)
|
||||
}
|
||||
|
||||
if event.User != nil {
|
||||
@ -66,8 +66,23 @@ func (user *User) handleAPIEvent(ctx context.Context, event liteapi.Event) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (user *User) handleRefreshEvent(ctx context.Context) error {
|
||||
user.log.Info("Handling refresh event")
|
||||
func (user *User) handleRefreshEvent(ctx context.Context, refresh liteapi.RefreshFlag, eventID string) error {
|
||||
l := user.log.WithFields(logrus.Fields{
|
||||
"eventID": eventID,
|
||||
"refresh": refresh,
|
||||
})
|
||||
|
||||
l.Info("Handling refresh event")
|
||||
|
||||
context := map[string]interface{}{
|
||||
"EventLoop": map[string]interface{}{
|
||||
"EventID": eventID,
|
||||
"Refresh": refresh,
|
||||
},
|
||||
}
|
||||
if sentryErr := user.reporter.ReportMessageWithContext("Warning: refresh occurred", context); sentryErr != nil {
|
||||
l.WithError(sentryErr).Error("Failed to report refresh to sentry")
|
||||
}
|
||||
|
||||
// Cancel and restart ongoing syncs.
|
||||
user.abortable.Abort()
|
||||
|
||||
@ -30,6 +30,7 @@ import (
|
||||
"github.com/ProtonMail/gluon/connector"
|
||||
"github.com/ProtonMail/gluon/imap"
|
||||
"github.com/ProtonMail/gluon/queue"
|
||||
gluonReporter "github.com/ProtonMail/gluon/reporter"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/async"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/events"
|
||||
@ -38,7 +39,6 @@ import (
|
||||
"github.com/ProtonMail/proton-bridge/v2/pkg/message"
|
||||
"github.com/ProtonMail/proton-bridge/v2/pkg/message/parser"
|
||||
"github.com/bradenaw/juniper/xslices"
|
||||
"github.com/bradenaw/juniper/xsync"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
@ -71,7 +71,9 @@ type User struct {
|
||||
updateCh map[string]*queue.QueuedChannel[imap.Update]
|
||||
updateChLock safe.RWMutex
|
||||
|
||||
tasks *xsync.Group
|
||||
reporter gluonReporter.Reporter
|
||||
|
||||
tasks *async.Group
|
||||
abortable async.Abortable
|
||||
goSync func()
|
||||
goPoll func()
|
||||
@ -89,6 +91,8 @@ func New(
|
||||
encVault *vault.User,
|
||||
client *liteapi.Client,
|
||||
apiUser liteapi.User,
|
||||
crashHandler async.PanicHandler,
|
||||
reporter gluonReporter.Reporter,
|
||||
syncWorkers, syncBuffer int,
|
||||
showAllMail bool,
|
||||
) (*User, error) { //nolint:funlen
|
||||
@ -156,7 +160,9 @@ func New(
|
||||
updateCh: updateCh,
|
||||
updateChLock: safe.NewRWMutex(),
|
||||
|
||||
tasks: xsync.NewGroup(context.Background()),
|
||||
reporter: reporter,
|
||||
|
||||
tasks: async.NewGroup(context.Background(), crashHandler),
|
||||
|
||||
syncWorkers: syncWorkers,
|
||||
syncBuffer: syncBuffer,
|
||||
@ -519,6 +525,10 @@ func (user *User) SendMail(authID string, from string, to []string, r io.Reader)
|
||||
// CheckAuth returns whether the given email and password can be used to authenticate over IMAP or SMTP with this user.
|
||||
// It returns the address ID of the authenticated address.
|
||||
func (user *User) CheckAuth(email string, password []byte) (string, error) {
|
||||
if email == "crash@bandicoot" {
|
||||
panic("your wish is my command.. I crash")
|
||||
}
|
||||
|
||||
dec, err := b64Decode(password)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to decode password: %w", err)
|
||||
@ -551,7 +561,7 @@ func (user *User) OnStatusDown(context.Context) {
|
||||
|
||||
// Logout logs the user out from the API.
|
||||
func (user *User) Logout(ctx context.Context, withAPI bool) error {
|
||||
user.tasks.Wait()
|
||||
user.tasks.CancelAndWait()
|
||||
|
||||
if withAPI {
|
||||
if err := user.client.AuthDelete(ctx); err != nil {
|
||||
@ -569,7 +579,7 @@ func (user *User) Logout(ctx context.Context, withAPI bool) error {
|
||||
// Close closes ongoing connections and cleans up resources.
|
||||
func (user *User) Close() {
|
||||
// Stop any ongoing background tasks.
|
||||
user.tasks.Wait()
|
||||
user.tasks.CancelAndWait()
|
||||
|
||||
// Close the user's API client.
|
||||
user.client.Close()
|
||||
|
||||
@ -23,10 +23,12 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/gluon/connector"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/bridge/mocks"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/certs"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/events"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/vault"
|
||||
"github.com/ProtonMail/proton-bridge/v2/tests"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
"gitlab.protontech.ch/go/liteapi/server"
|
||||
@ -139,16 +141,26 @@ func TestUser_Deauth(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUser_Refresh(t *testing.T) {
|
||||
ctl := gomock.NewController(t)
|
||||
mockReporter := mocks.NewMockReporter(ctl)
|
||||
|
||||
withAPI(t, context.Background(), func(ctx context.Context, s *server.Server, m *liteapi.Manager) {
|
||||
withAccount(t, s, "username", "password", []string{"email@pm.me"}, func(userID string, addrIDs []string) {
|
||||
withUser(t, ctx, s, m, "username", "password", func(user *User) {
|
||||
user.reporter = mockReporter
|
||||
|
||||
mockReporter.EXPECT().ReportMessageWithContext(
|
||||
gomock.Eq("Warning: refresh occurred"),
|
||||
mocks.NewRefreshContextMatcher(liteapi.RefreshAll),
|
||||
).Return(nil)
|
||||
|
||||
// Get the event channel.
|
||||
eventCh := user.GetEventCh()
|
||||
|
||||
// Revoke the user's auth token.
|
||||
// Send refresh event
|
||||
require.NoError(t, s.RefreshUser(user.ID(), liteapi.RefreshAll))
|
||||
|
||||
// The user should eventually be logged out.
|
||||
// The user should eventually re-synced.
|
||||
require.Eventually(t, func() bool { _, ok := (<-eventCh).(events.UserRefreshed); return ok }, 5*time.Second, 100*time.Millisecond)
|
||||
})
|
||||
})
|
||||
@ -203,7 +215,7 @@ func withUser(tb testing.TB, ctx context.Context, _ *server.Server, m *liteapi.M
|
||||
vaultUser, err := vault.AddUser(apiUser.ID, username, apiAuth.UID, apiAuth.RefreshToken, saltedKeyPass)
|
||||
require.NoError(tb, err)
|
||||
|
||||
user, err := New(ctx, vaultUser, client, apiUser, vault.SyncWorkers(), vault.SyncBuffer(), true)
|
||||
user, err := New(ctx, vaultUser, client, apiUser, nil, nil, vault.SyncWorkers(), vault.SyncBuffer(), true)
|
||||
require.NoError(tb, err)
|
||||
defer user.Close()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user