142 lines
4.1 KiB
Go
142 lines
4.1 KiB
Go
package appstate
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"git.julianfamily.org/keepassgo/vault"
|
|
)
|
|
|
|
type SyncMode string
|
|
|
|
const (
|
|
SyncModeManual SyncMode = "manual"
|
|
SyncModeAutomaticOnOpenSave SyncMode = "automatic_on_open_save"
|
|
)
|
|
|
|
type RemoteBinding struct {
|
|
LocalVaultPath string `json:"localVaultPath"`
|
|
RemoteProfileID string `json:"remoteProfileId"`
|
|
CredentialEntryID string `json:"credentialEntryId"`
|
|
SyncMode SyncMode `json:"syncMode,omitempty"`
|
|
}
|
|
|
|
type ResolvedRemoteBinding struct {
|
|
Profile vault.RemoteProfile
|
|
Credentials vault.Entry
|
|
}
|
|
|
|
type RemoteBindingInput struct {
|
|
LocalVaultPath string
|
|
RemoteProfileID string
|
|
RemoteProfileName string
|
|
BaseURL string
|
|
RemotePath string
|
|
CredentialEntryID string
|
|
CredentialTitle string
|
|
Username string
|
|
Password string
|
|
CredentialPath []string
|
|
SyncMode SyncMode
|
|
}
|
|
|
|
func (b RemoteBinding) Resolve(model vault.Model) (ResolvedRemoteBinding, error) {
|
|
profile, err := model.RemoteProfileByID(b.RemoteProfileID)
|
|
if err != nil {
|
|
return ResolvedRemoteBinding{}, fmt.Errorf("resolve remote profile: %w", err)
|
|
}
|
|
credentials, err := model.EntryByID(b.CredentialEntryID)
|
|
if err != nil {
|
|
return ResolvedRemoteBinding{}, fmt.Errorf("resolve remote credentials: %w", err)
|
|
}
|
|
return ResolvedRemoteBinding{
|
|
Profile: profile,
|
|
Credentials: credentials,
|
|
}, nil
|
|
}
|
|
|
|
func ConfigureRemoteBinding(model *vault.Model, input RemoteBindingInput) (RemoteBinding, error) {
|
|
if model == nil {
|
|
return RemoteBinding{}, fmt.Errorf("model is required")
|
|
}
|
|
|
|
input.LocalVaultPath = strings.TrimSpace(input.LocalVaultPath)
|
|
input.RemoteProfileID = strings.TrimSpace(input.RemoteProfileID)
|
|
input.RemoteProfileName = strings.TrimSpace(input.RemoteProfileName)
|
|
input.BaseURL = strings.TrimSpace(input.BaseURL)
|
|
input.RemotePath = strings.TrimSpace(input.RemotePath)
|
|
input.CredentialEntryID = strings.TrimSpace(input.CredentialEntryID)
|
|
input.CredentialTitle = strings.TrimSpace(input.CredentialTitle)
|
|
input.Username = strings.TrimSpace(input.Username)
|
|
|
|
switch {
|
|
case input.LocalVaultPath == "":
|
|
return RemoteBinding{}, fmt.Errorf("local vault path is required")
|
|
case input.RemoteProfileID == "":
|
|
return RemoteBinding{}, fmt.Errorf("remote profile id is required")
|
|
case input.BaseURL == "":
|
|
return RemoteBinding{}, fmt.Errorf("remote base URL is required")
|
|
case input.RemotePath == "":
|
|
return RemoteBinding{}, fmt.Errorf("remote path is required")
|
|
case input.CredentialEntryID == "":
|
|
return RemoteBinding{}, fmt.Errorf("credential entry id is required")
|
|
case input.Password == "":
|
|
return RemoteBinding{}, fmt.Errorf("credential password is required")
|
|
}
|
|
|
|
if input.RemoteProfileName == "" {
|
|
input.RemoteProfileName = input.RemoteProfileID
|
|
}
|
|
if input.CredentialTitle == "" {
|
|
input.CredentialTitle = "Remote Sign-In"
|
|
}
|
|
|
|
model.UpsertRemoteProfile(vault.RemoteProfile{
|
|
ID: input.RemoteProfileID,
|
|
Name: input.RemoteProfileName,
|
|
Backend: vault.RemoteBackendWebDAV,
|
|
BaseURL: input.BaseURL,
|
|
Path: input.RemotePath,
|
|
})
|
|
model.UpsertEntry(vault.Entry{
|
|
ID: input.CredentialEntryID,
|
|
Title: input.CredentialTitle,
|
|
Username: input.Username,
|
|
Password: input.Password,
|
|
URL: input.BaseURL,
|
|
Path: append([]string(nil), input.CredentialPath...),
|
|
})
|
|
|
|
return RemoteBinding{
|
|
LocalVaultPath: input.LocalVaultPath,
|
|
RemoteProfileID: input.RemoteProfileID,
|
|
CredentialEntryID: input.CredentialEntryID,
|
|
SyncMode: normalizeSyncMode(input.SyncMode),
|
|
}, nil
|
|
}
|
|
|
|
func RemoveRemoteBinding(model *vault.Model, binding RemoteBinding) error {
|
|
if model == nil {
|
|
return fmt.Errorf("model is required")
|
|
}
|
|
if strings.TrimSpace(binding.RemoteProfileID) == "" {
|
|
return fmt.Errorf("remote profile id is required")
|
|
}
|
|
if strings.TrimSpace(binding.CredentialEntryID) == "" {
|
|
return fmt.Errorf("credential entry id is required")
|
|
}
|
|
|
|
model.RemoveRemoteProfileByID(binding.RemoteProfileID)
|
|
model.RemoveEntryByID(binding.CredentialEntryID)
|
|
return nil
|
|
}
|
|
|
|
func normalizeSyncMode(mode SyncMode) SyncMode {
|
|
switch mode {
|
|
case SyncModeAutomaticOnOpenSave:
|
|
return SyncModeAutomaticOnOpenSave
|
|
default:
|
|
return SyncModeManual
|
|
}
|
|
}
|