Implement list action (#12)

This commit is contained in:
Maxim Baz
2018-04-16 01:38:55 +02:00
committed by GitHub
parent 66850cfa4a
commit bd6ab67d3a
8 changed files with 120 additions and 18 deletions

11
Gopkg.lock generated
View File

@@ -1,6 +1,15 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. # 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]] [[projects]]
name = "github.com/rifflock/lfshook" name = "github.com/rifflock/lfshook"
packages = ["."] packages = ["."]
@@ -34,6 +43,6 @@
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "f6199a143c790c5c1422bd35477ede08e5d2e3a0e5552d769e7c4de6ed8a14b1" inputs-digest = "1f59ddaed2db7de2b34f8485550888fa1cb625342398af10acb68e5ee227f3f8"
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View File

@@ -27,3 +27,7 @@
[[constraint]] [[constraint]]
name = "github.com/rifflock/lfshook" name = "github.com/rifflock/lfshook"
version = "2.3.0" version = "2.3.0"
[[constraint]]
branch = "master"
name = "github.com/mattn/go-zglob"

View File

@@ -41,16 +41,18 @@ 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 | error | | 10 | Unable to parse browser request length | error |
| 11 | Unable to parse browser request | error | | 11 | Unable to parse browser request | error |
| 12 | Invalid request action | action | | 12 | Invalid request action | action |
| 13 | Inaccessible user-configured password store | error, name, path | | 13 | Inaccessible user-configured password store | error, name, path |
| 14 | Inaccessible default password store | error, path | | 14 | Inaccessible default password store | error, path |
| 15 | Unable to determine the location of the default password store | error | | 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 | | 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 | | 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 ## Settings
@@ -171,7 +173,7 @@ Get the decrypted contents of a specific file.
"status": "ok", "status": "ok",
"version": <int>, "version": <int>,
"data": { "data": {
"data": "<decrypted file contents>" "contents": "<decrypted file contents>"
} }
} }
``` ```

View File

@@ -33,6 +33,12 @@ const (
// CodeUnreadableDefaultPasswordStoreDefaultSettings error reading the default settings of the default password store // CodeUnreadableDefaultPasswordStoreDefaultSettings error reading the default settings of the default password store
CodeUnreadableDefaultPasswordStoreDefaultSettings = 17 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 // ExitWithCode exit with error code

View File

@@ -94,11 +94,11 @@ function configure()
done done
[ -n "$PASSWORD_STORE_DIR" ] || PASSWORD_STORE_DIR="~/.password-store" [ -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) STOREPATH=$(echo "$PASSWORD_STORE_DIR" | sed 's/^~/$HOME/' | envsubst)
if [ -f "$STOREPATH/.browserpass.json" ]; then 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 else
OUTPUT=$(jq '.defaultSettings = ""' <<< "$OUTPUT") OUTPUT=$(jq '.defaultSettings = ""' <<< "$OUTPUT")
fi fi
@@ -155,7 +155,7 @@ function fetch()
DATA="$(gpg -q --decrypt "$FILEPATH")" DATA="$(gpg -q --decrypt "$FILEPATH")"
# build output # build output
echo "$(jq -n --arg data "$DATA" '.data = $data')" echo "$(jq -n --arg data "$DATA" '.contents = $data')"
} }
function run() function run()

69
request/list.go Normal file
View 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)
}

View File

@@ -31,7 +31,7 @@ func Process() {
case "configure": case "configure":
configure(request) configure(request)
case "list": case "list":
break listFiles(request)
case "fetch": case "fetch":
break break
default: default:

View File

@@ -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 // SendOk sends a success response to the browser extension in the predefined json format
func SendOk(data interface{}) { func SendOk(data interface{}) {
send(&okResponse{ send(&okResponse{