diff --git a/.docker/Dockerfile b/.docker/Dockerfile index c0396eb..ea129c7 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -1,5 +1,5 @@ -FROM golang:1.17-alpine as builder -LABEL maintainer="https://github.com/hyperjumptech/hyper-wallet" +FROM golang:1.22-alpine as builder +LABEL maintainer="https://github.com/hyperjumptech/bookkeeping" ENV CGO_ENABLED=0 \ GOOS=linux \ @@ -22,7 +22,7 @@ RUN adduser \ COPY . . RUN go mod tidy -RUN go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o wallet-go-img cmd/Main.go +RUN go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o bookkeeping-go-img cmd/Main.go ############################# @@ -32,11 +32,11 @@ FROM scratch COPY --from=builder /etc/passwd /etc/passwd COPY --from=builder /etc/group /etc/group -COPY --from=builder /build/wallet-go-img /app/ +COPY --from=builder /build/bookkeeping-go-img /app/ WORKDIR /app # Use an unprivileged user. USER appuser:appuser EXPOSE 7000 -CMD ["/app/wallet-go-img"] \ No newline at end of file +CMD ["/app/bookkeeping-go-img"] \ No newline at end of file diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..b5d3b49 --- /dev/null +++ b/.env.example @@ -0,0 +1,5 @@ +db.host=localhost +db.port=3306 +db.user=bookkeeping_user +db.password=bookkeeping +db.name=bookkeeping \ No newline at end of file diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index c08e3eb..510eac2 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -31,4 +31,4 @@ jobs: run: go build -v cmd/Main.go - name: Build docker - run: docker build . --file .docker/Dockerfile -t wallet-go-img:$(date +%s) + run: docker build . --file .docker/Dockerfile -t bookkeeping-go-img:$(date +%s) diff --git a/.gitignore b/.gitignore index 4370971..7a9f9b8 100644 --- a/.gitignore +++ b/.gitignore @@ -289,4 +289,11 @@ $RECYCLE.BIN/ ### ignore images *-go-img +### logs +bookkeeping*.log +logs/ + # End of https://www.toptal.com/developers/gitignore/api/go,visualstudiocode,git + +.env +mariadb/ diff --git a/Makefile b/Makefile index 7db1697..bfee218 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ -# hyper-wallet makefile +# bookkeeping makefile CURRENT_PATH ?= $(shell pwd) -IMAGE_NAME ?= wallet-go-img +IMAGE_NAME ?= bookkeeping-go-img .PHONY: all test clean build docker @@ -14,7 +14,8 @@ clean: rm -f $(IMAGE_NAME) lint: build - golint -set_exit_status ./... + go install honnef.co/go/tools/cmd/staticcheck@latest + staticcheck -f stylish ./... test-short: lint go test ./... -v -covermode=count -coverprofile=coverage.out -short diff --git a/README.md b/README.md index dad1f51..7c05d42 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # Hyperjump Bookkeeping -Bookkeeping is a generic double entry book keeping and journaling management service. It implements the [acccore](https://github.com/hyperjumptech/acccore) accounting library. The service is intended for any applications where double-entry bookkeeping is required, such as walletsand loyalty programs. +Bookkeeping is a generic double entry book keeping and journaling management service. It implements the [acccore](https://github.com/hyperjumptech/acccore) accounting library. The service is intended for any applications where double-entry bookkeeping is required, such as wallets and loyalty programs. ## building -This project is built on golang. You need golang installed on your system to run. Minimal version is **1.16** since this project uses `go mod` and resource `embedding`. +This project is built on golang. You need golang installed on your system to run. Minimal version is **1.22** since this project uses `go mod` and resource `embedding`. You can click here for the [golang resource](https://golang.org) and for more information on go and installations. @@ -22,7 +22,7 @@ or ## binary generation -`go build -a -o wallet-go-img cmd/Main.go` +`go build -a -o bookkeeping-go-img cmd/Main.go` or @@ -38,7 +38,7 @@ or ## api docs -Open API sepecificaations can be seen by hitting the `/docs` endpoint of the running instance. +Open API specifications can be seen by hitting the `/docs` endpoint of the running instance. The file swagger.json can be found in `/static/api/spec` ## Admin Dashboard diff --git a/build/azure/doBuild.yml b/build/azure/doBuild.yml index 0aabfa1..431f197 100644 --- a/build/azure/doBuild.yml +++ b/build/azure/doBuild.yml @@ -5,7 +5,7 @@ parameters: - name: imageName type: string - default: 'wallet-go-img' + default: 'bookkeeping-go-img' - name: path type: string default: './...' diff --git a/build/azure/doTests.yml b/build/azure/doTests.yml index e6b9eb1..d29b860 100644 --- a/build/azure/doTests.yml +++ b/build/azure/doTests.yml @@ -12,23 +12,22 @@ steps: - script: | set -ex go version - go get github.com/jstemmer/go-junit-report - go get github.com/axw/gocov/gocov - go get github.com/AlekSi/gocov-xml - go get golang.org/x/lint/golint - go get github.com/t-yuki/gocover-cobertura - go install github.com/newm4n/goornogo + go install github.com/jstemmer/go-junit-report/v2@latest + go install github.com/axw/gocov/gocov@latest + go install github.com/AlekSi/gocov-xml@latest + go install honnef.co/go/tools/cmd/staticcheck@latest + go install github.com/t-yuki/gocover-cobertura@latest sudo timedatectl set-timezone Asia/Jakarta workingDirectory: '$(System.DefaultWorkingDirectory)' displayName: 'Fetch dependencies' - script: | - set -ex - /home/vsts/go/bin/golint -set_exit_status ${{ parameters.testPath }} - go test ./... -cover -vet -all -v -short -covermode=count -coverprofile=coverage.out > test_results.txt + set -ex + /home/vsts/go/bin/staticcheck -version + /home/vsts/go/bin/staticcheck ${{ parameters.testPath }} + go test ./... -cover -v -short -covermode=count -coverprofile=coverage.out > test_results.txt /home/vsts/go/bin/go-junit-report < test_results.txt > report.xml /home/vsts/go/bin/gocover-cobertura < coverage.out > coverage.xml - /home/vsts/go/bin/goornogo -c 30 -i coverage.out workingDirectory: '$(System.DefaultWorkingDirectory)' displayName: 'Run unit test' diff --git a/cmd/Main.go b/cmd/Main.go index 4fc09c4..0c6f4c5 100644 --- a/cmd/Main.go +++ b/cmd/Main.go @@ -4,28 +4,18 @@ import ( "fmt" "github.com/hyperjumptech/bookkeeping/internal" - log "github.com/sirupsen/logrus" ) var ( splashScreen = ` - - ███████████████████████████████████████████████████████████████████████████████████████████████████ - █░░░░░░██████████░░░░░░█░░░░░░░░░░░░░░█░░░░░░█████████░░░░░░█████████░░░░░░░░░░░░░░█░░░░░░░░░░░░░░█ - █░░▄▀░░██████████░░▄▀░░█░░▄▀▄▀▄▀▄▀▄▀░░█░░▄▀░░█████████░░▄▀░░█████████░░▄▀▄▀▄▀▄▀▄▀░░█░░▄▀▄▀▄▀▄▀▄▀░░█ - █░░▄▀░░██████████░░▄▀░░█░░▄▀░░░░░░▄▀░░█░░▄▀░░█████████░░▄▀░░█████████░░▄▀░░░░░░░░░░█░░░░░░▄▀░░░░░░█ - █░░▄▀░░██████████░░▄▀░░█░░▄▀░░██░░▄▀░░█░░▄▀░░█████████░░▄▀░░█████████░░▄▀░░█████████████░░▄▀░░█████ - █░░▄▀░░██░░░░░░██░░▄▀░░█░░▄▀░░░░░░▄▀░░█░░▄▀░░█████████░░▄▀░░█████████░░▄▀░░░░░░░░░░█████░░▄▀░░█████ - █░░▄▀░░██░░▄▀░░██░░▄▀░░█░░▄▀▄▀▄▀▄▀▄▀░░█░░▄▀░░█████████░░▄▀░░█████████░░▄▀▄▀▄▀▄▀▄▀░░█████░░▄▀░░█████ - █░░▄▀░░██░░▄▀░░██░░▄▀░░█░░▄▀░░░░░░▄▀░░█░░▄▀░░█████████░░▄▀░░█████████░░▄▀░░░░░░░░░░█████░░▄▀░░█████ - █░░▄▀░░░░░░▄▀░░░░░░▄▀░░█░░▄▀░░██░░▄▀░░█░░▄▀░░█████████░░▄▀░░█████████░░▄▀░░█████████████░░▄▀░░█████ - █░░▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀░░█░░▄▀░░██░░▄▀░░█░░▄▀░░░░░░░░░░█░░▄▀░░░░░░░░░░█░░▄▀░░░░░░░░░░█████░░▄▀░░█████ - █░░▄▀░░░░░░▄▀░░░░░░▄▀░░█░░▄▀░░██░░▄▀░░█░░▄▀▄▀▄▀▄▀▄▀░░█░░▄▀▄▀▄▀▄▀▄▀░░█░░▄▀▄▀▄▀▄▀▄▀░░█████░░▄▀░░█████ - █░░░░░░██░░░░░░██░░░░░░█░░░░░░██░░░░░░█░░░░░░░░░░░░░░█░░░░░░░░░░░░░░█░░░░░░░░░░░░░░█████░░░░░░█████ - ███████████████████████████████████████████████████████████████████████████████████████████████████ - - - (c)2021 hyperjumptech wallet service +██████╗ ██████╗ ██████╗ ██╗ ██╗██╗ ██╗███████╗███████╗██████╗ ██╗███╗ ██╗ ██████╗ +██╔══██╗██╔═══██╗██╔═══██╗██║ ██╔╝██║ ██╔╝██╔════╝██╔════╝██╔══██╗██║████╗ ██║ ██╔════╝ +██████╔╝██║ ██║██║ ██║█████╔╝ █████╔╝ █████╗ █████╗ ██████╔╝██║██╔██╗ ██║ ██║ ███╗ +██╔══██╗██║ ██║██║ ██║██╔═██╗ ██╔═██╗ ██╔══╝ ██╔══╝ ██╔═══╝ ██║██║╚██╗██║ ██║ ██║ +██████╔╝╚██████╔╝╚██████╔╝██║ ██╗██║ ██╗███████╗███████╗██║ ██║██║ ╚████║ ╚██████╔╝ +╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ + + (c)2021-2024 hyperjumptech double bookkeeping service https://github.com/hyperjumptech/bookkeeping/README.md ` @@ -33,7 +23,6 @@ var ( func init() { fmt.Println(splashScreen) - log.Info("initialzing...") } // Main entry point diff --git a/go.mod b/go.mod index 9e2baa2..2c4b14f 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/hyperjumptech/bookkeeping -go 1.17 +go 1.22 require ( github.com/AppsFlyer/go-sundheit v0.4.0 @@ -14,17 +14,34 @@ require ( github.com/sirupsen/logrus v1.8.1 github.com/spf13/viper v1.8.0 github.com/stretchr/testify v1.7.0 - golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect + golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect ) -require github.com/snowzach/rotatefilehook v0.0.0-20180327172521-2f64f265f58c +require ( + firebase.google.com/go v3.13.0+incompatible + github.com/JamesStewy/go-mysqldump v0.2.2 + github.com/mattn/go-colorable v0.1.13 + github.com/robfig/cron/v3 v3.0.1 + github.com/snowzach/rotatefilehook v0.0.0-20180327172521-2f64f265f58c + google.golang.org/api v0.44.0 +) require ( + cloud.google.com/go v0.81.0 // indirect + cloud.google.com/go/firestore v1.1.0 // indirect + cloud.google.com/go/storage v1.10.0 // indirect + github.com/DATA-DOG/go-sqlmock v1.5.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fsnotify/fsnotify v1.4.9 // indirect + github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/google/go-cmp v0.5.5 // indirect github.com/google/uuid v1.2.0 // indirect + github.com/googleapis/gax-go/v2 v2.0.5 // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/jstemmer/go-junit-report v0.9.1 // indirect github.com/magiconair/properties v1.8.5 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/pelletier/go-toml v1.9.3 // indirect github.com/pkg/errors v0.8.1 // indirect @@ -35,7 +52,17 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.2.0 // indirect + go.opencensus.io v0.23.0 // indirect + golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect + golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect + golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect + golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 // indirect golang.org/x/text v0.3.8 // indirect + golang.org/x/tools v0.1.12 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect + google.golang.org/grpc v1.38.0 // indirect + google.golang.org/protobuf v1.26.0 // indirect gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index f33a881..12eb6bf 100644 --- a/go.sum +++ b/go.sum @@ -17,6 +17,7 @@ cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKP cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= @@ -26,6 +27,7 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0 h1:9x7Bx0A9R5/M9jibeJeZWqjeVEIxYW9fZYqB9a70/bY= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= @@ -35,13 +37,20 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +firebase.google.com/go v3.13.0+incompatible h1:3TdYC3DDi6aHn20qoRkxwGqNgdjtblwVAyRLQwGn/+4= +firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIwjt8toICdV5Wh9ptHs= github.com/AppsFlyer/go-sundheit v0.4.0 h1:7ECd0YWaXJQ9LzdCFrpGxJVeAgXvNarN6uwxrJsh69A= github.com/AppsFlyer/go-sundheit v0.4.0/go.mod h1:iZ8zWMS7idcvmqewf5mEymWWgoOiG/0WD4+aeh+heX4= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= +github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= +github.com/JamesStewy/go-mysqldump v0.2.2 h1:tMtZDnIi2hz6H3Nna0TPhvWfBZlXe4i7vkjc5Vd8Gdo= +github.com/JamesStewy/go-mysqldump v0.2.2/go.mod h1:JuJhv4dTbe2OQpABlwqj0B+6E9VLjGLG1t4NJRTcB3w= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -89,6 +98,7 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -114,6 +124,7 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -127,10 +138,13 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0 h1:wCKgOCHuUEVfsaQLpPSJb7VdYCdTVZQAuOdYm1yc/60= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 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= @@ -148,6 +162,7 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -184,11 +199,13 @@ github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXL github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -201,8 +218,12 @@ github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -235,6 +256,8 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/cors v1.8.0 h1:P2KMzcFwrPoSjkF1WLRPsp3UMLyql8L4v9hQpVeK5so= @@ -278,7 +301,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= @@ -288,6 +310,7 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= @@ -299,7 +322,6 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 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-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -323,6 +345,7 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= @@ -335,6 +358,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 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= @@ -372,6 +396,7 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 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= @@ -384,6 +409,7 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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= @@ -396,7 +422,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/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-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -440,12 +465,9 @@ golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/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= @@ -453,7 +475,6 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -510,10 +531,12 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -536,6 +559,7 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0 h1:URs6qR1lAxDsqWITsQXI4ZkGiYJ5dHtRNiCpfs2OeKA= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -543,6 +567,7 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -584,6 +609,7 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -604,6 +630,7 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -616,6 +643,7 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 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= diff --git a/internal/Server.go b/internal/Server.go index b9e4e69..50e2c52 100644 --- a/internal/Server.go +++ b/internal/Server.go @@ -11,6 +11,8 @@ import ( "github.com/hyperjumptech/acccore" "github.com/hyperjumptech/bookkeeping/internal/accounting" + "github.com/hyperjumptech/bookkeeping/internal/firebase" + "github.com/robfig/cron/v3" "github.com/gorilla/mux" "github.com/hyperjumptech/bookkeeping/internal/config" @@ -27,7 +29,7 @@ var ( // StartUpTime records first ime up startUpTime time.Time // ServerVersion is a semver versioning - serverVersion string + // serverVersion string // HTTPServer object HTTPServer *http.Server @@ -39,19 +41,21 @@ var ( address string // dbRepo database repository - dbRepo connector.MySQLDBRepository + dbRepo connector.DBRepository + + // cron timer + cr *cron.Cron ) // InitializeServer initializes all server connections func InitializeServer() error { logf := srvLog.WithField("fn", "InitializeServer") + // load system / env configs + config.LoadConfig() // configure logging logger.ConfigureLogging() - startUpTime = time.Now() - // load system / env configs - config.LoadConfig() t := time.Duration(config.GetInt("server.context.timeout")) ctx, cancel := context.WithTimeout(context.Background(), t*time.Second) @@ -62,17 +66,17 @@ func InitializeServer() error { appRouter.Router = mux.NewRouter() // setup db connection - dbRepo = connector.MySQLDBRepository{} + dbRepo = &connector.MySQLDBRepository{} err := dbRepo.Connect(ctx) if err != nil { logf.Fatal("could not connect to db. Error: ", err) panic("DB connection failed. please check log.") } - accounting.AccountMgr = accounting.NewMySQLAccountManager(&dbRepo) - accounting.JournalMgr = accounting.NewMySQLJournalManager(&dbRepo) - accounting.TransactionMgr = accounting.NewMySQLTransactionManager(&dbRepo) - accounting.ExchangeMgr = accounting.NewMySQLExchangeManager(&dbRepo) + accounting.AccountMgr = accounting.NewMySQLAccountManager(dbRepo) + accounting.JournalMgr = accounting.NewMySQLJournalManager(dbRepo) + accounting.TransactionMgr = accounting.NewMySQLTransactionManager(dbRepo) + accounting.ExchangeMgr = accounting.NewMySQLExchangeManager(dbRepo) accounting.UniqueIDGenerator = &acccore.RandomGenUniqueIDGenerator{ Length: 16, LowerAlpha: false, @@ -81,7 +85,7 @@ func InitializeServer() error { } // setup health monitoring - err = health.InitializeHealthCheck(ctx, &dbRepo) + err = health.InitializeHealthCheck(ctx, dbRepo.(*connector.MySQLDBRepository)) if err != nil { logf.Warn("health monitor error: ", err) } @@ -98,6 +102,21 @@ func InitializeServer() error { Handler: appRouter.Router, // Pass our instance of gorilla/mux in. } + // cron scheduler setup + cr = cron.New() + fmt.Println("schedule is: ", config.Get("cron.backup.daily")) + cr.AddFunc(config.Get("cron.backup.daily"), func() { cronBackupUpload(context.Background()) }) + cr.Start() + + // indicate if dev or production mode + env := config.Get("app.env") + + if env == "production" { + logf.Info("environment is: ", env) + } else { + logf.Warn("environment is: ", env) + } + return nil } @@ -105,9 +124,40 @@ func InitializeServer() error { func shutdownServer() error { logf := srvLog.WithField("fn", "shutdownServer") - dbRepo.Disconnect() + dbRepo.DB().DB.Close() logf.Info("done: db closed") + cr.Stop() + logf.Info("done: cron stopped") + + return nil +} + +// cronBackupUpload() runs periodically to dump db and upload to storage backup +func cronBackupUpload(ctx context.Context) error { + logf := srvLog.WithField("fn", "cronBackupUpload") + + file, err := dbRepo.DumpDB(ctx) + if err != nil { + logf.Error("failed to dump db to file, got: ", err) + if err = os.Remove(file); err != nil { + logf.Error("coudn't remove file, got: ", err) + } + return err + } + if err = firebase.Upload(ctx, file); err != nil { + logf.Error("failed to upload file, got: ", err) + if err = os.Remove(file); err != nil { + logf.Error("coudn't remove file, got: ", err) + } + return err + } + if err = os.Remove(file); err != nil { + logf.Error("coudn't remove file, got: ", err) + return err + } + + logf.Info("success cleaning up: ", file) return nil } diff --git a/internal/accounting/AccountingRest.go b/internal/accounting/AccountingRest.go index 0186301..4f7c5f3 100755 --- a/internal/accounting/AccountingRest.go +++ b/internal/accounting/AccountingRest.go @@ -6,7 +6,8 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" + "math/big" "net/http" "strconv" @@ -522,7 +523,7 @@ func CreateAccount(w http.ResponseWriter, r *http.Request) { return } - bodyByte, err := ioutil.ReadAll(r.Body) + bodyByte, err := io.ReadAll(r.Body) if err != nil { llog.Errorf("got %s", err.Error()) helpers.HTTPResponseBuilder(r.Context(), w, r, 500, "error reading body", err.Error(), 0) @@ -759,7 +760,7 @@ func CreateJournal(w http.ResponseWriter, r *http.Request) { } reqBod := &CreateJournalRequest{} - bodBytes, err := ioutil.ReadAll(r.Body) + bodBytes, err := io.ReadAll(r.Body) if err != nil { helpers.HTTPResponseBuilder(r.Context(), w, r, 500, "internal server error when reading body", err.Error(), 0) return @@ -823,7 +824,7 @@ func CreateReversalJournal(w http.ResponseWriter, r *http.Request) { return } - byteBody, err := ioutil.ReadAll(r.Body) + byteBody, err := io.ReadAll(r.Body) if err != nil { helpers.HTTPResponseBuilder(r.Context(), w, r, 500, "internal server error when reading body", err.Error(), 0) return @@ -877,7 +878,7 @@ func CreateReversalJournal(w http.ResponseWriter, r *http.Request) { Description: fmt.Sprintf("%s - reversed", txinfo.GetDescription()), TransactionType: tx, Amount: txinfo.GetAmount(), - AccountBalance: txinfo.GetAccountBalance(), + AccountBalance: txinfo.GetAmount(), CreateTime: time.Now(), CreateBy: rBody.Creator, } @@ -981,7 +982,7 @@ func SetCurrency(w http.ResponseWriter, r *http.Request) { return } - bodyByte, err := ioutil.ReadAll(r.Body) + bodyByte, err := io.ReadAll(r.Body) if err != nil { llog.Errorf("error while reading body. got : %s", err.Error()) helpers.HTTPResponseBuilder(r.Context(), w, r, 500, "internal server error", err.Error(), 1) diff --git a/internal/config/configuration.go b/internal/config/configuration.go index 475b342..8006145 100644 --- a/internal/config/configuration.go +++ b/internal/config/configuration.go @@ -19,13 +19,21 @@ func init() { // LoadConfig loads configuration file func LoadConfig() { - - log.Info("loading config...") + logf := log.WithField("fn", "LoadConfig") + logf.Info("loading config...") viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) - viper.AutomaticEnv() + viper.SetConfigType("env") + viper.SetConfigFile("./.env") // define config .env file to read + viper.AutomaticEnv() // read also from environment variables + err := viper.ReadInConfig() // Find and read the config file + if err != nil { // Handle errors reading the config file + logf.Warn("config file not found, got err:", err) + } else { + logf.Info("config file found and loaded.") + } - defCfg["app.id"] = "wallet-go-img" + defCfg["app.id"] = "bookkeeping-go-img" defCfg["app.version"] = "1.0.1" defCfg["app.env"] = "development" // set to production @@ -41,17 +49,32 @@ func LoadConfig() { defCfg["db.host"] = "localhost" defCfg["db.port"] = "3306" - defCfg["db.user"] = "wallet_user" - defCfg["db.password"] = "wallet" - defCfg["db.name"] = "wallet" + defCfg["db.user"] = "bookkeeping_user" + defCfg["db.password"] = "bookkeeping_password" + defCfg["db.name"] = "bookkeeping" defCfg["health.local"] = "https://httpbin.org/status/200" - defCfg["health.delay"] = "1" // seconds + defCfg["health.delay"] = "5" // seconds defCfg["health.interval"] = "30" // seconds defCfg["hmac.secret"] = "th1s?MusT#b3!4*veRY%d33p#53creT" defCfg["hmac.age.minute"] = "10" + // cron + defCfg["cron.backup.daily"] = "0 1 30 2 *" // default at 1:00 am on feb 30th (disabled) + + // firebase + defCfg["firebase.storage.bucket"] = "bookkeeping.appspot.com" + defCfg["firebase.ServiceAccountKey"] = `{ + "type": "service_account", + "project_id": "place-holder", + }` // define the serviceAccountKey in environment + + defCfg["midtrans.url"] = "https://app.sandbox.midtrans.com/snap/v1/transactions" // sandbox url + defCfg["midtrans.key"] = "SB-Mid-server-11234567890" + defCfg["midtrans.finish_url"] = "http://localhost:3000/o/transaction/callback" + defCfg["midtrans.callback_url"] = "http://localhost:8080/beta/voucher/callback" + for k := range defCfg { err := viper.BindEnv(k) if err != nil { diff --git a/internal/connector/DBConnector.go b/internal/connector/DBConnector.go index 44f9d65..ea1a90e 100755 --- a/internal/connector/DBConnector.go +++ b/internal/connector/DBConnector.go @@ -5,10 +5,10 @@ import ( "time" "github.com/jmoiron/sqlx" + "github.com/sirupsen/logrus" //Anonymous import for mysql initialization _ "github.com/go-sql-driver/mysql" - "github.com/sirupsen/logrus" ) var ( @@ -108,7 +108,7 @@ type DBRepository interface { // Connect connect there repository to the database, it uses the configuration internally for connection arguments and parameters. Connect(ctx context.Context) error - // Disconnect the already establshed connection. Throws error if the underlying database connection yield an error + // Disconnect the already established connection. Throws error if the underlying database connection yield an error Disconnect() error // IsConnected check if the connection is already established @@ -117,6 +117,9 @@ type DBRepository interface { // DB the database connection object. DB() *sqlx.DB + // Dump database for backup + DumpDB(ctx context.Context) (string, error) + // ClearTables clear all table for testing purpose ClearTables(ctx context.Context) error diff --git a/internal/connector/backup.go b/internal/connector/backup.go new file mode 100644 index 0000000..37617a2 --- /dev/null +++ b/internal/connector/backup.go @@ -0,0 +1,37 @@ +package connector + +import ( + "context" + "fmt" + + "github.com/JamesStewy/go-mysqldump" + + //Anonymous import for mysql initialization + _ "github.com/go-sql-driver/mysql" +) + +// DumpDB dumps the repository into a file +func (r *MySQLDBRepository) DumpDB(ctx context.Context) (string, error) { + logf := mysqlLog.WithField("fn", "dumpDB") + + if !r.IsConnected() { + logf.Error("database is not connected, exiting dumpDB") + return "", fmt.Errorf("database is not connected, exiting dumpDB") + } + + dumper, err := mysqldump.Register(r.db.DB, "./", "bookeepingBackup-20060102T1504") + if err != nil { + logf.Error("error registering db, got: ", err) + return "", fmt.Errorf("error registering db, got: %v", err) + } + + // Dump database to file + resultFilename, err := dumper.Dump() + if err != nil { + logf.Error("error dumping db, got: ", err) + return "", fmt.Errorf("error dumping db, got: %v", err) + } + logf.Info("Dump file saved to ", resultFilename) + + return resultFilename, nil +} diff --git a/internal/firebase/firebase.go b/internal/firebase/firebase.go new file mode 100644 index 0000000..55d4dc2 --- /dev/null +++ b/internal/firebase/firebase.go @@ -0,0 +1,86 @@ +// Package firebase handles uploads to firebase storage +package firebase + +import ( + "context" + "fmt" + "io" + "os" + + firebase "firebase.google.com/go" + + "github.com/hyperjumptech/bookkeeping/internal/config" + log "github.com/sirupsen/logrus" + "google.golang.org/api/option" +) + +var ( + fireLog = log.WithField("module", "firebase") +) + +// createApp creates a firebase app instance +func createApp(ctx context.Context) (*firebase.App, error) { + logf := fireLog.WithField("fn", "createApp") + var opt option.ClientOption + var cfg firebase.Config + + cfg.StorageBucket = config.Get("firebase.storage.bucket") + + if config.Get("app.env") == "development" { + opt = option.WithCredentialsFile("./serviceAccountKey.json") + } else { + configJSON := config.Get("firebase.ServiceAccountKey") + opt = option.WithCredentialsJSON([]byte(configJSON)) + } + + app, err := firebase.NewApp(ctx, &cfg, opt) + if err != nil { + logf.Error("error creating app got: ", err) + return nil, fmt.Errorf("error creating app: %v", err) + } + + return app, nil +} + +// Upload backs up a file to firebase +func Upload(ctx context.Context, fname string) error { + logf := fireLog.WithField("fn", "uploadFirebase") + logf.Info("starting upload..") + + app, err := createApp(ctx) + if err != nil { + logf.Error("error creating app, got: ", err) + return fmt.Errorf("error creating app: %v", err) + } + + client, err := app.Storage(ctx) + if err != nil { + logf.Error("error creating storage client, got: ", err) + return fmt.Errorf("error creating client: %v", err) + } + + bucket, err := client.DefaultBucket() + if err != nil { + logf.Error("error creating client, got: ", err) + return fmt.Errorf("error creating client: %v", err) + } + + f, err := os.Open(fname) + if err != nil { + return fmt.Errorf("os.Open: %v", err) + } + defer f.Close() + + wc := bucket.Object(fname).NewWriter(ctx) + count, err := io.Copy(wc, f) + if err != nil { + return fmt.Errorf("io.Copy: %v", err) + } + log.Info("upload success, size uploaded: ", count) + + if err := wc.Close(); err != nil { + return fmt.Errorf("Writer.Close: %v", err) + } + + return nil +} diff --git a/internal/health/health.go b/internal/health/health.go index d0bc36b..a6ccc2c 100644 --- a/internal/health/health.go +++ b/internal/health/health.go @@ -28,7 +28,7 @@ func InitializeHealthCheck(ctx context.Context, repo *connector.MySQLDBRepositor } if !repo.IsConnected() { - return errors.New("Db not connected, healthcheck disabled") + return errors.New("db not connected, healthcheck disabled") } // create a new health instance H = gosundheit.New() @@ -47,6 +47,7 @@ func InitializeHealthCheck(ctx context.Context, repo *connector.MySQLDBRepositor httpCheck, err := checks.NewHTTPCheck(httpCheckConf) if err != nil { logf.Error("could not setup httpCheck") + return err } err = H.RegisterCheck( httpCheck, @@ -55,10 +56,11 @@ func InitializeHealthCheck(ctx context.Context, repo *connector.MySQLDBRepositor ) if err != nil { logf.Error("Failed to register check(s): ", err) + return err } // For checking database connections - dbCheck, err := checks.NewPingCheck("db.check", repo.DB().DB) + dbCheck, err := checks.NewPingCheck("db.check", repo.DB()) if err != nil { logf.Error("could not setup dbCheck") } diff --git a/internal/logger/logger.go b/internal/logger/logger.go index 504dd25..e2e4f05 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -5,6 +5,7 @@ import ( "time" "github.com/hyperjumptech/bookkeeping/internal/config" + "github.com/mattn/go-colorable" log "github.com/sirupsen/logrus" "github.com/snowzach/rotatefilehook" ) @@ -12,7 +13,6 @@ import ( // ConfigureLogging set logging lever from config func ConfigureLogging() { lLevel := config.Get("server.log.level") - log.SetFormatter(&log.JSONFormatter{}) log.Info("Setting log level to: ", lLevel) switch strings.ToUpper(lLevel) { default: @@ -35,7 +35,7 @@ func ConfigureLogging() { currentTime := time.Now() rotateFileHook, err := rotatefilehook.NewRotateFileHook(rotatefilehook.RotateFileConfig{ - Filename: "bookkeeping-" + currentTime.Format("2006-01-02") + ".log", + Filename: "logs/bookkeeping-" + currentTime.Format("2006-01-02") + ".log", MaxSize: 50, // megabytes MaxBackups: 3, MaxAge: 7, //days @@ -48,6 +48,7 @@ func ConfigureLogging() { if err != nil { log.Error("Failed to initialize file rotate hook: ", err) } + log.SetOutput(colorable.NewColorableStdout()) log.SetFormatter(&log.JSONFormatter{ TimestampFormat: time.RFC3339, PrettyPrint: false, diff --git a/internal/middlewares/HMACMiddleware.go b/internal/middlewares/HMACMiddleware.go index aa65968..cf5ac0f 100755 --- a/internal/middlewares/HMACMiddleware.go +++ b/internal/middlewares/HMACMiddleware.go @@ -101,7 +101,7 @@ func DevKey(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) gHMAC := GenHMAC() if hocuspocus == "AvadaCadavra" { - w.Write([]byte(fmt.Sprintf("Looking for magical incantation.... Found\n"))) + w.Write([]byte("Looking for magical incantation.... Found\n")) first := rand.Intn(4) for i := 0; i < first; i++ { w.Write([]byte(fmt.Sprintf("%s\n", MakeResidue(gHMAC)))) @@ -111,7 +111,7 @@ func DevKey(w http.ResponseWriter, r *http.Request) { w.Write([]byte(fmt.Sprintf("%s\n", MakeResidue(gHMAC)))) } } else if len(hocuspocus) > 0 { - w.Write([]byte(fmt.Sprintf("Looking for magical incantation.... Not Found : nothing happen"))) + w.Write([]byte("Looking for magical incantation.... Not Found : nothing happen")) } else { w.Write([]byte("not found")) } diff --git a/migrations/Delete_all_tables.sql b/migrations/Delete_all_tables.sql index 0889f47..fc99b08 100755 --- a/migrations/Delete_all_tables.sql +++ b/migrations/Delete_all_tables.sql @@ -1,4 +1,4 @@ -use wallet; +use bookkeeping; DELETE FROM accounts; DELETE FROM currencies; diff --git a/migrations/Drop_all_tables.sql b/migrations/Drop_all_tables.sql index bc44c0d..ad8e594 100644 --- a/migrations/Drop_all_tables.sql +++ b/migrations/Drop_all_tables.sql @@ -1,4 +1,4 @@ -use wallet; +use bookkeeping; DROP TABLE accounts; DROP TABLE currencies; diff --git a/migrations/Generate_all_tables.sql b/migrations/Generate_all_tables.sql index 95518cd..7f76cc0 100644 --- a/migrations/Generate_all_tables.sql +++ b/migrations/Generate_all_tables.sql @@ -1,4 +1,4 @@ -use wallet; +use bookkeeping; CREATE TABLE IF NOT EXISTS accounts ( `account_number` VARCHAR(20) NOT NULL, diff --git a/static/api/swagger/spec/swagger.json b/static/api/swagger/spec/swagger.json index 293a873..bc4e525 100644 --- a/static/api/swagger/spec/swagger.json +++ b/static/api/swagger/spec/swagger.json @@ -1,7 +1,7 @@ { "openapi": "3.0.2", "info": { - "description": "This is the API documentation for a generic wallet service with double bookkeeping. You can find\nout more about Swagger at\n[http://swagger.io](http://swagger.io) or on\n[irc.freenode.net, #swagger](http://swagger.io/irc/).\n", + "description": "This is the double bookkeeping service swagger api documentation. You can find\nout more about Swagger at\n[http://swagger.io](http://swagger.io) or on\n[irc.freenode.net, #swagger](http://swagger.io/irc/).\n", "version": "1.0.0", "title": "bookkeeping", "termsOfService": "http://swagger.io/terms/", @@ -1712,4 +1712,4 @@ } } } -} \ No newline at end of file +}