mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-10 12:46:46 +00:00
GODT-1051: Add factory reset to bridge object
- remove deleted test no_internet.feature - clean up old remnants of import export - FactoryReset docstring
This commit is contained in:
@ -156,7 +156,7 @@ func (b *Bridge) SetUpdateChannel(channel updater.UpdateChannel) (needRestart bo
|
|||||||
|
|
||||||
// We have to deal right away only with downgrade - that action needs to
|
// We have to deal right away only with downgrade - that action needs to
|
||||||
// clear data and updates, and install bridge right away. But regular
|
// clear data and updates, and install bridge right away. But regular
|
||||||
// upgrade can be leaved out for periodic check.
|
// upgrade can be left out for periodic check.
|
||||||
if !b.updater.IsDowngrade(version) {
|
if !b.updater.IsDowngrade(version) {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
@ -164,6 +164,7 @@ func (b *Bridge) SetUpdateChannel(channel updater.UpdateChannel) (needRestart bo
|
|||||||
if err := b.Users.ClearData(); err != nil {
|
if err := b.Users.ClearData(); err != nil {
|
||||||
log.WithError(err).Error("Failed to clear data while downgrading channel")
|
log.WithError(err).Error("Failed to clear data while downgrading channel")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := b.locations.ClearUpdates(); err != nil {
|
if err := b.locations.ClearUpdates(); err != nil {
|
||||||
log.WithError(err).Error("Failed to clear updates while downgrading channel")
|
log.WithError(err).Error("Failed to clear updates while downgrading channel")
|
||||||
}
|
}
|
||||||
@ -175,6 +176,23 @@ func (b *Bridge) SetUpdateChannel(channel updater.UpdateChannel) (needRestart bo
|
|||||||
return true, b.versioner.RemoveOtherVersions(version.Version)
|
return true, b.versioner.RemoveOtherVersions(version.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FactoryReset will remove all local cache and settings.
|
||||||
|
// We want to downgrade to latest stable version if user is early higher than stable.
|
||||||
|
// Setting the channel back to stable will do this for us.
|
||||||
|
func (b *Bridge) FactoryReset() {
|
||||||
|
if _, err := b.SetUpdateChannel(updater.StableChannel); err != nil {
|
||||||
|
log.WithError(err).Error("Failed to revert to stable update channel")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := b.Users.ClearUsers(); err != nil {
|
||||||
|
log.WithError(err).Error("Failed to remove bridge users")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := b.Users.ClearData(); err != nil {
|
||||||
|
log.WithError(err).Error("Failed to remove bridge data")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GetKeychainApp returns current keychain helper.
|
// GetKeychainApp returns current keychain helper.
|
||||||
func (b *Bridge) GetKeychainApp() string {
|
func (b *Bridge) GetKeychainApp() string {
|
||||||
return b.settings.Get(settings.PreferredKeychainKey)
|
return b.settings.Get(settings.PreferredKeychainKey)
|
||||||
|
|||||||
@ -192,14 +192,34 @@ func (f *frontendCLI) deleteAccounts(c *ishell.Context) {
|
|||||||
if !f.yesNoQuestion("Do you really want remove all accounts") {
|
if !f.yesNoQuestion("Do you really want remove all accounts") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, user := range f.bridge.GetUsers() {
|
for _, user := range f.bridge.GetUsers() {
|
||||||
if err := f.bridge.DeleteUser(user.ID(), false); err != nil {
|
if err := f.bridge.DeleteUser(user.ID(), false); err != nil {
|
||||||
f.printAndLogError("Cannot delete account ", user.Username(), ": ", err)
|
f.printAndLogError("Cannot delete account ", user.Username(), ": ", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Println("Keychain cleared")
|
c.Println("Keychain cleared")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *frontendCLI) deleteEverything(c *ishell.Context) {
|
||||||
|
f.ShowPrompt(false)
|
||||||
|
defer f.ShowPrompt(true)
|
||||||
|
|
||||||
|
if !f.yesNoQuestion("Do you really want remove everything") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f.bridge.FactoryReset()
|
||||||
|
|
||||||
|
c.Println("Everything cleared")
|
||||||
|
|
||||||
|
// Clearing data removes everything (db, preferences, ...) so everything has to be stopped and started again.
|
||||||
|
f.restarter.SetToRestart()
|
||||||
|
|
||||||
|
f.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
func (f *frontendCLI) changeMode(c *ishell.Context) {
|
func (f *frontendCLI) changeMode(c *ishell.Context) {
|
||||||
user := f.askUserByIndexOrName(c)
|
user := f.askUserByIndexOrName(c)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
|
|||||||
@ -84,6 +84,11 @@ func New( //nolint[funlen]
|
|||||||
Aliases: []string{"a", "k", "keychain"},
|
Aliases: []string{"a", "k", "keychain"},
|
||||||
Func: fe.deleteAccounts,
|
Func: fe.deleteAccounts,
|
||||||
})
|
})
|
||||||
|
clearCmd.AddCmd(&ishell.Cmd{Name: "everything",
|
||||||
|
Help: "remove everything",
|
||||||
|
Aliases: []string{"a", "k", "keychain"},
|
||||||
|
Func: fe.deleteEverything,
|
||||||
|
})
|
||||||
fe.AddCmd(clearCmd)
|
fe.AddCmd(clearCmd)
|
||||||
|
|
||||||
// Change commands.
|
// Change commands.
|
||||||
|
|||||||
@ -58,14 +58,17 @@ func (f *frontendCLI) deleteCache(c *ishell.Context) {
|
|||||||
if !f.yesNoQuestion("Do you really want to remove all stored preferences") {
|
if !f.yesNoQuestion("Do you really want to remove all stored preferences") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := f.bridge.ClearData(); err != nil {
|
if err := f.bridge.ClearData(); err != nil {
|
||||||
f.printAndLogError("Cache clear failed: ", err.Error())
|
f.printAndLogError("Cache clear failed: ", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
f.Println("Cached cleared, restarting bridge")
|
f.Println("Cached cleared, restarting bridge")
|
||||||
// Clearing data removes everything (db, preferences, ...)
|
|
||||||
// so everything has to be stopped and started again.
|
// Clearing data removes everything (db, preferences, ...) so everything has to be stopped and started again.
|
||||||
f.restarter.SetToRestart()
|
f.restarter.SetToRestart()
|
||||||
|
|
||||||
f.Stop()
|
f.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -53,6 +53,8 @@ type UserManager interface {
|
|||||||
GetUser(query string) (User, error)
|
GetUser(query string) (User, error)
|
||||||
DeleteUser(userID string, clearCache bool) error
|
DeleteUser(userID string, clearCache bool) error
|
||||||
ClearData() error
|
ClearData() error
|
||||||
|
ClearUsers() error
|
||||||
|
FactoryReset()
|
||||||
}
|
}
|
||||||
|
|
||||||
// User is an interface of user needed by frontend.
|
// User is an interface of user needed by frontend.
|
||||||
|
|||||||
@ -73,28 +73,20 @@ func (l *Locations) getLicenseFilePath() string {
|
|||||||
|
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "linux":
|
case "linux":
|
||||||
appName := l.configName
|
|
||||||
if l.configName == "importExport" {
|
|
||||||
appName = "import-export"
|
|
||||||
}
|
|
||||||
// Most Linux distributions.
|
// Most Linux distributions.
|
||||||
path := "/usr/share/doc/protonmail/" + appName + "/LICENSE"
|
path := "/usr/share/doc/protonmail/" + l.configName + "/LICENSE"
|
||||||
if _, err := os.Stat(path); err == nil {
|
if _, err := os.Stat(path); err == nil {
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
// Arch distributions.
|
// Arch distributions.
|
||||||
return "/usr/share/licenses/protonmail-" + appName + "/LICENSE"
|
return "/usr/share/licenses/protonmail-" + l.configName + "/LICENSE"
|
||||||
case "darwin": //nolint[goconst]
|
case "darwin": //nolint[goconst]
|
||||||
path := filepath.Join(filepath.Dir(os.Args[0]), "..", "Resources", "LICENSE")
|
path := filepath.Join(filepath.Dir(os.Args[0]), "..", "Resources", "LICENSE")
|
||||||
if _, err := os.Stat(path); err == nil {
|
if _, err := os.Stat(path); err == nil {
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
appName := "ProtonMail Bridge.app"
|
return "/Applications/ProtonMail Bridge.app/Contents/Resources/LICENSE"
|
||||||
if l.configName == "importExport" {
|
|
||||||
appName = "ProtonMail Import-Export.app"
|
|
||||||
}
|
|
||||||
return "/Applications/" + appName + "/Contents/Resources/LICENSE"
|
|
||||||
case "windows":
|
case "windows":
|
||||||
path := filepath.Join(filepath.Dir(os.Args[0]), "LICENSE.txt")
|
path := filepath.Join(filepath.Dir(os.Args[0]), "LICENSE.txt")
|
||||||
if _, err := os.Stat(path); err == nil {
|
if _, err := os.Stat(path); err == nil {
|
||||||
@ -205,10 +197,10 @@ func (l *Locations) getUpdatesPath() string {
|
|||||||
// Clear removes everything except the lock and update files.
|
// Clear removes everything except the lock and update files.
|
||||||
func (l *Locations) Clear() error {
|
func (l *Locations) Clear() error {
|
||||||
return files.Remove(
|
return files.Remove(
|
||||||
l.getSettingsPath(),
|
l.userConfig,
|
||||||
l.getLogsPath(),
|
l.userCache,
|
||||||
l.getCachePath(),
|
|
||||||
).Except(
|
).Except(
|
||||||
|
l.GetLockFile(),
|
||||||
l.getUpdatesPath(),
|
l.getUpdatesPath(),
|
||||||
).Do()
|
).Do()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -331,6 +331,7 @@ func (u *Users) ClearData() error {
|
|||||||
if err := user.Logout(); err != nil {
|
if err := user.Logout(); err != nil {
|
||||||
result = multierror.Append(result, err)
|
result = multierror.Append(result, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := user.closeStore(); err != nil {
|
if err := user.closeStore(); err != nil {
|
||||||
result = multierror.Append(result, err)
|
result = multierror.Append(result, err)
|
||||||
}
|
}
|
||||||
@ -340,8 +341,7 @@ func (u *Users) ClearData() error {
|
|||||||
result = multierror.Append(result, err)
|
result = multierror.Append(result, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to clear imap cache otherwise fetch response will be remembered
|
// Need to clear imap cache otherwise fetch response will be remembered from previous test.
|
||||||
// from previous test
|
|
||||||
imapcache.Clear()
|
imapcache.Clear()
|
||||||
|
|
||||||
return result
|
return result
|
||||||
@ -385,6 +385,19 @@ func (u *Users) DeleteUser(userID string, clearStore bool) error {
|
|||||||
return errors.New("user " + userID + " not found")
|
return errors.New("user " + userID + " not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClearUsers deletes all users.
|
||||||
|
func (u *Users) ClearUsers() error {
|
||||||
|
var result error
|
||||||
|
|
||||||
|
for _, user := range u.GetUsers() {
|
||||||
|
if err := u.DeleteUser(user.ID(), false); err != nil {
|
||||||
|
result = multierror.Append(result, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// SendMetric sends a metric. We don't want to return any errors, only log them.
|
// SendMetric sends a metric. We don't want to return any errors, only log them.
|
||||||
func (u *Users) SendMetric(m metrics.Metric) error {
|
func (u *Users) SendMetric(m metrics.Metric) error {
|
||||||
cat, act, lab := m.Get()
|
cat, act, lab := m.Get()
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
Feature: Servers are closed when no internet
|
|
||||||
|
|
||||||
Scenario: All connection are closed and then restored multiple times
|
|
||||||
Given there is connected user "user"
|
|
||||||
And there is IMAP client "i1" logged in as "user"
|
|
||||||
And there is SMTP client "s1" logged in as "user"
|
|
||||||
When there is no internet connection
|
|
||||||
And 1 second pass
|
|
||||||
Then IMAP client "i1" is logged out
|
|
||||||
And SMTP client "s1" is logged out
|
|
||||||
Given the internet connection is restored
|
|
||||||
And 1 second pass
|
|
||||||
And there is IMAP client "i2" logged in as "user"
|
|
||||||
And there is SMTP client "s2" logged in as "user"
|
|
||||||
When IMAP client "i2" gets info of "INBOX"
|
|
||||||
When SMTP client "s2" sends "HELO example.com"
|
|
||||||
Then IMAP response to "i2" is "OK"
|
|
||||||
Then SMTP response to "s2" is "OK"
|
|
||||||
When there is no internet connection
|
|
||||||
And 1 second pass
|
|
||||||
Then IMAP client "i2" is logged out
|
|
||||||
And SMTP client "s2" is logged out
|
|
||||||
Given the internet connection is restored
|
|
||||||
And 1 second pass
|
|
||||||
And there is IMAP client "i3" logged in as "user"
|
|
||||||
And there is SMTP client "s3" logged in as "user"
|
|
||||||
When IMAP client "i3" gets info of "INBOX"
|
|
||||||
When SMTP client "s3" sends "HELO example.com"
|
|
||||||
Then IMAP response to "i3" is "OK"
|
|
||||||
Then SMTP response to "s3" is "OK"
|
|
||||||
@ -86,20 +86,13 @@ func (pc *persistentClient) GetEvent(ctx context.Context, eventID string) (*pmap
|
|||||||
func SetupPersistentClients() {
|
func SetupPersistentClients() {
|
||||||
app := os.Getenv("TEST_APP")
|
app := os.Getenv("TEST_APP")
|
||||||
|
|
||||||
persistentClients.manager = pmapi.New(pmapi.NewConfig(getAppVersionName(app), constants.Version))
|
persistentClients.manager = pmapi.New(pmapi.NewConfig(app, constants.Version))
|
||||||
persistentClients.manager.SetLogging(logrus.WithField("pkg", "liveapi"), logrus.GetLevel() == logrus.TraceLevel)
|
persistentClients.manager.SetLogging(logrus.WithField("pkg", "liveapi"), logrus.GetLevel() == logrus.TraceLevel)
|
||||||
|
|
||||||
persistentClients.byName = map[string]clientAuthGetter{}
|
persistentClients.byName = map[string]clientAuthGetter{}
|
||||||
persistentClients.saltByName = map[string]string{}
|
persistentClients.saltByName = map[string]string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAppVersionName(app string) string {
|
|
||||||
if app == "ie" {
|
|
||||||
return "importExport"
|
|
||||||
}
|
|
||||||
return app
|
|
||||||
}
|
|
||||||
|
|
||||||
func CleanupPersistentClients() {
|
func CleanupPersistentClients() {
|
||||||
for username, client := range persistentClients.byName {
|
for username, client := range persistentClients.byName {
|
||||||
if err := client.AuthDelete(context.Background()); err != nil {
|
if err := client.AuthDelete(context.Background()); err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user