Introduce password store ID (#19)

This commit is contained in:
Maxim Baz
2018-04-23 11:24:23 +02:00
committed by GitHub
parent ebfe600b0b
commit 81fe8db636
7 changed files with 62 additions and 49 deletions

View File

@@ -42,22 +42,22 @@ should be supplied as a `message` parameter.
## List of Error Codes ## List of Error Codes
| Code | Description | Parameters | | Code | Description | Parameters |
| ---- | ----------------------------------------------------------------------- | -------------------------------------------------- | | ---- | ----------------------------------------------------------------------- | ----------------------------------------------------------- |
| 10 | Unable to parse browser request length | message, error | | 10 | Unable to parse browser request length | message, error |
| 11 | Unable to parse browser request | message, error | | 11 | Unable to parse browser request | message, error |
| 12 | Invalid request action | message, action | | 12 | Invalid request action | message, action |
| 13 | Inaccessible user-configured password store | message, action, error, storePath, storeName | | 13 | Inaccessible user-configured password store | message, action, error, storeId, storePath, storeName |
| 14 | Inaccessible default password store | message, action, error, storePath | | 14 | Inaccessible default password store | message, action, error, storePath |
| 15 | Unable to determine the location of the default password store | message, action, error | | 15 | Unable to determine the location of the default password store | message, action, error |
| 16 | Unable to read the default settings of a user-configured password store | message, action, error, storePath, storeName | | 16 | Unable to read the default settings of a user-configured password store | message, action, error, storeId, storePath, storeName |
| 17 | Unable to read the default settings of the default password store | message, action, error, storePath | | 17 | Unable to read the default settings of the default password store | message, action, error, storePath |
| 18 | Unable to list files in a password store | message, action, error, storePath, storeName | | 18 | Unable to list files in a password store | message, action, error, storeId, storePath, storeName |
| 19 | Unable to determine a relative path for a file in a password store | message, action, error, storePath, storeName, file | | 19 | Unable to determine a relative path for a file in a password store | message, action, error, storeId, storePath, storeName, file |
| 20 | Invalid password store name | message, action, storeName | | 20 | Invalid password store ID | message, action, storeId |
| 21 | Invalid gpg path | message, action, error, gpgPath | | 21 | Invalid gpg path | message, action, error, gpgPath |
| 22 | Unable to detect the location of the gpg binary | message, action, error | | 22 | Unable to detect the location of the gpg binary | message, action, error |
| 23 | Invalid password file extension | message, action, file | | 23 | Invalid password file extension | message, action, file |
| 24 | Unable to decrypt the password file | message, action, error, storePath, storeName, file | | 24 | Unable to decrypt the password file | message, action, error, storeId, storePath, storeName, file |
## Settings ## Settings
@@ -87,8 +87,9 @@ Settings are applied using the following priority, highest first:
### Store-specific Settings ### Store-specific Settings
| Setting | Description | Default | | Setting | Description | Default |
| ------- | ------------------------------------ | ------- | | ------- | --------------------------------------- | ------- |
| name | Store name (same as the store key) | <key> | | id | Unique store id (same as the store key) | `<key>` |
| name | Store name (same as the store key) | `""` |
| path | Path to the password store directory | `""` | | path | Path to the password store directory | `""` |
## Actions ## Actions
@@ -121,7 +122,7 @@ is alive, determine the version at startup, and provide per-store defaults.
"settings": "<raw contents of $defaultPath/.browserpass.json>", "settings": "<raw contents of $defaultPath/.browserpass.json>",
}, },
“storeSettings”: { “storeSettings”: {
“storeName”: "<raw contents of storePath/.browserpass.json>" “storeId”: "<raw contents of storePath/.browserpass.json>"
} }
} }
} }
@@ -130,7 +131,7 @@ is alive, determine the version at startup, and provide per-store defaults.
### List ### List
Get a list of all `*.gpg` files for each of a provided array of directory paths. The `storeN` Get a list of all `*.gpg` files for each of a provided array of directory paths. The `storeN`
is the name of a password store, the key in `"settings.stores"` object. is the ID of a password store, the key in `"settings.stores"` object.
#### Request #### Request
@@ -166,7 +167,7 @@ Get the decrypted contents of a specific file.
{ {
"settings": <settings object>, "settings": <settings object>,
"action": "fetch", "action": "fetch",
"store": "<storeName>", "storeId": "<storeId>",
"file": "relative/path/to/file.gpg" "file": "relative/path/to/file.gpg"
} }
``` ```

View File

@@ -40,7 +40,7 @@ const (
// CodeUnableToDetermineRelativeFilePathInPasswordStore error determining a relative path for a file in a password store // CodeUnableToDetermineRelativeFilePathInPasswordStore error determining a relative path for a file in a password store
CodeUnableToDetermineRelativeFilePathInPasswordStore Code = 19 CodeUnableToDetermineRelativeFilePathInPasswordStore Code = 19
// CodeInvalidPasswordStore error looking for a password store with the given name // CodeInvalidPasswordStore error looking for a password store with the given ID
CodeInvalidPasswordStore Code = 20 CodeInvalidPasswordStore Code = 20
// CodeInvalidGpgPath error looking for a gpg binary at the given path // CodeInvalidGpgPath error looking for a gpg binary at the given path
@@ -69,6 +69,9 @@ const (
// FieldError an error message returned from an external system // FieldError an error message returned from an external system
FieldError Field = "error" FieldError Field = "error"
// FieldStoreID a password store id
FieldStoreID Field = "storeId"
// FieldStoreName a password store name // FieldStoreName a password store name
FieldStoreName Field = "storeName" FieldStoreName Field = "storeName"

View File

@@ -20,8 +20,8 @@ func configure(request *request) {
normalizedStorePath, err := normalizePasswordStorePath(store.Path) normalizedStorePath, err := normalizePasswordStorePath(store.Path)
if err != nil { if err != nil {
log.Errorf( log.Errorf(
"The password store '%v' is not accessible at the location '%v': %+v", "The password store '%+v' is not accessible at its location: %+v",
store.Name, store.Path, err, store, err,
) )
response.SendErrorAndExit( response.SendErrorAndExit(
errors.CodeInaccessiblePasswordStore, errors.CodeInaccessiblePasswordStore,
@@ -29,6 +29,7 @@ func configure(request *request) {
errors.FieldMessage: "The password store is not accessible", errors.FieldMessage: "The password store is not accessible",
errors.FieldAction: "configure", errors.FieldAction: "configure",
errors.FieldError: err.Error(), errors.FieldError: err.Error(),
errors.FieldStoreID: store.ID,
errors.FieldStoreName: store.Name, errors.FieldStoreName: store.Name,
errors.FieldStorePath: store.Path, errors.FieldStorePath: store.Path,
}, },
@@ -37,11 +38,11 @@ func configure(request *request) {
store.Path = normalizedStorePath store.Path = normalizedStorePath
responseData.StoreSettings[store.Name], err = readDefaultSettings(store.Path) responseData.StoreSettings[store.ID], err = readDefaultSettings(store.Path)
if err != nil { if err != nil {
log.Errorf( log.Errorf(
"Unable to read the default settings of the user-configured password store '%v' in '%v': %+v", "Unable to read the default settings of the user-configured password store '%+v' in its location: %+v",
store.Name, store.Path, err, store, err,
) )
response.SendErrorAndExit( response.SendErrorAndExit(
errors.CodeUnreadablePasswordStoreDefaultSettings, errors.CodeUnreadablePasswordStoreDefaultSettings,
@@ -49,6 +50,7 @@ func configure(request *request) {
errors.FieldMessage: "Unable to read the default settings of the password store", errors.FieldMessage: "Unable to read the default settings of the password store",
errors.FieldAction: "configure", errors.FieldAction: "configure",
errors.FieldError: err.Error(), errors.FieldError: err.Error(),
errors.FieldStoreID: store.ID,
errors.FieldStoreName: store.Name, errors.FieldStoreName: store.Name,
errors.FieldStorePath: store.Path, errors.FieldStorePath: store.Path,
}, },

View File

@@ -29,18 +29,18 @@ func fetchDecryptedContents(request *request) {
) )
} }
store, ok := request.Settings.Stores[request.Store] store, ok := request.Settings.Stores[request.StoreID]
if !ok { if !ok {
log.Errorf( log.Errorf(
"The password store '%v' is not present in the list of stores '%v'", "The password store with ID '%v' is not present in the list of stores '%+v'",
request.Store, request.Settings.Stores, request.StoreID, request.Settings.Stores,
) )
response.SendErrorAndExit( response.SendErrorAndExit(
errors.CodeInvalidPasswordStore, errors.CodeInvalidPasswordStore,
&map[errors.Field]string{ &map[errors.Field]string{
errors.FieldMessage: "The password store is not present in the list of stores", errors.FieldMessage: "The password store is not present in the list of stores",
errors.FieldAction: "fetch", errors.FieldAction: "fetch",
errors.FieldStoreName: request.Store, errors.FieldStoreID: request.StoreID,
}, },
) )
} }
@@ -48,8 +48,8 @@ func fetchDecryptedContents(request *request) {
normalizedStorePath, err := normalizePasswordStorePath(store.Path) normalizedStorePath, err := normalizePasswordStorePath(store.Path)
if err != nil { if err != nil {
log.Errorf( log.Errorf(
"The password store '%v' is not accessible at the location '%v': %+v", "The password store '%+v' is not accessible at its location: %+v",
store.Name, store.Path, err, store, err,
) )
response.SendErrorAndExit( response.SendErrorAndExit(
errors.CodeInaccessiblePasswordStore, errors.CodeInaccessiblePasswordStore,
@@ -57,6 +57,7 @@ func fetchDecryptedContents(request *request) {
errors.FieldMessage: "The password store is not accessible", errors.FieldMessage: "The password store is not accessible",
errors.FieldAction: "fetch", errors.FieldAction: "fetch",
errors.FieldError: err.Error(), errors.FieldError: err.Error(),
errors.FieldStoreID: store.ID,
errors.FieldStoreName: store.Name, errors.FieldStoreName: store.Name,
errors.FieldStorePath: store.Path, errors.FieldStorePath: store.Path,
}, },
@@ -100,8 +101,8 @@ func fetchDecryptedContents(request *request) {
responseData.Contents, err = decryptFile(&store, request.File, gpgPath) responseData.Contents, err = decryptFile(&store, request.File, gpgPath)
if err != nil { if err != nil {
log.Errorf( log.Errorf(
"Unable to decrypt the password file '%v' in the password store '%v' located in '%v': %+v", "Unable to decrypt the password file '%v' in the password store '%+v': %+v",
request.File, store.Name, store.Path, err, request.File, store, err,
) )
response.SendErrorAndExit( response.SendErrorAndExit(
errors.CodeUnableToDecryptPasswordFile, errors.CodeUnableToDecryptPasswordFile,
@@ -110,6 +111,7 @@ func fetchDecryptedContents(request *request) {
errors.FieldAction: "fetch", errors.FieldAction: "fetch",
errors.FieldError: err.Error(), errors.FieldError: err.Error(),
errors.FieldFile: request.File, errors.FieldFile: request.File,
errors.FieldStoreID: store.ID,
errors.FieldStoreName: store.Name, errors.FieldStoreName: store.Name,
errors.FieldStorePath: store.Path, errors.FieldStorePath: store.Path,
}, },

View File

@@ -17,8 +17,8 @@ func listFiles(request *request) {
normalizedStorePath, err := normalizePasswordStorePath(store.Path) normalizedStorePath, err := normalizePasswordStorePath(store.Path)
if err != nil { if err != nil {
log.Errorf( log.Errorf(
"The password store '%v' is not accessible at the location '%v': %+v", "The password store '%+v' is not accessible at its location: %+v",
store.Name, store.Path, err, store, err,
) )
response.SendErrorAndExit( response.SendErrorAndExit(
errors.CodeInaccessiblePasswordStore, errors.CodeInaccessiblePasswordStore,
@@ -26,6 +26,7 @@ func listFiles(request *request) {
errors.FieldMessage: "The password store is not accessible", errors.FieldMessage: "The password store is not accessible",
errors.FieldAction: "list", errors.FieldAction: "list",
errors.FieldError: err.Error(), errors.FieldError: err.Error(),
errors.FieldStoreID: store.ID,
errors.FieldStoreName: store.Name, errors.FieldStoreName: store.Name,
errors.FieldStorePath: store.Path, errors.FieldStorePath: store.Path,
}, },
@@ -37,8 +38,8 @@ func listFiles(request *request) {
files, err := zglob.GlobFollowSymlinks(filepath.Join(store.Path, "/**/*.gpg")) files, err := zglob.GlobFollowSymlinks(filepath.Join(store.Path, "/**/*.gpg"))
if err != nil { if err != nil {
log.Errorf( log.Errorf(
"Unable to list the files in the password store '%v' at the location '%v': %+v", "Unable to list the files in the password store '%+v' at its location: %+v",
store.Name, store.Path, err, store, err,
) )
response.SendErrorAndExit( response.SendErrorAndExit(
errors.CodeUnableToListFilesInPasswordStore, errors.CodeUnableToListFilesInPasswordStore,
@@ -46,6 +47,7 @@ func listFiles(request *request) {
errors.FieldMessage: "Unable to list the files in the password store", errors.FieldMessage: "Unable to list the files in the password store",
errors.FieldAction: "list", errors.FieldAction: "list",
errors.FieldError: err.Error(), errors.FieldError: err.Error(),
errors.FieldStoreID: store.ID,
errors.FieldStoreName: store.Name, errors.FieldStoreName: store.Name,
errors.FieldStorePath: store.Path, errors.FieldStorePath: store.Path,
}, },
@@ -56,8 +58,8 @@ func listFiles(request *request) {
relativePath, err := filepath.Rel(store.Path, file) relativePath, err := filepath.Rel(store.Path, file)
if err != nil { if err != nil {
log.Errorf( log.Errorf(
"Unable to determine the relative path for a file '%v' in the password store '%v' at the location '%v': %+v", "Unable to determine the relative path for a file '%v' in the password store '%+v': %+v",
file, store.Name, store.Path, err, file, store, err,
) )
response.SendErrorAndExit( response.SendErrorAndExit(
errors.CodeUnableToDetermineRelativeFilePathInPasswordStore, errors.CodeUnableToDetermineRelativeFilePathInPasswordStore,
@@ -66,6 +68,7 @@ func listFiles(request *request) {
errors.FieldAction: "list", errors.FieldAction: "list",
errors.FieldError: err.Error(), errors.FieldError: err.Error(),
errors.FieldFile: file, errors.FieldFile: file,
errors.FieldStoreID: store.ID,
errors.FieldStoreName: store.Name, errors.FieldStoreName: store.Name,
errors.FieldStorePath: store.Path, errors.FieldStorePath: store.Path,
}, },
@@ -75,7 +78,7 @@ func listFiles(request *request) {
} }
sort.Strings(files) sort.Strings(files)
responseData.Files[store.Name] = files responseData.Files[store.ID] = files
} }
response.SendOk(responseData) response.SendOk(responseData)

View File

@@ -12,6 +12,7 @@ import (
) )
type store struct { type store struct {
ID string `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Path string `json:"path"` Path string `json:"path"`
} }
@@ -25,7 +26,7 @@ type request struct {
Action string `json:"action"` Action string `json:"action"`
Settings settings `json:"settings"` Settings settings `json:"settings"`
File string `json:"file"` File string `json:"file"`
Store string `json:"store"` StoreID string `json:"storeId"`
EchoResponse interface{} `json:"echoResponse"` EchoResponse interface{} `json:"echoResponse"`
} }

View File

@@ -49,7 +49,8 @@ func Test_ParseRequest_CanParse(t *testing.T) {
Action: "list", Action: "list",
Settings: settings{ Settings: settings{
Stores: map[string]store{ Stores: map[string]store{
"default": store{ "id1": store{
ID: "id1",
Name: "default", Name: "default",
Path: "~/.password-store", Path: "~/.password-store",
}, },