chore(GODT-2551): Store and Recover Last User Agent from Vault
This commit is contained in:
@ -237,6 +237,8 @@ func newBridge(
|
|||||||
return nil, fmt.Errorf("failed to save last version indicator: %w", err)
|
return nil, fmt.Errorf("failed to save last version indicator: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
identifier.SetClientString(vault.GetLastUserAgent())
|
||||||
|
|
||||||
imapServer, err := newIMAPServer(
|
imapServer, err := newIMAPServer(
|
||||||
gluonCacheDir,
|
gluonCacheDir,
|
||||||
gluonDataDir,
|
gluonDataDir,
|
||||||
|
|||||||
@ -171,6 +171,41 @@ func TestBridge_UserAgent(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBridge_UserAgent_Persistence(t *testing.T) {
|
||||||
|
withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, vaultKey []byte) {
|
||||||
|
withBridge(ctx, t, s.GetHostURL(), netCtl, locator, vaultKey, func(b *bridge.Bridge, mocks *bridge.Mocks) {
|
||||||
|
currentUserAgent := b.GetCurrentUserAgent()
|
||||||
|
require.Contains(t, currentUserAgent, vault.DefaultUserAgent)
|
||||||
|
|
||||||
|
imapClient, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer func() { _ = imapClient.Logout() }()
|
||||||
|
|
||||||
|
idClient := imapid.NewClient(imapClient)
|
||||||
|
|
||||||
|
// Set IMAP ID before Login to have the value capture in the Login API Call.
|
||||||
|
_, err = idClient.ID(imapid.ID{
|
||||||
|
imapid.FieldName: "MyFancyClient",
|
||||||
|
imapid.FieldVersion: "0.1.2",
|
||||||
|
})
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Login the user.
|
||||||
|
_, err = b.LoginFull(context.Background(), username, password, nil, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Assert that the user agent then contains the platform.
|
||||||
|
require.Contains(t, b.GetCurrentUserAgent(), "MyFancyClient/0.1.2")
|
||||||
|
})
|
||||||
|
|
||||||
|
withBridge(ctx, t, s.GetHostURL(), netCtl, locator, vaultKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) {
|
||||||
|
currentUserAgent := bridge.GetCurrentUserAgent()
|
||||||
|
require.Contains(t, currentUserAgent, "MyFancyClient/0.1.2")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestBridge_UserAgentFromIMAPID(t *testing.T) {
|
func TestBridge_UserAgentFromIMAPID(t *testing.T) {
|
||||||
withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, vaultKey []byte) {
|
withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, vaultKey []byte) {
|
||||||
var (
|
var (
|
||||||
|
|||||||
@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
package bridge
|
package bridge
|
||||||
|
|
||||||
|
import "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
func (bridge *Bridge) GetCurrentUserAgent() string {
|
func (bridge *Bridge) GetCurrentUserAgent() string {
|
||||||
return bridge.identifier.GetUserAgent()
|
return bridge.identifier.GetUserAgent()
|
||||||
}
|
}
|
||||||
@ -24,3 +26,17 @@ func (bridge *Bridge) GetCurrentUserAgent() string {
|
|||||||
func (bridge *Bridge) SetCurrentPlatform(platform string) {
|
func (bridge *Bridge) SetCurrentPlatform(platform string) {
|
||||||
bridge.identifier.SetPlatform(platform)
|
bridge.identifier.SetPlatform(platform)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bridge *Bridge) setUserAgent(name, version string) {
|
||||||
|
currentUserAgent := bridge.identifier.GetClientString()
|
||||||
|
|
||||||
|
bridge.identifier.SetClient(name, version)
|
||||||
|
|
||||||
|
newUserAgent := bridge.identifier.GetClientString()
|
||||||
|
|
||||||
|
if currentUserAgent != newUserAgent {
|
||||||
|
if err := bridge.vault.SetLastUserAgent(newUserAgent); err != nil {
|
||||||
|
logrus.WithError(err).Error("Failed to write new user agent to vault")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -41,11 +41,6 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
defaultClientName = "UnknownClient"
|
|
||||||
defaultClientVersion = "0.0.1"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (bridge *Bridge) serveIMAP() error {
|
func (bridge *Bridge) serveIMAP() error {
|
||||||
port, err := func() (int, error) {
|
port, err := func() (int, error) {
|
||||||
if bridge.imapServer == nil {
|
if bridge.imapServer == nil {
|
||||||
@ -249,11 +244,6 @@ func (bridge *Bridge) handleIMAPEvent(event imapEvents.Event) {
|
|||||||
}).Info("Received mailbox message count")
|
}).Info("Received mailbox message count")
|
||||||
}
|
}
|
||||||
|
|
||||||
case imapEvents.SessionAdded:
|
|
||||||
if !bridge.identifier.HasClient() {
|
|
||||||
bridge.identifier.SetClient(defaultClientName, defaultClientVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
case imapEvents.IMAPID:
|
case imapEvents.IMAPID:
|
||||||
logrus.WithFields(logrus.Fields{
|
logrus.WithFields(logrus.Fields{
|
||||||
"sessionID": event.SessionID,
|
"sessionID": event.SessionID,
|
||||||
@ -262,7 +252,7 @@ func (bridge *Bridge) handleIMAPEvent(event imapEvents.Event) {
|
|||||||
}).Info("Received IMAP ID")
|
}).Info("Received IMAP ID")
|
||||||
|
|
||||||
if event.IMAPID.Name != "" && event.IMAPID.Version != "" {
|
if event.IMAPID.Name != "" && event.IMAPID.Version != "" {
|
||||||
bridge.identifier.SetClient(event.IMAPID.Name, event.IMAPID.Version)
|
bridge.setUserAgent(event.IMAPID.Name, event.IMAPID.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
case imapEvents.LoginFailed:
|
case imapEvents.LoginFailed:
|
||||||
|
|||||||
@ -38,6 +38,8 @@ type Identifier interface {
|
|||||||
HasClient() bool
|
HasClient() bool
|
||||||
SetClient(name, version string)
|
SetClient(name, version string)
|
||||||
SetPlatform(platform string)
|
SetPlatform(platform string)
|
||||||
|
SetClientString(client string)
|
||||||
|
GetClientString() string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProxyController interface {
|
type ProxyController interface {
|
||||||
|
|||||||
@ -550,7 +550,7 @@ func (bridge *Bridge) addUserWithVault(
|
|||||||
// As such, if we find this ID in the context, we should use it to update our user agent.
|
// As such, if we find this ID in the context, we should use it to update our user agent.
|
||||||
client.AddPreRequestHook(func(_ *resty.Client, r *resty.Request) error {
|
client.AddPreRequestHook(func(_ *resty.Client, r *resty.Request) error {
|
||||||
if imapID, ok := imap.GetIMAPIDFromContext(r.Context()); ok {
|
if imapID, ok := imap.GetIMAPIDFromContext(r.Context()); ok {
|
||||||
bridge.identifier.SetClient(imapID.Name, imapID.Version)
|
bridge.setUserAgent(imapID.Name, imapID.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -44,6 +44,20 @@ func (ua *UserAgent) SetClient(name, version string) {
|
|||||||
ua.client = fmt.Sprintf("%v/%v", name, regexp.MustCompile(`(.*) \((.*)\)`).ReplaceAllString(version, "$1-$2"))
|
ua.client = fmt.Sprintf("%v/%v", name, regexp.MustCompile(`(.*) \((.*)\)`).ReplaceAllString(version, "$1-$2"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ua *UserAgent) SetClientString(client string) {
|
||||||
|
ua.lock.Lock()
|
||||||
|
defer ua.lock.Unlock()
|
||||||
|
|
||||||
|
ua.client = client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ua *UserAgent) GetClientString() string {
|
||||||
|
ua.lock.RLock()
|
||||||
|
defer ua.lock.RUnlock()
|
||||||
|
|
||||||
|
return ua.client
|
||||||
|
}
|
||||||
|
|
||||||
func (ua *UserAgent) HasClient() bool {
|
func (ua *UserAgent) HasClient() bool {
|
||||||
ua.lock.RLock()
|
ua.lock.RLock()
|
||||||
defer ua.lock.RUnlock()
|
defer ua.lock.RUnlock()
|
||||||
|
|||||||
@ -225,3 +225,22 @@ func (vault *Vault) SetMaxSyncMemory(maxMemory uint64) error {
|
|||||||
data.Settings.MaxSyncMemory = maxMemory
|
data.Settings.MaxSyncMemory = maxMemory
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetLastUserAgent returns the last user agent recorded by bridge.
|
||||||
|
func (vault *Vault) GetLastUserAgent() string {
|
||||||
|
v := vault.get().Settings.LastUserAgent
|
||||||
|
|
||||||
|
// Handle case where there may be no value.
|
||||||
|
if len(v) == 0 {
|
||||||
|
v = DefaultUserAgent
|
||||||
|
}
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLastUserAgent store the last user agent recorded by bridge.
|
||||||
|
func (vault *Vault) SetLastUserAgent(userAgent string) error {
|
||||||
|
return vault.mod(func(data *Data) {
|
||||||
|
data.Settings.LastUserAgent = userAgent
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@ -216,3 +216,11 @@ func TestVault_Settings_MaxSyncMemory(t *testing.T) {
|
|||||||
// Check the default first start value.
|
// Check the default first start value.
|
||||||
require.Equal(t, vault.DefaultMaxSyncMemory, s.GetMaxSyncMemory())
|
require.Equal(t, vault.DefaultMaxSyncMemory, s.GetMaxSyncMemory())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestVault_Settings_LastUserAgent(t *testing.T) {
|
||||||
|
// create a new test vault.
|
||||||
|
s := newVault(t)
|
||||||
|
|
||||||
|
// Check the default first start value.
|
||||||
|
require.Equal(t, vault.DefaultUserAgent, s.GetLastUserAgent())
|
||||||
|
}
|
||||||
|
|||||||
@ -46,12 +46,15 @@ type Settings struct {
|
|||||||
|
|
||||||
MaxSyncMemory uint64
|
MaxSyncMemory uint64
|
||||||
|
|
||||||
|
LastUserAgent string
|
||||||
|
|
||||||
// **WARNING**: These entry can't be removed until they vault has proper migration support.
|
// **WARNING**: These entry can't be removed until they vault has proper migration support.
|
||||||
SyncWorkers int
|
SyncWorkers int
|
||||||
SyncAttPool int
|
SyncAttPool int
|
||||||
}
|
}
|
||||||
|
|
||||||
const DefaultMaxSyncMemory = 2 * 1024 * uint64(1024*1024)
|
const DefaultMaxSyncMemory = 2 * 1024 * uint64(1024*1024)
|
||||||
|
const DefaultUserAgent = "UnknownClient/0.0.1"
|
||||||
|
|
||||||
func GetDefaultSyncWorkerCount() int {
|
func GetDefaultSyncWorkerCount() int {
|
||||||
const minSyncWorkers = 16
|
const minSyncWorkers = 16
|
||||||
@ -91,5 +94,7 @@ func newDefaultSettings(gluonDir string) Settings {
|
|||||||
MaxSyncMemory: DefaultMaxSyncMemory,
|
MaxSyncMemory: DefaultMaxSyncMemory,
|
||||||
SyncWorkers: syncWorkers,
|
SyncWorkers: syncWorkers,
|
||||||
SyncAttPool: syncWorkers,
|
SyncAttPool: syncWorkers,
|
||||||
|
|
||||||
|
LastUserAgent: DefaultUserAgent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user