2024-01-02 13:32:11 +00:00
// Copyright (c) 2024 Proton AG
2022-10-13 08:58:11 +00:00
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
2022-08-26 15:00:21 +00:00
package app
import (
"fmt"
2023-06-28 11:34:19 +00:00
"io"
2022-10-11 17:40:28 +00:00
"net/http"
"net/http/cookiejar"
2023-04-20 13:24:16 +00:00
"net/url"
2022-10-13 01:04:02 +00:00
"os"
2022-08-26 15:00:21 +00:00
"path/filepath"
2022-10-13 02:08:44 +00:00
"runtime"
2024-01-05 08:30:13 +00:00
"time"
2022-08-26 15:00:21 +00:00
2022-10-12 21:30:43 +00:00
"github.com/Masterminds/semver/v3"
2023-04-04 13:27:03 +00:00
"github.com/ProtonMail/gluon/async"
2022-11-23 14:25:41 +00:00
"github.com/ProtonMail/proton-bridge/v3/internal/bridge"
"github.com/ProtonMail/proton-bridge/v3/internal/constants"
"github.com/ProtonMail/proton-bridge/v3/internal/cookies"
"github.com/ProtonMail/proton-bridge/v3/internal/crash"
"github.com/ProtonMail/proton-bridge/v3/internal/events"
"github.com/ProtonMail/proton-bridge/v3/internal/focus"
2023-04-20 13:24:16 +00:00
"github.com/ProtonMail/proton-bridge/v3/internal/frontend/theme"
2022-11-23 14:25:41 +00:00
"github.com/ProtonMail/proton-bridge/v3/internal/locations"
"github.com/ProtonMail/proton-bridge/v3/internal/logging"
"github.com/ProtonMail/proton-bridge/v3/internal/sentry"
"github.com/ProtonMail/proton-bridge/v3/internal/useragent"
"github.com/ProtonMail/proton-bridge/v3/internal/vault"
2023-11-08 13:05:57 +00:00
"github.com/ProtonMail/proton-bridge/v3/pkg/keychain"
2022-11-23 14:25:41 +00:00
"github.com/ProtonMail/proton-bridge/v3/pkg/restarter"
2022-08-26 15:00:21 +00:00
"github.com/pkg/profile"
2022-10-11 17:40:28 +00:00
"github.com/sirupsen/logrus"
2022-08-26 15:00:21 +00:00
"github.com/urfave/cli/v2"
)
2022-10-18 11:54:12 +00:00
// Visible flags.
2022-08-26 15:00:21 +00:00
const (
flagCPUProfile = "cpu-prof"
flagCPUProfileShort = "p"
2023-08-28 09:23:41 +00:00
flagTraceProfile = "trace-prof"
flagTraceProfileShort = "t"
2022-08-26 15:00:21 +00:00
flagMemProfile = "mem-prof"
flagMemProfileShort = "m"
flagLogLevel = "log-level"
flagLogLevelShort = "l"
2022-11-04 00:10:23 +00:00
flagGRPC = "grpc"
flagGRPCShort = "g"
2022-08-26 15:00:21 +00:00
flagCLI = "cli"
flagCLIShort = "c"
2022-11-04 00:10:23 +00:00
flagNonInteractive = "noninteractive"
flagNonInteractiveShort = "n"
2022-10-11 14:03:28 +00:00
flagLogIMAP = "log-imap"
flagLogSMTP = "log-smtp"
2022-10-11 22:20:04 +00:00
)
2022-10-12 13:22:02 +00:00
2022-10-18 11:54:12 +00:00
// Hidden flags.
2022-10-11 22:20:04 +00:00
const (
2023-01-03 16:54:57 +00:00
flagLauncher = "launcher"
flagNoWindow = "no-window"
flagParentPID = "parent-pid"
flagSoftwareRenderer = "software-renderer"
2023-06-06 13:44:33 +00:00
flagSessionID = "session-id"
2022-08-26 15:00:21 +00:00
)
const (
2023-06-06 13:44:33 +00:00
appUsage = "Proton Mail IMAP and SMTP Bridge"
appShortName = "bridge"
2022-08-26 15:00:21 +00:00
)
2023-02-03 15:18:25 +00:00
func New ( ) * cli . App {
2022-08-26 15:00:21 +00:00
app := cli . NewApp ( )
app . Name = constants . FullAppName
app . Usage = appUsage
app . Flags = [ ] cli . Flag {
& cli . BoolFlag {
Name : flagCPUProfile ,
Aliases : [ ] string { flagCPUProfileShort } ,
Usage : "Generate CPU profile" ,
} ,
2023-08-28 09:23:41 +00:00
& cli . BoolFlag {
Name : flagTraceProfile ,
Aliases : [ ] string { flagTraceProfileShort } ,
Usage : "Generate Trace profile" ,
} ,
2022-08-26 15:00:21 +00:00
& cli . BoolFlag {
Name : flagMemProfile ,
Aliases : [ ] string { flagMemProfileShort } ,
Usage : "Generate memory profile" ,
} ,
& cli . StringFlag {
Name : flagLogLevel ,
Aliases : [ ] string { flagLogLevelShort } ,
Usage : "Set the log level (one of panic, fatal, error, warn, info, debug)" ,
} ,
2022-11-04 00:10:23 +00:00
& cli . BoolFlag {
Name : flagGRPC ,
Aliases : [ ] string { flagGRPCShort } ,
Usage : "Start the gRPC service" ,
} ,
2022-08-26 15:00:21 +00:00
& cli . BoolFlag {
Name : flagCLI ,
Aliases : [ ] string { flagCLIShort } ,
2022-11-04 00:10:23 +00:00
Usage : "Start the command line interface" ,
2022-08-26 15:00:21 +00:00
} ,
& cli . BoolFlag {
2022-11-04 00:10:23 +00:00
Name : flagNonInteractive ,
Aliases : [ ] string { flagNonInteractiveShort } ,
Usage : "Start the app in non-interactive mode" ,
2022-08-26 15:00:21 +00:00
} ,
2022-10-11 14:03:28 +00:00
& cli . StringFlag {
Name : flagLogIMAP ,
Usage : "Enable logging of IMAP communications (all|client|server) (may contain decrypted data!)" ,
} ,
& cli . BoolFlag {
Name : flagLogSMTP ,
Usage : "Enable logging of SMTP communications (may contain decrypted data!)" ,
} ,
2022-10-12 13:22:02 +00:00
// Hidden flags
& cli . BoolFlag {
Name : flagNoWindow ,
Usage : "Don't show window after start" ,
Hidden : true ,
} ,
2022-10-13 02:15:25 +00:00
& cli . StringFlag {
2022-10-12 13:22:02 +00:00
Name : flagLauncher ,
Usage : "The launcher used to start the app" ,
Hidden : true ,
} ,
2022-11-16 14:21:33 +00:00
& cli . IntFlag {
Name : flagParentPID ,
Usage : "Process ID of the parent" ,
Hidden : true ,
2022-11-17 12:32:13 +00:00
Value : - 1 ,
2022-11-16 14:21:33 +00:00
} ,
2023-01-03 16:54:57 +00:00
& cli . BoolFlag {
Name : flagSoftwareRenderer , // This flag is ignored by bridge, but should be passed to launcher in case of restart, so it need to be accepted by the CLI parser.
Usage : "GUI is using software renderer" ,
Hidden : true ,
Value : false ,
} ,
2023-06-06 13:44:33 +00:00
& cli . StringFlag {
Name : flagSessionID ,
Hidden : true ,
} ,
2022-08-26 15:00:21 +00:00
}
app . Action = run
return app
}
2023-02-03 15:18:25 +00:00
func run ( c * cli . Context ) error {
2022-10-12 21:30:43 +00:00
// Get the current bridge version.
version , err := semver . NewVersion ( constants . Version )
if err != nil {
return fmt . Errorf ( "could not create version: %w" , err )
2022-08-26 15:00:21 +00:00
}
2022-10-11 17:40:28 +00:00
// Create a user agent that will be used for all requests.
identifier := useragent . New ( )
// Create a new Sentry client that will be used to report crashes etc.
2023-02-14 16:27:55 +00:00
reporter := sentry . NewReporter ( constants . FullAppName , identifier )
2022-10-11 17:40:28 +00:00
2022-10-13 01:04:02 +00:00
// Determine the exe that should be used to restart/autostart the app.
// By default, this is the launcher, if used. Otherwise, we try to get
// the current exe, and fall back to os.Args[0] if that fails.
var exe string
if launcher := c . String ( flagLauncher ) ; launcher != "" {
exe = launcher
} else if executable , err := os . Executable ( ) ; err == nil {
exe = executable
} else {
exe = os . Args [ 0 ]
}
2023-06-28 11:34:19 +00:00
var logCloser io . Closer
defer func ( ) {
_ = logging . Close ( logCloser )
} ( )
2023-03-22 16:18:17 +00:00
// Restart the app if requested.
2023-11-02 13:17:35 +00:00
err = withRestarter ( exe , func ( restarter * restarter . Restarter ) error {
2023-03-22 16:18:17 +00:00
// Handle crashes with various actions.
return withCrashHandler ( restarter , reporter , func ( crashHandler * crash . Handler , quitCh <- chan struct { } ) error {
migrationErr := migrateOldVersions ( )
// Run with profiling if requested.
return withProfiler ( c , func ( ) error {
2022-10-11 17:40:28 +00:00
// Load the locations where we store our files.
2022-10-26 08:11:25 +00:00
return WithLocations ( func ( locations * locations . Locations ) error {
2022-11-21 00:38:51 +00:00
// Migrate the keychain helper.
if err := migrateKeychainHelper ( locations ) ; err != nil {
logrus . WithError ( err ) . Error ( "Failed to migrate keychain helper" )
}
2022-10-12 21:30:43 +00:00
// Initialize logging.
2023-06-28 11:34:19 +00:00
return withLogging ( c , crashHandler , locations , func ( closer io . Closer ) error {
logCloser = closer
2022-11-17 12:32:13 +00:00
// If there was an error during migration, log it now.
2022-11-14 10:42:24 +00:00
if migrationErr != nil {
2022-11-17 12:32:13 +00:00
logrus . WithError ( migrationErr ) . Error ( "Failed to migrate old app data" )
2022-11-14 10:42:24 +00:00
}
2022-11-17 12:32:13 +00:00
2022-10-12 21:30:43 +00:00
// Ensure we are the only instance running.
2023-02-08 10:06:53 +00:00
settings , err := locations . ProvideSettingsPath ( )
if err != nil {
logrus . WithError ( err ) . Error ( "Failed to get settings path" )
}
return withSingleInstance ( settings , locations . GetLockFile ( ) , version , func ( ) error {
2023-11-08 13:05:57 +00:00
// Look for available keychains
2023-12-14 15:41:00 +00:00
return WithKeychainList ( crashHandler , func ( keychains * keychain . List ) error {
2023-11-08 13:05:57 +00:00
// Unlock the encrypted vault.
return WithVault ( locations , keychains , crashHandler , func ( v * vault . Vault , insecure , corrupt bool ) error {
if ! v . Migrated ( ) {
// Migrate old settings into the vault.
if err := migrateOldSettings ( v ) ; err != nil {
logrus . WithError ( err ) . Error ( "Failed to migrate old settings" )
2022-11-17 12:32:13 +00:00
}
2023-11-08 13:05:57 +00:00
// Migrate old accounts into the vault.
if err := migrateOldAccounts ( locations , keychains , v ) ; err != nil {
logrus . WithError ( err ) . Error ( "Failed to migrate old accounts" )
2022-11-17 12:32:13 +00:00
}
2023-04-21 08:06:01 +00:00
2023-11-08 13:05:57 +00:00
// The vault has been migrated.
if err := v . SetMigrated ( ) ; err != nil {
logrus . WithError ( err ) . Error ( "Failed to mark vault as migrated" )
}
}
2022-11-17 12:32:13 +00:00
2023-11-08 13:05:57 +00:00
logrus . WithFields ( logrus . Fields {
"lastVersion" : v . GetLastVersion ( ) . String ( ) ,
"showAllMail" : v . GetShowAllMail ( ) ,
"updateCh" : v . GetUpdateChannel ( ) ,
"autoUpdate" : v . GetAutoUpdate ( ) ,
"rollout" : v . GetUpdateRollout ( ) ,
"DoH" : v . GetProxyAllowed ( ) ,
} ) . Info ( "Vault loaded" )
// Load the cookies from the vault.
return withCookieJar ( v , func ( cookieJar http . CookieJar ) error {
// Create a new bridge instance.
return withBridge ( c , exe , locations , version , identifier , crashHandler , reporter , v , cookieJar , keychains , func ( b * bridge . Bridge , eventCh <- chan events . Event ) error {
if insecure {
logrus . Warn ( "The vault key could not be retrieved; the vault will not be encrypted" )
b . PushError ( bridge . ErrVaultInsecure )
}
if corrupt {
logrus . Warn ( "The vault is corrupt and has been wiped" )
b . PushError ( bridge . ErrVaultCorrupt )
}
// Remove old updates files
b . RemoveOldUpdates ( )
// Run the frontend.
return runFrontend ( c , crashHandler , restarter , locations , b , eventCh , quitCh , c . Int ( flagParentPID ) )
} )
2022-11-17 12:32:13 +00:00
} )
2022-10-12 21:30:43 +00:00
} )
2022-10-11 17:40:28 +00:00
} )
} )
} )
} )
} )
} )
} )
2023-11-02 13:17:35 +00:00
// if an error occurs, it must be logged now because we're about to close the log file.
if err != nil {
logrus . Fatal ( err )
}
return err
2022-10-11 17:40:28 +00:00
}
2022-10-12 21:30:43 +00:00
// If there's another instance already running, try to raise it and exit.
2023-02-08 10:06:53 +00:00
func withSingleInstance ( settingPath , lockFile string , version * semver . Version , fn func ( ) error ) error {
2022-11-01 14:00:52 +00:00
logrus . Debug ( "Checking for other instances" )
2022-11-22 11:59:07 +00:00
defer logrus . Debug ( "Single instance stopped" )
2022-11-01 14:00:52 +00:00
2023-02-08 10:06:53 +00:00
lock , err := checkSingleInstance ( settingPath , lockFile , version )
2022-10-12 21:30:43 +00:00
if err != nil {
2022-11-01 11:54:38 +00:00
logrus . Info ( "Another instance is already running; raising it" )
2023-02-08 10:06:53 +00:00
if ok := focus . TryRaise ( settingPath ) ; ! ok {
2022-10-12 21:30:43 +00:00
return fmt . Errorf ( "another instance is already running but it could not be raised" )
}
2022-11-01 11:54:38 +00:00
logrus . Info ( "The other instance has been raised" )
2022-10-12 21:30:43 +00:00
return nil
}
defer func ( ) {
if err := lock . Close ( ) ; err != nil {
logrus . WithError ( err ) . Error ( "Failed to close lock file" )
}
} ( )
return fn ( )
}
// Initialize our logging system.
2023-06-28 11:34:19 +00:00
func withLogging ( c * cli . Context , crashHandler * crash . Handler , locations * locations . Locations , fn func ( closer io . Closer ) error ) error {
2022-11-22 11:59:07 +00:00
logrus . Debug ( "Initializing logging" )
defer logrus . Debug ( "Logging stopped" )
2022-10-13 02:24:52 +00:00
// Get a place to keep our logs.
logsPath , err := locations . ProvideLogsPath ( )
if err != nil {
return fmt . Errorf ( "could not provide logs path: %w" , err )
}
2022-11-22 11:59:07 +00:00
logrus . WithField ( "path" , logsPath ) . Debug ( "Received logs path" )
2022-11-01 14:00:52 +00:00
2022-10-13 02:24:52 +00:00
// Initialize logging.
2023-06-06 13:44:33 +00:00
sessionID := logging . NewSessionIDFromString ( c . String ( flagSessionID ) )
2023-06-28 11:34:19 +00:00
var closer io . Closer
if closer , err = logging . Init (
2023-06-07 16:00:29 +00:00
logsPath ,
sessionID ,
logging . BridgeShortAppName ,
logging . DefaultMaxLogFileSize ,
logging . DefaultPruningSize ,
c . String ( flagLogLevel ) ,
) ; err != nil {
2022-10-12 21:30:43 +00:00
return fmt . Errorf ( "could not initialize logging: %w" , err )
}
2022-10-13 02:24:52 +00:00
// Ensure we dump a stack trace if we crash.
2023-06-06 13:44:33 +00:00
crashHandler . AddRecoveryAction ( logging . DumpStackTrace ( logsPath , sessionID , appShortName ) )
2022-10-13 02:24:52 +00:00
2022-10-13 02:08:44 +00:00
logrus .
WithField ( "appName" , constants . FullAppName ) .
WithField ( "version" , constants . Version ) .
WithField ( "revision" , constants . Revision ) .
2023-05-26 13:07:35 +00:00
WithField ( "tag" , constants . Tag ) .
2022-10-13 02:08:44 +00:00
WithField ( "build" , constants . BuildTime ) .
WithField ( "runtime" , runtime . GOOS ) .
WithField ( "args" , os . Args ) .
2023-05-31 06:40:15 +00:00
WithField ( "SentryID" , sentry . GetProtectedHostname ( ) ) .
2022-10-13 02:08:44 +00:00
Info ( "Run app" )
2022-10-12 21:30:43 +00:00
2024-01-05 08:30:13 +00:00
now := time . Now ( )
logrus .
WithField ( "timeZone" , now . Format ( "MST" ) ) .
WithField ( "offset" , now . Format ( "-07:00:00" ) ) .
Info ( "Time zone info" )
2023-06-28 11:34:19 +00:00
return fn ( closer )
2022-10-12 21:30:43 +00:00
}
2022-10-26 08:11:25 +00:00
// WithLocations provides access to locations where we store our files.
func WithLocations ( fn func ( * locations . Locations ) error ) error {
2022-11-01 14:00:52 +00:00
logrus . Debug ( "Creating locations" )
2022-11-22 11:59:07 +00:00
defer logrus . Debug ( "Locations stopped" )
2022-11-01 14:00:52 +00:00
2022-10-11 17:40:28 +00:00
// Create a locations provider to determine where to store our files.
provider , err := locations . NewDefaultProvider ( filepath . Join ( constants . VendorName , constants . ConfigName ) )
if err != nil {
return fmt . Errorf ( "could not create locations provider: %w" , err )
}
// Create a new locations object that will be used to provide paths to store files.
2023-01-18 07:43:45 +00:00
return fn ( locations . New ( provider , constants . ConfigName ) )
2022-10-11 17:40:28 +00:00
}
2022-10-12 21:30:43 +00:00
// Start profiling if requested.
2022-10-11 17:40:28 +00:00
func withProfiler ( c * cli . Context , fn func ( ) error ) error {
2022-11-22 11:59:07 +00:00
defer logrus . Debug ( "Profiler stopped" )
2022-08-26 15:00:21 +00:00
if c . Bool ( flagCPUProfile ) {
2022-11-01 14:00:52 +00:00
logrus . Debug ( "Running with CPU profiling" )
2022-10-11 17:40:28 +00:00
defer profile . Start ( profile . CPUProfile , profile . ProfilePath ( "." ) ) . Stop ( )
2022-08-26 15:00:21 +00:00
}
2023-08-28 09:23:41 +00:00
if c . Bool ( flagTraceProfile ) {
logrus . Debug ( "Running with Trace profiling" )
defer profile . Start ( profile . TraceProfile , profile . ProfilePath ( "." ) ) . Stop ( )
}
2022-08-26 15:00:21 +00:00
if c . Bool ( flagMemProfile ) {
2022-11-01 14:00:52 +00:00
logrus . Debug ( "Running with memory profiling" )
2022-10-11 17:40:28 +00:00
defer profile . Start ( profile . MemProfile , profile . MemProfileAllocs , profile . ProfilePath ( "." ) ) . Stop ( )
2022-08-26 15:00:21 +00:00
}
2022-10-11 17:40:28 +00:00
return fn ( )
}
2022-10-12 21:30:43 +00:00
// Restart the app if necessary.
2022-10-13 01:04:02 +00:00
func withRestarter ( exe string , fn func ( * restarter . Restarter ) error ) error {
2022-11-01 14:00:52 +00:00
logrus . Debug ( "Creating restarter" )
2022-11-22 11:59:07 +00:00
defer logrus . Debug ( "Restarter stopped" )
2022-11-01 14:00:52 +00:00
2022-10-13 01:04:02 +00:00
restarter := restarter . New ( exe )
2022-08-26 15:00:21 +00:00
defer restarter . Restart ( )
2022-10-11 17:40:28 +00:00
return fn ( restarter )
}
2022-08-26 15:00:21 +00:00
2022-10-12 21:30:43 +00:00
// Handle crashes if they occur.
2022-11-22 11:59:07 +00:00
func withCrashHandler ( restarter * restarter . Restarter , reporter * sentry . Reporter , fn func ( * crash . Handler , <- chan struct { } ) error ) error {
2022-11-01 14:00:52 +00:00
logrus . Debug ( "Creating crash handler" )
2022-11-22 11:59:07 +00:00
defer logrus . Debug ( "Crash handler stopped" )
2022-11-01 14:00:52 +00:00
2022-10-11 17:40:28 +00:00
crashHandler := crash . NewHandler ( crash . ShowErrorNotification ( constants . FullAppName ) )
2023-04-04 13:27:03 +00:00
defer async . HandlePanic ( crashHandler )
2022-08-26 15:00:21 +00:00
2022-10-11 17:40:28 +00:00
// On crash, send crash report to Sentry.
crashHandler . AddRecoveryAction ( reporter . ReportException )
2022-08-26 15:00:21 +00:00
2022-10-11 17:40:28 +00:00
// On crash, notify the user and restart the app.
crashHandler . AddRecoveryAction ( crash . ShowErrorNotification ( constants . FullAppName ) )
2022-08-26 15:00:21 +00:00
2022-10-11 17:40:28 +00:00
// On crash, restart the app.
2022-11-01 14:00:52 +00:00
crashHandler . AddRecoveryAction ( func ( any ) error { restarter . Set ( true , true ) ; return nil } )
2022-10-11 17:40:28 +00:00
2022-11-22 11:59:07 +00:00
// quitCh is closed when the app is quitting.
quitCh := make ( chan struct { } )
// On crash, quit the app.
crashHandler . AddRecoveryAction ( func ( any ) error { close ( quitCh ) ; return nil } )
return fn ( crashHandler , quitCh )
2022-10-11 17:40:28 +00:00
}
2022-08-26 15:00:21 +00:00
2022-10-12 21:30:43 +00:00
// Use a custom cookie jar to persist values across runs.
2022-10-11 17:40:28 +00:00
func withCookieJar ( vault * vault . Vault , fn func ( http . CookieJar ) error ) error {
2022-11-01 14:00:52 +00:00
logrus . Debug ( "Creating cookie jar" )
2022-11-22 11:59:07 +00:00
defer logrus . Debug ( "Cookie jar stopped" )
2022-11-01 14:00:52 +00:00
2022-10-11 17:40:28 +00:00
// Create the underlying cookie jar.
jar , err := cookiejar . New ( nil )
2022-08-26 15:00:21 +00:00
if err != nil {
2022-10-11 17:40:28 +00:00
return fmt . Errorf ( "could not create cookie jar: %w" , err )
2022-08-26 15:00:21 +00:00
}
2022-10-11 17:40:28 +00:00
// Create the cookie jar which persists to the vault.
persister , err := cookies . NewCookieJar ( jar , vault )
if err != nil {
return fmt . Errorf ( "could not create cookie jar: %w" , err )
}
2022-08-26 15:00:21 +00:00
2023-04-20 13:24:16 +00:00
if err := setDeviceCookies ( persister ) ; err != nil {
return fmt . Errorf ( "could not set device cookies: %w" , err )
}
2022-10-11 17:40:28 +00:00
// Persist the cookies to the vault when we close.
defer func ( ) {
2022-11-01 14:00:52 +00:00
logrus . Debug ( "Persisting cookies" )
2022-10-11 17:40:28 +00:00
if err := persister . PersistCookies ( ) ; err != nil {
logrus . WithError ( err ) . Error ( "Failed to persist cookies" )
2022-08-26 15:00:21 +00:00
}
2022-10-11 17:40:28 +00:00
} ( )
2022-08-26 15:00:21 +00:00
2022-10-11 17:40:28 +00:00
return fn ( persister )
2022-08-26 15:00:21 +00:00
}
2023-04-20 13:24:16 +00:00
2023-11-13 13:58:03 +00:00
// WithKeychainList init the list of usable keychains.
2023-12-14 15:41:00 +00:00
func WithKeychainList ( panicHandler async . PanicHandler , fn func ( * keychain . List ) error ) error {
2023-11-08 13:05:57 +00:00
logrus . Debug ( "Creating keychain list" )
defer logrus . Debug ( "Keychain list stop" )
2023-12-14 15:41:00 +00:00
defer async . HandlePanic ( panicHandler )
2023-11-08 13:05:57 +00:00
return fn ( keychain . NewList ( ) )
}
2023-04-20 13:24:16 +00:00
func setDeviceCookies ( jar * cookies . Jar ) error {
url , err := url . Parse ( constants . APIHost )
if err != nil {
return err
}
for name , value := range map [ string ] string {
"hhn" : sentry . GetProtectedHostname ( ) ,
"tz" : sentry . GetTimeZone ( ) ,
"lng" : sentry . GetSystemLang ( ) ,
"clr" : string ( theme . DefaultTheme ( ) ) ,
} {
jar . SetCookies ( url , [ ] * http . Cookie { { Name : name , Value : value , Secure : true } } )
}
return nil
}