mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-15 22:56:48 +00:00
GODT-2003: introduces 3 phases user state (SignedOut/Locked/Connected)
WIP: introduced UserState enum in GUI and implemented logic.
This commit is contained in:
@ -529,14 +529,14 @@ func must[T any](val T, err error) T {
|
||||
return val
|
||||
}
|
||||
|
||||
func getConnectedUserIDs(t *testing.T, bridge *bridge.Bridge) []string {
|
||||
func getConnectedUserIDs(t *testing.T, b *bridge.Bridge) []string {
|
||||
t.Helper()
|
||||
|
||||
return xslices.Filter(bridge.GetUserIDs(), func(userID string) bool {
|
||||
info, err := bridge.GetUserInfo(userID)
|
||||
return xslices.Filter(b.GetUserIDs(), func(userID string) bool {
|
||||
info, err := b.GetUserInfo(userID)
|
||||
require.NoError(t, err)
|
||||
|
||||
return info.Connected
|
||||
return info.State == bridge.Connected
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -69,14 +69,14 @@ func TestBridge_Sync(t *testing.T) {
|
||||
})
|
||||
|
||||
// If we then connect an IMAP client, it should see all the messages.
|
||||
withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) {
|
||||
withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(b *bridge.Bridge, mocks *bridge.Mocks) {
|
||||
mocks.Reporter.EXPECT().ReportMessageWithContext(gomock.Any(), gomock.Any()).AnyTimes()
|
||||
|
||||
info, err := bridge.GetUserInfo(userID)
|
||||
info, err := b.GetUserInfo(userID)
|
||||
require.NoError(t, err)
|
||||
require.True(t, info.Connected)
|
||||
require.True(t, info.State == bridge.Connected)
|
||||
|
||||
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
|
||||
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, client.Login("imap@pm.me", string(info.BridgePass)))
|
||||
defer func() { _ = client.Logout() }()
|
||||
@ -95,23 +95,23 @@ func TestBridge_Sync(t *testing.T) {
|
||||
netCtl.SetReadLimit(2 * total / 3)
|
||||
|
||||
// Login the user; its sync should fail.
|
||||
withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) {
|
||||
withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(b *bridge.Bridge, mocks *bridge.Mocks) {
|
||||
mocks.Reporter.EXPECT().ReportMessageWithContext(gomock.Any(), gomock.Any()).AnyTimes()
|
||||
|
||||
{
|
||||
syncCh, done := chToType[events.Event, events.SyncFailed](bridge.GetEvents(events.SyncFailed{}))
|
||||
syncCh, done := chToType[events.Event, events.SyncFailed](b.GetEvents(events.SyncFailed{}))
|
||||
defer done()
|
||||
|
||||
userID, err := bridge.LoginFull(ctx, "imap", password, nil, nil)
|
||||
userID, err := b.LoginFull(ctx, "imap", password, nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, userID, (<-syncCh).UserID)
|
||||
|
||||
info, err := bridge.GetUserInfo(userID)
|
||||
info, err := b.GetUserInfo(userID)
|
||||
require.NoError(t, err)
|
||||
require.True(t, info.Connected)
|
||||
require.True(t, info.State == bridge.Connected)
|
||||
|
||||
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
|
||||
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, client.Login("imap@pm.me", string(info.BridgePass)))
|
||||
defer func() { _ = client.Logout() }()
|
||||
@ -125,16 +125,16 @@ func TestBridge_Sync(t *testing.T) {
|
||||
netCtl.SetReadLimit(0)
|
||||
|
||||
{
|
||||
syncCh, done := chToType[events.Event, events.SyncFinished](bridge.GetEvents(events.SyncFinished{}))
|
||||
syncCh, done := chToType[events.Event, events.SyncFinished](b.GetEvents(events.SyncFinished{}))
|
||||
defer done()
|
||||
|
||||
require.Equal(t, userID, (<-syncCh).UserID)
|
||||
|
||||
info, err := bridge.GetUserInfo(userID)
|
||||
info, err := b.GetUserInfo(userID)
|
||||
require.NoError(t, err)
|
||||
require.True(t, info.Connected)
|
||||
require.True(t, info.State == bridge.Connected)
|
||||
|
||||
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
|
||||
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, client.Login("imap@pm.me", string(info.BridgePass)))
|
||||
defer func() { _ = client.Logout() }()
|
||||
|
||||
@ -34,6 +34,14 @@ import (
|
||||
"gitlab.protontech.ch/go/liteapi"
|
||||
)
|
||||
|
||||
type UserState int
|
||||
|
||||
const (
|
||||
SignedOut UserState = iota
|
||||
Locked
|
||||
Connected
|
||||
)
|
||||
|
||||
type UserInfo struct {
|
||||
// UserID is the user's API ID.
|
||||
UserID string
|
||||
@ -41,8 +49,8 @@ type UserInfo struct {
|
||||
// Username is the user's API username.
|
||||
Username string
|
||||
|
||||
// Connected is true if the user is logged in (has API auth).
|
||||
Connected bool
|
||||
// Signed Out is true if the user is signed out (no AuthUID, user will need to provide credentials to log in again)
|
||||
State UserState
|
||||
|
||||
// Addresses holds the user's email addresses. The first address is the primary address.
|
||||
Addresses []string
|
||||
@ -75,7 +83,11 @@ func (bridge *Bridge) GetUserInfo(userID string) (UserInfo, error) {
|
||||
var info UserInfo
|
||||
|
||||
if err := bridge.vault.GetUser(userID, func(user *vault.User) {
|
||||
info = getUserInfo(user.UserID(), user.Username(), user.AddressMode())
|
||||
state := Locked
|
||||
if len(user.AuthUID()) == 0 {
|
||||
state = SignedOut
|
||||
}
|
||||
info = getUserInfo(user.UserID(), user.Username(), state, user.AddressMode())
|
||||
}); err != nil {
|
||||
return UserInfo{}, fmt.Errorf("failed to get user info: %w", err)
|
||||
}
|
||||
@ -515,8 +527,9 @@ func (bridge *Bridge) logoutUser(ctx context.Context, user *user.User, withAPI,
|
||||
}
|
||||
|
||||
// getUserInfo returns information about a disconnected user.
|
||||
func getUserInfo(userID, username string, addressMode vault.AddressMode) UserInfo {
|
||||
func getUserInfo(userID, username string, state UserState, addressMode vault.AddressMode) UserInfo {
|
||||
return UserInfo{
|
||||
State: state,
|
||||
UserID: userID,
|
||||
Username: username,
|
||||
AddressMode: addressMode,
|
||||
@ -526,7 +539,7 @@ func getUserInfo(userID, username string, addressMode vault.AddressMode) UserInf
|
||||
// getConnUserInfo returns information about a connected user.
|
||||
func getConnUserInfo(user *user.User) UserInfo {
|
||||
return UserInfo{
|
||||
Connected: true,
|
||||
State: Connected,
|
||||
UserID: user.ID(),
|
||||
Username: user.Name(),
|
||||
Addresses: user.Emails(),
|
||||
|
||||
Reference in New Issue
Block a user