Merge pull request #51 from owncloud/user-list-ui

User list ui
This commit is contained in:
Jörn Friedrich Dreyer
2020-07-02 13:20:41 +02:00
committed by GitHub
39 changed files with 11364 additions and 1112 deletions

View File

@@ -4,5 +4,7 @@ exclude_paths:
- changelog/**
- docs/**
- pkg/proto/**
- package.json
- rollup.config.js
...

View File

@@ -32,6 +32,17 @@ def testing(ctx):
'arch': 'amd64',
},
'steps': [
{
'name': 'frontend',
'image': 'webhippie/nodejs:latest',
'pull': 'always',
'commands': [
'yarn install --frozen-lockfile',
'yarn lint',
'yarn test',
'yarn build',
],
},
{
'name': 'generate',
'image': 'webhippie/golang:1.13',
@@ -152,6 +163,15 @@ def docker(ctx, arch):
'arch': arch,
},
'steps': [
{
'name': 'frontend',
'image': 'webhippie/nodejs:latest',
'pull': 'always',
'commands': [
'yarn install --frozen-lockfile',
'yarn build',
],
},
{
'name': 'generate',
'image': 'webhippie/golang:1.13',
@@ -290,6 +310,15 @@ def binary(ctx, name):
'arch': 'amd64',
},
'steps': [
{
'name': 'frontend',
'image': 'webhippie/nodejs:latest',
'pull': 'always',
'commands': [
'yarn install --frozen-lockfile',
'yarn build',
],
},
{
'name': 'generate',
'image': 'webhippie/golang:1.13',

17
.eslintrc.json Normal file
View File

@@ -0,0 +1,17 @@
{
"env": {
"browser": true,
"es6": true,
"amd": true
},
"extends": [
"standard",
"plugin:vue/essential"
],
"parserOptions": {
"sourceType": "module"
},
"rules": {
}
}

View File

@@ -23,7 +23,7 @@ endif
PACKAGES ?= $(shell go list ./...)
SOURCES ?= $(shell find . -name "*.go" -type f -not -path "./node_modules/*")
GENERATE ?= $(PACKAGES)
GENERATE ?= $(IMPORT)/pkg/assets
TAGS ?=
@@ -79,7 +79,7 @@ lint:
for PKG in $(PACKAGES); do go run golang.org/x/lint/golint -set_exit_status $$PKG || exit 1; done;
.PHONY: generate
generate:
generate: protobuf
go generate $(GENERATE)
.PHONY: changelog
@@ -156,6 +156,44 @@ docs: docs-copy docs-build
watch:
go run github.com/cespare/reflex -c reflex.conf
.PHONY: pb
pb:
protoc -I=$(PROTO_SRC) -I=third_party --go_out=. --micro_out=. $(PROTO_SRC)/*.proto
$(GOPATH)/bin/protoc-gen-go:
GO111MODULE=off go get -v github.com/golang/protobuf/protoc-gen-go
$(GOPATH)/bin/protoc-gen-micro:
GO111MODULE=on go get -v github.com/micro/protoc-gen-micro/v2
$(GOPATH)/bin/protoc-gen-microweb:
GO111MODULE=off go get -v github.com/owncloud/protoc-gen-microweb
$(GOPATH)/bin/protoc-gen-swagger:
GO111MODULE=off go get -v github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
$(PROTO_SRC)/accounts.pb.go: $(PROTO_SRC)/accounts.proto
protoc \
-I=third_party/ \
-I=$(PROTO_SRC)/ \
--go_out=. accounts.proto
$(PROTO_SRC)/accounts.pb.micro.go: $(PROTO_SRC)/accounts.proto
protoc \
-I=third_party/ \
-I=$(PROTO_SRC)/ \
--micro_out=. accounts.proto
$(PROTO_SRC)/accounts.pb.web.go: $(PROTO_SRC)/accounts.proto
protoc \
-I=third_party/ \
-I=$(PROTO_SRC)/ \
--microweb_out=. accounts.proto
$(PROTO_SRC)/accounts.swagger.json: $(PROTO_SRC)/accounts.proto
# the other commands above respect the declared package in the .proto file for placement of the resulting file.
# `swagger_out` doesn't, so we have to specify the output path as `$(PROTO_SRC)` instead of `.`
protoc \
-I=third_party/ \
-I=$(PROTO_SRC)/ \
--swagger_out=$(PROTO_SRC) accounts.proto
.PHONY: protobuf
protobuf: $(GOPATH)/bin/protoc-gen-go $(GOPATH)/bin/protoc-gen-micro $(GOPATH)/bin/protoc-gen-microweb $(GOPATH)/bin/protoc-gen-swagger \
$(PROTO_SRC)/accounts.pb.go $(PROTO_SRC)/accounts.pb.micro.go $(PROTO_SRC)/accounts.pb.web.go $(PROTO_SRC)/accounts.swagger.json

25
babel.config.js Normal file
View File

@@ -0,0 +1,25 @@
module.exports = function (api) {
api.cache(true)
const presets = [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: '3'
}
]
]
const plugins = [
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-object-rest-spread',
'@babel/plugin-transform-runtime',
'@babel/plugin-proposal-export-default-from'
]
return {
presets,
plugins
}
}

View File

@@ -0,0 +1,5 @@
Change: Align structure of this extension with other extensions
We aim to have a similar project structure for all our ocis extensions. This extension was different with regard to the structure of the server command and naming of some flag names.
https://github.com/owncloud/ocis-accounts/pull/51

View File

@@ -0,0 +1,5 @@
Enhancement: Add simple user listing UI
We added an extension for ocis-web that shows a simple list of all existing users.
https://github.com/owncloud/ocis-accounts/pull/51

84
docs/configuration.md Normal file
View File

@@ -0,0 +1,84 @@
---
title: "Configuration"
date: "2020-07-01T11:10:52+0200"
weight: 20
geekdocRepo: https://github.com/owncloud/ocis-reva
geekdocEditPath: edit/master/docs
geekdocFilePath: configuration.md
---
{{< toc >}}
## Configuration
oCIS Single Binary is not responsible for configuring extensions. Instead, each extension could either be configured by environment variables, cli flags or config files.
Each extension has its dedicated documentation page (e.g. https://owncloud.github.io/extensions/ocis_proxy/configuration) which lists all possible configurations. Config files and environment variables are picked up if you use the `./bin/ocis server` command within the oCIS single binary. Command line flags must be set explicitly on the extensions subcommands.
### Configuration using config files
Out of the box extensions will attempt to read configuration details from:
```console
/etc/ocis
$HOME/.ocis
./config
```
For this configuration to be picked up, have a look at your extension `root` command and look for which default config name it has assigned. *i.e: ocis-proxy reads `proxy.json | yaml | toml ...`*.
So far we support the file formats `JSON` and `YAML`, if you want to get a full example configuration just take a look at [our repository](https://github.com/owncloud/ocis/tree/master/config), there you can always see the latest configuration format. These example configurations include all available options and the default values. The configuration file will be automatically loaded if it's placed at `/etc/ocis/ocis.yml`, `${HOME}/.ocis/ocis.yml` or `$(pwd)/config/ocis.yml`.
### Envrionment variables
If you prefer to configure the service with environment variables you can see the available variables below.
### Commandline flags
If you prefer to configure the service with commandline flags you can see the available variables below. Command line flags are only working when calling the subcommand directly.
### ocis-reva server
Start ocis accounts service
Usage: `ocis-reva server [command options] [arguments...]`
--http-namespace | $ACCOUNTS_HTTP_NAMESPACE
: Set the base namespace for the http namespace. Default: `com.owncloud.web`.
--http-addr | $ACCOUNTS_HTTP_ADDR
: Address to bind http server. Default: `localhost:9181`.
--http-root | $ACCOUNTS_HTTP_ROOT
: Root path of http server. Default: `/`.
--grpc-namespace | $ACCOUNTS_GRPC_NAMESPACE
: Set the base namespace for the grpc namespace. Default: `com.owncloud.api`.
--grpc-addr | $ACCOUNTS_GRPC_ADDR
: Address to bind grpc server. Default: `localhost:9180`.
--name | $ACCOUNTS_NAME
: service name. Default: `accounts`.
--accounts-data-path | $ACCOUNTS_DATA_PATH
: accounts folder. Default: `/var/tmp/ocis-accounts`.
--asset-path | $HELLO_ASSET_PATH
: Path to custom assets.
### ocis-reva ocis-accounts
Provide accounts and groups for oCIS
Usage: `ocis-reva ocis-accounts [command options] [arguments...]`
--log-level | $ACCOUNTS_LOG_LEVEL
: Set logging level. Default: `info`.
--log-pretty | $ACCOUNTS_LOG_PRETTY
: Enable pretty logging. Default: `true`.
--log-color | $ACCOUNTS_LOG_COLOR
: Enable colored logging. Default: `true`.

9
go.mod
View File

@@ -11,25 +11,28 @@ require (
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c // indirect
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 // indirect
github.com/go-chi/chi v4.1.0+incompatible
github.com/go-chi/render v1.0.1
github.com/go-test/deep v1.0.6 // indirect
github.com/gofrs/uuid v3.3.0+incompatible
github.com/gogo/protobuf v1.3.1 // indirect
github.com/golang/protobuf v1.4.2
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect
github.com/joho/godotenv v1.3.0
github.com/micro/cli/v2 v2.1.2
github.com/micro/go-micro/v2 v2.6.0
github.com/oklog/run v1.1.0
github.com/owncloud/ocis-pkg/v2 v2.2.1
github.com/owncloud/ocis-pkg/v2 v2.2.2-0.20200602070144-cd0620668170
github.com/owncloud/ocis-settings v0.0.0-20200522101320-46ea31026363
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/restic/calens v0.2.0
github.com/spf13/viper v1.7.0
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect
github.com/tredoe/osutil v1.0.5
golang.org/x/net v0.0.0-20200301022130-244492dfa37a
google.golang.org/genproto v0.0.0-20200420144010-e5e8543f8aeb
honnef.co/go/tools v0.0.1-2020.1.0.20200427215036-cd1ad299aeab // indirect
google.golang.org/protobuf v1.23.0
honnef.co/go/tools v0.0.1-2020.1.4 // indirect
)
replace google.golang.org/grpc => google.golang.org/grpc v1.26.0

94
go.sum
View File

@@ -16,6 +16,7 @@ contrib.go.opencensus.io/exporter/jaeger v0.2.0/go.mod h1:ukdzwIYYHgZ7QYtwVFQUji
contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA=
contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0=
contrib.go.opencensus.io/exporter/ocagent v0.6.0/go.mod h1:zmKjrJcdo0aYcVS7bmEeSEBLPA9YJp5bjrofdU3pIXs=
contrib.go.opencensus.io/exporter/prometheus v0.1.0/go.mod h1:cGFniUXGZlKRjzOyuZJ6mgB+PgBcCIa79kEKR8YCW+A=
contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e5CWqyUk/cLzKnWsOKPVW3no6OTw=
contrib.go.opencensus.io/exporter/zipkin v0.1.1/go.mod h1:GMvdSl3eJ2gapOaLKzTKE3qDgUkJ86k9k3yY2eqwkzc=
contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE=
@@ -52,8 +53,12 @@ github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3
github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190605020000-c4ba1fdf4d36/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo=
github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg=
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/semver/v3 v3.0.2 h1:tRi7ENs+AaOUCH+j6qwNQgPYfV26dX3JNonq+V4mhqc=
github.com/Masterminds/semver/v3 v3.0.2/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
github.com/Masterminds/sprig/v3 v3.0.1 h1:RuaOafp+8qOLUPX1lInLfUrLc1MEVbnz7a40RLoixKY=
github.com/Masterminds/sprig/v3 v3.0.1/go.mod h1:Cp7HwZjmqKrC+Y7XqSJOU2yRvAJRGLiohfgz5ZJj8+4=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
@@ -71,6 +76,7 @@ github.com/RoaringBitmap/roaring v0.4.21/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/sarama v1.24.1/go.mod h1:fGP8eQ6PugKEI0iUETYYtnP6d1pH/bdDMTel1X5ajsU=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/UnnoTed/fileb0x v1.1.4 h1:IUgFzgBipF/ujNx9wZgkrKOF3oltUuXMSoaejrBws+A=
github.com/UnnoTed/fileb0x v1.1.4/go.mod h1:X59xXT18tdNk/D6j+KZySratBsuKJauMtVuJ9cgOiZs=
github.com/abbot/go-http-auth v0.4.1-0.20181019201920-860ed7f246ff/go.mod h1:Cz6ARTIzApMJDzh5bRMSUou6UMSp0IEXg9km/ci7TJM=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
@@ -102,6 +108,9 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/ascarter/requestid v0.0.0-20170313220838-5b76ab3d4aee h1:3T/l+vMotQ7cDSLWNAn2Vg1SAQ3mdyLgBWWBitSS3uU=
github.com/ascarter/requestid v0.0.0-20170313220838-5b76ab3d4aee/go.mod h1:u7Wtt4WATGGgae9mURNGQQqxAudPKrxfsbSDSGOso+g=
github.com/asim/go-awsxray v0.0.0-20161209120537-0d8a60b6e205/go.mod h1:frVmN4PtXUuL1EbZn0uL4PHSTKNKFnbMpBIhngqMuNQ=
github.com/asim/go-bson v0.0.0-20160318195205-84522947cabd/go.mod h1:L59ZX7HuzTbNzFBt8g3SJkRraj+GBOgvLAfJYJUcQ5w=
@@ -110,6 +119,7 @@ github.com/aws/aws-sdk-go v1.19.18/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpi
github.com/aws/aws-sdk-go v1.19.45/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.25.31/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.29.26/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@@ -141,6 +151,7 @@ github.com/blevesearch/zap/v13 v13.0.1 h1:NSCM6uKu77Vn/x9nlPp4pE1o/bftqcOWZEHSyZ
github.com/blevesearch/zap/v13 v13.0.1/go.mod h1:XmyNLMvMf8Z5FjLANXwUeDW3e1+o77TTGUWrth7T9WI=
github.com/blevesearch/zap/v14 v14.0.0 h1:HF8Ysjm13qxB0jTGaKLlatNXmJbQD8bY+PrPxm5v4hE=
github.com/blevesearch/zap/v14 v14.0.0/go.mod h1:sUc/gPGJlFbSQ2ZUh/wGRYwkKx+Dg/5p+dd+eq6QMXk=
github.com/bmatcuk/doublestar v1.1.1 h1:YroD6BJCZBYx06yYFEWvUuKVWQn3vLLQAVmDmvTSaiQ=
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
@@ -156,12 +167,14 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/reflex v0.2.0 h1:6d9WpWJseKjJvZEevKP7Pk42nPx2+BUTqmhNk8wZPwM=
github.com/cespare/reflex v0.2.0/go.mod h1:ooqOLJ4algvHP/oYvKWfWJ9tFUzCLDk5qkIJduMYrgI=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.0 h1:yTUvW7Vhb89inJ+8irsUqiWjh8iT6sQPZiQzI6ReGkA=
github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM=
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
github.com/cheggaaa/pb v1.0.28/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/cloudflare/cloudflare-go v0.10.2/go.mod h1:qhVI5MKwBGhdNU89ZRz2plgYutcJ5PCekLxXn56w6SY=
@@ -186,6 +199,8 @@ github.com/coreos/etcd v3.3.18+incompatible h1:Zz1aXgDrFFi1nadh58tA9ktt06cmPTwNN
github.com/coreos/etcd v3.3.18+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=
github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -205,7 +220,12 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cs3org/go-cs3apis v0.0.0-20200306065539-29abc33f5be0 h1:jTKILSBtDm0GEw3FtXPxc5wxGpaw2pxzREg1GBV9LIQ=
github.com/cs3org/go-cs3apis v0.0.0-20200306065539-29abc33f5be0/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
github.com/cs3org/reva v0.1.0 h1:PYzDejKm/+xG3OTS2WgzBxcksVogEGmPgjJVegwSR2c=
github.com/cs3org/reva v0.1.0/go.mod h1:8j6QyyAq9Kjj7RPfJb7M1aEmw5DmsuCJKUULXxYOyRo=
github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d h1:SwD98825d6bdB+pEuTxWOXiSjBrHdOl/UVp75eI7JT8=
github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8=
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 h1:iwZdTE0PVqJCos1vaoKsclOGD3ADKpshg3SRtYBbwso=
@@ -239,6 +259,7 @@ github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7j
github.com/ef-ds/deque v1.0.4-0.20190904040645-54cb57c252a1/go.mod h1:HvODWzv6Y6kBf3Ah2WzN1bHjDUezGLaAhwuWVwfpEJs=
github.com/eknkc/basex v1.0.0/go.mod h1:k/F/exNEHFdbs3ZHuasoP2E7zeWwZblG84Y7Z59vQRo=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elazarl/goproxy v0.0.0-20181003060214-f58a169a71a5/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
@@ -269,6 +290,7 @@ github.com/fsouza/go-dockerclient v1.6.0/go.mod h1:YWwtNPuL4XTX1SKJQk86cWPmmqwx+
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gizak/termui/v3 v3.1.0 h1:ZZmVDgwHl7gR7elfKf1xc4IudXZ5qqfDh4wExk4Iajc=
github.com/gizak/termui/v3 v3.1.0/go.mod h1:bXQEBkJpzxUAKf0+xq9MSWAvWZlE7c+aidmyFlkYTrY=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
@@ -306,9 +328,11 @@ github.com/go-log/log v0.1.0/go.mod h1:4mBwpdRMFLiuXZDCwU2lKQFsoSCo72j3HqBK9d81N
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
@@ -316,6 +340,7 @@ github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEK
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-redsync/redsync v1.3.1/go.mod h1:qxZwM5JOimfq8y98Wk2+c8dKtxJgG5/yIl2ODz2E5Dk=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-stomp/stomp v2.0.3+incompatible/go.mod h1:VqCtqNZv1226A1/79yh+rMiFUcfY3R109np+7ke4n0c=
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM=
@@ -397,6 +422,7 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU=
github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gopherjs/gopherjs v0.0.0-20181004151105-1babbf986f6f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@@ -412,6 +438,7 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 h1:THDBEeQ9xZ8JEaCLyLQqXMMdRqNr0QAUJTIkQAUtFjg=
github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
@@ -471,6 +498,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo=
github.com/huandu/xstrings v1.2.0 h1:yPeWdRnmynF7p+lLYz0H2tthW9lqhMJrQV/U7yy4wX0=
github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4=
github.com/huandu/xstrings v1.3.0 h1:gvV6jG9dTgFEncxo+AF7PH6MZXi/vZl25owA/8Dg8Wo=
github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd/go.mod h1:3LVOLeyx9XVvwPgrt2be44XgSqndprz1G18rSk8KD84=
@@ -481,6 +510,7 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
@@ -505,7 +535,9 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/justinas/alice v1.2.0/go.mod h1:fN5HRH/reO/zrUflLfTN43t3vXvKzvZIENsNEe7i7qA=
github.com/karrick/godirwalk v1.7.8 h1:VfG72pyIxgtC7+3X9CMHI0AOl4LwyRAg98WAgsvffi8=
github.com/karrick/godirwalk v1.7.8/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
@@ -523,13 +555,16 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA=
github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w=
github.com/labstack/echo v3.2.1+incompatible h1:J2M7YArHx4gi8p/3fDw8tX19SXhBCoRpviyAZSN3I88=
github.com/labstack/echo v3.2.1+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/gommon v0.2.7 h1:2qOPq/twXDrQ6ooBGrn3mrmVOC+biLlatwgIu8lbzRM=
github.com/labstack/gommon v0.2.7/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
@@ -551,12 +586,15 @@ github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGD
github.com/marten-seemann/qtls v0.3.2/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk=
github.com/marten-seemann/qtls v0.4.1/go.mod h1:pxVXcHHw1pNIt8Qo0pwSYQEoZ8yYOOPXTCZLQQunvRc=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
@@ -601,6 +639,7 @@ github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y=
@@ -618,7 +657,9 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/moul/http2curl v0.0.0-20170919181001-9ac6cf4d929b/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
@@ -654,13 +695,16 @@ github.com/nrdcg/auroradns v1.0.0/go.mod h1:6JPXKzIRzZzMqtTDgueIhTi6rFf1QvYE/Hzq
github.com/nrdcg/dnspod-go v0.3.0/go.mod h1:vZSoFSFeQVm2gWLMkyX61LZ8HI3BaqtHZWgPTGKr6KQ=
github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2SwKQ=
github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw=
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d h1:x3S6kxmy49zXVVyhcnrFqxvNVCBPb2KZ9hV2RBdS840=
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
github.com/nsqio/go-nsq v1.0.7/go.mod h1:XP5zaUs3pqf+Q71EqUJs3HYfBIqfK6G83WQMdNN+Ito=
github.com/ogier/pflag v0.0.1 h1:RW6JSWSu/RkSatfcLtogGfFgpim5p7ARQ10ECk5O750=
github.com/ogier/pflag v0.0.1/go.mod h1:zkFki7tvTa0tafRvTBIZTvzYyAu6kQhPZFnshFFPE+g=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/oleiade/reflections v1.0.0/go.mod h1:RbATFBbKYkVdqmSFtx13Bb/tVhR0lgOBXunWTZKeL4w=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -683,17 +727,20 @@ github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
github.com/ory/fosite v0.30.4/go.mod h1:Lq9qQ9Sl6mcea2Tt8J7PU+wUeFYPZ+vg7N3zPVKGbN8=
github.com/ory/go-convenience v0.1.0/go.mod h1:uEY/a60PL5c12nYz4V5cHY03IBmwIAEm8TWB0yn9KNs=
github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ=
github.com/owncloud/ocis-hello v0.1.0-alpha1/go.mod h1:tU2bOB7DjuXZ+ju+5A+7pUHmTfPIYUk3tMflqHTBTpE=
github.com/owncloud/ocis-pkg v1.2.1-0.20191217084055-eab942498596 h1:3aMNmuDCIdKsaa4YdVTQEBJMjGz8KiuIB/+xlJUCT3k=
github.com/owncloud/ocis-pkg v1.2.1-0.20191217084055-eab942498596/go.mod h1:Wo0QfOmhadh2vNcUoQIsw2yaOT3zeftk+xaOOwP3y88=
github.com/owncloud/ocis-pkg/v2 v2.0.1/go.mod h1:7bVnn3VUaqdmvpMkXF0QVEF1fRugs35hSkuVTAq9yjk=
github.com/owncloud/ocis-pkg/v2 v2.2.1 h1:LK7WxHYugEFQ9NHTOz0EP8DRjbt51wXhyqruV03z6zI=
github.com/owncloud/ocis-pkg/v2 v2.2.1/go.mod h1:MXv7QzsYsu4YWuyJxhq1kLLmJa/r5gbqHe1FXulMHaw=
github.com/owncloud/ocis-pkg/v2 v2.2.2-0.20200602070144-cd0620668170 h1:MYfyffPyTZbTofJjAz3LSQUIaKKcjjBBBIJGaEAkP8g=
github.com/owncloud/ocis-pkg/v2 v2.2.2-0.20200602070144-cd0620668170/go.mod h1:s894msGwDsULmsROHkbsXFCP/eSqDcteDFUntZOiJdc=
github.com/owncloud/ocis-settings v0.0.0-20200522101320-46ea31026363 h1:wk/7aAUITTrM192TFoIDq4fqzJQtFOQ0dDdSRkJ25SU=
github.com/owncloud/ocis-settings v0.0.0-20200522101320-46ea31026363/go.mod h1:/h0ceztOoFc3KAnm8nqZI4zwsaaZK9q4MTgtintwsXc=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
github.com/parnurzeal/gorequest v0.2.15/go.mod h1:3Kh2QUMJoqw3icWAecsyzkpY7UzRfDhbRdTjtNwNiUE=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
@@ -712,13 +759,16 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pkg/xattr v0.4.1/go.mod h1:W2cGD0TBEus7MkUgv0tNZ9JutLtVO3cXu+IBRuHqnFs=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU=
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
@@ -731,6 +781,7 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
@@ -738,6 +789,7 @@ github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+
github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
@@ -760,6 +812,8 @@ github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.17.2 h1:RMRHFw2+wF7LO0QqtELQwo8hqSmqISyCJeFeAAuWcRo=
github.com/rs/zerolog v1.17.2/go.mod h1:9nvC1axdVrAHcu/s9taAVfBuIdTZLVQmKQyvrUjF5+I=
github.com/rs/zerolog v1.18.0 h1:CbAm3kP2Tptby1i9sYy2MGRg0uxIN9cyDb59Ys7W8z8=
github.com/rs/zerolog v1.18.0/go.mod h1:9nvC1axdVrAHcu/s9taAVfBuIdTZLVQmKQyvrUjF5+I=
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
@@ -786,6 +840,7 @@ github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:s
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
@@ -835,6 +890,7 @@ github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpP
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok=
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8=
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY=
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU=
@@ -842,6 +898,7 @@ github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDW
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20200122045848-3419fae592fc h1:yUaosFVTJwnltaHbSNC3i82I92quFs+OFPRl8kNMVwo=
github.com/tmc/grpc-websocket-proxy v0.0.0-20200122045848-3419fae592fc/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce h1:fb190+cK2Xz/dvi9Hv8eCYJYvIGUTN2/KLq1pT6CjEc=
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4=
github.com/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY=
github.com/tredoe/fileutil v1.0.0/go.mod h1:PBayWPFCURwkmW0u6E8E8C6Jtd9ZzWq/U1iMa6BLRPg=
@@ -854,7 +911,9 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 h1:gKMu1Bf6QINDnvyZuTaACm9ofY+PRh+5vFz4oxBZeF8=
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4/go.mod h1:50wTf68f99/Zt14pr046Tgt3Lp2vLyFZKzbFXTOabXw=
github.com/vultr/govultr v0.1.4/go.mod h1:9H008Uxr/C4vFNGLqKx232C206GL0PBHzOP0809bGNA=
github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
@@ -872,12 +931,12 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
@@ -885,6 +944,8 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
@@ -906,6 +967,7 @@ gocloud.dev/pubsub/rabbitpubsub v0.17.0/go.mod h1:7o1XYDiIC+b0mmcwJuofsDg08t0DtU
golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -915,6 +977,7 @@ golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -950,14 +1013,13 @@ golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCc
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180611182652-db08ff08e862/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180921000356-2f5d2388922f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -988,12 +1050,14 @@ golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20191109021931-daa7c04131f5/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191207000613-e7e4b65ae663/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181003184128-c57b0facaced/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1008,6 +1072,7 @@ golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181019160139-8e24a49d80f8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181021155630-eda9bb28ed51/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1024,6 +1089,7 @@ golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190415081028-16da32be82c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1082,12 +1148,11 @@ golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361 h1:RIIXAeV6GvDBuADKumTODatUqANFZ+5BPMnzsy4hulY=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200427214658-4697a2867c88 h1:Nj7oNnL9tSACMt2JvszZN6P4IXiy1t6E/YRMr7YtaSw=
golang.org/x/tools v0.0.0-20200427214658-4697a2867c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
@@ -1102,8 +1167,10 @@ google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEn
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
@@ -1145,6 +1212,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
@@ -1164,12 +1232,16 @@ gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eR
gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
gopkg.in/ldap.v2 v2.5.1/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk=
gopkg.in/ldap.v3 v3.1.0/go.mod h1:dQjCc0R0kfyFjIlWNMH1DORwUASZyDxo2Ry1B51dXaQ=
gopkg.in/ns1/ns1-go.v2 v2.0.0-20190730140822-b51389932cbc/go.mod h1:VV+3haRsgDiVLxyifmMBrBIuCWFBPYKbRssXB9z67Hw=
gopkg.in/olivere/elastic.v5 v5.0.82/go.mod h1:uhHoB4o3bvX5sorxBU29rPcmBQdV2Qfg0FBrx5D6pV0=
gopkg.in/redis.v3 v3.6.4/go.mod h1:6XeGv/CrsUFDU9aVbUdNykN7k1zVmoeg83KC9RbQfiU=
gopkg.in/resty.v1 v1.9.1/go.mod h1:vo52Hzryw9PnPHcJfPsBiFW62XhNx5OczbV9y+IMpgc=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.1.9/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4=
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
@@ -1191,8 +1263,8 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.0.20200427215036-cd1ad299aeab h1:33/51YKJC1SC6WAomp3Feij834LXL1uK1Jmt45mkghE=
honnef.co/go/tools v0.0.1-2020.1.0.20200427215036-cd1ad299aeab/go.mod h1:NELv708mC2Q9lQf29l+sO/v7NIOAQzEXu7jcugNzwvM=
honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.0.0-20191109101513-0171b7c15da1/go.mod h1:VJq7+38rpM4TSUbRiZX4P5UVAKK2UQpNQLZClkFQkpE=
k8s.io/apimachinery v0.0.0-20191109100837-dffb012825f2/go.mod h1:+6CX7hP4aLfX2sb91JYDMIp0VqDSog2kZu0BHe+lP+s=
k8s.io/apimachinery v0.0.0-20191111054156-6eb29fdf75dc/go.mod h1:+6CX7hP4aLfX2sb91JYDMIp0VqDSog2kZu0BHe+lP+s=

66
package.json Normal file
View File

@@ -0,0 +1,66 @@
{
"private": true,
"name": "ocis-accounts",
"version": "0.0.0",
"description": "",
"homepage": "https://github.com/owncloud/ocis-accounts#readme",
"license": "Apache-2.0",
"author": "ownCloud GmbH <devops@owncloud.com>",
"repository": "https://github.com/owncloud/ocis-accounts.git",
"bugs": {
"url": "https://github.com/owncloud/ocis-accounts/issues",
"email": "support@owncloud.com"
},
"scripts": {
"lint": "eslint ui/**/*.vue ui/**/*.js --color --global requirejs --global require",
"build": "rollup -c",
"watch": "rollup -c -w",
"test": "echo 'Not implemented'",
"generate-api": "node node_modules/swagger-vue-generator/bin/generate-api.js --package-version v0 --source pkg/proto/v0/accounts.swagger.json --moduleName accounts --destination ui/client/accounts/index.js"
},
"devDependencies": {
"@babel/core": "^7.7.7",
"@babel/plugin-proposal-class-properties": "^7.7.4",
"@babel/plugin-proposal-export-default-from": "^7.7.4",
"@babel/plugin-proposal-object-rest-spread": "^7.7.7",
"@babel/plugin-syntax-dynamic-import": "^7.7.4",
"@babel/plugin-transform-runtime": "^7.8.0",
"@babel/preset-env": "^7.7.7",
"@erquhart/rollup-plugin-node-builtins": "^2.1.5",
"@rollup/plugin-commonjs": "^11.0.1",
"@rollup/plugin-json": "^4.0.1",
"@rollup/plugin-replace": "^2.3.0",
"axios": "^0.19.0",
"core-js": "3",
"cross-env": "^6.0.3",
"debounce": "^1.2.0",
"easygettext": "^2.7.0",
"eslint": "6.8.0",
"eslint-config-standard": "^14.1.0",
"eslint-plugin-import": "^2.17.3",
"eslint-plugin-node": "11.0.0",
"eslint-plugin-promise": "^4.1.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^6.1.2",
"qs": "^6.9.1",
"rimraf": "^3.0.0",
"rollup": "^1.28.0",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-eslint": "^7.0.0",
"rollup-plugin-filesize": "^6.2.1",
"rollup-plugin-node-globals": "^1.4.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-terser": "^5.1.3",
"rollup-plugin-vue": "^5.1.4",
"swagger-vue-generator": "^1.0.6",
"vue-template-compiler": "^2.6.11"
},
"browserslist": [
"> 1%",
"not dead"
],
"peerDependencies": {
"owncloud-design-system": "^1.7.0",
"vuex": "^3.5.1"
}
}

66
pkg/assets/assets.go Normal file
View File

@@ -0,0 +1,66 @@
package assets
import (
"net/http"
"os"
"path"
"github.com/owncloud/ocis-accounts/pkg/config"
"github.com/owncloud/ocis-pkg/v2/log"
// Fake the import to make the dep tree happy.
_ "golang.org/x/net/context"
// Fake the import to make the dep tree happy.
_ "golang.org/x/net/webdav"
)
//go:generate go run github.com/UnnoTed/fileb0x embed.yml
// assets gets initialized by New and provides the handler.
type assets struct {
logger log.Logger
config *config.Config
}
// Open just implements the HTTP filesystem interface.
func (a assets) Open(original string) (http.File, error) {
if a.config.Asset.Path != "" {
if stat, err := os.Stat(a.config.Asset.Path); err == nil && stat.IsDir() {
custom := path.Join(
a.config.Asset.Path,
original,
)
if _, err := os.Stat(custom); !os.IsNotExist(err) {
f, err := os.Open(custom)
if err != nil {
return nil, err
}
return f, nil
}
} else {
a.logger.Warn().
Str("path", a.config.Asset.Path).
Msg("Assets directory doesn't exist")
}
}
return FS.OpenFile(
CTX,
original,
os.O_RDONLY,
0644,
)
}
// New returns a new http filesystem to serve assets.
func New(opts ...Option) http.FileSystem {
options := newOptions(opts...)
return assets{
config: options.Config,
}
}

173
pkg/assets/embed.go Normal file
View File

File diff suppressed because one or more lines are too long

17
pkg/assets/embed.yml Normal file
View File

@@ -0,0 +1,17 @@
---
pkg: "assets"
dest: "."
output: "embed.go"
fmt: true
noprefix: true
compression:
compress: true
custom:
- files:
- "../../assets/"
base: "../../assets/"
prefix: ""
...

40
pkg/assets/option.go Normal file
View File

@@ -0,0 +1,40 @@
package assets
import (
"github.com/owncloud/ocis-accounts/pkg/config"
"github.com/owncloud/ocis-pkg/v2/log"
)
// Option defines a single option function.
type Option func(o *Options)
// Options defines the available options for this package.
type Options struct {
Logger log.Logger
Config *config.Config
}
// newOptions initializes the available default options.
func newOptions(opts ...Option) Options {
opt := Options{}
for _, o := range opts {
o(&opt)
}
return opt
}
// Logger provides a function to set the logger option.
func Logger(val log.Logger) Option {
return func(o *Options) {
o.Logger = val
}
}
// Config provides a function to set the config option.
func Config(val *config.Config) Option {
return func(o *Options) {
o.Config = val
}
}

View File

@@ -2,13 +2,10 @@ package command
import (
"os"
"os/user"
"path"
"strings"
"github.com/owncloud/ocis-accounts/pkg/flagset"
"github.com/joho/godotenv"
"github.com/micro/cli/v2"
"github.com/owncloud/ocis-accounts/pkg/config"
"github.com/owncloud/ocis-accounts/pkg/version"
@@ -27,29 +24,8 @@ func Execute() error {
app := &cli.App{
Name: "ocis-accounts",
Version: version.String,
Usage: "Example service for Reva/oCIS",
Usage: "Provide accounts and groups for oCIS",
Compiled: version.Compiled(),
Flags: flagset.RootWithConfig(cfg),
Before: func(c *cli.Context) error {
err := ParseConfig(c, cfg)
logger := NewLogger(cfg)
for _, v := range defaultConfigPaths {
// location is the user's home
if v[0] == '$' || v[0] == '~' {
usr, _ := user.Current()
err := godotenv.Load(path.Join(usr.HomeDir, ".ocis", defaultFilename+".env"))
if err != nil {
logger.Debug().Msgf("ignoring missing env file on dir: %v", v)
}
} else {
err := godotenv.Load(path.Join(v, defaultFilename+".env"))
if err != nil {
logger.Debug().Msgf("ignoring missing env file on dir: %v", v)
}
}
}
return err
},
Authors: []*cli.Author{
{
@@ -58,6 +34,12 @@ func Execute() error {
},
},
Flags: flagset.RootWithConfig(cfg),
Before: func(c *cli.Context) error {
return ParseConfig(c, cfg)
},
Commands: []*cli.Command{
Server(cfg),
},

View File

@@ -2,14 +2,17 @@ package command
import (
"context"
"syscall"
"github.com/owncloud/ocis-accounts/pkg/flagset"
"os"
"os/signal"
"strings"
"github.com/micro/cli/v2"
"github.com/oklog/run"
"github.com/owncloud/ocis-accounts/pkg/config"
"github.com/owncloud/ocis-accounts/pkg/flagset"
"github.com/owncloud/ocis-accounts/pkg/metrics"
"github.com/owncloud/ocis-accounts/pkg/server/grpc"
"github.com/owncloud/ocis-accounts/pkg/server/http"
svc "github.com/owncloud/ocis-accounts/pkg/service/v0"
)
@@ -20,41 +23,83 @@ func Server(cfg *config.Config) *cli.Command {
Usage: "Start ocis accounts service",
Description: "uses an LDAP server as the storage backend",
Flags: flagset.ServerWithConfig(cfg),
Before: func(c *cli.Context) error {
return ParseConfig(c, cfg)
Before: func(ctx *cli.Context) error {
if cfg.HTTP.Root != "/" {
cfg.HTTP.Root = strings.TrimSuffix(cfg.HTTP.Root, "/")
}
// When running on single binary mode the before hook from the root command won't get called. We manually
// call this before hook from ocis command, so the configuration can be loaded.
return ParseConfig(ctx, cfg)
},
Action: func(c *cli.Context) error {
logger := NewLogger(cfg)
gr := run.Group{}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
service := grpc.NewService(
grpc.Logger(logger),
grpc.Context(ctx),
grpc.Config(cfg),
grpc.Name(cfg.Server.Name),
grpc.Namespace(cfg.Server.Namespace),
grpc.Address(cfg.Server.Address),
grpc.Flags(flagset.RootWithConfig(config.New())),
var (
gr = run.Group{}
ctx, cancel = context.WithCancel(context.Background())
mtrcs = metrics.New()
)
gr.Add(func() error {
logger.Info().Str("service", service.Name()).Msg("Reporting settings bundle to account service")
go svc.RegisterSettingsBundles(&logger)
return service.Run()
}, func(err error) {
if err != nil {
logger.Error().Err(err).Msg("account service died")
} else {
logger.Info().
Str("service", service.Name()).
Msg("Shutting down server")
}
cancel()
})
defer cancel()
{
server := http.Server(
http.Logger(logger),
http.Name(cfg.Server.Name),
http.Context(ctx),
http.Config(cfg),
http.Metrics(mtrcs),
http.Flags(flagset.RootWithConfig(cfg)),
http.Flags(flagset.ServerWithConfig(cfg)),
)
gr.Add(server.Run, func(_ error) {
logger.Info().
Str("server", "http").
Msg("Shutting down server")
cancel()
})
}
{
server := grpc.Server(
grpc.Logger(logger),
grpc.Name(cfg.Server.Name),
grpc.Context(ctx),
grpc.Config(cfg),
grpc.Metrics(mtrcs),
)
gr.Add(func() error {
logger.Info().Str("service", server.Name()).Msg("Reporting settings bundles to settings service")
go svc.RegisterSettingsBundles(&logger)
return server.Run()
}, func(_ error) {
logger.Info().
Str("server", "grpc").
Msg("Shutting down server")
cancel()
})
}
{
stop := make(chan os.Signal, 1)
gr.Add(func() error {
signal.Notify(stop, os.Interrupt)
<-stop
return nil
}, func(err error) {
close(stop)
cancel()
})
}
run.SignalHandler(ctx, syscall.SIGKILL)
return gr.Run()
},
}

View File

@@ -24,14 +24,30 @@ type LDAPSchema struct {
Groups string
}
// HTTP defines the available http configuration.
type HTTP struct {
Addr string
Namespace string
Root string
}
// GRPC defines the available grpc configuration.
type GRPC struct {
Addr string
Namespace string
}
// Server configures a server.
type Server struct {
Name string
Namespace string
Address string
AccountsDataPath string
}
// Asset defines the available asset configuration.
type Asset struct {
Path string
}
// Log defines the available logging configuration.
type Log struct {
Level string
@@ -42,7 +58,10 @@ type Log struct {
// Config merges all Account config parameters.
type Config struct {
LDAP LDAP
HTTP HTTP
GRPC GRPC
Server Server
Asset Asset
Log Log
}

View File

@@ -35,39 +35,61 @@ func RootWithConfig(cfg *config.Config) []cli.Flag {
// ServerWithConfig applies cfg to the root flagset
func ServerWithConfig(cfg *config.Config) []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Name: "http-namespace",
Value: "com.owncloud.web",
Usage: "Set the base namespace for the http namespace",
EnvVars: []string{"ACCOUNTS_HTTP_NAMESPACE"},
Destination: &cfg.HTTP.Namespace,
},
&cli.StringFlag{
Name: "http-addr",
Value: "0.0.0.0:9181",
Usage: "Address to bind http server",
EnvVars: []string{"ACCOUNTS_HTTP_ADDR"},
Destination: &cfg.HTTP.Addr,
},
&cli.StringFlag{
Name: "http-root",
Value: "/",
Usage: "Root path of http server",
EnvVars: []string{"ACCOUNTS_HTTP_ROOT"},
Destination: &cfg.HTTP.Root,
},
&cli.StringFlag{
Name: "grpc-namespace",
Value: "com.owncloud.api",
Usage: "Set the base namespace for the grpc namespace",
EnvVars: []string{"ACCOUNTS_GRPC_NAMESPACE"},
Destination: &cfg.GRPC.Namespace,
},
&cli.StringFlag{
Name: "grpc-addr",
Value: "0.0.0.0:9180",
Usage: "Address to bind grpc server",
EnvVars: []string{"ACCOUNTS_GRPC_ADDR"},
Destination: &cfg.GRPC.Addr,
},
&cli.StringFlag{
Name: "name",
Value: "accounts",
DefaultText: "accounts",
Usage: "service name",
EnvVars: []string{"ACCOUNTS_NAME"},
Destination: &cfg.Server.Name,
},
&cli.StringFlag{
Name: "namespace",
Aliases: []string{"ns"},
Value: "com.owncloud.api",
DefaultText: "com.owncloud.api",
Usage: "namespace",
EnvVars: []string{"ACCOUNTS_NAMESPACE"},
Destination: &cfg.Server.Namespace,
},
&cli.StringFlag{
Name: "address",
Aliases: []string{"addr"},
Value: "localhost:9180",
DefaultText: "localhost:9180",
Usage: "service endpoint",
EnvVars: []string{"ACCOUNTS_ADDRESS"},
Destination: &cfg.Server.Address,
},
&cli.StringFlag{
Name: "accounts-data-path",
Value: "/var/tmp/ocis-accounts",
DefaultText: "/var/tmp/ocis-accounts",
Usage: "accounts folder",
EnvVars: []string{"ACCOUNTS_DATA_PATH"},
Destination: &cfg.Server.AccountsDataPath,
},
&cli.StringFlag{
Name: "asset-path",
Value: "",
Usage: "Path to custom assets",
EnvVars: []string{"HELLO_ASSET_PATH"},
Destination: &cfg.Asset.Path,
},
}
}

22
pkg/metrics/metrics.go Normal file
View File

@@ -0,0 +1,22 @@
package metrics
var (
// Namespace defines the namespace for the defines metrics.
Namespace = "ocis"
// Subsystem defines the subsystem for the defines metrics.
Subsystem = "accounts"
)
// Metrics defines the available metrics of this service.
type Metrics struct {
// Counter *prometheus.CounterVec
}
// New initializes the available metrics.
func New() *Metrics {
m := &Metrics{
}
// TODO: implement metrics
return m
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -15,6 +15,7 @@ import (
import (
context "context"
api "github.com/micro/go-micro/v2/api"
client "github.com/micro/go-micro/v2/client"
server "github.com/micro/go-micro/v2/server"
)
@@ -31,10 +32,53 @@ var _ = math.Inf
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
// Reference imports to suppress errors if they are not otherwise used.
var _ api.Endpoint
var _ context.Context
var _ client.Option
var _ server.Option
// Api Endpoints for AccountsService service
func NewAccountsServiceEndpoints() []*api.Endpoint {
return []*api.Endpoint{
&api.Endpoint{
Name: "AccountsService.ListAccounts",
Path: []string{"/api/v0/accounts/accounts-list"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
},
&api.Endpoint{
Name: "AccountsService.GetAccount",
Path: []string{"/api/v0/accounts/accounts-get"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
},
&api.Endpoint{
Name: "AccountsService.CreateAccount",
Path: []string{"/api/v0/accounts/accounts-create"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
},
&api.Endpoint{
Name: "AccountsService.UpdateAccount",
Path: []string{"/api/v0/accounts/accounts-update"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
},
&api.Endpoint{
Name: "AccountsService.DeleteAccount",
Path: []string{"/api/v0/accounts/accounts-delete"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
},
}
}
// Client API for AccountsService service
type AccountsService interface {
@@ -139,6 +183,41 @@ func RegisterAccountsServiceHandler(s server.Server, hdlr AccountsServiceHandler
accountsService
}
h := &accountsServiceHandler{hdlr}
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "AccountsService.ListAccounts",
Path: []string{"/api/v0/accounts/accounts-list"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "AccountsService.GetAccount",
Path: []string{"/api/v0/accounts/accounts-get"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "AccountsService.CreateAccount",
Path: []string{"/api/v0/accounts/accounts-create"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "AccountsService.UpdateAccount",
Path: []string{"/api/v0/accounts/accounts-update"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "AccountsService.DeleteAccount",
Path: []string{"/api/v0/accounts/accounts-delete"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
}))
return s.Handle(s.NewHandler(&AccountsService{h}, opts...))
}
@@ -166,6 +245,66 @@ func (h *accountsServiceHandler) DeleteAccount(ctx context.Context, in *DeleteAc
return h.AccountsServiceHandler.DeleteAccount(ctx, in, out)
}
// Api Endpoints for GroupsService service
func NewGroupsServiceEndpoints() []*api.Endpoint {
return []*api.Endpoint{
&api.Endpoint{
Name: "GroupsService.ListGroups",
Path: []string{"/v0/groups"},
Method: []string{"GET"},
Handler: "rpc",
},
&api.Endpoint{
Name: "GroupsService.GetGroup",
Path: []string{"/v0/groups/{id=*}"},
Method: []string{"GET"},
Handler: "rpc",
},
&api.Endpoint{
Name: "GroupsService.CreateGroup",
Path: []string{"/v0/groups"},
Method: []string{"POST"},
Body: "group",
Handler: "rpc",
},
&api.Endpoint{
Name: "GroupsService.UpdateGroup",
Path: []string{"/v0/groups/{group.id=*}"},
Method: []string{"PATCH"},
Body: "group",
Handler: "rpc",
},
&api.Endpoint{
Name: "GroupsService.DeleteGroup",
Path: []string{"/v0/groups/{id=*}"},
Method: []string{"DELETE"},
Body: "",
Handler: "rpc",
},
&api.Endpoint{
Name: "GroupsService.AddMember",
Path: []string{"/v0/groups/{id=*}/members/$ref"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
},
&api.Endpoint{
Name: "GroupsService.RemoveMember",
Path: []string{"/v0/groups/{id=*}/members/{account_id}/$ref"},
Method: []string{"DELETE"},
Body: "",
Handler: "rpc",
},
&api.Endpoint{
Name: "GroupsService.ListMembers",
Path: []string{"/v0/groups/{id=*}/members/$ref"},
Method: []string{"GET"},
Handler: "rpc",
},
}
}
// Client API for GroupsService service
type GroupsService interface {
@@ -315,6 +454,59 @@ func RegisterGroupsServiceHandler(s server.Server, hdlr GroupsServiceHandler, op
groupsService
}
h := &groupsServiceHandler{hdlr}
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "GroupsService.ListGroups",
Path: []string{"/v0/groups"},
Method: []string{"GET"},
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "GroupsService.GetGroup",
Path: []string{"/v0/groups/{id=*}"},
Method: []string{"GET"},
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "GroupsService.CreateGroup",
Path: []string{"/v0/groups"},
Method: []string{"POST"},
Body: "group",
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "GroupsService.UpdateGroup",
Path: []string{"/v0/groups/{group.id=*}"},
Method: []string{"PATCH"},
Body: "group",
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "GroupsService.DeleteGroup",
Path: []string{"/v0/groups/{id=*}"},
Method: []string{"DELETE"},
Body: "",
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "GroupsService.AddMember",
Path: []string{"/v0/groups/{id=*}/members/$ref"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "GroupsService.RemoveMember",
Path: []string{"/v0/groups/{id=*}/members/{account_id}/$ref"},
Method: []string{"DELETE"},
Body: "",
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "GroupsService.ListMembers",
Path: []string{"/v0/groups/{id=*}/members/$ref"},
Method: []string{"GET"},
Handler: "rpc",
}))
return s.Handle(s.NewHandler(&GroupsService{h}, opts...))
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -18,13 +18,14 @@ service AccountsService {
rpc ListAccounts(ListAccountsRequest) returns (ListAccountsResponse) {
// List method maps to HTTP GET
option (google.api.http) = {
get: "/v0/accounts"
post: "/api/v0/accounts/accounts-list",
body: "*"
};
}
// Gets an account
rpc GetAccount(GetAccountRequest) returns (Account) {
option (google.api.http) = {
get: "/v0/accounts/{id=*}"
post: "/api/v0/accounts/accounts-get",
body: "*"
};
}
@@ -33,8 +34,8 @@ service AccountsService {
// Create maps to HTTP POST. URL path as the collection name.
// HTTP request body contains the resource
option (google.api.http) = {
post: "/v0/accounts"
body: "account"
post: "/api/v0/accounts/accounts-create"
body: "*"
};
}
// Updates an account
@@ -42,8 +43,8 @@ service AccountsService {
// Update maps to HTTP PATCH. Resource name is mapped to a URL path.
// Resource is contained in the HTTP request body
option (google.api.http) = {
patch: "/v0/accounts/{account.id=*}"
body: "account"
post: "/api/v0/accounts/accounts-update"
body: "*"
};
};
// Deletes an account
@@ -51,7 +52,8 @@ service AccountsService {
// Delete maps to HTTP DELETE. Resource name maps to the URL path.
// There is no request body
option (google.api.http) = {
delete: "/v0/accounts/{id=*}"
post: "/api/v0/accounts/accounts-delete",
body: "*"
};
}
}
@@ -68,7 +70,6 @@ service GroupsService {
rpc GetGroup(GetGroupRequest) returns (Group) {
option (google.api.http) = {
get: "/v0/groups/{id=*}"
body: "*"
};
}
// Creates a group
@@ -115,8 +116,7 @@ service GroupsService {
rpc RemoveMember(RemoveMemberRequest) returns (Group) {
// All request parameters go into body.
option (google.api.http) = {
delete: "/v0/groups/{id=*}/members/{account.id}/$ref"
body: "*"
delete: "/v0/groups/{id=*}/members/{account_id}/$ref"
};
}
// group:listmembers https://docs.microsoft.com/en-us/graph/api/group-list-members?view=graph-rest-1.0
@@ -476,9 +476,11 @@ message AddMemberRequest {
}
message RemoveMemberRequest {
// The account id to remove
// TODO id in the body indt in the url? not necessary ... use empty?
// The group id
string id = 1;
// The account id to remove
string account_id = 2;
}
message ListMembersRequest {
@@ -511,6 +513,9 @@ message ListMembersRequest {
// * Query `display_name=\\"Test String\\"` returns groups with
// display names that include both "Test" and "String"
string query = 4 [(google.api.field_behavior) = OPTIONAL];
// The group id
string id = 5;
}
message ListMembersResponse {
@@ -638,4 +643,4 @@ message OnPremisesProvisioningError {
string property_causing_error = 3;
// Value of the property causing the error.
string value = 4;
}
}

View File

File diff suppressed because one or more lines are too long

View File

@@ -5,6 +5,7 @@ import (
"github.com/micro/cli/v2"
"github.com/owncloud/ocis-accounts/pkg/config"
"github.com/owncloud/ocis-accounts/pkg/metrics"
"github.com/owncloud/ocis-pkg/v2/log"
)
@@ -14,11 +15,10 @@ type Option func(o *Options)
// Options defines the available options for this package.
type Options struct {
Name string
Address string
Logger log.Logger
Context context.Context
Config *config.Config
Namespace string
Metrics *metrics.Metrics
Flags []cli.Flag
}
@@ -33,13 +33,6 @@ func newOptions(opts ...Option) Options {
return opt
}
// Logger provides a function to set the logger option.
func Logger(val log.Logger) Option {
return func(o *Options) {
o.Logger = val
}
}
// Name provides a name for the service.
func Name(val string) Option {
return func(o *Options) {
@@ -47,10 +40,10 @@ func Name(val string) Option {
}
}
// Address provides an address for the service.
func Address(val string) Option {
// Logger provides a function to set the logger option.
func Logger(val log.Logger) Option {
return func(o *Options) {
o.Address = val
o.Logger = val
}
}
@@ -68,10 +61,10 @@ func Config(val *config.Config) Option {
}
}
// Namespace provides a function to set the namespace option.
func Namespace(val string) Option {
// Metrics provides a function to set the metrics option.
func Metrics(val *metrics.Metrics) Option {
return func(o *Options) {
o.Namespace = val
o.Metrics = val
}
}

View File

@@ -6,15 +6,15 @@ import (
"github.com/owncloud/ocis-pkg/v2/service/grpc"
)
// NewService initializes a new go-micro service ready to run
func NewService(opts ...Option) grpc.Service {
// Server initializes a new go-micro service ready to run
func Server(opts ...Option) grpc.Service {
options := newOptions(opts...)
service := grpc.NewService(
grpc.Name(options.Name),
grpc.Name(options.Config.Server.Name),
grpc.Context(options.Context),
grpc.Address(options.Address),
grpc.Namespace(options.Namespace),
grpc.Address(options.Config.GRPC.Addr),
grpc.Namespace(options.Config.GRPC.Namespace),
grpc.Logger(options.Logger),
grpc.Flags(options.Flags...),
)

76
pkg/server/http/option.go Normal file
View File

@@ -0,0 +1,76 @@
package http
import (
"context"
"github.com/micro/cli/v2"
"github.com/owncloud/ocis-accounts/pkg/config"
"github.com/owncloud/ocis-accounts/pkg/metrics"
"github.com/owncloud/ocis-pkg/v2/log"
)
// Option defines a single option function.
type Option func(o *Options)
// Options defines the available options for this package.
type Options struct {
Name string
Logger log.Logger
Context context.Context
Config *config.Config
Metrics *metrics.Metrics
Flags []cli.Flag
}
// newOptions initializes the available default options.
func newOptions(opts ...Option) Options {
opt := Options{}
for _, o := range opts {
o(&opt)
}
return opt
}
// Name provides a name for the service.
func Name(val string) Option {
return func(o *Options) {
o.Name = val
}
}
// Logger provides a function to set the logger option.
func Logger(val log.Logger) Option {
return func(o *Options) {
o.Logger = val
}
}
// Context provides a function to set the context option.
func Context(val context.Context) Option {
return func(o *Options) {
o.Context = val
}
}
// Config provides a function to set the config option.
func Config(val *config.Config) Option {
return func(o *Options) {
o.Config = val
}
}
// Metrics provides a function to set the metrics option.
func Metrics(val *metrics.Metrics) Option {
return func(o *Options) {
o.Metrics = val
}
}
// Flags provides a function to set the flags option.
func Flags(val []cli.Flag) Option {
return func(o *Options) {
o.Flags = append(o.Flags, val...)
}
}

71
pkg/server/http/server.go Normal file
View File

@@ -0,0 +1,71 @@
package http
import (
"github.com/go-chi/chi"
"github.com/owncloud/ocis-accounts/pkg/assets"
"github.com/owncloud/ocis-accounts/pkg/proto/v0"
svc "github.com/owncloud/ocis-accounts/pkg/service/v0"
"github.com/owncloud/ocis-accounts/pkg/version"
"github.com/owncloud/ocis-pkg/v2/middleware"
"github.com/owncloud/ocis-pkg/v2/service/http"
)
// Server initializes the http service and server.
func Server(opts ...Option) http.Service {
options := newOptions(opts...)
service := http.NewService(
http.Logger(options.Logger),
http.Name(options.Name),
http.Version(version.String),
http.Address(options.Config.HTTP.Addr),
http.Namespace(options.Config.HTTP.Namespace),
http.Context(options.Context),
http.Flags(options.Flags...),
)
handler, err := svc.New(svc.Logger(options.Logger), svc.Config(options.Config))
if err != nil {
options.Logger.Fatal().Err(err).Msg("could not initialize service handler")
}
mux := chi.NewMux()
mux.Use(middleware.RealIP)
mux.Use(middleware.RequestID)
mux.Use(middleware.Cache)
mux.Use(middleware.Cors)
mux.Use(middleware.Secure)
mux.Use(middleware.Version(
options.Name,
version.String,
))
mux.Use(middleware.Logger(
options.Logger,
))
mux.Use(middleware.Static(
options.Config.HTTP.Root,
assets.New(
assets.Logger(options.Logger),
assets.Config(options.Config),
),
))
mux.Route(options.Config.HTTP.Root, func(r chi.Router) {
proto.RegisterAccountsServiceWeb(r, handler)
proto.RegisterGroupsServiceWeb(r, handler)
})
service.Handle(
"/",
mux,
)
if err := service.Init(); err != nil {
panic(err)
}
return service
}

View File

@@ -33,7 +33,6 @@ import (
)
// New returns a new instance of Service
// TODO pass in logger as options
func New(opts ...Option) (s *Service, err error) {
options := newOptions(opts...)
logger := options.Logger
@@ -121,14 +120,14 @@ func New(opts ...Option) (s *Service, err error) {
// TODO groups
for i := range accounts {
var bytes []byte
if bytes, err = json.Marshal(accounts[i]); err != nil {
logger.Error().Err(err).Interface("account", accounts[i]).Msg("could not marshal default account")
if bytes, err = json.Marshal(&accounts[i]); err != nil {
logger.Error().Err(err).Interface("account", &accounts[i]).Msg("could not marshal default account")
return
}
path := filepath.Join(accountsDir, accounts[i].Id)
if err = ioutil.WriteFile(path, bytes, 0600); err != nil {
accounts[i].PasswordProfile.Password = "***REMOVED***"
logger.Error().Err(err).Str("path", path).Interface("account", accounts[i]).Msg("could not persist default account")
logger.Error().Err(err).Str("path", path).Interface("account", &accounts[i]).Msg("could not persist default account")
return
}
}
@@ -173,9 +172,9 @@ func New(opts ...Option) (s *Service, err error) {
logger.Error().Err(err).Str("path", path).Msg("could not unmarshal account")
continue
}
logger.Debug().Interface("account", a).Msg("found account")
if err = s.index.Index(a.Id, a); err != nil {
logger.Error().Err(err).Str("path", path).Interface("account", a).Msg("could not index account")
logger.Debug().Interface("account", &a).Msg("found account")
if err = s.index.Index(a.Id, &a); err != nil {
logger.Error().Err(err).Str("path", path).Interface("account", &a).Msg("could not index account")
continue
}
}
@@ -263,11 +262,11 @@ func (s Service) ListAccounts(ctx context.Context, in *proto.ListAccountsRequest
s.log.Error().Err(err).Str("path", path).Msg("could not unmarshal account")
continue
}
s.log.Debug().Interface("account", a).Msg("found account")
s.log.Debug().Interface("account", &a).Msg("found account")
if password != "" {
if a.PasswordProfile == nil {
s.log.Debug().Interface("account", a).Msg("no password profile")
s.log.Debug().Interface("account", &a).Msg("no password profile")
return fmt.Errorf("invalid password")
}
if !s.passwordIsValid(a.PasswordProfile.Password, password) {
@@ -421,6 +420,21 @@ func (s Service) DeleteGroup(c context.Context, req *proto.DeleteGroupRequest, r
return errors.New("not implemented")
}
// AddMember implements the AccountsServiceHandler interface
func (s Service) AddMember(c context.Context, req *proto.AddMemberRequest, res *proto.Group) error {
return errors.New("not implemented")
}
// RemoveMember implements the AccountsServiceHandler interface
func (s Service) RemoveMember(c context.Context, req *proto.RemoveMemberRequest, res *proto.Group) error {
return errors.New("not implemented")
}
// ListMembers implements the AccountsServiceHandler interface
func (s Service) ListMembers(c context.Context, req *proto.ListMembersRequest, res *proto.ListMembersResponse) error {
return errors.New("not implemented")
}
// RegisterSettingsBundles pushes the settings bundle definitions for this extension to the ocis-settings service.
func RegisterSettingsBundles(l *log.Logger) {
// TODO this won't work with a registry other than mdns. Look into Micro's client initialization.

5
reflex.conf Normal file
View File

@@ -0,0 +1,5 @@
# backend
-r '^(cmd|pkg)/.*\.go$' -R '^node_modules/' -s -- sh -c 'make bin/ocis-accounts && bin/ocis-accounts server --asset-path assets/'
# frontend
-r '^ui/.*\.(vue|js)$' -R '^node_modules/' -- sh -c 'yarn build && make generate'

52
rollup.config.js Normal file
View File

@@ -0,0 +1,52 @@
import vue from 'rollup-plugin-vue'
import { terser } from 'rollup-plugin-terser'
import replace from '@rollup/plugin-replace'
import filesize from 'rollup-plugin-filesize'
import resolve from 'rollup-plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import babel from 'rollup-plugin-babel'
import json from '@rollup/plugin-json'
import builtins from '@erquhart/rollup-plugin-node-builtins'
import globals from 'rollup-plugin-node-globals'
const production = !process.env.ROLLUP_WATCH
// We can't really do much about circular dependencies in node_modules
function onwarn (warning) {
if (warning.code !== 'CIRCULAR_DEPENDENCY') {
console.error(`(!) ${warning.message}`)
}
}
export default {
input: 'ui/app.js',
output: {
file: 'assets/accounts.js',
format: 'amd',
sourcemap: !production
},
onwarn,
plugins: [
vue(),
replace({
'process.env.NODE_ENV': JSON.stringify('production')
}),
resolve({
mainFields: ['browser', 'jsnext', 'module', 'main'],
include: 'node_modules/**',
preferBuiltins: true
}),
babel({
exclude: 'node_modules/**',
runtimeHelpers: true
}),
commonjs({
include: 'node_modules/**'
}),
json(),
globals(),
builtins(),
production && terser(),
production && filesize()
]
}

39
ui/app.js Normal file
View File

@@ -0,0 +1,39 @@
import 'regenerator-runtime/runtime'
import App from './components/App.vue'
import store from './store'
const appInfo = {
name: 'Accounts',
id: 'accounts',
icon: 'text-vcard',
isFileEditor: false,
extensions: []
}
const routes = [
{
name: 'accounts',
path: '/',
components: {
app: App
}
}
]
const navItems = [
{
name: 'Accounts',
iconMaterial: appInfo.icon,
route: {
name: 'accounts',
path: `/${appInfo.id}/`
}
}
]
export default {
appInfo,
routes,
navItems,
store
}

723
ui/client/accounts/index.js Normal file
View File

@@ -0,0 +1,723 @@
/* eslint-disable */
import axios from 'axios'
import qs from 'qs'
let domain = ''
export const getDomain = () => {
return domain
}
export const setDomain = ($domain) => {
domain = $domain
}
export const request = (method, url, body, queryParameters, form, config) => {
method = method.toLowerCase()
let keys = Object.keys(queryParameters)
let queryUrl = url
if (keys.length > 0) {
queryUrl = url + '?' + qs.stringify(queryParameters)
}
// let queryUrl = url+(keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '')
if (body) {
return axios[method](queryUrl, body, config)
} else if (method === 'get') {
return axios[method](queryUrl, config)
} else {
return axios[method](queryUrl, qs.stringify(form), config)
}
}
/*==========================================================
*
==========================================================*/
/**
* Creates an account
* request: AccountsService_CreateAccount
* url: AccountsService_CreateAccountURL
* method: AccountsService_CreateAccount_TYPE
* raw_url: AccountsService_CreateAccount_RAW_URL
* @param body -
*/
export const AccountsService_CreateAccount = function(parameters = {}) {
const domain = parameters.$domain ? parameters.$domain : getDomain()
const config = parameters.$config
let path = '/api/v0/accounts/accounts-create'
let body
let queryParameters = {}
let form = {}
if (parameters['body'] !== undefined) {
body = parameters['body']
}
if (parameters['body'] === undefined) {
return Promise.reject(new Error('Missing required parameter: body'))
}
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
});
}
return request('post', domain + path, body, queryParameters, form, config)
}
export const AccountsService_CreateAccount_RAW_URL = function() {
return '/api/v0/accounts/accounts-create'
}
export const AccountsService_CreateAccount_TYPE = function() {
return 'post'
}
export const AccountsService_CreateAccountURL = function(parameters = {}) {
let queryParameters = {}
const domain = parameters.$domain ? parameters.$domain : getDomain()
let path = '/api/v0/accounts/accounts-create'
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
})
}
let keys = Object.keys(queryParameters)
return domain + path + (keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '')
}
/**
* Deletes an account
* request: AccountsService_DeleteAccount
* url: AccountsService_DeleteAccountURL
* method: AccountsService_DeleteAccount_TYPE
* raw_url: AccountsService_DeleteAccount_RAW_URL
* @param body -
*/
export const AccountsService_DeleteAccount = function(parameters = {}) {
const domain = parameters.$domain ? parameters.$domain : getDomain()
const config = parameters.$config
let path = '/api/v0/accounts/accounts-delete'
let body
let queryParameters = {}
let form = {}
if (parameters['body'] !== undefined) {
body = parameters['body']
}
if (parameters['body'] === undefined) {
return Promise.reject(new Error('Missing required parameter: body'))
}
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
});
}
return request('post', domain + path, body, queryParameters, form, config)
}
export const AccountsService_DeleteAccount_RAW_URL = function() {
return '/api/v0/accounts/accounts-delete'
}
export const AccountsService_DeleteAccount_TYPE = function() {
return 'post'
}
export const AccountsService_DeleteAccountURL = function(parameters = {}) {
let queryParameters = {}
const domain = parameters.$domain ? parameters.$domain : getDomain()
let path = '/api/v0/accounts/accounts-delete'
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
})
}
let keys = Object.keys(queryParameters)
return domain + path + (keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '')
}
/**
* Gets an account
* request: AccountsService_GetAccount
* url: AccountsService_GetAccountURL
* method: AccountsService_GetAccount_TYPE
* raw_url: AccountsService_GetAccount_RAW_URL
* @param body -
*/
export const AccountsService_GetAccount = function(parameters = {}) {
const domain = parameters.$domain ? parameters.$domain : getDomain()
const config = parameters.$config
let path = '/api/v0/accounts/accounts-get'
let body
let queryParameters = {}
let form = {}
if (parameters['body'] !== undefined) {
body = parameters['body']
}
if (parameters['body'] === undefined) {
return Promise.reject(new Error('Missing required parameter: body'))
}
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
});
}
return request('post', domain + path, body, queryParameters, form, config)
}
export const AccountsService_GetAccount_RAW_URL = function() {
return '/api/v0/accounts/accounts-get'
}
export const AccountsService_GetAccount_TYPE = function() {
return 'post'
}
export const AccountsService_GetAccountURL = function(parameters = {}) {
let queryParameters = {}
const domain = parameters.$domain ? parameters.$domain : getDomain()
let path = '/api/v0/accounts/accounts-get'
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
})
}
let keys = Object.keys(queryParameters)
return domain + path + (keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '')
}
/**
* Lists accounts
* request: AccountsService_ListAccounts
* url: AccountsService_ListAccountsURL
* method: AccountsService_ListAccounts_TYPE
* raw_url: AccountsService_ListAccounts_RAW_URL
* @param body -
*/
export const AccountsService_ListAccounts = function(parameters = {}) {
const domain = parameters.$domain ? parameters.$domain : getDomain()
const config = parameters.$config
let path = '/api/v0/accounts/accounts-list'
let body
let queryParameters = {}
let form = {}
if (parameters['body'] !== undefined) {
body = parameters['body']
}
if (parameters['body'] === undefined) {
return Promise.reject(new Error('Missing required parameter: body'))
}
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
});
}
return request('post', domain + path, body, queryParameters, form, config)
}
export const AccountsService_ListAccounts_RAW_URL = function() {
return '/api/v0/accounts/accounts-list'
}
export const AccountsService_ListAccounts_TYPE = function() {
return 'post'
}
export const AccountsService_ListAccountsURL = function(parameters = {}) {
let queryParameters = {}
const domain = parameters.$domain ? parameters.$domain : getDomain()
let path = '/api/v0/accounts/accounts-list'
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
})
}
let keys = Object.keys(queryParameters)
return domain + path + (keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '')
}
/**
* Updates an account
* request: AccountsService_UpdateAccount
* url: AccountsService_UpdateAccountURL
* method: AccountsService_UpdateAccount_TYPE
* raw_url: AccountsService_UpdateAccount_RAW_URL
* @param body -
*/
export const AccountsService_UpdateAccount = function(parameters = {}) {
const domain = parameters.$domain ? parameters.$domain : getDomain()
const config = parameters.$config
let path = '/api/v0/accounts/accounts-update'
let body
let queryParameters = {}
let form = {}
if (parameters['body'] !== undefined) {
body = parameters['body']
}
if (parameters['body'] === undefined) {
return Promise.reject(new Error('Missing required parameter: body'))
}
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
});
}
return request('post', domain + path, body, queryParameters, form, config)
}
export const AccountsService_UpdateAccount_RAW_URL = function() {
return '/api/v0/accounts/accounts-update'
}
export const AccountsService_UpdateAccount_TYPE = function() {
return 'post'
}
export const AccountsService_UpdateAccountURL = function(parameters = {}) {
let queryParameters = {}
const domain = parameters.$domain ? parameters.$domain : getDomain()
let path = '/api/v0/accounts/accounts-update'
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
})
}
let keys = Object.keys(queryParameters)
return domain + path + (keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '')
}
/**
* Lists groups
* request: GroupsService_ListGroups
* url: GroupsService_ListGroupsURL
* method: GroupsService_ListGroups_TYPE
* raw_url: GroupsService_ListGroups_RAW_URL
* @param pageSize - Optional. The maximum number of groups to return in the response.
* @param pageToken - Optional. A pagination token returned from a previous call to `Get`
that indicates from where search should continue.
* @param fieldMaskPaths - The set of field mask paths.
* @param query - Optional. Search criteria used to select the groups to return.
If no search criteria is specified then all groups will be
returned. TODO update query language
Query expressions can be used to restrict results based upon
the account properties where the operators `=`, `NOT`, `AND` and `OR`
can be used along with the suffix wildcard symbol `*`.
The string properties in a query expression should use escaped quotes
for values that include whitespace to prevent unexpected behavior.
Some example queries are:
* Query `display_name=Th*` returns accounts whose display_name
starts with "Th"
* Query `display_name=\\"Test String\\"` returns groups with
display names that include both "Test" and "String"
*/
export const GroupsService_ListGroups = function(parameters = {}) {
const domain = parameters.$domain ? parameters.$domain : getDomain()
const config = parameters.$config
let path = '/v0/groups'
let body
let queryParameters = {}
let form = {}
if (parameters['pageSize'] !== undefined) {
queryParameters['page_size'] = parameters['pageSize']
}
if (parameters['pageToken'] !== undefined) {
queryParameters['page_token'] = parameters['pageToken']
}
if (parameters['fieldMaskPaths'] !== undefined) {
queryParameters['field_mask.paths'] = parameters['fieldMaskPaths']
}
if (parameters['query'] !== undefined) {
queryParameters['query'] = parameters['query']
}
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
});
}
return request('get', domain + path, body, queryParameters, form, config)
}
export const GroupsService_ListGroups_RAW_URL = function() {
return '/v0/groups'
}
export const GroupsService_ListGroups_TYPE = function() {
return 'get'
}
export const GroupsService_ListGroupsURL = function(parameters = {}) {
let queryParameters = {}
const domain = parameters.$domain ? parameters.$domain : getDomain()
let path = '/v0/groups'
if (parameters['pageSize'] !== undefined) {
queryParameters['page_size'] = parameters['pageSize']
}
if (parameters['pageToken'] !== undefined) {
queryParameters['page_token'] = parameters['pageToken']
}
if (parameters['fieldMaskPaths'] !== undefined) {
queryParameters['field_mask.paths'] = parameters['fieldMaskPaths']
}
if (parameters['query'] !== undefined) {
queryParameters['query'] = parameters['query']
}
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
})
}
let keys = Object.keys(queryParameters)
return domain + path + (keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '')
}
/**
* Creates a group
* request: GroupsService_CreateGroup
* url: GroupsService_CreateGroupURL
* method: GroupsService_CreateGroup_TYPE
* raw_url: GroupsService_CreateGroup_RAW_URL
* @param body - The account resource to create
*/
export const GroupsService_CreateGroup = function(parameters = {}) {
const domain = parameters.$domain ? parameters.$domain : getDomain()
const config = parameters.$config
let path = '/v0/groups'
let body
let queryParameters = {}
let form = {}
if (parameters['body'] !== undefined) {
body = parameters['body']
}
if (parameters['body'] === undefined) {
return Promise.reject(new Error('Missing required parameter: body'))
}
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
});
}
return request('post', domain + path, body, queryParameters, form, config)
}
export const GroupsService_CreateGroup_RAW_URL = function() {
return '/v0/groups'
}
export const GroupsService_CreateGroup_TYPE = function() {
return 'post'
}
export const GroupsService_CreateGroupURL = function(parameters = {}) {
let queryParameters = {}
const domain = parameters.$domain ? parameters.$domain : getDomain()
let path = '/v0/groups'
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
})
}
let keys = Object.keys(queryParameters)
return domain + path + (keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '')
}
/**
* Updates a group
* request: GroupsService_UpdateGroup
* url: GroupsService_UpdateGroupURL
* method: GroupsService_UpdateGroup_TYPE
* raw_url: GroupsService_UpdateGroup_RAW_URL
* @param groupId - The unique identifier for the group.
Returned by default. Inherited from directoryObject. Key. Not nullable. Read-only.
* @param body - The group resource which replaces the resource on the server
*/
export const GroupsService_UpdateGroup = function(parameters = {}) {
const domain = parameters.$domain ? parameters.$domain : getDomain()
const config = parameters.$config
let path = '/v0/groups/{group.id}'
let body
let queryParameters = {}
let form = {}
path = path.replace('{group.id}', `${parameters['groupId']}`)
if (parameters['groupId'] === undefined) {
return Promise.reject(new Error('Missing required parameter: groupId'))
}
if (parameters['body'] !== undefined) {
body = parameters['body']
}
if (parameters['body'] === undefined) {
return Promise.reject(new Error('Missing required parameter: body'))
}
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
});
}
return request('patch', domain + path, body, queryParameters, form, config)
}
export const GroupsService_UpdateGroup_RAW_URL = function() {
return '/v0/groups/{group.id}'
}
export const GroupsService_UpdateGroup_TYPE = function() {
return 'patch'
}
export const GroupsService_UpdateGroupURL = function(parameters = {}) {
let queryParameters = {}
const domain = parameters.$domain ? parameters.$domain : getDomain()
let path = '/v0/groups/{group.id}'
path = path.replace('{group.id}', `${parameters['groupId']}`)
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
})
}
let keys = Object.keys(queryParameters)
return domain + path + (keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '')
}
/**
* Gets an groups
* request: GroupsService_GetGroup
* url: GroupsService_GetGroupURL
* method: GroupsService_GetGroup_TYPE
* raw_url: GroupsService_GetGroup_RAW_URL
* @param id -
*/
export const GroupsService_GetGroup = function(parameters = {}) {
const domain = parameters.$domain ? parameters.$domain : getDomain()
const config = parameters.$config
let path = '/v0/groups/{id}'
let body
let queryParameters = {}
let form = {}
path = path.replace('{id}', `${parameters['id']}`)
if (parameters['id'] === undefined) {
return Promise.reject(new Error('Missing required parameter: id'))
}
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
});
}
return request('get', domain + path, body, queryParameters, form, config)
}
export const GroupsService_GetGroup_RAW_URL = function() {
return '/v0/groups/{id}'
}
export const GroupsService_GetGroup_TYPE = function() {
return 'get'
}
export const GroupsService_GetGroupURL = function(parameters = {}) {
let queryParameters = {}
const domain = parameters.$domain ? parameters.$domain : getDomain()
let path = '/v0/groups/{id}'
path = path.replace('{id}', `${parameters['id']}`)
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
})
}
let keys = Object.keys(queryParameters)
return domain + path + (keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '')
}
/**
* Deletes a group
* request: GroupsService_DeleteGroup
* url: GroupsService_DeleteGroupURL
* method: GroupsService_DeleteGroup_TYPE
* raw_url: GroupsService_DeleteGroup_RAW_URL
* @param id -
*/
export const GroupsService_DeleteGroup = function(parameters = {}) {
const domain = parameters.$domain ? parameters.$domain : getDomain()
const config = parameters.$config
let path = '/v0/groups/{id}'
let body
let queryParameters = {}
let form = {}
path = path.replace('{id}', `${parameters['id']}`)
if (parameters['id'] === undefined) {
return Promise.reject(new Error('Missing required parameter: id'))
}
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
});
}
return request('delete', domain + path, body, queryParameters, form, config)
}
export const GroupsService_DeleteGroup_RAW_URL = function() {
return '/v0/groups/{id}'
}
export const GroupsService_DeleteGroup_TYPE = function() {
return 'delete'
}
export const GroupsService_DeleteGroupURL = function(parameters = {}) {
let queryParameters = {}
const domain = parameters.$domain ? parameters.$domain : getDomain()
let path = '/v0/groups/{id}'
path = path.replace('{id}', `${parameters['id']}`)
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
})
}
let keys = Object.keys(queryParameters)
return domain + path + (keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '')
}
/**
* group:listmembers https://docs.microsoft.com/en-us/graph/api/group-list-members?view=graph-rest-1.0
* request: GroupsService_ListMembers
* url: GroupsService_ListMembersURL
* method: GroupsService_ListMembers_TYPE
* raw_url: GroupsService_ListMembers_RAW_URL
* @param id - The group id
* @param pageSize -
* @param pageToken - Optional. A pagination token returned from a previous call to `Get`
that indicates from where search should continue.
* @param fieldMaskPaths - The set of field mask paths.
* @param query - Optional. Search criteria used to select the groups to return.
If no search criteria is specified then all groups will be
returned. TODO update query language
Query expressions can be used to restrict results based upon
the account properties where the operators `=`, `NOT`, `AND` and `OR`
can be used along with the suffix wildcard symbol `*`.
The string properties in a query expression should use escaped quotes
for values that include whitespace to prevent unexpected behavior.
Some example queries are:
* Query `display_name=Th*` returns accounts whose display_name
starts with "Th"
* Query `display_name=\\"Test String\\"` returns groups with
display names that include both "Test" and "String"
*/
export const GroupsService_ListMembers = function(parameters = {}) {
const domain = parameters.$domain ? parameters.$domain : getDomain()
const config = parameters.$config
let path = '/v0/groups/{id}/members/$ref'
let body
let queryParameters = {}
let form = {}
path = path.replace('{id}', `${parameters['id']}`)
if (parameters['id'] === undefined) {
return Promise.reject(new Error('Missing required parameter: id'))
}
if (parameters['pageSize'] !== undefined) {
queryParameters['page_size'] = parameters['pageSize']
}
if (parameters['pageToken'] !== undefined) {
queryParameters['page_token'] = parameters['pageToken']
}
if (parameters['fieldMaskPaths'] !== undefined) {
queryParameters['field_mask.paths'] = parameters['fieldMaskPaths']
}
if (parameters['query'] !== undefined) {
queryParameters['query'] = parameters['query']
}
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
});
}
return request('get', domain + path, body, queryParameters, form, config)
}
export const GroupsService_ListMembers_RAW_URL = function() {
return '/v0/groups/{id}/members/$ref'
}
export const GroupsService_ListMembers_TYPE = function() {
return 'get'
}
export const GroupsService_ListMembersURL = function(parameters = {}) {
let queryParameters = {}
const domain = parameters.$domain ? parameters.$domain : getDomain()
let path = '/v0/groups/{id}/members/$ref'
path = path.replace('{id}', `${parameters['id']}`)
if (parameters['pageSize'] !== undefined) {
queryParameters['page_size'] = parameters['pageSize']
}
if (parameters['pageToken'] !== undefined) {
queryParameters['page_token'] = parameters['pageToken']
}
if (parameters['fieldMaskPaths'] !== undefined) {
queryParameters['field_mask.paths'] = parameters['fieldMaskPaths']
}
if (parameters['query'] !== undefined) {
queryParameters['query'] = parameters['query']
}
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
})
}
let keys = Object.keys(queryParameters)
return domain + path + (keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '')
}
/**
* group:addmember https://docs.microsoft.com/en-us/graph/api/group-post-members?view=graph-rest-1.0&tabs=http
* request: GroupsService_AddMember
* url: GroupsService_AddMemberURL
* method: GroupsService_AddMember_TYPE
* raw_url: GroupsService_AddMember_RAW_URL
* @param id - The account id to add
* @param body -
*/
export const GroupsService_AddMember = function(parameters = {}) {
const domain = parameters.$domain ? parameters.$domain : getDomain()
const config = parameters.$config
let path = '/v0/groups/{id}/members/$ref'
let body
let queryParameters = {}
let form = {}
path = path.replace('{id}', `${parameters['id']}`)
if (parameters['id'] === undefined) {
return Promise.reject(new Error('Missing required parameter: id'))
}
if (parameters['body'] !== undefined) {
body = parameters['body']
}
if (parameters['body'] === undefined) {
return Promise.reject(new Error('Missing required parameter: body'))
}
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
});
}
return request('post', domain + path, body, queryParameters, form, config)
}
export const GroupsService_AddMember_RAW_URL = function() {
return '/v0/groups/{id}/members/$ref'
}
export const GroupsService_AddMember_TYPE = function() {
return 'post'
}
export const GroupsService_AddMemberURL = function(parameters = {}) {
let queryParameters = {}
const domain = parameters.$domain ? parameters.$domain : getDomain()
let path = '/v0/groups/{id}/members/$ref'
path = path.replace('{id}', `${parameters['id']}`)
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
})
}
let keys = Object.keys(queryParameters)
return domain + path + (keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '')
}
/**
* group:removemember https://docs.microsoft.com/en-us/graph/api/group-delete-members?view=graph-rest-1.0
* request: GroupsService_RemoveMember
* url: GroupsService_RemoveMemberURL
* method: GroupsService_RemoveMember_TYPE
* raw_url: GroupsService_RemoveMember_RAW_URL
* @param id - The group id
* @param accountId - The account id to remove
*/
export const GroupsService_RemoveMember = function(parameters = {}) {
const domain = parameters.$domain ? parameters.$domain : getDomain()
const config = parameters.$config
let path = '/v0/groups/{id}/members/{account_id}/$ref'
let body
let queryParameters = {}
let form = {}
path = path.replace('{id}', `${parameters['id']}`)
if (parameters['id'] === undefined) {
return Promise.reject(new Error('Missing required parameter: id'))
}
path = path.replace('{account_id}', `${parameters['accountId']}`)
if (parameters['accountId'] === undefined) {
return Promise.reject(new Error('Missing required parameter: accountId'))
}
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
});
}
return request('delete', domain + path, body, queryParameters, form, config)
}
export const GroupsService_RemoveMember_RAW_URL = function() {
return '/v0/groups/{id}/members/{account_id}/$ref'
}
export const GroupsService_RemoveMember_TYPE = function() {
return 'delete'
}
export const GroupsService_RemoveMemberURL = function(parameters = {}) {
let queryParameters = {}
const domain = parameters.$domain ? parameters.$domain : getDomain()
let path = '/v0/groups/{id}/members/{account_id}/$ref'
path = path.replace('{id}', `${parameters['id']}`)
path = path.replace('{account_id}', `${parameters['accountId']}`)
if (parameters.$queryParameters) {
Object.keys(parameters.$queryParameters).forEach(function(parameterName) {
queryParameters[parameterName] = parameters.$queryParameters[parameterName]
})
}
let keys = Object.keys(queryParameters)
return domain + path + (keys.length > 0 ? '?' + (keys.map(key => key + '=' + encodeURIComponent(queryParameters[key])).join('&')) : '')
}

34
ui/components/App.vue Normal file
View File

@@ -0,0 +1,34 @@
<template>
<div>
<div class="uk-container uk-padding">
<h1>
Accounts
</h1>
<template v-if="isInitialized">
<accounts-list :accounts="accounts" />
</template>
<oc-loader v-else />
</div>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
import AccountsList from './accounts/AccountsList.vue'
export default {
name: 'App',
components: { AccountsList },
computed: {
...mapGetters('Accounts', ['isInitialized', 'getAccountsSorted']),
accounts () {
return this.getAccountsSorted
}
},
methods: {
...mapActions('Accounts', ['initialize'])
},
created () {
this.initialize()
}
}
</script>

View File

@@ -0,0 +1,47 @@
<template>
<div>
<oc-table middle divider>
<oc-table-group>
<oc-table-row>
<oc-table-cell shrink type="head" />
<oc-table-cell type="head" v-text="$gettext('Username')" />
<oc-table-cell type="head" v-text="$gettext('Display name')" />
<oc-table-cell type="head" v-text="$gettext('Email')" />
<oc-table-cell shrink type="head" class="uk-text-nowrap" v-text="$gettext('Uid number')" />
<oc-table-cell shrink type="head" class="uk-text-nowrap" v-text="$gettext('Gid number')" />
<oc-table-cell shrink type="head" v-text="$gettext('Enabled')" />
</oc-table-row>
</oc-table-group>
<oc-table-group>
<oc-table-row v-for="account in accounts" :key="`account-list-row-${account.id}`">
<oc-table-cell>
<avatar :user-name="account.displayName || account.preferredName" :userid="account.id" :width="35" />
</oc-table-cell>
<oc-table-cell v-text="account.preferredName" />
<oc-table-cell v-text="account.displayName || '-'" />
<oc-table-cell v-text="account.mail" />
<oc-table-cell v-text="account.uidNumber || '-'" />
<oc-table-cell v-text="account.gidNumber || '-'" />
<oc-table-cell class="uk-text-center">
<oc-icon v-if="account.accountEnabled" name="ready" variation="success" :aria-label="$gettext('Account is enabled')" />
<oc-icon v-else name="deprecated" variation="danger" :aria-label="$gettext('Account is disabled')" />
</oc-table-cell>
</oc-table-row>
</oc-table-group>
</oc-table>
</div>
</template>
<script>
import Avatar from './Avatar.vue'
export default {
name: 'AccountsList',
components: { Avatar },
props: {
accounts: {
type: Array,
required: true
}
}
}
</script>

View File

@@ -0,0 +1,130 @@
<template>
<component :is="type" v-if="enabled">
<oc-spinner
v-if="loading"
key="avatar-loading"
size="small"
:aria-label="$gettext('Loading')"
:style="`width: ${width}px; height: ${width}px;`"
/>
<oc-avatar
v-else
key="avatar-loaded"
:width="width"
:src="avatarSource"
:user-name="userName"
/>
</component>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
/**
* FIXME: this component has been copied over from phoenix. It should be moved over to ODS, then we can reuse it in
* this extension.
*/
name: 'Avatar',
props: {
/**
* The html element used for the avatar container.
* `div, span`
*/
type: {
type: String,
default: 'div',
validator: value => {
return value.match(/(div|span)/)
}
},
userName: {
type: String,
default: ''
},
userid: {
/**
* Allow empty string to show placeholder
*/
type: String,
default: ''
},
width: {
type: Number,
required: false,
default: 42
}
},
data () {
return {
/**
* Set to object URL when loaded, or on failure, icon placeholder is shown
*/
avatarSource: '',
/**
* Shows spinner in place whilst loading avatar from server
*/
loading: true
}
},
computed: {
...mapGetters(['getToken']),
enabled: function () {
return this.$root.config.enableAvatars || true
}
},
watch: {
userid: function (userid, old) {
this.setUser(userid)
}
},
mounted: function () {
// Handled mounted situation. Userid might not be set yet so try placeholder
if (this.userid !== '') {
this.setUser(this.userid)
} else {
this.loading = false
}
},
methods: {
/**
* Load a new avatar from this userid
*/
setUser (userid) {
this.loading = true
this.avatarSource = ''
if (!this.enabled || userid === '') {
this.loading = false
return
}
const headers = new Headers()
const instance = this.$root.config.server || window.location.origin
const url = instance + '/remote.php/dav/avatars/' + this.userid + '/128.png'
headers.append('Authorization', 'Bearer ' + this.getToken)
headers.append('X-Requested-With', 'XMLHttpRequest')
fetch(url, { headers })
.then(response => {
if (response.ok) {
return response.blob()
}
if (response.status !== 404) {
throw new Error(`Unexpected status code ${response.status}`)
}
})
.then(blob => {
this.loading = false
if (blob) {
this.avatarSource = window.URL.createObjectURL(blob)
} else {
// 404, none found
this.avatarSource = ''
}
})
.catch(error => {
this.avatarSource = ''
this.loading = false
console.error(`Error loading avatar image for user "${this.userid}": `, error.message)
})
}
}
}
</script>

85
ui/store/index.js Normal file
View File

@@ -0,0 +1,85 @@
import {
// eslint-disable-next-line camelcase
AccountsService_ListAccounts
} from '../client/accounts'
import axios from 'axios'
const state = {
config: null,
initialized: false,
accounts: {}
}
const getters = {
config: state => state.config,
isInitialized: state => state.initialized,
getAccountsSorted: state => {
return Object.values(state.accounts).sort((a1, a2) => {
if (a1.preferredName === a2.preferredName) {
return a1.id.localeCompare(a2.id)
}
return a1.preferredName.localeCompare(a2.preferredName)
})
}
}
const mutations = {
LOAD_CONFIG (state, config) {
state.config = config
},
SET_INITIALIZED (state, value) {
state.initialized = value
},
SET_ACCOUNTS (state, accounts) {
state.accounts = accounts
}
}
const actions = {
loadConfig ({ commit }, config) {
commit('LOAD_CONFIG', config)
},
async initialize ({ commit, dispatch }) {
await dispatch('fetchAccounts')
commit('SET_INITIALIZED', true)
},
async fetchAccounts ({ commit, dispatch, rootGetters }) {
injectAuthToken(rootGetters)
const response = await AccountsService_ListAccounts({
$domain: rootGetters.configuration.server,
body: {}
})
if (response.status === 201) {
const accounts = response.data.accounts
commit('SET_ACCOUNTS', accounts || [])
} else {
dispatch('showMessage', {
title: 'Failed to fetch accounts.',
desc: response.statusText,
status: 'danger'
}, { root: true })
}
}
}
export default {
namespaced: true,
state,
getters,
actions,
mutations
}
function injectAuthToken (rootGetters) {
axios.interceptors.request.use(config => {
if (typeof config.headers.Authorization === 'undefined') {
const token = rootGetters.user.token
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
}
return config
})
}

5097
yarn.lock Normal file
View File

File diff suppressed because it is too large Load Diff