Introduce password store ID (#19)
This commit is contained in:
25
PROTOCOL.md
25
PROTOCOL.md
@@ -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"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@@ -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"
|
||||||
|
|
||||||
|
@@ -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,
|
||||||
},
|
},
|
||||||
|
@@ -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,
|
||||||
},
|
},
|
||||||
|
@@ -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)
|
||||||
|
@@ -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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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",
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user