Implement list
action (#12)
This commit is contained in:
11
Gopkg.lock
generated
11
Gopkg.lock
generated
@@ -1,6 +1,15 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mattn/go-zglob"
|
||||
packages = [
|
||||
".",
|
||||
"fastwalk"
|
||||
]
|
||||
revision = "4959821b481786922ac53e7ef25c61ae19fb7c36"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/rifflock/lfshook"
|
||||
packages = ["."]
|
||||
@@ -34,6 +43,6 @@
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "f6199a143c790c5c1422bd35477ede08e5d2e3a0e5552d769e7c4de6ed8a14b1"
|
||||
inputs-digest = "1f59ddaed2db7de2b34f8485550888fa1cb625342398af10acb68e5ee227f3f8"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
@@ -27,3 +27,7 @@
|
||||
[[constraint]]
|
||||
name = "github.com/rifflock/lfshook"
|
||||
version = "2.3.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/mattn/go-zglob"
|
||||
|
24
PROTOCOL.md
24
PROTOCOL.md
@@ -41,16 +41,18 @@ should be supplied as a `message` parameter.
|
||||
|
||||
## List of Error Codes
|
||||
|
||||
| Code | Description | Parameters |
|
||||
| ---- | ----------------------------------------------------------------------- | ----------------- |
|
||||
| 10 | Unable to parse browser request length | error |
|
||||
| 11 | Unable to parse browser request | error |
|
||||
| 12 | Invalid request action | action |
|
||||
| 13 | Inaccessible user-configured password store | error, name, path |
|
||||
| 14 | Inaccessible default password store | error, path |
|
||||
| 15 | Unable to determine the location of the default password store | error |
|
||||
| 16 | Unable to read the default settings of a user-configured password store | error, name, path |
|
||||
| 17 | Unable to read the default settings of the default password store | error, path |
|
||||
| Code | Description | Parameters |
|
||||
| ---- | ----------------------------------------------------------------------- | ----------------------- |
|
||||
| 10 | Unable to parse browser request length | error |
|
||||
| 11 | Unable to parse browser request | error |
|
||||
| 12 | Invalid request action | action |
|
||||
| 13 | Inaccessible user-configured password store | error, name, path |
|
||||
| 14 | Inaccessible default password store | error, path |
|
||||
| 15 | Unable to determine the location of the default password store | error |
|
||||
| 16 | Unable to read the default settings of a user-configured password store | error, name, path |
|
||||
| 17 | Unable to read the default settings of the default password store | error, path |
|
||||
| 18 | Unable to list files in a password store | error, name, path |
|
||||
| 19 | Unable to determine a relative path for a file in a password store | error, file, name, path |
|
||||
|
||||
## Settings
|
||||
|
||||
@@ -171,7 +173,7 @@ Get the decrypted contents of a specific file.
|
||||
"status": "ok",
|
||||
"version": <int>,
|
||||
"data": {
|
||||
"data": "<decrypted file contents>"
|
||||
"contents": "<decrypted file contents>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@@ -33,6 +33,12 @@ const (
|
||||
|
||||
// CodeUnreadableDefaultPasswordStoreDefaultSettings error reading the default settings of the default password store
|
||||
CodeUnreadableDefaultPasswordStoreDefaultSettings = 17
|
||||
|
||||
// CodeUnableToListFilesInPasswordStore error listing files in a password store
|
||||
CodeUnableToListFilesInPasswordStore = 18
|
||||
|
||||
// CodeUnableToDetermineRelativeFilePathInPasswordStore error determining a relative path for a file in a password store
|
||||
CodeUnableToDetermineRelativeFilePathInPasswordStore = 19
|
||||
)
|
||||
|
||||
// ExitWithCode exit with error code
|
||||
|
@@ -16,7 +16,7 @@ function require()
|
||||
if ! `command -v "$1" >/dev/null`; then
|
||||
OUTPUT="{\n \"status\": \"error\"\n "version": $VERSION,\n \"params\": {\n \"message\": \"Required dependency '$1' is missing\"\n }, \"code\": 1\n}"
|
||||
LANG=C LC_ALL=C LENGTH=${#OUTPUT}
|
||||
echo -n
|
||||
echo -n
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
@@ -94,11 +94,11 @@ function configure()
|
||||
done
|
||||
|
||||
[ -n "$PASSWORD_STORE_DIR" ] || PASSWORD_STORE_DIR="~/.password-store"
|
||||
OUTPUT="$(jq -n --arg defaultPath "$PASSWORD_STORE_DIR" '.defaultPath = $defaultPath')"
|
||||
OUTPUT="$(jq -n --arg defaultPath "$PASSWORD_STORE_DIR" '.defaultStore.path = $defaultPath')"
|
||||
|
||||
STOREPATH=$(echo "$PASSWORD_STORE_DIR" | sed 's/^~/$HOME/' | envsubst)
|
||||
if [ -f "$STOREPATH/.browserpass.json" ]; then
|
||||
OUTPUT=$(jq --arg settings "$(cat "$STOREPATH/.browserpass.json")" '.defaultSettings = $settings' <<< "$OUTPUT")
|
||||
OUTPUT=$(jq --arg settings "$(cat "$STOREPATH/.browserpass.json")" '.defaultStore.settings = $settings' <<< "$OUTPUT")
|
||||
else
|
||||
OUTPUT=$(jq '.defaultSettings = ""' <<< "$OUTPUT")
|
||||
fi
|
||||
@@ -153,9 +153,9 @@ function fetch()
|
||||
# get file contents
|
||||
[ -f "$FILEPATH" ] || fail "Requested file does not exist: $STORE:$FILE"
|
||||
DATA="$(gpg -q --decrypt "$FILEPATH")"
|
||||
|
||||
|
||||
# build output
|
||||
echo "$(jq -n --arg data "$DATA" '.data = $data')"
|
||||
echo "$(jq -n --arg data "$DATA" '.contents = $data')"
|
||||
}
|
||||
|
||||
function run()
|
||||
|
69
request/list.go
Normal file
69
request/list.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
"github.com/browserpass/browserpass-native/errors"
|
||||
"github.com/browserpass/browserpass-native/response"
|
||||
"github.com/mattn/go-zglob"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func listFiles(request request) {
|
||||
responseData := response.MakeListResponse()
|
||||
|
||||
for _, store := range request.Settings.Stores {
|
||||
normalizedStorePath, err := normalizePasswordStorePath(store.Path)
|
||||
if err != nil {
|
||||
log.Errorf(
|
||||
"The password store '%v' is not accessible at the location '%v': %+v",
|
||||
store.Name, store.Path, err,
|
||||
)
|
||||
response.SendError(
|
||||
errors.CodeInaccessiblePasswordStore,
|
||||
"The password store is not accessible",
|
||||
&map[string]string{"error": err.Error(), "name": store.Name, "path": store.Path},
|
||||
)
|
||||
errors.ExitWithCode(errors.CodeInaccessiblePasswordStore)
|
||||
}
|
||||
|
||||
store.Path = normalizedStorePath
|
||||
|
||||
files, err := zglob.GlobFollowSymlinks(filepath.Join(store.Path, "/**/*.gpg"))
|
||||
if err != nil {
|
||||
log.Errorf(
|
||||
"Unable to list the files in the password store '%v' at the location '%v': %+v",
|
||||
store.Name, store.Path, err,
|
||||
)
|
||||
response.SendError(
|
||||
errors.CodeUnableToListFilesInPasswordStore,
|
||||
"Unable to list the files in the password store",
|
||||
&map[string]string{"error": err.Error(), "name": store.Name, "path": store.Path},
|
||||
)
|
||||
errors.ExitWithCode(errors.CodeUnableToListFilesInPasswordStore)
|
||||
}
|
||||
|
||||
for i, file := range files {
|
||||
relativePath, err := filepath.Rel(store.Path, file)
|
||||
if err != nil {
|
||||
log.Errorf(
|
||||
"Unable to determine the relative path for a file '%v' in the password store '%v' at the location '%v': %+v",
|
||||
file, store.Name, store.Path, err,
|
||||
)
|
||||
response.SendError(
|
||||
errors.CodeUnableToDetermineRelativeFilePathInPasswordStore,
|
||||
"Unable to determine the relative path for a file in the password store",
|
||||
&map[string]string{"error": err.Error(), "file": file, "name": store.Name, "path": store.Path},
|
||||
)
|
||||
errors.ExitWithCode(errors.CodeUnableToDetermineRelativeFilePathInPasswordStore)
|
||||
}
|
||||
files[i] = relativePath
|
||||
}
|
||||
|
||||
sort.Strings(files)
|
||||
responseData.Files[store.Name] = files
|
||||
}
|
||||
|
||||
response.SendOk(responseData)
|
||||
}
|
@@ -31,7 +31,7 @@ func Process() {
|
||||
case "configure":
|
||||
configure(request)
|
||||
case "list":
|
||||
break
|
||||
listFiles(request)
|
||||
case "fetch":
|
||||
break
|
||||
default:
|
||||
|
@@ -40,6 +40,18 @@ func MakeConfigureResponse() *ConfigureResponse {
|
||||
}
|
||||
}
|
||||
|
||||
// ListResponse a response format for the "list" request
|
||||
type ListResponse struct {
|
||||
Files map[string][]string `json:"files"`
|
||||
}
|
||||
|
||||
// MakeListResponse initializes an empty list response
|
||||
func MakeListResponse() *ListResponse {
|
||||
return &ListResponse{
|
||||
Files: make(map[string][]string),
|
||||
}
|
||||
}
|
||||
|
||||
// SendOk sends a success response to the browser extension in the predefined json format
|
||||
func SendOk(data interface{}) {
|
||||
send(&okResponse{
|
||||
|
Reference in New Issue
Block a user