Avoid blocking UI during vault open and unlock
This commit is contained in:
+127
-40
@@ -32,6 +32,33 @@ type Manager struct {
|
||||
remoteVersion webdav.Version
|
||||
}
|
||||
|
||||
type PreparedLocalOpen struct {
|
||||
Model vault.Model
|
||||
Config *vault.KDBXConfig
|
||||
Path string
|
||||
Key vault.MasterKey
|
||||
Encoded []byte
|
||||
VaultRoot string
|
||||
}
|
||||
|
||||
type PreparedRemoteOpen struct {
|
||||
Model vault.Model
|
||||
Config *vault.KDBXConfig
|
||||
Client webdav.Client
|
||||
Path string
|
||||
Key vault.MasterKey
|
||||
Encoded []byte
|
||||
VaultRoot string
|
||||
RemoteVersion webdav.Version
|
||||
}
|
||||
|
||||
type PreparedUnlock struct {
|
||||
Model vault.Model
|
||||
Config *vault.KDBXConfig
|
||||
Key vault.MasterKey
|
||||
VaultRoot string
|
||||
}
|
||||
|
||||
func (m *Manager) SecuritySettings() vault.SecuritySettings {
|
||||
return vault.DetectSecuritySettings(m.config)
|
||||
}
|
||||
@@ -65,6 +92,10 @@ func (m *Manager) HasVault() bool {
|
||||
return len(m.encoded) > 0 || m.path != "" || m.remotePath != ""
|
||||
}
|
||||
|
||||
func (m *Manager) EncodedBytes() []byte {
|
||||
return append([]byte(nil), m.encoded...)
|
||||
}
|
||||
|
||||
func (m *Manager) IsLocked() bool {
|
||||
return m.locked
|
||||
}
|
||||
@@ -74,23 +105,11 @@ func (m *Manager) IsRemote() bool {
|
||||
}
|
||||
|
||||
func (m *Manager) Open(path string, key vault.MasterKey) error {
|
||||
content, err := os.ReadFile(path)
|
||||
prepared, err := PrepareLocalOpen(path, key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("read %s: %w", path, err)
|
||||
return err
|
||||
}
|
||||
|
||||
model, config, err := vault.LoadKDBXWithConfig(bytes.NewReader(content), key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open %s: %w", path, err)
|
||||
}
|
||||
|
||||
m.model = model
|
||||
m.config = config
|
||||
m.path = path
|
||||
m.key = key
|
||||
m.vaultRoot = detectSingleVaultRoot(model)
|
||||
m.encoded = content
|
||||
m.locked = false
|
||||
m.ApplyPreparedLocalOpen(prepared)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -107,25 +126,11 @@ func (m *Manager) Save() error {
|
||||
}
|
||||
|
||||
func (m *Manager) OpenRemote(client webdav.Client, path string, key vault.MasterKey) error {
|
||||
content, version, err := client.Open(path)
|
||||
prepared, err := PrepareRemoteOpen(client, path, key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open remote %s: %w", path, err)
|
||||
return err
|
||||
}
|
||||
|
||||
model, config, err := vault.LoadKDBXWithConfig(bytes.NewReader(content), key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("decode remote %s: %w", path, err)
|
||||
}
|
||||
|
||||
m.model = model
|
||||
m.config = config
|
||||
m.key = key
|
||||
m.vaultRoot = detectSingleVaultRoot(model)
|
||||
m.encoded = content
|
||||
m.locked = false
|
||||
m.remoteClient = &client
|
||||
m.remotePath = path
|
||||
m.remoteVersion = version
|
||||
m.ApplyPreparedRemoteOpen(prepared)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -265,19 +270,101 @@ func (m *Manager) Lock() error {
|
||||
}
|
||||
|
||||
func (m *Manager) Unlock(key vault.MasterKey) error {
|
||||
model, config, err := vault.LoadKDBXWithConfig(bytes.NewReader(m.encoded), key)
|
||||
prepared, err := PrepareUnlock(m.encoded, key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unlock vault: %w", err)
|
||||
return err
|
||||
}
|
||||
|
||||
m.model = model
|
||||
m.config = config
|
||||
m.key = key
|
||||
m.vaultRoot = detectSingleVaultRoot(model)
|
||||
m.locked = false
|
||||
m.ApplyPreparedUnlock(prepared)
|
||||
return nil
|
||||
}
|
||||
|
||||
func PrepareLocalOpen(path string, key vault.MasterKey) (PreparedLocalOpen, error) {
|
||||
content, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return PreparedLocalOpen{}, fmt.Errorf("read %s: %w", path, err)
|
||||
}
|
||||
model, config, err := vault.LoadKDBXWithConfig(bytes.NewReader(content), key)
|
||||
if err != nil {
|
||||
return PreparedLocalOpen{}, fmt.Errorf("open %s: %w", path, err)
|
||||
}
|
||||
return PreparedLocalOpen{
|
||||
Model: model,
|
||||
Config: config,
|
||||
Path: path,
|
||||
Key: key,
|
||||
Encoded: content,
|
||||
VaultRoot: detectSingleVaultRoot(model),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func PrepareRemoteOpen(client webdav.Client, path string, key vault.MasterKey) (PreparedRemoteOpen, error) {
|
||||
content, version, err := client.Open(path)
|
||||
if err != nil {
|
||||
return PreparedRemoteOpen{}, fmt.Errorf("open remote %s: %w", path, err)
|
||||
}
|
||||
model, config, err := vault.LoadKDBXWithConfig(bytes.NewReader(content), key)
|
||||
if err != nil {
|
||||
return PreparedRemoteOpen{}, fmt.Errorf("decode remote %s: %w", path, err)
|
||||
}
|
||||
return PreparedRemoteOpen{
|
||||
Model: model,
|
||||
Config: config,
|
||||
Client: client,
|
||||
Path: path,
|
||||
Key: key,
|
||||
Encoded: content,
|
||||
VaultRoot: detectSingleVaultRoot(model),
|
||||
RemoteVersion: version,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func PrepareUnlock(encoded []byte, key vault.MasterKey) (PreparedUnlock, error) {
|
||||
model, config, err := vault.LoadKDBXWithConfig(bytes.NewReader(encoded), key)
|
||||
if err != nil {
|
||||
return PreparedUnlock{}, fmt.Errorf("unlock vault: %w", err)
|
||||
}
|
||||
return PreparedUnlock{
|
||||
Model: model,
|
||||
Config: config,
|
||||
Key: key,
|
||||
VaultRoot: detectSingleVaultRoot(model),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *Manager) ApplyPreparedLocalOpen(prepared PreparedLocalOpen) {
|
||||
m.model = prepared.Model
|
||||
m.config = prepared.Config
|
||||
m.path = prepared.Path
|
||||
m.key = prepared.Key
|
||||
m.vaultRoot = prepared.VaultRoot
|
||||
m.encoded = prepared.Encoded
|
||||
m.locked = false
|
||||
m.remoteClient = nil
|
||||
m.remotePath = ""
|
||||
m.remoteVersion = webdav.Version{}
|
||||
}
|
||||
|
||||
func (m *Manager) ApplyPreparedRemoteOpen(prepared PreparedRemoteOpen) {
|
||||
m.model = prepared.Model
|
||||
m.config = prepared.Config
|
||||
m.key = prepared.Key
|
||||
m.vaultRoot = prepared.VaultRoot
|
||||
m.encoded = prepared.Encoded
|
||||
m.locked = false
|
||||
m.remoteClient = &prepared.Client
|
||||
m.remotePath = prepared.Path
|
||||
m.remoteVersion = prepared.RemoteVersion
|
||||
m.path = ""
|
||||
}
|
||||
|
||||
func (m *Manager) ApplyPreparedUnlock(prepared PreparedUnlock) {
|
||||
m.model = prepared.Model
|
||||
m.config = prepared.Config
|
||||
m.key = prepared.Key
|
||||
m.vaultRoot = prepared.VaultRoot
|
||||
m.locked = false
|
||||
}
|
||||
|
||||
func (m *Manager) ChangeMasterKey(key vault.MasterKey) error {
|
||||
var (
|
||||
model vault.Model
|
||||
|
||||
Reference in New Issue
Block a user