5 Commits

24 changed files with 5806 additions and 9161 deletions

View File

@ -40,8 +40,7 @@ tidy:
go mod tidy go mod tidy
watch: watch:
go get github.com/cortesi/modd/cmd/modd modd
go run github.com/cortesi/modd/cmd/modd
lint: lint:
golangci-lint run --enable-all golangci-lint run --enable-all

View File

@ -40,8 +40,23 @@ powow:
# Clé d'API à utiliser par les clients Powow utilisant le mock # Clé d'API à utiliser par les clients Powow utilisant le mock
apiKey: powow apiKey: powow
# La création/mise à jour de modèles de SMS s'effectue via les méthodes TransactionalSMS.Create et TransactionalSMS.Update. # Modèles de SMS transactionnels
# Voir le fichier ./misc/powow.http pour un exemple de requête. # Voir https://powow4.iroquois.fr/user/docs/api/#create-transactional-sms
# et https://powow4.iroquois.fr/user/docs/api/#update-transactional-sms
#
# L'identifiant (SmsID) de chaque modèle est son index dans le tableau.
sms:
- name: Powow SMS
from: FakeSMS
# Modèle de contenu pour le SMS avec patrons d'insertion
# Voir https://powow4.iroquois.fr/user/docs/api/#send-transactional-sms, "About the CustomData parameter"
content: |
Bonjour %Subscriber:Firstname%,
Lorem ipsum dolor sit amet...
# Cet attribut n'est pas utilisé dans le cadre du mock
shortLink: false
``` ```
### Variables d'environnement ### Variables d'environnement
@ -50,20 +65,12 @@ La configuration de FakeSMTP peut être personnalisée via des variables d'envir
Les valeurs des variables d'environnement surchargent les valeurs présentes dans le fichier de configuration. Les valeurs des variables d'environnement surchargent les valeurs présentes dans le fichier de configuration.
| Variable | Correspondance dans le fichier de configuration | |Variable|Correspondance dans le fichier de configuration|
| -------------------------- | ----------------------------------------------- | |--------|-----------------------------------------------|
| `FAKESMS_HTTP_ADDRESS` | `http.address` | |`FAKESMS_HTTP_ADDRESS`|`http.address`|
| `FAKESMS_HTTP_TEMPLATEDIR` | `http.templateDir` | |`FAKESMS_HTTP_TEMPLATEDIR`|`http.templateDir`|
| `FAKESMS_HTTP_PUBLICDIR` | `http.publicDir` | |`FAKESMS_HTTP_PUBLICDIR`|`http.publicDir`|
| `FAKESMS_POWOW_API_KEY` | `powow.apiKey` | |`FAKESMS_POWOW_API_KEY`|`powow.apiKey`|
### Lancer en mode read-only
Pour lancer le conteneur en mode read-only, la variable `FAKESMTP_DATA_PATH` doit être définie et un volume doit être créé à cet emplacement. Exemple avec docker :
```sh
docker run -it --rm -p 3000:3000 --env FAKESMS_DATA_PATH='/app/data/fakesms.db' --read-only -v $(pwd)/data:/app/data cadoles/fake-sms
```
## Mocks ## Mocks
@ -73,9 +80,9 @@ Un mock de l'API Powow est disponible via l'URL `http://<fake_sms_host>/api/v1/m
Les commandes suivantes sont implémentées: Les commandes suivantes sont implémentées:
| Commande | Documentation officiele | Notes | |Commande|Documentation officiele|Notes|
| ----------------------- | ---------------------------------------------------------------- | ----------------------------------------------------------------- | |--------|-----------------------|-----------|
| `TransactionalSms.Send` | https://powow4.iroquois.fr/user/docs/api/#send-transactional-sms | La définition des modèles de SMS s'effectue via la configuration. | |`TransactionalSms.Send`|https://powow4.iroquois.fr/user/docs/api/#send-transactional-sms|La définition des modèles de SMS s'effectue via la configuration.|
Un exemple d'appel à l'API est disponible dans le fichier [`misc/powow.http`](./misc/powow.http). Un exemple d'appel à l'API est disponible dans le fichier [`misc/powow.http`](./misc/powow.http).
@ -83,10 +90,10 @@ Un exemple d'appel à l'API est disponible dans le fichier [`misc/powow.http`](.
### Dépendances ### Dépendances
- Go 1.17 - Go 1.13
- modd - modd
- make - make
- NodeJS (20.x) / npm - NodeJS/npm
### Compiler et démarrer le serveur de développement ### Compiler et démarrer le serveur de développement
@ -107,4 +114,4 @@ make release
## Licence ## Licence
AGPL-3.0 AGPL-3.0

View File

@ -8,8 +8,6 @@ import (
"forge.cadoles.com/Cadoles/fake-sms/internal/command" "forge.cadoles.com/Cadoles/fake-sms/internal/command"
"forge.cadoles.com/Cadoles/fake-sms/internal/config" "forge.cadoles.com/Cadoles/fake-sms/internal/config"
"forge.cadoles.com/Cadoles/fake-sms/internal/model"
"forge.cadoles.com/Cadoles/fake-sms/internal/model/powow"
"forge.cadoles.com/Cadoles/fake-sms/internal/query" "forge.cadoles.com/Cadoles/fake-sms/internal/query"
"forge.cadoles.com/Cadoles/fake-sms/internal/storm" "forge.cadoles.com/Cadoles/fake-sms/internal/storm"
"gitlab.com/wpetit/goweb/cqrs" "gitlab.com/wpetit/goweb/cqrs"
@ -42,10 +40,6 @@ func getServiceContainer(conf *config.Config) (*service.Container, error) {
ctn.Provide(storm.ServiceName, storm.ServiceProvider( ctn.Provide(storm.ServiceName, storm.ServiceProvider(
storm.WithPath(conf.Data.Path), storm.WithPath(conf.Data.Path),
storm.WithObjects(
&model.SMS{},
&powow.SMSTemplate{},
),
)) ))
ctn.Provide(cqrs.ServiceName, cqrs.ServiceProvider()) ctn.Provide(cqrs.ServiceName, cqrs.ServiceProvider())

View File

@ -2,7 +2,7 @@
<div class="columns is-mobile"> <div class="columns is-mobile">
<div class="column is-narrow"> <div class="column is-narrow">
<h1 class="is-size-3 title"> <h1 class="is-size-3 title">
<a href="{{ .BaseURL }}/" rel="Inbox" class="has-text-grey-dark"> <a href="{{ .BaseURL }}" rel="Inbox" class="has-text-grey-dark">
{{if or .Messages .SMS}} {{if or .Messages .SMS}}
📳 📳
{{else}} {{else}}

View File

@ -23,11 +23,10 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{{ $baseURL := .BaseURL }}
{{range .Messages}} {{range .Messages}}
<tr data-controller="inbox-entry" <tr data-controller="inbox-entry"
data-action="click->outbox-entry#onClick" data-action="click->outbox-entry#onClick"
data-inbox-entry-link="{{ $baseURL }}/sms/{{ .ID }}"> data-inbox-entry-link="{{ .BaseURL }}/sms/{{ .ID }}">
<td class="sms-from"> <td class="sms-from">
<span class="is-size-7">{{ .From }}</span> <span class="is-size-7">{{ .From }}</span>
</td> </td>
@ -39,7 +38,7 @@
</td> </td>
<td class="sms-actions"> <td class="sms-actions">
<div class="buttons is-right"> <div class="buttons is-right">
<a href="{{ $baseURL }}/sms/{{ .ID }}" class="button is-small is-link">👁️ See</a> <a href="{{ .BaseURL }}/sms/{{ .ID }}" class="button is-small is-link">👁️ See</a>
</div> </div>
</td> </td>
</tr> </tr>

View File

@ -2,9 +2,9 @@
{{define "header_buttons"}} {{define "header_buttons"}}
<button class="button is-danger" <button class="button is-danger"
data-controller="restful" data-controller="restful"
data-restful-endpoint="{{ .BaseURL }}/sms/{{ .SMS.ID }}" data-restful-endpoint="{{ .BaseURL }}/{{ .SMS.ID }}"
data-restful-method="DELETE" data-restful-method="DELETE"
data-restful-redirect="{{ .BaseURL }}/"> data-restful-redirect="{{ .BaseURL }}">
🗑️ Delete 🗑️ Delete
</button> </button>
{{end}} {{end}}

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
9

14
debian/control vendored Normal file
View File

@ -0,0 +1,14 @@
Source: fake-sms
Section: unknown
Priority: optional
Maintainer: Cadoles <contact@cadoles.com>
Build-Depends: debhelper (>= 8.0.0), wget, ca-certificates, tar, curl
Standards-Version: 3.9.4
Homepage: http://forge.cadoles.com/Cadoles/fake-sms
Vcs-Git: http://forge.cadoles.com/Cadoles/fake-sms.git
Vcs-Browser: http://forge.cadoles.com/Cadoles/fake-sms
Package: fake-sms
Architecture: amd64
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Serveur d'envoi de SMS factice pour le développement avec interface web

1
debian/fake-sms.dirs vendored Normal file
View File

@ -0,0 +1 @@
var/lib/fake-sms

11
debian/fake-sms.service vendored Normal file
View File

@ -0,0 +1,11 @@
[Unit]
Description=Serveur d'envoi de SMS factice pour le développement avec interface web
After=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/fake-sms -workdir /usr/share/fake-sms -config /etc/fake-sms/config.yml
Restart=on-failure
[Install]
WantedBy=multi-user.target

54
debian/rules vendored Normal file
View File

@ -0,0 +1,54 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Uncomment this to turn on verbose mode.
export DH_VERBOSE=1
GO_VERSION := 1.15.6
OS := linux
ARCH := amd64
GOPATH=$(HOME)/go
ifeq (, $(shell which go 2>/dev/null))
override_dh_auto_build: install-go
endif
ifeq (, $(shell which node 2>/dev/null))
override_dh_auto_build: install-nodejs
endif
%:
dh $@ --with systemd
override_dh_auto_build: $(GOPATH)
GOPATH=$(GOPATH) PATH="$(PATH):/usr/local/go/bin:$(GOPATH)/bin" make tooling
npm install
GOPATH=$(GOPATH) PATH="$(PATH):/usr/local/go/bin:$(GOPATH)/bin" go mod vendor
GOPATH=$(GOPATH) PATH="$(PATH):/usr/local/go/bin:$(GOPATH)/bin" ARCH_TARGETS=$(ARCH) make release
$(GOPATH):
mkdir -p $(GOPATH)
install-go:
wget https://dl.google.com/go/go$(GO_VERSION).$(OS)-$(ARCH).tar.gz
tar -C /usr/local -xzf go$(GO_VERSION).$(OS)-$(ARCH).tar.gz
install-nodejs:
curl -sL https://deb.nodesource.com/setup_14.x | bash -
apt-get install -y nodejs
override_dh_auto_install:
mkdir -p debian/fake-sms/usr/share/fake-sms
mkdir -p debian/fake-sms/etc/fake-sms
mkdir -p debian/fake-sms/usr/bin
cp -r release/fake-sms-$(OS)-$(ARCH)/* debian/fake-sms/usr/share/fake-sms/
mv debian/fake-sms/usr/share/fake-sms/bin/fake-sms debian/fake-sms/usr/bin/fake-sms
mv debian/fake-sms/usr/share/fake-sms/config.yml debian/fake-sms/etc/fake-sms/config.yml
install -d debian/fake-sms
override_dh_strip:
override_dh_auto_test:

1
debian/source/format vendored Normal file
View File

@ -0,0 +1 @@
3.0 (native)

8
go.mod
View File

@ -5,16 +5,10 @@ go 1.14
require ( require (
github.com/asdine/storm/v3 v3.1.1 github.com/asdine/storm/v3 v3.1.1
github.com/caarlos0/env/v6 v6.2.1 github.com/caarlos0/env/v6 v6.2.1
github.com/cortesi/modd v0.0.0-20221227201034-99fec65d0ecf // indirect
github.com/davecgh/go-spew v1.1.1
github.com/go-chi/chi v4.1.1+incompatible github.com/go-chi/chi v4.1.1+incompatible
github.com/google/go-cmp v0.5.4 // indirect
github.com/kovetskiy/go-php-serialize v0.0.0-20141101074437-71ef41a548d8
github.com/kr/text v0.2.0 // indirect
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.7.0 // indirect
gitlab.com/wpetit/goweb v0.0.0-20200707070104-985ce3eba3c2 gitlab.com/wpetit/goweb v0.0.0-20200707070104-985ce3eba3c2
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
gopkg.in/yaml.v2 v2.2.8 gopkg.in/yaml.v2 v2.2.8
) )

100
go.sum
View File

@ -34,26 +34,12 @@ github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae/go.mod h1:+inYUS
github.com/alecthomas/kong-hcl v0.1.8-0.20190615233001-b21fea9723c8/go.mod h1:MRgZdU3vrFd05IQ89AxUZ0aYdF39BYoNFa324SodPCA= github.com/alecthomas/kong-hcl v0.1.8-0.20190615233001-b21fea9723c8/go.mod h1:MRgZdU3vrFd05IQ89AxUZ0aYdF39BYoNFa324SodPCA=
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY= github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY=
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ= github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15 h1:AUNCr9CiJuwrRYS3XieqF+Z9B9gNxo/eANAJCF2eiN4=
github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/asdine/storm/v3 v3.1.1 h1:5ESJvmcNhQQOFcvpxkIHcZs7mp8Z6XGdBqEoAgf+11g= github.com/asdine/storm/v3 v3.1.1 h1:5ESJvmcNhQQOFcvpxkIHcZs7mp8Z6XGdBqEoAgf+11g=
github.com/asdine/storm/v3 v3.1.1/go.mod h1:LEpXwGt4pIqrE/XcTvCnZHT5MgZCV6Ub9q7yQzOFWr0= github.com/asdine/storm/v3 v3.1.1/go.mod h1:LEpXwGt4pIqrE/XcTvCnZHT5MgZCV6Ub9q7yQzOFWr0=
github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
github.com/caarlos0/env/v6 v6.2.1 h1:/bFpX1dg4TNioJjg7mrQaSrBoQvRfLUHNfXivdFbbEo= github.com/caarlos0/env/v6 v6.2.1 h1:/bFpX1dg4TNioJjg7mrQaSrBoQvRfLUHNfXivdFbbEo=
github.com/caarlos0/env/v6 v6.2.1/go.mod h1:3LpmfcAYCG6gCiSgDLaFR5Km1FRpPwFvBbRcjHar6Sw= github.com/caarlos0/env/v6 v6.2.1/go.mod h1:3LpmfcAYCG6gCiSgDLaFR5Km1FRpPwFvBbRcjHar6Sw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cortesi/modd v0.0.0-20221227201034-99fec65d0ecf h1:NjFxMa5TC3Yb4jhI+7QnC6OZOL11sLpo5i0KlH3TWKw=
github.com/cortesi/modd v0.0.0-20221227201034-99fec65d0ecf/go.mod h1:WgVcz6/4WJwygF7In33TF8u5yu3SOSpO957IEu0SQ0g=
github.com/cortesi/moddwatch v0.0.0-20210222043437-a6aaad86a36e h1:vNbhR09qtq9ELJgvhAWng4zl/4CVTPBPVev3R8MlUYc=
github.com/cortesi/moddwatch v0.0.0-20210222043437-a6aaad86a36e/go.mod h1:MUkYRZrwFTHATqCI5tDJRPqmBt9xf3q4+Avfut7kCCE=
github.com/cortesi/termlog v0.0.0-20210222042314-a1eec763abec h1:v7D8uHsIKsyjfyhhNdY4qivqN558Ejiq+CDXiUljZ+4=
github.com/cortesi/termlog v0.0.0-20210222042314-a1eec763abec/go.mod h1:10Fm2kasJmcKf1FSMQGSWb976sfR29hejNtfS9AydB4=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ= github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk= github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
@ -65,11 +51,8 @@ github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
github.com/go-chi/chi v4.1.1+incompatible h1:MmTgB0R8Bt/jccxp+t6S/1VGIKdJw5J74CK/c9tTfA4= github.com/go-chi/chi v4.1.1+incompatible h1:MmTgB0R8Bt/jccxp+t6S/1VGIKdJw5J74CK/c9tTfA4=
github.com/go-chi/chi v4.1.1+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-chi/chi v4.1.1+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
@ -96,9 +79,8 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.2-0.20191216170541-340f1ebe299e h1:4WfjkTUTsO6siF8ghDQQk6t7x/FPsv3w6MXkc47do7Q=
github.com/google/go-cmp v0.3.2-0.20191216170541-340f1ebe299e/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.3.2-0.20191216170541-340f1ebe299e/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
@ -110,7 +92,9 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
github.com/gorilla/csrf v1.6.0/go.mod h1:7tSf8kmjNYr7IWDCYhd3U8Ck34iQ/Yw5CJu7bAkHEGI= github.com/gorilla/csrf v1.6.0/go.mod h1:7tSf8kmjNYr7IWDCYhd3U8Ck34iQ/Yw5CJu7bAkHEGI=
github.com/gorilla/handlers v1.4.1/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/handlers v1.4.1/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ=
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
@ -118,35 +102,24 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kovetskiy/go-php-serialize v0.0.0-20141101074437-71ef41a548d8 h1:5SuynDl9zQBugAPyvRjca4mClezQH954P4fBxdUB7GA= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kovetskiy/go-php-serialize v0.0.0-20141101074437-71ef41a548d8/go.mod h1:vbjtdVbbitDdc7FZj0ojJf+O/fEqf6Io1OmvIf9sWVg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 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/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.4/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/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw= 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/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@ -154,19 +127,16 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rjeczalik/notify v0.0.0-20181126183243-629144ba06a1 h1:FLWDC+iIP9BWgYKvWKKtOUZux35LIQNAuIzp/63RQJU=
github.com/rjeczalik/notify v0.0.0-20181126183243-629144ba06a1/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
@ -182,11 +152,8 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -216,12 +183,10 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d h1:1aflnvSoWWLI2k/dMUAl5lvU1YO4Mb4hz0gh+1rjcxU= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210323141857-08027d57d8cf h1:sewfyKLWuY3ko6EI4hbFziQ8bHkfammpzCDfLT92I1c=
golang.org/x/net v0.0.0-20210323141857-08027d57d8cf/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/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-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -230,11 +195,7 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -246,28 +207,14 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43 h1:SgQ6LNaYJU0JIuEHv9+s6EbhSCwYeAf5Yvj6lpYlqAE=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20191110171634-ad39bd3f0407/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210317153231-de623e64d2a6 h1:EC6+IGYTjPpRfv9a2b/6Puw0W+hLtAhkV1tPsXhutqs=
golang.org/x/term v0.0.0-20210317153231-de623e64d2a6/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -317,13 +264,11 @@ google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1 h1:wdKvqQk7IttEw92GoRyKG2IDrUIpgpj6H6m81yfeMW0= google.golang.org/grpc v1.25.1 h1:wdKvqQk7IttEw92GoRyKG2IDrUIpgpj6H6m81yfeMW0=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
@ -332,14 +277,9 @@ gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWd
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 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.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-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
mvdan.cc/editorconfig v0.1.1-0.20200121172147-e40951bde157/go.mod h1:Ge4atmRUYqueGppvJ7JNrtqpqokoJEFxYbP0Z+WeKS8=
mvdan.cc/sh/v3 v3.3.0-0.dev.0.20210224101809-fb5052e7a010 h1:0xJA1YM0Ppa63jEfcdPsjRHo1qxklwXWhIPr9tAQ2J4=
mvdan.cc/sh/v3 v3.3.0-0.dev.0.20210224101809-fb5052e7a010/go.mod h1:fPQmabBpREM/XQ9YXSU5ZFZ/Sm+PmKP9/vkFHgYKJEI=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=

View File

@ -28,8 +28,8 @@ type DataConfig struct {
} }
type PowowConfig struct { type PowowConfig struct {
APIKey string `yaml:"apiKey" env:"FAKESMS_POWOW_API_KEY"` APIKey string `yaml:"apiKey" env:"FAKESMS_POWOW_API_KEY"`
InvalidPhoneNumber string `yaml:"invalidPhoneNumber" env:"FAKESMS_POWOW_INVALID_PHONE_NUMBER"` SMS []PowowSMS `yaml:"sms"`
} }
type PowowSMS struct { type PowowSMS struct {
@ -79,8 +79,18 @@ func NewDefault() *Config {
Path: "fakesms.db", Path: "fakesms.db",
}, },
Powow: PowowConfig{ Powow: PowowConfig{
APIKey: "powow", APIKey: "powow",
InvalidPhoneNumber: "+33666666666", SMS: []PowowSMS{
{
Name: "Powow SMS",
From: "FakeSMS",
ShortLink: false,
Content: `Bonjour %Subscriber:Firstname%,
Lorem ipsum dolor sit amet...
`,
},
},
}, },
} }
} }

View File

@ -1,10 +0,0 @@
package powow
type SMSTemplate struct {
ID int `storm:"id,increment"`
SmsName string
FromName string
Content string
ShortLink int
Language string
}

View File

@ -103,7 +103,17 @@ func HandleGetOutbox(ctx context.Context, qry cqrs.Query) (interface{}, error) {
match := true match := true
if req.Search.Recipient != "" { if req.Search.Recipient != "" {
match = strings.Contains(sms.Recipient, req.Search.Recipient) found := false
if strings.Contains(sms.Recipient, req.Search.Recipient) {
found = true
break
}
if !found {
match = false
}
} }
if !req.Search.After.IsZero() && !sms.SentAt.After(req.Search.After) { if !req.Search.After.IsZero() && !sms.SentAt.After(req.Search.After) {

View File

@ -4,16 +4,12 @@ import (
"context" "context"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"io/ioutil"
"net/http" "net/http"
"strconv"
"strings" "strings"
"forge.cadoles.com/Cadoles/fake-sms/internal/command" "forge.cadoles.com/Cadoles/fake-sms/internal/command"
"forge.cadoles.com/Cadoles/fake-sms/internal/config" "forge.cadoles.com/Cadoles/fake-sms/internal/config"
"forge.cadoles.com/Cadoles/fake-sms/internal/model/powow"
"forge.cadoles.com/Cadoles/fake-sms/internal/storm"
"github.com/davecgh/go-spew/spew"
php "github.com/kovetskiy/go-php-serialize"
"github.com/pkg/errors" "github.com/pkg/errors"
"gitlab.com/wpetit/goweb/cqrs" "gitlab.com/wpetit/goweb/cqrs"
"gitlab.com/wpetit/goweb/logger" "gitlab.com/wpetit/goweb/logger"
@ -24,32 +20,25 @@ import (
type ErrorCode int type ErrorCode int
const ( const (
ErrorCodeInvalidCommand ErrorCode = 99997 ErrorCodeInvalidCommand ErrorCode = 99997
ErrorCodeAuthenticationFailure ErrorCode = 99998 ErrorCodeAuthenticationFailure ErrorCode = 99998
ErrorCodeNotEnoughPrivileges ErrorCode = 99999 ErrorCodeNotEnoughPrivileges ErrorCode = 99999
ErrorCodeTransactionSMSSendMissingSMSID ErrorCode = 1 ErrorCodeMissingSMSID ErrorCode = 1
ErrorCodeTransactionSMSSendMissingMobilePhoneNumber ErrorCode = 2 ErrorCodeMissingMobilePhoneNumber ErrorCode = 2
ErrorCodeTransactionSMSSendInvalidSMSID ErrorCode = 3 ErrorCodeInvalidSMSID ErrorCode = 3
ErrorCodeTransactionSMSSendInvalidMobilePhoneNumber ErrorCode = 4 ErrorCodeInvalidMobilePhoneNumber ErrorCode = 4
ErrorCodeTransactionSMSSendInvalidCustomData ErrorCode = 5 ErrorCodeInvalidCustomData ErrorCode = 5
ErrorCodeTransactionSMSSendInvalidTimeToSend ErrorCode = 6 ErrorCodeInvalidTimeToSend ErrorCode = 6
ErrorCodeTransactionSMSSendAccountSubscribersLimitExceeded ErrorCode = 7 ErrorCodeAccountSubscribersLimitExceeded ErrorCode = 7
ErrorCodeTransactionSMSSendMobilePhoneNumberCannotBeSaved ErrorCode = 7 ErrorCodeMobilePhoneNumberCannotBeSaved ErrorCode = 7
ErrorCodeTransactionSMSSendTransactionalIDCannotBeCreated ErrorCode = 9 ErrorCodeTransactionalIDCannotBeCreated ErrorCode = 9
ErrorCodeTransactionSMSSendSMSSentLimitExceeded ErrorCode = 10 ErrorCodeSMSSentLimitExceeded ErrorCode = 10
ErrorCodeTransactionSMSUpdateMissingSMSID ErrorCode = 1
ErrorCodeTransactionSMSUpdateInvalidSMSID ErrorCode = 3
ErrorCodeTransactionSMSUpdateInvalidFromName ErrorCode = 4
ErrorCodeTransactionSMSUpdateInvalidLanguage ErrorCode = 7
) )
type Command string type Command string
const ( const (
CommandTransactionalSMSSend = "TransactionalSms.Send" CommandTransactionalSMSSend = "TransactionalSms.Send"
CommandTransactionalSMSCreate = "TransactionalSms.Create"
CommandTransactionalSMSUpdate = "TransactionalSms.Update"
) )
type PowowRequest struct { type PowowRequest struct {
@ -60,11 +49,6 @@ type PowowRequest struct {
} }
type PowowResponse struct { type PowowResponse struct {
Success bool
ErrorCode map[int]ErrorCode
}
type PowowResponseSuccess struct {
Success bool Success bool
ErrorCode ErrorCode ErrorCode ErrorCode
} }
@ -75,75 +59,38 @@ func handlePowowEntrypoint(w http.ResponseWriter, r *http.Request) {
ctn := container.Must(ctx) ctn := container.Must(ctx)
conf := config.Must(ctn) conf := config.Must(ctn)
err := r.ParseForm() data, err := ioutil.ReadAll(r.Body)
if err != nil { if err != nil {
logger.Error(ctx, "could not parse form", logger.E(errors.WithStack(err))) logger.Error(ctx, "could not read body", logger.E(errors.WithStack(err)))
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
} }
defer r.Body.Close()
pr := &PowowRequest{ pr := &PowowRequest{
Payload: make(map[string]interface{}), Payload: make(map[string]interface{}),
} }
pr.APIKey = r.FormValue("APIKey") if err := json.Unmarshal(data, pr); err != nil {
pr.Command = Command(r.FormValue("Command")) logger.Error(ctx, "could not parse request", logger.E(errors.WithStack(err)))
pr.ResponseFormat = r.FormValue("ResponseFormat") http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
if pr.Command == CommandTransactionalSMSUpdate { return
smsid, err := strconv.ParseFloat(r.FormValue("SmsID"), 64)
if err != nil {
logger.Error(ctx, "could not convert SmsID to float", logger.E(errors.WithStack(err)))
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
pr.Payload = map[string]interface{}{
"SmsID": smsid,
"Content": r.FormValue("Content"),
"ShortLink": r.FormValue("ShortLink"),
"Language": r.FormValue("Language"),
"FromName": r.FormValue("FromName"),
"SmsName": r.FormValue("SmsName"),
}
} }
if pr.Command == CommandTransactionalSMSSend { if err := json.Unmarshal(data, &pr.Payload); err != nil {
customData, err := php.Decode(r.FormValue("CustomData")) logger.Error(ctx, "could not parse request payload", logger.E(errors.WithStack(err)))
if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
logger.Error(ctx, "could not cunserialized custom data", logger.E(errors.WithStack(err)))
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return
}
var smsid float64
if r.FormValue("SmsID") != "" {
smsid, err = strconv.ParseFloat(r.FormValue("SmsID"), 64)
if err != nil {
logger.Error(ctx, "could not convert SmsID to float", logger.E(errors.WithStack(err)))
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
}
pr.Payload = map[string]interface{}{
"SmsID": smsid,
"MobilePhoneNumber": strings.TrimSpace(r.FormValue("MobilePhoneNumber")),
"TimeToSend": r.FormValue("TimeToSend"),
"CustomData": customData,
}
} }
// Authenticate user // Authenticate user
if conf.Powow.APIKey != pr.APIKey { if conf.Powow.APIKey != pr.APIKey {
res := &PowowResponse{ res := &PowowResponse{
Success: false, Success: false,
ErrorCode: map[int]ErrorCode{0: ErrorCodeAuthenticationFailure}, ErrorCode: ErrorCodeAuthenticationFailure,
}
sendPowowResponse(w, res)
return
}
// If phone number must return an error
if conf.Powow.InvalidPhoneNumber == pr.Payload["MobilePhoneNumber"] {
res := &PowowResponse{
Success: false,
ErrorCode: map[int]ErrorCode{0: ErrorCodeTransactionSMSSendInvalidMobilePhoneNumber},
} }
sendPowowResponse(w, res) sendPowowResponse(w, res)
@ -156,19 +103,11 @@ func handlePowowEntrypoint(w http.ResponseWriter, r *http.Request) {
case CommandTransactionalSMSSend: case CommandTransactionalSMSSend:
handleTransactionalSMSSend(ctx, ctn, w, pr) handleTransactionalSMSSend(ctx, ctn, w, pr)
return
case CommandTransactionalSMSCreate:
handleTransactionalSMSCreate(ctx, ctn, w, pr)
return
case CommandTransactionalSMSUpdate:
handleTransactionalSMSUpdate(ctx, ctn, w, pr)
return return
default: default:
res := &PowowResponse{ res := &PowowResponse{
Success: false, Success: false,
ErrorCode: map[int]ErrorCode{0: ErrorCodeInvalidCommand}, ErrorCode: ErrorCodeInvalidCommand,
} }
sendPowowResponse(w, res) sendPowowResponse(w, res)
@ -180,70 +119,63 @@ func handlePowowEntrypoint(w http.ResponseWriter, r *http.Request) {
// Mock https://powow4.iroquois.fr/user/docs/api/#send-transactional-sms // Mock https://powow4.iroquois.fr/user/docs/api/#send-transactional-sms
func handleTransactionalSMSSend(ctx context.Context, ctn *service.Container, w http.ResponseWriter, req *PowowRequest) { func handleTransactionalSMSSend(ctx context.Context, ctn *service.Container, w http.ResponseWriter, req *PowowRequest) {
bus := cqrs.Must(ctn) bus := cqrs.Must(ctn)
db := storm.Must(ctn) conf := config.Must(ctn)
smsID, exists, valid := getPowowSMSID(req) rawSMSID, exists := req.Payload["SmsID"]
if !exists { if !exists {
sendPowowResponse(w, &PowowResponse{ sendPowowResponse(w, &PowowResponse{
ErrorCode: map[int]ErrorCode{0: ErrorCodeTransactionSMSSendMissingSMSID}, ErrorCode: ErrorCodeMissingSMSID,
Success: false, Success: false,
}) })
return return
} }
if !valid { smsID, ok := rawSMSID.(float64)
if !ok {
sendPowowResponse(w, &PowowResponse{ sendPowowResponse(w, &PowowResponse{
ErrorCode: map[int]ErrorCode{0: ErrorCodeTransactionSMSSendInvalidSMSID}, ErrorCode: ErrorCodeInvalidSMSID,
Success: false, Success: false,
}) })
return return
} }
smsTmpl := &powow.SMSTemplate{} if smsID < 0 || int(smsID) > len(conf.Powow.SMS)-1 {
sendPowowResponse(w, &PowowResponse{
ErrorCode: ErrorCodeInvalidSMSID,
Success: false,
})
if err := db.One("ID", smsID, smsTmpl); err != nil { return
if errors.Is(err, storm.ErrNotFound) {
sendPowowResponse(w, &PowowResponse{
ErrorCode: map[int]ErrorCode{0: ErrorCodeTransactionSMSSendInvalidSMSID},
Success: false,
})
return
}
panic(errors.Wrap(err, "could not retrieve sms template"))
} }
customData := make(map[string]interface{}) customData := make(map[string]interface{})
rawCustomData, exists := req.Payload["CustomData"] rawCustomData, exists := req.Payload["CustomData"]
if exists { if exists {
cData, ok := rawCustomData.(map[interface{}]interface{}) customData, ok = rawCustomData.(map[string]interface{})
if !ok { if !ok {
sendPowowResponse(w, &PowowResponse{ sendPowowResponse(w, &PowowResponse{
ErrorCode: map[int]ErrorCode{0: ErrorCodeTransactionSMSSendInvalidCustomData}, ErrorCode: ErrorCodeInvalidCustomData,
Success: false, Success: false,
}) })
return return
} }
for k, v := range cData {
customData[k.(string)] = v
}
req.Payload["CustomData"] = customData
} }
body, err := createSMSBody(smsTmpl.Content, customData) sms := conf.Powow.SMS[int(smsID)]
body, err := createSMSBody(sms.Content, customData)
if err != nil { if err != nil {
panic(errors.Wrap(err, "could not generate sms body")) panic(errors.Wrap(err, "could not generate sms body"))
} }
req.Payload["_Template"] = smsTmpl req.Payload["_Template"] = sms
storeSMS := &command.StoreSMSRequest{ storeSMS := &command.StoreSMSRequest{
From: smsTmpl.FromName, From: sms.From,
Body: body, Body: body,
Recipient: req.Payload["MobilePhoneNumber"].(string), Recipient: req.Payload["MobilePhoneNumber"].(string),
Metadata: req.Payload, Metadata: req.Payload,
@ -255,10 +187,10 @@ func handleTransactionalSMSSend(ctx context.Context, ctn *service.Container, w h
} }
res := &struct { res := &struct {
PowowResponseSuccess PowowResponse
TransactionalID int TransactionalID int
}{ }{
PowowResponseSuccess: PowowResponseSuccess{ PowowResponse: PowowResponse{
Success: true, Success: true,
ErrorCode: 0, ErrorCode: 0,
}, },
@ -270,7 +202,7 @@ func handleTransactionalSMSSend(ctx context.Context, ctn *service.Container, w h
func createSMSBody(template string, customData map[string]interface{}) (string, error) { func createSMSBody(template string, customData map[string]interface{}) (string, error) {
content := template content := template
spew.Dump(customData)
for k, v := range customData { for k, v := range customData {
decoded, err := base64.StdEncoding.DecodeString(v.(string)) decoded, err := base64.StdEncoding.DecodeString(v.(string))
if err != nil { if err != nil {
@ -285,143 +217,6 @@ func createSMSBody(template string, customData map[string]interface{}) (string,
return content, nil return content, nil
} }
// Mock https://powow4.iroquois.fr/user/docs/api/#create-transactional-sms
func handleTransactionalSMSCreate(ctx context.Context, ctn *service.Container, w http.ResponseWriter, req *PowowRequest) {
db := storm.Must(ctn)
smsTemplate := &powow.SMSTemplate{}
if err := db.Save(smsTemplate); err != nil {
panic(errors.Wrap(err, "could not save sms template"))
}
res := &struct {
PowowResponseSuccess
SmsID int
}{
PowowResponseSuccess: PowowResponseSuccess{
Success: true,
ErrorCode: 0,
},
SmsID: smsTemplate.ID,
}
sendPowowResponse(w, res)
}
// Mock https://powow4.iroquois.fr/user/docs/api/#update-transactional-sms
func handleTransactionalSMSUpdate(ctx context.Context, ctn *service.Container, w http.ResponseWriter, req *PowowRequest) {
smsID, exists, valid := getPowowSMSID(req)
if !exists {
sendPowowResponse(w, &PowowResponse{
ErrorCode: map[int]ErrorCode{0: ErrorCodeTransactionSMSUpdateMissingSMSID},
Success: false,
})
return
}
if !valid {
sendPowowResponse(w, &PowowResponse{
ErrorCode: map[int]ErrorCode{0: ErrorCodeTransactionSMSUpdateInvalidSMSID},
Success: false,
})
return
}
db := storm.Must(ctn)
smsTmpl := &powow.SMSTemplate{}
if err := db.One("ID", smsID, smsTmpl); err != nil {
if errors.Is(err, storm.ErrNotFound) {
sendPowowResponse(w, &PowowResponse{
ErrorCode: map[int]ErrorCode{0: ErrorCodeTransactionSMSUpdateInvalidSMSID},
Success: false,
})
return
}
panic(errors.Wrap(err, "could not retrieve sms template"))
}
rawContent, exists := req.Payload["Content"]
if exists {
content, ok := rawContent.(string)
if ok {
smsTmpl.Content = content
}
}
rawLanguage, exists := req.Payload["Language"]
if exists {
language, ok := rawLanguage.(string)
if ok {
if !contains(language, "en", "fr", "it", "es", "de", "pt", "pl", "zh") {
sendPowowResponse(w, &PowowResponse{
ErrorCode: map[int]ErrorCode{0: ErrorCodeTransactionSMSUpdateInvalidLanguage},
Success: false,
})
return
}
smsTmpl.Language = language
}
}
rawFromName, exists := req.Payload["FromName"]
if exists {
fromName, ok := rawFromName.(string)
if ok {
smsTmpl.FromName = fromName
}
}
rawShortLink, exists := req.Payload["ShortLink"]
if exists {
shortLink, ok := rawShortLink.(float64)
if ok {
if shortLink == 1.0 {
smsTmpl.ShortLink = 1
} else {
smsTmpl.ShortLink = 0
}
}
}
rawSMSName, exists := req.Payload["SmsName"]
if exists {
smsName, ok := rawSMSName.(string)
if ok {
smsTmpl.SmsName = smsName
}
}
rawShortLink, exists = req.Payload["ShortLink"]
if exists {
shortLink, ok := rawShortLink.(float64)
if ok {
if shortLink == 1.0 {
smsTmpl.ShortLink = 1
} else {
smsTmpl.ShortLink = 0
}
}
}
if err := db.Save(smsTmpl); err != nil {
panic(errors.Wrap(err, "could not save sms template"))
}
sendPowowResponse(w, &PowowResponseSuccess{
ErrorCode: 0,
Success: true,
})
}
func sendPowowResponse(w http.ResponseWriter, res interface{}) { func sendPowowResponse(w http.ResponseWriter, res interface{}) {
w.Header().Add("Content-Type", "application/json") w.Header().Add("Content-Type", "application/json")
@ -432,17 +227,3 @@ func sendPowowResponse(w http.ResponseWriter, res interface{}) {
panic(errors.WithStack(err)) panic(errors.WithStack(err))
} }
} }
func getPowowSMSID(req *PowowRequest) (smsID int, exists bool, valid bool) {
rawSMSID, exists := req.Payload["SmsID"]
if !exists {
return -1, false, false
}
smsIDFloat, ok := rawSMSID.(float64)
if !ok {
return -1, true, false
}
return int(smsIDFloat), true, true
}

View File

@ -1,11 +0,0 @@
package route
func contains(search string, items ...string) bool {
for _, item := range items {
if item == search {
return true
}
}
return false
}

View File

@ -1,13 +1,13 @@
FROM golang:1.17 AS build FROM golang:1.15 AS build
ARG HTTP_PROXY= ARG HTTP_PROXY=
ARG HTTPS_PROXY= ARG HTTPS_PROXY=
ARG http_proxy= ARG http_proxy=
ARG https_proxy= ARG https_proxy=
RUN apt-get update && apt-get install -y build-essential git bash curl python2 RUN apt-get update && apt-get install -y build-essential git bash curl
RUN curl -sL https://deb.nodesource.com/setup_20.x | bash - \ RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - \
&& apt-get install -y nodejs && apt-get install -y nodejs
COPY . /src COPY . /src

View File

@ -1,53 +1,14 @@
### Create transactional SMS template
# @name createSms
POST http://localhost:3000/api/v1/mock/powow POST http://localhost:3000/api/v1/mock/powow
Content-Type: application/x-www-form-urlencoded Content-Type: application/json
APIKey=powow {
&Command=TransactionalSms.Create "APIKey": "powow",
"Command": "TransactionalSms.Send",
"ResponseFormat": "JSON",
### Update transactional SMS template "SmsID": 0,
"MobilePhoneNumber": "+33699999999",
@SmsID = {{createSms.response.body.$.SmsID}} "TimeToSend": "2017-01-01 10:00:00",
"CustomData": {
POST http://localhost:3000/api/v1/mock/powow "Firstname": "Rm9v"
Content-Type: application/x-www-form-urlencoded }
}
APIKey=powow
&Command=TransactionalSms.Update
&SmsID={{SmsID}}
&SmsName=Defaut SMS
&FromName=FakeSMS
&Content=Bonjour%20%25Subscriber%3AFirstname%25%2C%5CnLorem%20ipsum%20dolor%20sit%20amet...
&ShortLink=0
&Language=fr
### Send transactional SMS
POST http://localhost:3000/api/v1/mock/powow
Content-Type: application/x-www-form-urlencoded
APIKey=powow
&Command=TransactionalSms.Send
&ResponseFormat=JSON
&SmsID={{SmsID}}
&MobilePhoneNumber=+33699999999
&TimeToSend=2017-01-01 10:00:00
&CustomData=a%3A1%3A%7Bs%3A9%3A%22Firstname%22%3Bs%3A8%3A%22am9obg%3D%3D%22%3B%7D
# custom data [Firstname => "john"] = a:1:{s:9:"Firstname";s:8:"am9obg==";}
### Send transactional SMS - Generate InvalidPhoneNumber error with valid phone number
POST http://localhost:3000/api/v1/mock/powow
Content-Type: application/x-www-form-urlencoded
APIKey=powow
&Command=TransactionalSms.Send
&ResponseFormat=JSON
&SmsID={{SmsID}}
&MobilePhoneNumber=%2B33666666666
&TimeToSend=2017-01-01 10:00:00
&CustomData=a%3A1%3A%7Bs%3A9%3A%22Firstname%22%3Bs%3A8%3A%22am9obg%3D%3D%22%3B%7D

14225
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -11,21 +11,21 @@
"author": "Cadoles <contact@cadoles.com>", "author": "Cadoles <contact@cadoles.com>",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"devDependencies": { "devDependencies": {
"@babel/core": "^7.23.9", "@babel/core": "^7.2.0",
"@babel/plugin-proposal-class-properties": "^7.18.6", "@babel/plugin-proposal-class-properties": "^7.2.1",
"@babel/preset-env": "^7.23.9", "@babel/preset-env": "^7.2.0",
"babel-loader": "^9.1.3", "babel-loader": "^8.0.4",
"bulma": "^0.9.4", "bulma": "^0.8.2",
"bulma-switch": "^2.0.4", "bulma-switch": "^2.0.0",
"css-loader": "^6.10.0", "css-loader": "^3.5.2",
"file-loader": "^6.2.0", "file-loader": "^6.0.0",
"mini-css-extract-plugin": "^2.8.0", "mini-css-extract-plugin": "^0.9.0",
"node-sass": "~9.0", "node-sass": "^4.10.0",
"resolve-url-loader": "^5.0.0", "resolve-url-loader": "^3.0.0",
"sass-loader": "^14.1.1", "sass-loader": "^8.0.2",
"stimulus": "^3.2.2", "stimulus": "^1.1.0",
"style-loader": "^3.3.4", "style-loader": "^1.1.4",
"webpack": "^5.90.3", "webpack": "^4.25.0",
"webpack-cli": "^5.1.4" "webpack-cli": "^3.1.2"
} }
} }

View File

@ -64,8 +64,8 @@ module.exports = {
}, },
plugins: [ plugins: [
new MiniCssExtractPlugin({ new MiniCssExtractPlugin({
filename: "./css/[name].css", filename: "/css/[name].css",
chunkFilename: "./css/[id].css" chunkFilename: "/css/[id].css"
}) })
] ]
} }