Compare commits

...

55 Commits

Author SHA1 Message Date
MaysWind 1287c729f2 modify font color style in transaction view page 2023-04-03 00:29:25 +08:00
MaysWind c069faa6f4 modify item header color in ios dark theme 2023-04-03 00:25:50 +08:00
MaysWind 286fd91b2b modify setting ui 2023-04-02 23:29:41 +08:00
MaysWind 33250d2f3d optimize user data export process 2023-04-02 23:18:05 +08:00
MaysWind 44ca940ca3 add splash screen images for ios 2023-04-02 21:05:59 +08:00
MaysWind 3b0ef7a96d data management page shows all user data statistics 2023-04-02 19:36:10 +08:00
MaysWind dfb6c593e4 format code 2023-04-02 18:14:16 +08:00
MaysWind 853b01e2ca show message when force update exchange rates data and the data is up to date 2023-04-02 18:06:36 +08:00
MaysWind 5a924fa382 code refactor 2023-04-02 17:35:31 +08:00
MaysWind d4985a024d use unambiguous numeric variable type 2023-03-27 23:58:33 +08:00
MaysWind 2797266de6 check numeric setting value, add numeric value range comment in config file 2023-03-27 23:13:18 +08:00
MaysWind b476cc91ca bump year 2023-03-27 22:10:57 +08:00
MaysWind 9e3aa19a09 make related transaction has the same unix time with the original transaction 2023-03-27 00:11:39 +08:00
MaysWind 7443e8a532 uuid generator supports generating more than 1 uuid in one time 2023-03-27 00:02:48 +08:00
MaysWind 1d6dbf63c0 code refactor 2023-03-26 23:53:52 +08:00
MaysWind e17687f80d fix wrong string format placeholder 2023-03-26 23:24:29 +08:00
MaysWind 27f4e14a4e code refactor 2023-03-26 22:24:26 +08:00
MaysWind 8d5de98218 record transaction created ip 2023-03-26 22:10:04 +08:00
MaysWind dbf5c0a5bd update golang to 1.20 and update nodejs to 18.15 2023-03-24 00:45:33 +08:00
MaysWind c1422f789a update third party dependencies 2023-03-24 00:40:46 +08:00
MaysWind 613af9399a update badge image 2023-01-08 21:57:22 +08:00
MaysWind 34a6108bb2 modify the end time of last 7/30 days to the end time in today 2023-01-05 22:34:45 +08:00
MaysWind 66a5508abe update third party dependencies 2022-12-06 01:16:02 +08:00
MaysWind 3a273ea64f update base image 2022-12-06 01:14:39 +08:00
MaysWind 6f88e6ef26 add health check api 2022-12-05 22:59:26 +08:00
MaysWind fd7905833e optimize statistics page style 2022-08-01 00:33:19 +08:00
MaysWind 1977e436d6 add "sort by" drop down list in statistics page 2022-07-25 01:11:35 +08:00
MaysWind 0dfb3d00e9 code refactor 2022-07-25 00:22:04 +08:00
MaysWind 785ec9bdb1 update docker base image 2022-07-24 20:35:55 +08:00
MaysWind eeccc4fd49 update third party dependencies 2022-07-24 20:14:39 +08:00
MaysWind efea9a7c37 update year 2022-07-24 19:20:40 +08:00
MaysWind 04eafd6705 code refactor 2022-07-24 19:00:16 +08:00
MaysWind 73b554aa48 auto set transaction type in transaction adding page according to the category id 2022-07-24 17:56:49 +08:00
MaysWind d3ddcf4c20 bump version to 0.2.0 2022-07-24 15:45:12 +08:00
MaysWind ed9ea2f1d3 modify cancel button text and position in license popup 2022-07-21 01:10:36 +08:00
MaysWind 7eae3e9923 show currency code when show currency name 2022-07-21 01:07:43 +08:00
MaysWind 03d95033d7 allow set base amount in exchange rate page 2022-07-21 00:41:37 +08:00
MaysWind 9a79606565 support set user default account 2022-04-18 00:16:47 +08:00
MaysWind c5a101aad2 fix bug 2022-04-17 23:32:00 +08:00
MaysWind 2dbf4d652d update third party dependencies 2022-03-20 23:20:11 +08:00
MaysWind 7364380312 support filter by parent account in transaction list page 2022-03-20 22:26:27 +08:00
MaysWind b7fe70aba3 change method name 2022-03-07 00:27:12 +08:00
MaysWind bca9982c57 hide add icon when filter parent account in transaction list page 2022-03-07 00:02:00 +08:00
MaysWind 7c16435010 make parent account clickable in account list page 2022-03-06 23:55:18 +08:00
MaysWind a79def625c update third party dependencies 2022-03-06 22:59:24 +08:00
MaysWind 8d5f804a60 modify save button text 2022-01-03 20:25:56 +08:00
mayswind 0167381f0d Merge pull request #1 from jiangshengwu/fix_transaction_amount
remove uid in selected columns
2021-07-12 20:31:15 +08:00
Shengwu Jiang 4e2c4b39bb remove uid in selected columns 2021-07-12 20:18:00 +08:00
MaysWind 7bfc84abc8 update comment 2021-07-04 22:57:28 +08:00
MaysWind 5ac6c64079 add data & log folder for building package 2021-06-29 23:57:21 +08:00
MaysWind e7c4261b86 add generating secret key utility 2021-06-28 00:41:14 +08:00
MaysWind 163b75e81b modify method name 2021-06-28 00:39:12 +08:00
MaysWind 949132ef5a modify timezone 2021-06-27 23:15:10 +08:00
MaysWind 5617d31ed8 update build.sh help message 2021-06-23 00:13:17 +08:00
MaysWind 832d865397 modify comments in config file 2021-06-21 00:54:14 +08:00
125 changed files with 13575 additions and 8882 deletions
+3 -3
View File
@@ -1,5 +1,5 @@
# Build backend binary file # Build backend binary file
FROM golang:1.16.5-alpine3.13 AS be-builder FROM golang:1.20.2-alpine3.17 AS be-builder
ARG RELEASE_BUILD ARG RELEASE_BUILD
ENV RELEASE_BUILD=$RELEASE_BUILD ENV RELEASE_BUILD=$RELEASE_BUILD
WORKDIR /go/src/github.com/mayswind/ezbookkeeping WORKDIR /go/src/github.com/mayswind/ezbookkeeping
@@ -9,7 +9,7 @@ RUN apk add git gcc g++ libc-dev
RUN ./build.sh backend RUN ./build.sh backend
# Build frontend files # Build frontend files
FROM node:14.17.0-alpine3.13 AS fe-builder FROM node:18.15.0-alpine3.17 AS fe-builder
ARG RELEASE_BUILD ARG RELEASE_BUILD
ENV RELEASE_BUILD=$RELEASE_BUILD ENV RELEASE_BUILD=$RELEASE_BUILD
WORKDIR /go/src/github.com/mayswind/ezbookkeeping WORKDIR /go/src/github.com/mayswind/ezbookkeeping
@@ -19,7 +19,7 @@ RUN apk add git
RUN ./build.sh frontend RUN ./build.sh frontend
# Package docker image # Package docker image
FROM alpine:3.13.5 FROM alpine:3.17.2
LABEL maintainer="MaysWind <i@mayswind.net>" LABEL maintainer="MaysWind <i@mayswind.net>"
RUN addgroup -S -g 1000 ezbookkeeping && adduser -S -G ezbookkeeping -u 1000 ezbookkeeping RUN addgroup -S -g 1000 ezbookkeeping && adduser -S -G ezbookkeeping -u 1000 ezbookkeeping
RUN apk --no-cache add tzdata RUN apk --no-cache add tzdata
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2020-2021 MaysWind (i@mayswind.net) Copyright (c) 2020-2023 MaysWind (i@mayswind.net)
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+1 -1
View File
@@ -1,6 +1,6 @@
# ezBookkeeping # ezBookkeeping
[![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/mayswind/ezbookkeeping/blob/master/LICENSE) [![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/mayswind/ezbookkeeping/blob/master/LICENSE)
[![Latest Build](https://img.shields.io/github/workflow/status/mayswind/ezbookkeeping/Docker%20Release?style=flat)](https://github.com/mayswind/ezbookkeeping/actions) [![Latest Build](https://img.shields.io/github/actions/workflow/status/mayswind/ezbookkeeping/docker-snapshot.yml?branch=main)](https://github.com/mayswind/ezbookkeeping/actions)
[![Go Report](https://goreportcard.com/badge/github.com/mayswind/ezbookkeeping)](https://goreportcard.com/report/github.com/mayswind/ezbookkeeping) [![Go Report](https://goreportcard.com/badge/github.com/mayswind/ezbookkeeping)](https://goreportcard.com/report/github.com/mayswind/ezbookkeeping)
[![Latest Docker Image Size](https://img.shields.io/docker/image-size/mayswind/ezbookkeeping.svg?style=flat)](https://hub.docker.com/r/mayswind/ezbookkeeping) [![Latest Docker Image Size](https://img.shields.io/docker/image-size/mayswind/ezbookkeeping.svg?style=flat)](https://hub.docker.com/r/mayswind/ezbookkeeping)
[![Latest Release](https://img.shields.io/github/release/mayswind/ezbookkeeping.svg?style=flat)](https://github.com/mayswind/ezbookkeeping/releases) [![Latest Release](https://img.shields.io/github/release/mayswind/ezbookkeeping.svg?style=flat)](https://github.com/mayswind/ezbookkeeping/releases)
+4 -1
View File
@@ -38,7 +38,7 @@ Types:
Options: Options:
-r, --release Build release (The script will use environment variable "RELEASE_BUILD" to detect whether this is release building by default) -r, --release Build release (The script will use environment variable "RELEASE_BUILD" to detect whether this is release building by default)
-o, --output Package file name (For "package" type only) -o, --output <filename> Package file name (For "package" type only)
-t, --tag Docker tag (For "docker" type only) -t, --tag Docker tag (For "docker" type only)
-h, --help Show help -h, --help Show help
EOF EOF
@@ -135,6 +135,7 @@ build_frontend() {
npm install npm install
echo "Building frontend files ($RELEASE_TYPE)..." echo "Building frontend files ($RELEASE_TYPE)..."
export NODE_OPTIONS=--openssl-legacy-provider
npm run build -- "$frontend_build_arguments" npm run build -- "$frontend_build_arguments"
} }
@@ -158,6 +159,8 @@ build_package() {
rm -rf package rm -rf package
mkdir package mkdir package
mkdir package/data
mkdir package/log
cp ezbookkeeping package/ cp ezbookkeeping package/
cp -R dist package/public cp -R dist package/public
cp -R conf package/conf cp -R conf package/conf
+49
View File
@@ -0,0 +1,49 @@
package cmd
import (
"fmt"
"github.com/urfave/cli/v2"
"github.com/mayswind/ezbookkeeping/pkg/utils"
)
// SecurityUtils represents the security command
var SecurityUtils = &cli.Command{
Name: "security",
Usage: "ezBookkeeping security utilities",
Subcommands: []*cli.Command{
{
Name: "gen-secret-key",
Usage: "Generate a random secret key",
Action: genSecretKey,
Flags: []cli.Flag{
&cli.IntFlag{
Name: "length",
Aliases: []string{"l"},
Required: false,
DefaultText: "32",
Usage: "The length of secret key",
},
},
},
},
}
func genSecretKey(c *cli.Context) error {
length := c.Int("length")
if length <= 0 {
length = 32
}
secretKey, err := utils.GetRandomNumberOrLetter(length)
if err != nil {
return err
}
fmt.Printf("[Secret Key] %s\n", secretKey)
return nil
}
+1
View File
@@ -399,6 +399,7 @@ func printUserInfo(user *models.User) {
fmt.Printf("[Password] %s\n", user.Password) fmt.Printf("[Password] %s\n", user.Password)
fmt.Printf("[Salt] %s\n", user.Salt) fmt.Printf("[Salt] %s\n", user.Salt)
fmt.Printf("[DefaultCurrency] %s\n", user.DefaultCurrency) fmt.Printf("[DefaultCurrency] %s\n", user.DefaultCurrency)
fmt.Printf("[DefaultAccountId] %d\n", user.DefaultAccountId)
fmt.Printf("[FirstDayOfWeek] %s\n", user.FirstDayOfWeek) fmt.Printf("[FirstDayOfWeek] %s\n", user.FirstDayOfWeek)
fmt.Printf("[TransactionEditScope] %s\n", user.TransactionEditScope) fmt.Printf("[TransactionEditScope] %s\n", user.TransactionEditScope)
fmt.Printf("[Deleted] %t\n", user.Deleted) fmt.Printf("[Deleted] %t\n", user.Deleted)
+7 -9
View File
@@ -131,6 +131,8 @@ func startWebServer(c *cli.Context) error {
router.StaticFile("/desktop/touchicon.png", filepath.Join(config.StaticRootPath, "touchicon.png")) router.StaticFile("/desktop/touchicon.png", filepath.Join(config.StaticRootPath, "touchicon.png"))
router.StaticFile("/desktop/manifest.json", filepath.Join(config.StaticRootPath, "manifest.json")) router.StaticFile("/desktop/manifest.json", filepath.Join(config.StaticRootPath, "manifest.json"))
router.GET("/healthz.json", bindApi(api.Healths.HealthStatusHandler))
apiRoute := router.Group("/api") apiRoute := router.Group("/api")
apiRoute.Use(bindMiddleware(middlewares.RequestId(config))) apiRoute.Use(bindMiddleware(middlewares.RequestId(config)))
@@ -151,15 +153,6 @@ func startWebServer(c *cli.Context) error {
apiRoute.POST("/register.json", bindApi(api.Users.UserRegisterHandler)) apiRoute.POST("/register.json", bindApi(api.Users.UserRegisterHandler))
} }
if config.EnableDataExport {
dataRoute := apiRoute.Group("/data")
dataRoute.Use(bindMiddleware(middlewares.HeaderInQueryString))
dataRoute.Use(bindMiddleware(middlewares.JWTAuthorizationByQueryString))
{
dataRoute.GET("/export.csv", bindCsv(api.DataManagements.ExportDataHandler))
}
}
apiRoute.GET("/logout.json", bindApi(api.Tokens.TokenRevokeCurrentHandler)) apiRoute.GET("/logout.json", bindApi(api.Tokens.TokenRevokeCurrentHandler))
apiV1Route := apiRoute.Group("/v1") apiV1Route := apiRoute.Group("/v1")
@@ -185,8 +178,13 @@ func startWebServer(c *cli.Context) error {
} }
// Data // Data
apiV1Route.GET("/data/statistics.json", bindApi(api.DataManagements.DataStatisticsHandler))
apiV1Route.POST("/data/clear.json", bindApi(api.DataManagements.ClearDataHandler)) apiV1Route.POST("/data/clear.json", bindApi(api.DataManagements.ClearDataHandler))
if config.EnableDataExport {
apiV1Route.GET("/data/export.csv", bindCsv(api.DataManagements.ExportDataHandler))
}
// Accounts // Accounts
apiV1Route.GET("/accounts/list.json", bindApi(api.Accounts.AccountListHandler)) apiV1Route.GET("/accounts/list.json", bindApi(api.Accounts.AccountListHandler))
apiV1Route.GET("/accounts/get.json", bindApi(api.Accounts.AccountGetHandler)) apiV1Route.GET("/accounts/get.json", bindApi(api.Accounts.AccountGetHandler))
+12 -12
View File
@@ -28,13 +28,13 @@ cert_key_file =
# Unix socket path, for "socket" only # Unix socket path, for "socket" only
unix_socket = unix_socket =
# Static file root path (relative or absolute) # Static file root path (relative or absolute path)
static_root_path = public static_root_path = public
# Enable GZip # Enable GZip
enable_gzip = false enable_gzip = false
# Set to true to log each request and execution times # Set to true to log each request and execution time
log_request = true log_request = true
[database] [database]
@@ -50,19 +50,19 @@ passwd =
# For "postgres" only, Either "disable", "require" or "verify-full" # For "postgres" only, Either "disable", "require" or "verify-full"
ssl_mode = disable ssl_mode = disable
# For "sqlite3" only, absolute path of db file # For "sqlite3" only, db file path (relative or absolute path)
db_path = data/ezbookkeeping.db db_path = data/ezbookkeeping.db
# Max idle connection number, default is 2 # Max idle connection number (0 - 65535, 0 means no idle connections are retained), default is 2
max_idle_conn = 2 max_idle_conn = 2
# Max opened connection number, default is 0 (unlimited) # Max opened connection number (0 - 65535), default is 0 (unlimited)
max_open_conn = 0 max_open_conn = 0
# Max connection lifetime (seconds), default is 14400 (4 hours) # Max connection lifetime (0 - 4294967295 seconds), default is 14400 (4 hours)
conn_max_lifetime = 14400 conn_max_lifetime = 14400
# Set to true to log each sql statement and execution times # Set to true to log each sql statement and execution time
log_query = false log_query = false
# Set to true to automatically update database structure when starting web server # Set to true to automatically update database structure when starting web server
@@ -76,14 +76,14 @@ mode = console file
# Either "debug", "info", "warn", "error", default is "info" # Either "debug", "info", "warn", "error", default is "info"
level = info level = info
# For "file" only, absolute path of log file # For "file" only, log file path (relative or absolute path)
log_path = log/ezbookkeeping.log log_path = log/ezbookkeeping.log
[uuid] [uuid]
# Uuid generator type, supports "internal" currently # Uuid generator type, supports "internal" currently
generator_type = internal generator_type = internal
# For "internal" only, each server must have unique id # For "internal" only, each server must have unique id (0 - 255)
server_id = 0 server_id = 0
[security] [security]
@@ -93,10 +93,10 @@ secret_key =
# Set to true to enable two factor authorization # Set to true to enable two factor authorization
enable_two_factor = true enable_two_factor = true
# Token expired seconds, default is 2592000 (30 days) # Token expired seconds (0 - 4294967295), default is 2592000 (30 days)
token_expired_time = 2592000 token_expired_time = 2592000
# Temporary token expired seconds, default is 300 (5 minutes) # Temporary token expired seconds (0 - 4294967295), default is 300 (5 minutes)
temporary_token_expired_time = 300 temporary_token_expired_time = 300
# Add X-Request-Id header to response to track user request or error, default is true # Add X-Request-Id header to response to track user request or error, default is true
@@ -114,5 +114,5 @@ enable_export = true
# Exchange rates data source, supports "euro_central_bank", "bank_of_canada", "reserve_bank_of_australia", "czech_national_bank", "national_bank_of_poland" currently # Exchange rates data source, supports "euro_central_bank", "bank_of_canada", "reserve_bank_of_australia", "czech_national_bank", "national_bank_of_poland" currently
data_source = euro_central_bank data_source = euro_central_bank
# Requesting exchange rates data timeout (milliseconds), default is 10000 (10 seconds) # Requesting exchange rates data timeout (0 - 4294967295 milliseconds), default is 10000 (10 seconds)
request_timeout = 10000 request_timeout = 10000
+5
View File
@@ -9,6 +9,7 @@ import (
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"github.com/mayswind/ezbookkeeping/cmd" "github.com/mayswind/ezbookkeeping/cmd"
"github.com/mayswind/ezbookkeeping/pkg/settings"
"github.com/mayswind/ezbookkeeping/pkg/utils" "github.com/mayswind/ezbookkeeping/pkg/utils"
) )
@@ -24,6 +25,9 @@ var (
) )
func main() { func main() {
settings.Version = Version
settings.CommitHash = CommitHash
app := &cli.App{ app := &cli.App{
Name: "ezBookkeeping", Name: "ezBookkeeping",
Usage: "A lightweight personal bookkeeping app hosted by yourself.", Usage: "A lightweight personal bookkeeping app hosted by yourself.",
@@ -32,6 +36,7 @@ func main() {
cmd.WebServer, cmd.WebServer,
cmd.Database, cmd.Database,
cmd.UserData, cmd.UserData,
cmd.SecurityUtils,
}, },
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
+48 -16
View File
@@ -1,21 +1,53 @@
module github.com/mayswind/ezbookkeeping module github.com/mayswind/ezbookkeeping
go 1.14 go 1.20
require ( require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/gin-contrib/gzip v0.0.6
github.com/gin-contrib/gzip v0.0.3 github.com/gin-gonic/gin v1.9.0
github.com/gin-gonic/gin v1.6.3 github.com/go-playground/validator/v10 v10.12.0
github.com/go-playground/validator/v10 v10.4.1 github.com/go-sql-driver/mysql v1.7.0
github.com/go-sql-driver/mysql v1.5.0 github.com/golang-jwt/jwt/v4 v4.5.0
github.com/lib/pq v1.8.0 github.com/lib/pq v1.10.7
github.com/mattn/go-sqlite3 v1.14.4 github.com/mattn/go-sqlite3 v1.14.16
github.com/pquerna/otp v1.3.0 github.com/pquerna/otp v1.4.0
github.com/sirupsen/logrus v1.7.0 github.com/sirupsen/logrus v1.9.0
github.com/smartystreets/goconvey v1.6.4 // indirect github.com/stretchr/testify v1.8.2
github.com/stretchr/testify v1.6.1 github.com/urfave/cli/v2 v2.25.0
github.com/urfave/cli/v2 v2.3.0 golang.org/x/crypto v0.7.0
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 gopkg.in/ini.v1 v1.67.0
gopkg.in/ini.v1 v1.62.0 xorm.io/xorm v1.3.2
xorm.io/xorm v1.0.5 )
require (
github.com/boombuler/barcode v1.0.1 // indirect
github.com/bytedance/sonic v1.8.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/goccy/go-json v0.10.0 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/leodido/go-urn v1.2.2 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/syndtr/goleveldb v1.0.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.9 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
xorm.io/builder v0.3.12 // indirect
) )
+674 -74
View File
@@ -1,141 +1,741 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
gitee.com/travelliu/dm v1.8.11192/go.mod h1:DHTzyhCrM843x9VdKVbZ+GKXGRbKM2sJ4LxihRxShkE=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
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=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA=
github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gin-contrib/gzip v0.0.3 h1:etUaeesHhEORpZMp18zoOhepboiWnFtXrBZxszWUn4k= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/gzip v0.0.3/go.mod h1:YxxswVZIqOvcHEQpsSn+QF5guQtO1dCfy0shBPy4jFc= github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-playground/validator/v10 v10.12.0 h1:E4gtWgxWxp8YSxExrQFv5BpCahla0PVF2oTTEYaWQGI=
github.com/go-playground/validator/v10 v10.12.0/go.mod h1:hCAPuzYvKdP33pxWa+2+6AIKXEKqjIUyqsNCtbsSJrA=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
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=
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.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.5.3/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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
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/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk=
github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o=
github.com/jackc/pgconn v1.8.1/go.mod h1:JV6m6b6jhjdmzchES0drzCcYcAHS1OPD5xu3OZ/lE2g=
github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY=
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0=
github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po=
github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ=
github.com/jackc/pgtype v1.7.0/go.mod h1:ZnHF+rMePVqDKaOfJVI4Q8IVvAQMryDlDkZnKOI75BE=
github.com/jackc/pgtype v1.8.0/go.mod h1:PqDKcEBtllAtk/2p6z6SHdXW5UB+MhE75tUol2OKexE=
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA=
github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o=
github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg=
github.com/jackc/pgx/v4 v4.11.0/go.mod h1:i62xJgdrtVDsnL3U8ekyrQXEwGNTRoG7/8r+CIdYfcc=
github.com/jackc/pgx/v4 v4.12.0/go.mod h1:fE547h6VulLPA3kySjfnSG/e2D861g/50JlVUa/ub60=
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/leodido/go-urn v1.2.2 h1:7z68G0FCGvDk646jz1AelTYNYWrTNm0bEcFAo147wt4=
github.com/leodido/go-urn v1.2.2/go.mod h1:kUaIbLZWttglzwNuG0pgsh5vuV6u2YcGBYz1hIPjtOQ=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.7/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.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-sqlite3 v1.14.4 h1:4rQjbDxdu9fSgI/r3KN72G3c2goxknAqHHgPWWs8UlI= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-sqlite3 v1.14.4/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
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/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
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/pquerna/otp v1.3.0 h1:oJV/SkzR33anKXwQU3Of42rL4wbrffP4uvUf1SvS5Xs= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/rwtodd/Go.Sed v0.0.0-20210816025313-55464686f9ef/go.mod h1:8AEUvGVi2uQ5b24BIhcr0GCcpd/RNAFWaN2CJFrWIIQ=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
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/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
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/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU=
github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli/v2 v2.25.0 h1:ykdZKuQey2zq0yin/l7JOm9Mh+pg72ngYMeB0ABn6q8=
github.com/urfave/cli/v2 v2.25.0/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
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-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
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/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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=
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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/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-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/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-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/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-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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/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.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/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
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=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
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.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
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/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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/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.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
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= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
xorm.io/builder v0.3.7 h1:2pETdKRK+2QG4mLX4oODHEhn5Z8j1m8sXa7jfu+/SZI= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
xorm.io/xorm v1.0.5 h1:LRr5PfOUb4ODPR63YwbowkNDwcolT2LnkwP/TUaMaB0= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
xorm.io/xorm v1.0.5/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/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-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU=
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.34.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.4/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.5/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.7/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.18 h1:rMZhRcWrba0y3nVmdiQ7kxAgOOSq2m2f2VzjHLgEs6U=
modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60=
modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw=
modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI=
modernc.org/ccgo/v3 v3.11.1/go.mod h1:lWHxfsn13L3f7hgGsGlU28D9eUOf6y3ZYHKoPaKU0ag=
modernc.org/ccgo/v3 v3.11.3/go.mod h1:0oHunRBMBiXOKdaglfMlRPBALQqsfrCKXgw9okQ3GEw=
modernc.org/ccgo/v3 v3.12.4/go.mod h1:Bk+m6m2tsooJchP/Yk5ji56cClmN6R1cqc9o/YtbgBQ=
modernc.org/ccgo/v3 v3.12.6/go.mod h1:0Ji3ruvpFPpz+yu+1m0wk68pdr/LENABhTrDkMDWH6c=
modernc.org/ccgo/v3 v3.12.8/go.mod h1:Hq9keM4ZfjCDuDXxaHptpv9N24JhgBZmUG5q60iLgUo=
modernc.org/ccgo/v3 v3.12.11/go.mod h1:0jVcmyDwDKDGWbcrzQ+xwJjbhZruHtouiBEvDfoIsdg=
modernc.org/ccgo/v3 v3.12.14/go.mod h1:GhTu1k0YCpJSuWwtRAEHAol5W7g1/RRfS4/9hc9vF5I=
modernc.org/ccgo/v3 v3.12.18/go.mod h1:jvg/xVdWWmZACSgOiAhpWpwHWylbJaSzayCqNOJKIhs=
modernc.org/ccgo/v3 v3.12.20/go.mod h1:aKEdssiu7gVgSy/jjMastnv/q6wWGRbszbheXgWRHc8=
modernc.org/ccgo/v3 v3.12.21/go.mod h1:ydgg2tEprnyMn159ZO/N4pLBqpL7NOkJ88GT5zNU2dE=
modernc.org/ccgo/v3 v3.12.22/go.mod h1:nyDVFMmMWhMsgQw+5JH6B6o4MnZ+UQNw1pp52XYFPRk=
modernc.org/ccgo/v3 v3.12.25/go.mod h1:UaLyWI26TwyIT4+ZFNjkyTbsPsY3plAEB6E7L/vZV3w=
modernc.org/ccgo/v3 v3.12.29/go.mod h1:FXVjG7YLf9FetsS2OOYcwNhcdOLGt8S9bQ48+OP75cE=
modernc.org/ccgo/v3 v3.12.36/go.mod h1:uP3/Fiezp/Ga8onfvMLpREq+KUjUmYMxXPO8tETHtA8=
modernc.org/ccgo/v3 v3.12.38/go.mod h1:93O0G7baRST1vNj4wnZ49b1kLxt0xCW5Hsa2qRaZPqc=
modernc.org/ccgo/v3 v3.12.43/go.mod h1:k+DqGXd3o7W+inNujK15S5ZYuPoWYLpF5PYougCmthU=
modernc.org/ccgo/v3 v3.12.46/go.mod h1:UZe6EvMSqOxaJ4sznY7b23/k13R8XNlyWsO5bAmSgOE=
modernc.org/ccgo/v3 v3.12.47/go.mod h1:m8d6p0zNps187fhBwzY/ii6gxfjob1VxWb919Nk1HUk=
modernc.org/ccgo/v3 v3.12.50/go.mod h1:bu9YIwtg+HXQxBhsRDE+cJjQRuINuT9PUK4orOco/JI=
modernc.org/ccgo/v3 v3.12.51/go.mod h1:gaIIlx4YpmGO2bLye04/yeblmvWEmE4BBBls4aJXFiE=
modernc.org/ccgo/v3 v3.12.53/go.mod h1:8xWGGTFkdFEWBEsUmi+DBjwu/WLy3SSOrqEmKUjMeEg=
modernc.org/ccgo/v3 v3.12.54/go.mod h1:yANKFTm9llTFVX1FqNKHE0aMcQb1fuPJx6p8AcUx+74=
modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7IeU=
modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU=
modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc=
modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM=
modernc.org/ccgo/v3 v3.12.65/go.mod h1:D6hQtKxPNZiY6wDBtehSGKFKmyXn53F8nGTpH+POmS4=
modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ=
modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84=
modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ=
modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY=
modernc.org/ccgo/v3 v3.12.82 h1:wudcnJyjLj1aQQCXF3IM9Gz2X6UNjw+afIghzdtn0v8=
modernc.org/ccgo/v3 v3.12.82/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w=
modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q=
modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg=
modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M=
modernc.org/libc v1.11.5/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU=
modernc.org/libc v1.11.6/go.mod h1:ddqmzR6p5i4jIGK1d/EiSw97LBcE3dK24QEwCFvgNgE=
modernc.org/libc v1.11.11/go.mod h1:lXEp9QOOk4qAYOtL3BmMve99S5Owz7Qyowzvg6LiZso=
modernc.org/libc v1.11.13/go.mod h1:ZYawJWlXIzXy2Pzghaf7YfM8OKacP3eZQI81PDLFdY8=
modernc.org/libc v1.11.16/go.mod h1:+DJquzYi+DMRUtWI1YNxrlQO6TcA5+dRRiq8HWBWRC8=
modernc.org/libc v1.11.19/go.mod h1:e0dgEame6mkydy19KKaVPBeEnyJB4LGNb0bBH1EtQ3I=
modernc.org/libc v1.11.24/go.mod h1:FOSzE0UwookyT1TtCJrRkvsOrX2k38HoInhw+cSCUGk=
modernc.org/libc v1.11.26/go.mod h1:SFjnYi9OSd2W7f4ct622o/PAYqk7KHv6GS8NZULIjKY=
modernc.org/libc v1.11.27/go.mod h1:zmWm6kcFXt/jpzeCgfvUNswM0qke8qVwxqZrnddlDiE=
modernc.org/libc v1.11.28/go.mod h1:Ii4V0fTFcbq3qrv3CNn+OGHAvzqMBvC7dBNyC4vHZlg=
modernc.org/libc v1.11.31/go.mod h1:FpBncUkEAtopRNJj8aRo29qUiyx5AvAlAxzlx9GNaVM=
modernc.org/libc v1.11.34/go.mod h1:+Tzc4hnb1iaX/SKAutJmfzES6awxfU1BPvrrJO0pYLg=
modernc.org/libc v1.11.37/go.mod h1:dCQebOwoO1046yTrfUE5nX1f3YpGZQKNcITUYWlrAWo=
modernc.org/libc v1.11.39/go.mod h1:mV8lJMo2S5A31uD0k1cMu7vrJbSA3J3waQJxpV4iqx8=
modernc.org/libc v1.11.42/go.mod h1:yzrLDU+sSjLE+D4bIhS7q1L5UwXDOw99PLSX0BlZvSQ=
modernc.org/libc v1.11.44/go.mod h1:KFq33jsma7F5WXiYelU8quMJasCCTnHK0mkri4yPHgA=
modernc.org/libc v1.11.45/go.mod h1:Y192orvfVQQYFzCNsn+Xt0Hxt4DiO4USpLNXBlXg/tM=
modernc.org/libc v1.11.47/go.mod h1:tPkE4PzCTW27E6AIKIR5IwHAQKCAtudEIeAV1/SiyBg=
modernc.org/libc v1.11.49/go.mod h1:9JrJuK5WTtoTWIFQ7QjX2Mb/bagYdZdscI3xrvHbXjE=
modernc.org/libc v1.11.51/go.mod h1:R9I8u9TS+meaWLdbfQhq2kFknTW0O3aw3kEMqDDxMaM=
modernc.org/libc v1.11.53/go.mod h1:5ip5vWYPAoMulkQ5XlSJTy12Sz5U6blOQiYasilVPsU=
modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw=
modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M=
modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18=
modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8=
modernc.org/libc v1.11.70/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw=
modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw=
modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0=
modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI=
modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE=
modernc.org/libc v1.11.87 h1:PzIzOqtlzMDDcCzJ5cUP6h/Ku6Fa9iyflP2ccTY64aE=
modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY=
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8=
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14=
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM=
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.14.2 h1:ohsW2+e+Qe2To1W6GNezzKGwjXwSax6R+CrhRxVaFbE=
modernc.org/sqlite v1.14.2/go.mod h1:yqfn85u8wVOE6ub5UT8VI9JjhrwBUUCNyTACN0h6Sx8=
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/tcl v1.8.13/go.mod h1:V+q/Ef0IJaNUSECieLU4o+8IScapxnMyFV6i/7uQlAY=
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.2.19/go.mod h1:+ZpP0pc4zz97eukOzW3xagV/lS82IpPN9NGG5pNF9vY=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
xorm.io/builder v0.3.12 h1:ASZYX7fQmy+o8UJdhlLHSW57JDOkM8DNhcAF5d0LiJM=
xorm.io/builder v0.3.12/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
xorm.io/xorm v1.3.2 h1:uTRRKF2jYzbZ5nsofXVUx6ncMaek+SHjWYtCXyZo1oM=
xorm.io/xorm v1.3.2/go.mod h1:9NbjqdnjX6eyjRRhh01GHm64r6N9shTb/8Ak3YRt8Nw=
+10033 -7191
View File
File diff suppressed because it is too large Load Diff
+20 -20
View File
@@ -1,6 +1,6 @@
{ {
"name": "ezbookkeeping", "name": "ezbookkeeping",
"version": "0.1.0", "version": "0.2.0",
"private": true, "private": true,
"repository": { "repository": {
"type": "git", "type": "git",
@@ -12,42 +12,42 @@
"url": "https://github.com/mayswind/ezbookkeeping/issues" "url": "https://github.com/mayswind/ezbookkeeping/issues"
}, },
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "set NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve",
"build": "vue-cli-service build", "build": "set NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service build",
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^1.3.4",
"cbor-js": "^0.1.0", "cbor-js": "^0.1.0",
"core-js": "^3.6.5", "core-js": "^3.29.1",
"crypto-js": "^4.0.0", "crypto-js": "^4.1.1",
"framework7": "^5.7.14", "framework7": "^5.7.14",
"framework7-icons": "^3.0.1", "framework7-icons": "^5.0.5",
"framework7-vue": "^5.7.14", "framework7-vue": "^5.7.14",
"js-cookie": "^2.2.1", "js-cookie": "^3.0.1",
"line-awesome": "^1.3.0", "line-awesome": "^1.3.0",
"moment": "^2.29.1", "moment": "^2.29.4",
"moment-timezone": "^0.5.33", "moment-timezone": "^0.5.41",
"register-service-worker": "^1.7.2", "register-service-worker": "^1.7.2",
"ua-parser-js": "^0.7.28", "ua-parser-js": "^1.0.34",
"vue": "^2.6.12", "vue": "^2.7.14",
"vue-clipboard2": "^0.3.1", "vue-clipboard2": "^0.3.3",
"vue-i18n": "^8.24.3", "vue-i18n": "^8.28.2",
"vue-pincode-input": "^0.4.0", "vue-pincode-input": "^0.4.0",
"vuex": "^3.6.2" "vuex": "^3.6.2"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "^4.5.11", "@vue/cli-plugin-babel": "^4.5.19",
"@vue/cli-plugin-eslint": "^4.5.11", "@vue/cli-plugin-eslint": "^4.5.19",
"@vue/cli-plugin-pwa": "^4.5.11", "@vue/cli-plugin-pwa": "^4.5.19",
"@vue/cli-service": "^4.5.11", "@vue/cli-service": "^4.5.19",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"babel-plugin-component": "^1.1.1", "babel-plugin-component": "^1.1.1",
"eslint": "^6.7.2", "eslint": "^6.8.0",
"eslint-plugin-vue": "^6.2.2", "eslint-plugin-vue": "^6.2.2",
"git-revision-webpack-plugin": "^3.0.6", "git-revision-webpack-plugin": "^3.0.6",
"moment-locales-webpack-plugin": "^1.2.0", "moment-locales-webpack-plugin": "^1.2.0",
"vue-template-compiler": "^2.6.12" "vue-template-compiler": "^2.7.14"
}, },
"eslintConfig": { "eslintConfig": {
"root": true, "root": true,
+6 -6
View File
@@ -38,7 +38,7 @@ func (a *AccountsApi) AccountListHandler(c *core.Context) (interface{}, *errs.Er
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[accounts.AccountListHandler] failed to get all accounts for user \"uid:%d\", because %s", uid, err.Error()) log.ErrorfWithRequestId(c, "[accounts.AccountListHandler] failed to get all accounts for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
userAllAccountResps := make([]*models.AccountInfoResponse, len(accounts)) userAllAccountResps := make([]*models.AccountInfoResponse, len(accounts))
@@ -98,7 +98,7 @@ func (a *AccountsApi) AccountGetHandler(c *core.Context) (interface{}, *errs.Err
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[accounts.AccountGetHandler] failed to get account \"id:%d\" for user \"uid:%d\", because %s", accountGetReq.Id, uid, err.Error()) log.ErrorfWithRequestId(c, "[accounts.AccountGetHandler] failed to get account \"id:%d\" for user \"uid:%d\", because %s", accountGetReq.Id, uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
accountRespMap := make(map[int64]*models.AccountInfoResponse) accountRespMap := make(map[int64]*models.AccountInfoResponse)
@@ -190,7 +190,7 @@ func (a *AccountsApi) AccountCreateHandler(c *core.Context) (interface{}, *errs.
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[accounts.AccountCreateHandler] failed to get max display order for user \"uid:%d\", because %s", uid, err.Error()) log.ErrorfWithRequestId(c, "[accounts.AccountCreateHandler] failed to get max display order for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
mainAccount := a.createNewAccountModel(uid, &accountCreateReq, maxOrderId+1) mainAccount := a.createNewAccountModel(uid, &accountCreateReq, maxOrderId+1)
@@ -233,7 +233,7 @@ func (a *AccountsApi) AccountModifyHandler(c *core.Context) (interface{}, *errs.
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[accounts.AccountModifyHandler] failed to get account \"id:%d\" for user \"uid:%d\", because %s", accountModifyReq.Id, uid, err.Error()) log.ErrorfWithRequestId(c, "[accounts.AccountModifyHandler] failed to get account \"id:%d\" for user \"uid:%d\", because %s", accountModifyReq.Id, uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
accountMap := a.accounts.GetAccountMapByList(accountAndSubAccounts) accountMap := a.accounts.GetAccountMapByList(accountAndSubAccounts)
@@ -403,7 +403,7 @@ func (a *AccountsApi) AccountDeleteHandler(c *core.Context) (interface{}, *errs.
return true, nil return true, nil
} }
func (a *AccountsApi) createNewAccountModel(uid int64, accountCreateReq *models.AccountCreateRequest, order int) *models.Account { func (a *AccountsApi) createNewAccountModel(uid int64, accountCreateReq *models.AccountCreateRequest, order int32) *models.Account {
return &models.Account{ return &models.Account{
Uid: uid, Uid: uid,
Name: accountCreateReq.Name, Name: accountCreateReq.Name,
@@ -425,7 +425,7 @@ func (a *AccountsApi) createSubAccountModels(uid int64, accountCreateReq *models
childrenAccounts := make([]*models.Account, len(accountCreateReq.SubAccounts)) childrenAccounts := make([]*models.Account, len(accountCreateReq.SubAccounts))
for i := 0; i < len(accountCreateReq.SubAccounts); i++ { for i := int32(0); i < int32(len(accountCreateReq.SubAccounts)); i++ {
childrenAccounts[i] = a.createNewAccountModel(uid, accountCreateReq.SubAccounts[i], i+1) childrenAccounts[i] = a.createNewAccountModel(uid, accountCreateReq.SubAccounts[i], i+1)
} }
+44 -3
View File
@@ -118,6 +118,47 @@ func (a *DataManagementsApi) ExportDataHandler(c *core.Context) ([]byte, string,
return result, fileName, nil return result, fileName, nil
} }
// DataStatisticsHandler returns user data statistics
func (a *DataManagementsApi) DataStatisticsHandler(c *core.Context) (interface{}, *errs.Error) {
uid := c.GetCurrentUid()
totalAccountCount, err := a.accounts.GetTotalAccountCountByUid(uid)
if err != nil {
log.ErrorfWithRequestId(c, "[data_managements.DataStatisticsHandler] failed to get total account count for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed
}
totalTransactionCategoryCount, err := a.categories.GetTotalCategoryCountByUid(uid)
if err != nil {
log.ErrorfWithRequestId(c, "[data_managements.DataStatisticsHandler] failed to get total transaction category count for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed
}
totalTransactionTagCount, err := a.tags.GetTotalTagCountByUid(uid)
if err != nil {
log.ErrorfWithRequestId(c, "[data_managements.DataStatisticsHandler] failed to get total transaction tag count for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed
}
totalTransactionCount, err := a.transactions.GetTotalTransactionCountByUid(uid)
if err != nil {
log.ErrorfWithRequestId(c, "[data_managements.DataStatisticsHandler] failed to get total transaction count for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed
}
dataStatisticsResp := &models.DataStatisticsResponse{
TotalAccountCount: totalAccountCount,
TotalTransactionCategoryCount: totalTransactionCategoryCount,
TotalTransactionTagCount: totalTransactionTagCount,
TotalTransactionCount: totalTransactionCount,
}
return dataStatisticsResp, nil
}
// ClearDataHandler deletes all user data // ClearDataHandler deletes all user data
func (a *DataManagementsApi) ClearDataHandler(c *core.Context) (interface{}, *errs.Error) { func (a *DataManagementsApi) ClearDataHandler(c *core.Context) (interface{}, *errs.Error) {
var clearDataReq models.ClearDataRequest var clearDataReq models.ClearDataRequest
@@ -147,21 +188,21 @@ func (a *DataManagementsApi) ClearDataHandler(c *core.Context) (interface{}, *er
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[data_managements.ClearDataHandler] failed to delete all transactions, because %s", err.Error()) log.ErrorfWithRequestId(c, "[data_managements.ClearDataHandler] failed to delete all transactions, because %s", err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
err = a.categories.DeleteAllCategories(uid) err = a.categories.DeleteAllCategories(uid)
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[data_managements.ClearDataHandler] failed to delete all transaction categories, because %s", err.Error()) log.ErrorfWithRequestId(c, "[data_managements.ClearDataHandler] failed to delete all transaction categories, because %s", err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
err = a.tags.DeleteAllTags(uid) err = a.tags.DeleteAllTags(uid)
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[data_managements.ClearDataHandler] failed to delete all transaction tags, because %s", err.Error()) log.ErrorfWithRequestId(c, "[data_managements.ClearDataHandler] failed to delete all transaction tags, because %s", err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
log.InfofWithRequestId(c, "[data_managements.ClearDataHandler] user \"uid:%d\" has cleared all data", uid) log.InfofWithRequestId(c, "[data_managements.ClearDataHandler] user \"uid:%d\" has cleared all data", uid)
+2 -2
View File
@@ -1,7 +1,7 @@
package api package api
import ( import (
"io/ioutil" "io"
"net/http" "net/http"
"sort" "sort"
"time" "time"
@@ -53,7 +53,7 @@ func (a *ExchangeRatesApi) LatestExchangeRateHandler(c *core.Context) (interface
} }
defer resp.Body.Close() defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
exchangeRateResp, err := dataSource.Parse(c, body) exchangeRateResp, err := dataSource.Parse(c, body)
if err != nil { if err != nil {
+26
View File
@@ -0,0 +1,26 @@
package api
import (
"github.com/mayswind/ezbookkeeping/pkg/core"
"github.com/mayswind/ezbookkeeping/pkg/errs"
"github.com/mayswind/ezbookkeeping/pkg/settings"
)
// HealthsApi represents health api
type HealthsApi struct{}
// Initialize a healths api singleton instance
var (
Healths = &HealthsApi{}
)
// HealthStatusHandler returns the health status of current service
func (a *HealthsApi) HealthStatusHandler(c *core.Context) (interface{}, *errs.Error) {
result := make(map[string]string)
result["version"] = settings.Version
result["commit"] = settings.CommitHash
result["status"] = "ok"
return result, nil
}
+2 -2
View File
@@ -32,7 +32,7 @@ func (a *TokensApi) TokenListHandler(c *core.Context) (interface{}, *errs.Error)
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[tokens.TokenListHandler] failed to get all tokens for user \"uid:%d\", because %s", uid, err.Error()) log.ErrorfWithRequestId(c, "[tokens.TokenListHandler] failed to get all tokens for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
tokenResps := make(models.TokenInfoResponseSlice, len(tokens)) tokenResps := make(models.TokenInfoResponseSlice, len(tokens))
@@ -145,7 +145,7 @@ func (a *TokensApi) TokenRevokeAllHandler(c *core.Context) (interface{}, *errs.E
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[tokens.TokenRevokeAllHandler] failed to get all tokens for user \"uid:%d\", because %s", uid, err.Error()) log.ErrorfWithRequestId(c, "[tokens.TokenRevokeAllHandler] failed to get all tokens for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
claims := c.GetTokenClaims() claims := c.GetTokenClaims()
+9 -9
View File
@@ -37,7 +37,7 @@ func (a *TransactionCategoriesApi) CategoryListHandler(c *core.Context) (interfa
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transaction_categories.CategoryListHandler] failed to get categories for user \"uid:%d\", because %s", uid, err.Error()) log.ErrorfWithRequestId(c, "[transaction_categories.CategoryListHandler] failed to get categories for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
return a.getTransactionCategoryListByTypeResponse(categories, categoryListReq.ParentId) return a.getTransactionCategoryListByTypeResponse(categories, categoryListReq.ParentId)
@@ -58,7 +58,7 @@ func (a *TransactionCategoriesApi) CategoryGetHandler(c *core.Context) (interfac
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transaction_categories.CategoryGetHandler] failed to get category \"id:%d\" for user \"uid:%d\", because %s", categoryGetReq.Id, uid, err.Error()) log.ErrorfWithRequestId(c, "[transaction_categories.CategoryGetHandler] failed to get category \"id:%d\" for user \"uid:%d\", because %s", categoryGetReq.Id, uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
categoryResp := category.ToTransactionCategoryInfoResponse() categoryResp := category.ToTransactionCategoryInfoResponse()
@@ -102,7 +102,7 @@ func (a *TransactionCategoriesApi) CategoryCreateHandler(c *core.Context) (inter
} }
} }
var maxOrderId int var maxOrderId int32
if categoryCreateReq.ParentId <= 0 { if categoryCreateReq.ParentId <= 0 {
maxOrderId, err = a.categories.GetMaxDisplayOrder(uid, categoryCreateReq.Type) maxOrderId, err = a.categories.GetMaxDisplayOrder(uid, categoryCreateReq.Type)
@@ -112,7 +112,7 @@ func (a *TransactionCategoriesApi) CategoryCreateHandler(c *core.Context) (inter
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transaction_categories.CategoryCreateHandler] failed to get max display order for user \"uid:%d\", because %s", uid, err.Error()) log.ErrorfWithRequestId(c, "[transaction_categories.CategoryCreateHandler] failed to get max display order for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
category := a.createNewCategoryModel(uid, &categoryCreateReq, maxOrderId+1) category := a.createNewCategoryModel(uid, &categoryCreateReq, maxOrderId+1)
@@ -143,7 +143,7 @@ func (a *TransactionCategoriesApi) CategoryCreateBatchHandler(c *core.Context) (
uid := c.GetCurrentUid() uid := c.GetCurrentUid()
categoryTypeMaxOrderMap := make(map[models.TransactionCategoryType]int) categoryTypeMaxOrderMap := make(map[models.TransactionCategoryType]int32)
categoriesMap := make(map[*models.TransactionCategory][]*models.TransactionCategory) categoriesMap := make(map[*models.TransactionCategory][]*models.TransactionCategory)
categoriesMap[nil] = make([]*models.TransactionCategory, len(categoryCreateBatchReq.Categories)) categoriesMap[nil] = make([]*models.TransactionCategory, len(categoryCreateBatchReq.Categories))
totalCount := 0 totalCount := 0
@@ -157,7 +157,7 @@ func (a *TransactionCategoriesApi) CategoryCreateBatchHandler(c *core.Context) (
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transaction_categories.CategoryCreateBatchHandler] failed to get max display order for user \"uid:%d\", because %s", uid, err.Error()) log.ErrorfWithRequestId(c, "[transaction_categories.CategoryCreateBatchHandler] failed to get max display order for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
} }
@@ -170,7 +170,7 @@ func (a *TransactionCategoriesApi) CategoryCreateBatchHandler(c *core.Context) (
categoriesMap[category] = make([]*models.TransactionCategory, len(categoryCreateReq.SubCategories)) categoriesMap[category] = make([]*models.TransactionCategory, len(categoryCreateReq.SubCategories))
for j := 0; j < len(categoryCreateReq.SubCategories); j++ { for j := int32(0); j < int32(len(categoryCreateReq.SubCategories)); j++ {
subCategory := a.createNewCategoryModel(uid, categoryCreateReq.SubCategories[j], j+1) subCategory := a.createNewCategoryModel(uid, categoryCreateReq.SubCategories[j], j+1)
categoriesMap[category][j] = subCategory categoriesMap[category][j] = subCategory
totalCount++ totalCount++
@@ -208,7 +208,7 @@ func (a *TransactionCategoriesApi) CategoryModifyHandler(c *core.Context) (inter
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transaction_categories.CategoryModifyHandler] failed to get category \"id:%d\" for user \"uid:%d\", because %s", categoryModifyReq.Id, uid, err.Error()) log.ErrorfWithRequestId(c, "[transaction_categories.CategoryModifyHandler] failed to get category \"id:%d\" for user \"uid:%d\", because %s", categoryModifyReq.Id, uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
newCategory := &models.TransactionCategory{ newCategory := &models.TransactionCategory{
@@ -325,7 +325,7 @@ func (a *TransactionCategoriesApi) CategoryDeleteHandler(c *core.Context) (inter
return true, nil return true, nil
} }
func (a *TransactionCategoriesApi) createNewCategoryModel(uid int64, categoryCreateReq *models.TransactionCategoryCreateRequest, order int) *models.TransactionCategory { func (a *TransactionCategoriesApi) createNewCategoryModel(uid int64, categoryCreateReq *models.TransactionCategoryCreateRequest, order int32) *models.TransactionCategory {
return &models.TransactionCategory{ return &models.TransactionCategory{
Uid: uid, Uid: uid,
Name: categoryCreateReq.Name, Name: categoryCreateReq.Name,
+5 -5
View File
@@ -29,7 +29,7 @@ func (a *TransactionTagsApi) TagListHandler(c *core.Context) (interface{}, *errs
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transaction_tags.TagListHandler] failed to get tags for user \"uid:%d\", because %s", uid, err.Error()) log.ErrorfWithRequestId(c, "[transaction_tags.TagListHandler] failed to get tags for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
tagResps := make(models.TransactionTagInfoResponseSlice, len(tags)) tagResps := make(models.TransactionTagInfoResponseSlice, len(tags))
@@ -58,7 +58,7 @@ func (a *TransactionTagsApi) TagGetHandler(c *core.Context) (interface{}, *errs.
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transaction_tags.TagGetHandler] failed to get tag \"id:%d\" for user \"uid:%d\", because %s", tagGetReq.Id, uid, err.Error()) log.ErrorfWithRequestId(c, "[transaction_tags.TagGetHandler] failed to get tag \"id:%d\" for user \"uid:%d\", because %s", tagGetReq.Id, uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
tagResp := tag.ToTransactionTagInfoResponse() tagResp := tag.ToTransactionTagInfoResponse()
@@ -82,7 +82,7 @@ func (a *TransactionTagsApi) TagCreateHandler(c *core.Context) (interface{}, *er
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transaction_tags.TagCreateHandler] failed to get max display order for user \"uid:%d\", because %s", uid, err.Error()) log.ErrorfWithRequestId(c, "[transaction_tags.TagCreateHandler] failed to get max display order for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
tag := a.createNewTagModel(uid, &tagCreateReq, maxOrderId+1) tag := a.createNewTagModel(uid, &tagCreateReq, maxOrderId+1)
@@ -116,7 +116,7 @@ func (a *TransactionTagsApi) TagModifyHandler(c *core.Context) (interface{}, *er
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transaction_tags.TagModifyHandler] failed to get tag \"id:%d\" for user \"uid:%d\", because %s", tagModifyReq.Id, uid, err.Error()) log.ErrorfWithRequestId(c, "[transaction_tags.TagModifyHandler] failed to get tag \"id:%d\" for user \"uid:%d\", because %s", tagModifyReq.Id, uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
newTag := &models.TransactionTag{ newTag := &models.TransactionTag{
@@ -223,7 +223,7 @@ func (a *TransactionTagsApi) TagDeleteHandler(c *core.Context) (interface{}, *er
return true, nil return true, nil
} }
func (a *TransactionTagsApi) createNewTagModel(uid int64, tagCreateReq *models.TransactionTagCreateRequest, order int) *models.TransactionTag { func (a *TransactionTagsApi) createNewTagModel(uid int64, tagCreateReq *models.TransactionTagCreateRequest, order int32) *models.TransactionTag {
return &models.TransactionTag{ return &models.TransactionTag{
Uid: uid, Uid: uid,
Name: tagCreateReq.Name, Name: tagCreateReq.Name,
+71 -27
View File
@@ -46,14 +46,21 @@ func (a *TransactionsApi) TransactionCountHandler(c *core.Context) (interface{},
uid := c.GetCurrentUid() uid := c.GetCurrentUid()
allCategoryIds, err := a.getCategoryAndSubCategoryIds(transactionCountReq.CategoryId, uid) allAccountIds, err := a.getAccountOrSubAccountIds(transactionCountReq.AccountId, uid)
if err != nil {
log.WarnfWithRequestId(c, "[transactions.TransactionCountHandler] get account error, because %s", err.Error())
return nil, errs.Or(err, errs.ErrOperationFailed)
}
allCategoryIds, err := a.getCategoryOrSubCategoryIds(transactionCountReq.CategoryId, uid)
if err != nil { if err != nil {
log.WarnfWithRequestId(c, "[transactions.TransactionCountHandler] get transaction category error, because %s", err.Error()) log.WarnfWithRequestId(c, "[transactions.TransactionCountHandler] get transaction category error, because %s", err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
totalCount, err := a.transactions.GetTransactionCount(uid, transactionCountReq.MaxTime, transactionCountReq.MinTime, transactionCountReq.Type, allCategoryIds, transactionCountReq.AccountId, transactionCountReq.Keyword) totalCount, err := a.transactions.GetTransactionCount(uid, transactionCountReq.MaxTime, transactionCountReq.MinTime, transactionCountReq.Type, allCategoryIds, allAccountIds, transactionCountReq.Keyword)
countResp := &models.TransactionCountResponse{ countResp := &models.TransactionCountResponse{
TotalCount: totalCount, TotalCount: totalCount,
@@ -90,24 +97,31 @@ func (a *TransactionsApi) TransactionListHandler(c *core.Context) (interface{},
return nil, errs.ErrUserNotFound return nil, errs.ErrUserNotFound
} }
allCategoryIds, err := a.getCategoryAndSubCategoryIds(transactionListReq.CategoryId, uid) allAccountIds, err := a.getAccountOrSubAccountIds(transactionListReq.AccountId, uid)
if err != nil {
log.WarnfWithRequestId(c, "[transactions.TransactionListHandler] get account error, because %s", err.Error())
return nil, errs.Or(err, errs.ErrOperationFailed)
}
allCategoryIds, err := a.getCategoryOrSubCategoryIds(transactionListReq.CategoryId, uid)
if err != nil { if err != nil {
log.WarnfWithRequestId(c, "[transactions.TransactionListHandler] get transaction category error, because %s", err.Error()) log.WarnfWithRequestId(c, "[transactions.TransactionListHandler] get transaction category error, because %s", err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
transactions, err := a.transactions.GetTransactionsByMaxTime(uid, transactionListReq.MaxTime, transactionListReq.MinTime, transactionListReq.Type, allCategoryIds, transactionListReq.AccountId, transactionListReq.Keyword, transactionListReq.Count+1, true) transactions, err := a.transactions.GetTransactionsByMaxTime(uid, transactionListReq.MaxTime, transactionListReq.MinTime, transactionListReq.Type, allCategoryIds, allAccountIds, transactionListReq.Keyword, transactionListReq.Count+1, true)
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transactions.TransactionListHandler] failed to get transactions earlier than \"%d\" for user \"uid:%d\", because %s", transactionListReq.MaxTime, uid, err.Error()) log.ErrorfWithRequestId(c, "[transactions.TransactionListHandler] failed to get transactions earlier than \"%d\" for user \"uid:%d\", because %s", transactionListReq.MaxTime, uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
hasMore := false hasMore := false
var nextTimeSequenceId *int64 var nextTimeSequenceId *int64
if len(transactions) > transactionListReq.Count { if len(transactions) > int(transactionListReq.Count) {
hasMore = true hasMore = true
nextTimeSequenceId = &transactions[transactionListReq.Count].TransactionTime nextTimeSequenceId = &transactions[transactionListReq.Count].TransactionTime
transactions = transactions[:transactionListReq.Count] transactions = transactions[:transactionListReq.Count]
@@ -159,25 +173,32 @@ func (a *TransactionsApi) TransactionMonthListHandler(c *core.Context) (interfac
return nil, errs.ErrUserNotFound return nil, errs.ErrUserNotFound
} }
allCategoryIds, err := a.getCategoryAndSubCategoryIds(transactionListReq.CategoryId, uid) allAccountIds, err := a.getAccountOrSubAccountIds(transactionListReq.AccountId, uid)
if err != nil {
log.WarnfWithRequestId(c, "[transactions.TransactionMonthListHandler] get account error, because %s", err.Error())
return nil, errs.Or(err, errs.ErrOperationFailed)
}
allCategoryIds, err := a.getCategoryOrSubCategoryIds(transactionListReq.CategoryId, uid)
if err != nil { if err != nil {
log.WarnfWithRequestId(c, "[transactions.TransactionMonthListHandler] get transaction category error, because %s", err.Error()) log.WarnfWithRequestId(c, "[transactions.TransactionMonthListHandler] get transaction category error, because %s", err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
transactions, err := a.transactions.GetTransactionsInMonthByPage(uid, transactionListReq.Year, transactionListReq.Month, transactionListReq.Type, allCategoryIds, transactionListReq.AccountId, transactionListReq.Keyword, transactionListReq.Page, transactionListReq.Count, utcOffset) transactions, err := a.transactions.GetTransactionsInMonthByPage(uid, transactionListReq.Year, transactionListReq.Month, transactionListReq.Type, allCategoryIds, allAccountIds, transactionListReq.Keyword, transactionListReq.Page, transactionListReq.Count, utcOffset)
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transactions.TransactionMonthListHandler] failed to get transactions in month \"%d-%d\" for user \"uid:%d\", because %s", transactionListReq.Year, transactionListReq.Month, uid, err.Error()) log.ErrorfWithRequestId(c, "[transactions.TransactionMonthListHandler] failed to get transactions in month \"%d-%d\" for user \"uid:%d\", because %s", transactionListReq.Year, transactionListReq.Month, uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
totalCount, err := a.transactions.GetMonthTransactionCount(uid, transactionListReq.Year, transactionListReq.Month, transactionListReq.Type, allCategoryIds, transactionListReq.AccountId, transactionListReq.Keyword, utcOffset) totalCount, err := a.transactions.GetMonthTransactionCount(uid, transactionListReq.Year, transactionListReq.Month, transactionListReq.Type, allCategoryIds, allAccountIds, transactionListReq.Keyword, utcOffset)
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transactions.TransactionMonthListHandler] failed to get transaction count in month \"%d-%d\" for user \"uid:%d\", because %s", transactionListReq.Year, transactionListReq.Month, uid, err.Error()) log.ErrorfWithRequestId(c, "[transactions.TransactionMonthListHandler] failed to get transaction count in month \"%d-%d\" for user \"uid:%d\", because %s", transactionListReq.Year, transactionListReq.Month, uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
transactionResult, err := a.getTransactionListResult(c, user, transactions, utcOffset, transactionListReq.TrimAccount, transactionListReq.TrimCategory, transactionListReq.TrimTag) transactionResult, err := a.getTransactionListResult(c, user, transactions, utcOffset, transactionListReq.TrimAccount, transactionListReq.TrimCategory, transactionListReq.TrimTag)
@@ -261,7 +282,7 @@ func (a *TransactionsApi) TransactionAmountsHandler(c *core.Context) (interface{
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transactions.TransactionAmountsHandler] failed to get all accounts for user \"uid:%d\", because %s", uid, err.Error()) log.ErrorfWithRequestId(c, "[transactions.TransactionAmountsHandler] failed to get all accounts for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
amountsResp := make(map[string]*models.TransactionAmountsResponseItem) amountsResp := make(map[string]*models.TransactionAmountsResponseItem)
@@ -273,7 +294,7 @@ func (a *TransactionsApi) TransactionAmountsHandler(c *core.Context) (interface{
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transactions.TransactionAmountsHandler] failed to get transaction amounts item for user \"uid:%d\", because %s", uid, err.Error()) log.ErrorfWithRequestId(c, "[transactions.TransactionAmountsHandler] failed to get transaction amounts item for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
amountsMap := make(map[string]*models.TransactionAmountsResponseItemAmountInfo) amountsMap := make(map[string]*models.TransactionAmountsResponseItemAmountInfo)
@@ -369,7 +390,7 @@ func (a *TransactionsApi) TransactionMonthAmountsHandler(c *core.Context) (inter
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transactions.TransactionMonthAmountsHandler] failed to get all accounts for user \"uid:%d\", because %s", uid, err.Error()) log.ErrorfWithRequestId(c, "[transactions.TransactionMonthAmountsHandler] failed to get all accounts for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
totalAmounts, err := a.transactions.GetAccountsMonthTotalIncomeAndExpense(uid, startTime, endTime, pageCountForLoadTransactionAmounts) totalAmounts, err := a.transactions.GetAccountsMonthTotalIncomeAndExpense(uid, startTime, endTime, pageCountForLoadTransactionAmounts)
@@ -476,11 +497,11 @@ func (a *TransactionsApi) TransactionGetHandler(c *core.Context) (interface{}, *
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transactions.TransactionGetHandler] failed to get transaction \"id:%d\" for user \"uid:%d\", because %s", transactionGetReq.Id, uid, err.Error()) log.ErrorfWithRequestId(c, "[transactions.TransactionGetHandler] failed to get transaction \"id:%d\" for user \"uid:%d\", because %s", transactionGetReq.Id, uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_IN { if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_IN {
transaction = a.transactions.GetRelatedTransferTransaction(transaction, transaction.RelatedId) transaction = a.transactions.GetRelatedTransferTransaction(transaction)
} }
accountIds := make([]int64, 0, 2) accountIds := make([]int64, 0, 2)
@@ -509,7 +530,7 @@ func (a *TransactionsApi) TransactionGetHandler(c *core.Context) (interface{}, *
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transactions.TransactionGetHandler] failed to get transactions tag ids for user \"uid:%d\", because %s", uid, err.Error()) log.ErrorfWithRequestId(c, "[transactions.TransactionGetHandler] failed to get transactions tag ids for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
var category *models.TransactionCategory var category *models.TransactionCategory
@@ -520,7 +541,7 @@ func (a *TransactionsApi) TransactionGetHandler(c *core.Context) (interface{}, *
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transactions.TransactionGetHandler] failed to get transactions category for user \"uid:%d\", because %s", uid, err.Error()) log.ErrorfWithRequestId(c, "[transactions.TransactionGetHandler] failed to get transactions category for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
} }
@@ -529,7 +550,7 @@ func (a *TransactionsApi) TransactionGetHandler(c *core.Context) (interface{}, *
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transactions.TransactionGetHandler] failed to get transactions tags for user \"uid:%d\", because %s", uid, err.Error()) log.ErrorfWithRequestId(c, "[transactions.TransactionGetHandler] failed to get transactions tags for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
} }
@@ -611,7 +632,7 @@ func (a *TransactionsApi) TransactionCreateHandler(c *core.Context) (interface{}
return nil, errs.ErrUserNotFound return nil, errs.ErrUserNotFound
} }
transaction := a.createNewTransactionModel(uid, &transactionCreateReq) transaction := a.createNewTransactionModel(uid, &transactionCreateReq, c.ClientIP())
transactionEditable := user.CanEditTransactionByTransactionTime(transaction.TransactionTime, transactionCreateReq.UtcOffset) transactionEditable := user.CanEditTransactionByTransactionTime(transaction.TransactionTime, transactionCreateReq.UtcOffset)
if !transactionEditable { if !transactionEditable {
@@ -676,7 +697,7 @@ func (a *TransactionsApi) TransactionModifyHandler(c *core.Context) (interface{}
if err != nil { if err != nil {
log.ErrorfWithRequestId(c, "[transactions.TransactionModifyHandler] failed to get transactions tag ids for user \"uid:%d\", because %s", uid, err.Error()) log.ErrorfWithRequestId(c, "[transactions.TransactionModifyHandler] failed to get transactions tag ids for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed return nil, errs.Or(err, errs.ErrOperationFailed)
} }
transactionTagIds := allTransactionTagIds[transaction.TransactionId] transactionTagIds := allTransactionTagIds[transaction.TransactionId]
@@ -826,7 +847,29 @@ func (a *TransactionsApi) filterTransactions(c *core.Context, uid int64, transac
return finalTransactions return finalTransactions
} }
func (a *TransactionsApi) getCategoryAndSubCategoryIds(categoryId int64, uid int64) ([]int64, error) { func (a *TransactionsApi) getAccountOrSubAccountIds(accountId int64, uid int64) ([]int64, error) {
var allAccountIds []int64
if accountId > 0 {
allSubAccounts, err := a.accounts.GetSubAccountsByAccountId(uid, accountId)
if err != nil {
return nil, err
}
if len(allSubAccounts) > 0 {
for i := 0; i < len(allSubAccounts); i++ {
allAccountIds = append(allAccountIds, allSubAccounts[i].AccountId)
}
} else {
allAccountIds = append(allAccountIds, accountId)
}
}
return allAccountIds, nil
}
func (a *TransactionsApi) getCategoryOrSubCategoryIds(categoryId int64, uid int64) ([]int64, error) {
var allCategoryIds []int64 var allCategoryIds []int64
if categoryId > 0 { if categoryId > 0 {
@@ -940,7 +983,7 @@ func (a *TransactionsApi) getTransactionListResult(c *core.Context, user *models
transaction := transactions[i] transaction := transactions[i]
if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_IN { if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_IN {
transaction = a.transactions.GetRelatedTransferTransaction(transaction, transaction.RelatedId) transaction = a.transactions.GetRelatedTransferTransaction(transaction)
} }
transactionEditable := transaction.IsEditable(user, utcOffset, allAccounts[transaction.AccountId], allAccounts[transaction.RelatedAccountId]) transactionEditable := transaction.IsEditable(user, utcOffset, allAccounts[transaction.AccountId], allAccounts[transaction.RelatedAccountId])
@@ -973,7 +1016,7 @@ func (a *TransactionsApi) getTransactionListResult(c *core.Context, user *models
return result, nil return result, nil
} }
func (a *TransactionsApi) createNewTransactionModel(uid int64, transactionCreateReq *models.TransactionCreateRequest) *models.Transaction { func (a *TransactionsApi) createNewTransactionModel(uid int64, transactionCreateReq *models.TransactionCreateRequest, clientIp string) *models.Transaction {
var transactionDbType models.TransactionDbType var transactionDbType models.TransactionDbType
if transactionCreateReq.Type == models.TRANSACTION_TYPE_MODIFY_BALANCE { if transactionCreateReq.Type == models.TRANSACTION_TYPE_MODIFY_BALANCE {
@@ -996,6 +1039,7 @@ func (a *TransactionsApi) createNewTransactionModel(uid int64, transactionCreate
Amount: transactionCreateReq.SourceAmount, Amount: transactionCreateReq.SourceAmount,
HideAmount: transactionCreateReq.HideAmount, HideAmount: transactionCreateReq.HideAmount,
Comment: transactionCreateReq.Comment, Comment: transactionCreateReq.Comment,
CreatedIp: clientIp,
} }
if transactionCreateReq.Type == models.TRANSACTION_TYPE_TRANSFER { if transactionCreateReq.Type == models.TRANSACTION_TYPE_TRANSFER {
+14
View File
@@ -17,6 +17,7 @@ import (
type UsersApi struct { type UsersApi struct {
users *services.UserService users *services.UserService
tokens *services.TokenService tokens *services.TokenService
accounts *services.AccountService
} }
// Initialize a user api singleton instance // Initialize a user api singleton instance
@@ -24,6 +25,7 @@ var (
Users = &UsersApi{ Users = &UsersApi{
users: services.Users, users: services.Users,
tokens: services.Tokens, tokens: services.Tokens,
accounts: services.Accounts,
} }
) )
@@ -165,6 +167,18 @@ func (a *UsersApi) UserUpdateProfileHandler(c *core.Context) (interface{}, *errs
anythingUpdate = true anythingUpdate = true
} }
if userUpdateReq.DefaultAccountId > 0 && userUpdateReq.DefaultAccountId != user.DefaultAccountId {
accounts, err := a.accounts.GetAccountsByAccountIds(uid, []int64{userUpdateReq.DefaultAccountId})
if err != nil || len(accounts) < 1 {
return nil, errs.Or(err, errs.ErrUserDefaultAccountIsInvalid)
}
user.DefaultAccountId = userUpdateReq.DefaultAccountId
userNew.DefaultAccountId = userUpdateReq.DefaultAccountId
anythingUpdate = true
}
if userUpdateReq.FirstDayOfWeek != nil && *userUpdateReq.FirstDayOfWeek != user.FirstDayOfWeek { if userUpdateReq.FirstDayOfWeek != nil && *userUpdateReq.FirstDayOfWeek != user.FirstDayOfWeek {
user.FirstDayOfWeek = *userUpdateReq.FirstDayOfWeek user.FirstDayOfWeek = *userUpdateReq.FirstDayOfWeek
userNew.FirstDayOfWeek = *userUpdateReq.FirstDayOfWeek userNew.FirstDayOfWeek = *userUpdateReq.FirstDayOfWeek
+1 -1
View File
@@ -1,7 +1,7 @@
package core package core
import ( import (
"github.com/dgrijalva/jwt-go" "github.com/golang-jwt/jwt/v4"
) )
// TokenType represents token type // TokenType represents token type
+2 -2
View File
@@ -98,8 +98,8 @@ func initializeDatabase(dbConfig *settings.DatabaseConfig) (*Database, error) {
return nil, err return nil, err
} }
engineGroup.SetMaxIdleConns(dbConfig.MaxIdleConnection) engineGroup.SetMaxIdleConns(int(dbConfig.MaxIdleConnection))
engineGroup.SetMaxOpenConns(dbConfig.MaxOpenConnection) engineGroup.SetMaxOpenConns(int(dbConfig.MaxOpenConnection))
engineGroup.SetConnMaxLifetime(time.Duration(dbConfig.ConnectionMaxLifeTime) * time.Second) engineGroup.SetConnMaxLifetime(time.Duration(dbConfig.ConnectionMaxLifeTime) * time.Second)
return &Database{ return &Database{
+8 -8
View File
@@ -1,7 +1,7 @@
package errs package errs
// ErrorCategory represents error category // ErrorCategory represents error category
type ErrorCategory int type ErrorCategory int32
// Error categories // Error categories
const ( const (
@@ -32,8 +32,8 @@ const (
// Error represents the specific error returned to user // Error represents the specific error returned to user
type Error struct { type Error struct {
Category ErrorCategory Category ErrorCategory
SubCategory int SubCategory int32
Index int Index int32
HttpStatusCode int HttpStatusCode int
Message string Message string
BaseError []error BaseError []error
@@ -45,12 +45,12 @@ func (err *Error) Error() string {
} }
// Code returns the error code // Code returns the error code
func (err *Error) Code() int { func (err *Error) Code() int32 {
return int(err.Category)*100000 + err.SubCategory*1000 + err.Index return int32(err.Category)*100000 + err.SubCategory*1000 + err.Index
} }
// New returns a new error instance // New returns a new error instance
func New(category ErrorCategory, subCategory int, index int, httpStatusCode int, message string, baseError ...error) *Error { func New(category ErrorCategory, subCategory int32, index int32, httpStatusCode int, message string, baseError ...error) *Error {
return &Error{ return &Error{
Category: category, Category: category,
SubCategory: subCategory, SubCategory: subCategory,
@@ -62,12 +62,12 @@ func New(category ErrorCategory, subCategory int, index int, httpStatusCode int,
} }
// NewSystemError returns a new system error instance // NewSystemError returns a new system error instance
func NewSystemError(subCategory int, index int, httpStatusCode int, message string) *Error { func NewSystemError(subCategory int32, index int32, httpStatusCode int, message string) *Error {
return New(CATEGORY_SYSTEM, subCategory, index, httpStatusCode, message) return New(CATEGORY_SYSTEM, subCategory, index, httpStatusCode, message)
} }
// NewNormalError returns a new normal error instance // NewNormalError returns a new normal error instance
func NewNormalError(subCategory int, index int, httpStatusCode int, message string) *Error { func NewNormalError(subCategory int32, index int32, httpStatusCode int, message string) *Error {
return New(CATEGORY_NORMAL, subCategory, index, httpStatusCode, message) return New(CATEGORY_NORMAL, subCategory, index, httpStatusCode, message)
} }
+1
View File
@@ -21,4 +21,5 @@ var (
ErrUsernameAlreadyExists = NewNormalError(NormalSubcategoryUser, 12, http.StatusBadRequest, "username already exists") ErrUsernameAlreadyExists = NewNormalError(NormalSubcategoryUser, 12, http.StatusBadRequest, "username already exists")
ErrUserEmailAlreadyExists = NewNormalError(NormalSubcategoryUser, 13, http.StatusBadRequest, "email already exists") ErrUserEmailAlreadyExists = NewNormalError(NormalSubcategoryUser, 13, http.StatusBadRequest, "email already exists")
ErrUserRegistrationNotAllowed = NewNormalError(NormalSubcategoryUser, 14, http.StatusBadRequest, "user registration not allowed") ErrUserRegistrationNotAllowed = NewNormalError(NormalSubcategoryUser, 14, http.StatusBadRequest, "user registration not allowed")
ErrUserDefaultAccountIsInvalid = NewNormalError(NormalSubcategoryUser, 15, http.StatusBadRequest, "user default account is invalid")
) )
@@ -18,7 +18,7 @@ const euroCentralBankDataSource = "European Central Bank"
const euroCentralBankBaseCurrency = "EUR" const euroCentralBankBaseCurrency = "EUR"
const euroCentralBankDataUpdateDateFormat = "2006-01-02 15" const euroCentralBankDataUpdateDateFormat = "2006-01-02 15"
const euroCentralBankDataUpdateDateTimezone = "Etc/GMT-1" // UTC+01:00 const euroCentralBankDataUpdateDateTimezone = "Europe/Berlin"
// EuroCentralBankDataSource defines the structure of exchange rates data source of euro central bank // EuroCentralBankDataSource defines the structure of exchange rates data source of euro central bank
type EuroCentralBankDataSource struct { type EuroCentralBankDataSource struct {
-15
View File
@@ -37,21 +37,6 @@ func JWTAuthorization(c *core.Context) {
c.Next() c.Next()
} }
// JWTAuthorizationByQueryString verifies whether current request is valid by jwt token
func JWTAuthorizationByQueryString(c *core.Context) {
token, exists := c.GetQuery(tokenQueryStringParam)
if !exists {
log.WarnfWithRequestId(c, "[authorization.JWTAuthorizationByQueryString] no token provided")
utils.PrintJsonErrorResult(c, errs.ErrUnauthorizedAccess)
return
}
c.Request.Header.Set("Authorization", token)
JWTAuthorization(c)
}
// JWTTwoFactorAuthorization verifies whether current request is valid by 2fa passcode // JWTTwoFactorAuthorization verifies whether current request is valid by 2fa passcode
func JWTTwoFactorAuthorization(c *core.Context) { func JWTTwoFactorAuthorization(c *core.Context) {
claims, err := getTokenClaims(c) claims, err := getTokenClaims(c)
-16
View File
@@ -1,16 +0,0 @@
package middlewares
import (
"github.com/mayswind/ezbookkeeping/pkg/core"
)
const utcOffsetQueryStringParam = "utc_offset"
// HeaderInQueryString puts some headers from query string
func HeaderInQueryString(c *core.Context) {
utcOffset, exists := c.GetQuery(utcOffsetQueryStringParam)
if exists {
c.Request.Header.Set(core.ClientTimezoneOffsetHeaderName, utcOffset)
}
}
+2 -2
View File
@@ -3,7 +3,7 @@ package middlewares
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io/ioutil" "os"
"runtime" "runtime"
"github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/core"
@@ -49,7 +49,7 @@ func stack(skip int) []byte {
fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc) fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
if file != lastFile { if file != lastFile {
data, err := ioutil.ReadFile(file) data, err := os.ReadFile(file)
if err != nil { if err != nil {
continue continue
+1 -1
View File
@@ -18,7 +18,7 @@ func RequestLog(c *core.Context) {
now := time.Now() now := time.Now()
statusCode := c.Writer.Status() statusCode := c.Writer.Status()
errorCode := 0 errorCode := int32(0)
userId := "-" userId := "-"
claims := c.GetTokenClaims() claims := c.GetTokenClaims()
+1 -1
View File
@@ -19,7 +19,7 @@ func ServerSettingsCookie(config *settings.Config) core.MiddlewareHandlerFunc {
} }
bundledSettings := strings.Join(settingsArr, "_") bundledSettings := strings.Join(settingsArr, "_")
c.SetCookie(settingsCookieName, bundledSettings, config.TokenExpiredTime, "", "", false, false) c.SetCookie(settingsCookieName, bundledSettings, int(config.TokenExpiredTime), "", "", false, false)
c.Next() c.Next()
} }
+3 -3
View File
@@ -55,7 +55,7 @@ type Account struct {
Type AccountType `xorm:"NOT NULL"` Type AccountType `xorm:"NOT NULL"`
ParentAccountId int64 `xorm:"INDEX(IDX_account_uid_deleted_parent_account_id_order) NOT NULL"` ParentAccountId int64 `xorm:"INDEX(IDX_account_uid_deleted_parent_account_id_order) NOT NULL"`
Name string `xorm:"VARCHAR(32) NOT NULL"` Name string `xorm:"VARCHAR(32) NOT NULL"`
DisplayOrder int `xorm:"INDEX(IDX_account_uid_deleted_parent_account_id_order) NOT NULL"` DisplayOrder int32 `xorm:"INDEX(IDX_account_uid_deleted_parent_account_id_order) NOT NULL"`
Icon int64 `xorm:"NOT NULL"` Icon int64 `xorm:"NOT NULL"`
Color string `xorm:"VARCHAR(6) NOT NULL"` Color string `xorm:"VARCHAR(6) NOT NULL"`
Currency string `xorm:"VARCHAR(3) NOT NULL"` Currency string `xorm:"VARCHAR(3) NOT NULL"`
@@ -116,7 +116,7 @@ type AccountMoveRequest struct {
// AccountNewDisplayOrderRequest represents a data pair of id and display order // AccountNewDisplayOrderRequest represents a data pair of id and display order
type AccountNewDisplayOrderRequest struct { type AccountNewDisplayOrderRequest struct {
Id int64 `json:"id,string" binding:"required,min=1"` Id int64 `json:"id,string" binding:"required,min=1"`
DisplayOrder int `json:"displayOrder"` DisplayOrder int32 `json:"displayOrder"`
} }
// AccountDeleteRequest represents all parameters of account deleting request // AccountDeleteRequest represents all parameters of account deleting request
@@ -136,7 +136,7 @@ type AccountInfoResponse struct {
Currency string `json:"currency"` Currency string `json:"currency"`
Balance int64 `json:"balance"` Balance int64 `json:"balance"`
Comment string `json:"comment"` Comment string `json:"comment"`
DisplayOrder int `json:"displayOrder"` DisplayOrder int32 `json:"displayOrder"`
IsAsset bool `json:"isAsset,omitempty"` IsAsset bool `json:"isAsset,omitempty"`
IsLiability bool `json:"isLiability,omitempty"` IsLiability bool `json:"isLiability,omitempty"`
Hidden bool `json:"hidden"` Hidden bool `json:"hidden"`
+8
View File
@@ -4,3 +4,11 @@ package models
type ClearDataRequest struct { type ClearDataRequest struct {
Password string `json:"password" binding:"omitempty,min=6,max=128"` Password string `json:"password" binding:"omitempty,min=6,max=128"`
} }
// DataStatisticsResponse represents a view-object of user data statistic
type DataStatisticsResponse struct {
TotalAccountCount int64 `json:"totalAccountCount,string"`
TotalTransactionCategoryCount int64 `json:"totalTransactionCategoryCount,string"`
TotalTransactionTagCount int64 `json:"totalTransactionTagCount,string"`
TotalTransactionCount int64 `json:"totalTransactionCount,string"`
}
+8 -7
View File
@@ -48,6 +48,7 @@ type Transaction struct {
RelatedAccountAmount int64 `xorm:"NOT NULL"` RelatedAccountAmount int64 `xorm:"NOT NULL"`
HideAmount bool `xorm:"NOT NULL"` HideAmount bool `xorm:"NOT NULL"`
Comment string `xorm:"VARCHAR(255) NOT NULL"` Comment string `xorm:"VARCHAR(255) NOT NULL"`
CreatedIp string `xorm:"VARCHAR(39)"`
CreatedUnixTime int64 CreatedUnixTime int64
UpdatedUnixTime int64 UpdatedUnixTime int64
DeletedUnixTime int64 DeletedUnixTime int64
@@ -101,7 +102,7 @@ type TransactionListByMaxTimeRequest struct {
Keyword string `form:"keyword"` Keyword string `form:"keyword"`
MaxTime int64 `form:"max_time" binding:"min=0"` MaxTime int64 `form:"max_time" binding:"min=0"`
MinTime int64 `form:"min_time" binding:"min=0"` MinTime int64 `form:"min_time" binding:"min=0"`
Count int `form:"count" binding:"required,min=1,max=50"` Count int32 `form:"count" binding:"required,min=1,max=50"`
TrimAccount bool `form:"trim_account"` TrimAccount bool `form:"trim_account"`
TrimCategory bool `form:"trim_category"` TrimCategory bool `form:"trim_category"`
TrimTag bool `form:"trim_tag"` TrimTag bool `form:"trim_tag"`
@@ -109,14 +110,14 @@ type TransactionListByMaxTimeRequest struct {
// TransactionListInMonthByPageRequest represents all parameters of transaction listing by month request // TransactionListInMonthByPageRequest represents all parameters of transaction listing by month request
type TransactionListInMonthByPageRequest struct { type TransactionListInMonthByPageRequest struct {
Year int `form:"year" binding:"required,min=1"` Year int32 `form:"year" binding:"required,min=1"`
Month int `form:"month" binding:"required,min=1"` Month int32 `form:"month" binding:"required,min=1"`
Type TransactionDbType `form:"type" binding:"min=0,max=4"` Type TransactionDbType `form:"type" binding:"min=0,max=4"`
CategoryId int64 `form:"category_id" binding:"min=0"` CategoryId int64 `form:"category_id" binding:"min=0"`
AccountId int64 `form:"account_id" binding:"min=0"` AccountId int64 `form:"account_id" binding:"min=0"`
Keyword string `form:"keyword"` Keyword string `form:"keyword"`
Page int `form:"page" binding:"required,min=1"` Page int32 `form:"page" binding:"required,min=1"`
Count int `form:"count" binding:"required,min=1,max=50"` Count int32 `form:"count" binding:"required,min=1,max=50"`
TrimAccount bool `form:"trim_account"` TrimAccount bool `form:"trim_account"`
TrimCategory bool `form:"trim_category"` TrimCategory bool `form:"trim_category"`
TrimTag bool `form:"trim_tag"` TrimTag bool `form:"trim_tag"`
@@ -231,8 +232,8 @@ type TransactionAmountsResponseItem struct {
// TransactionMonthAmountsResponseItem represents an item of transaction month amounts // TransactionMonthAmountsResponseItem represents an item of transaction month amounts
type TransactionMonthAmountsResponseItem struct { type TransactionMonthAmountsResponseItem struct {
Year int `json:"year"` Year int32 `json:"year"`
Month int `json:"month"` Month int32 `json:"month"`
Amounts []*TransactionAmountsResponseItemAmountInfo `json:"amounts"` Amounts []*TransactionAmountsResponseItemAmountInfo `json:"amounts"`
} }
+3 -3
View File
@@ -21,7 +21,7 @@ type TransactionCategory struct {
Type TransactionCategoryType `xorm:"INDEX(IDX_category_uid_deleted_type_parent_category_id_order) NOT NULL"` Type TransactionCategoryType `xorm:"INDEX(IDX_category_uid_deleted_type_parent_category_id_order) NOT NULL"`
ParentCategoryId int64 `xorm:"INDEX(IDX_category_uid_deleted_type_parent_category_id_order) NOT NULL"` ParentCategoryId int64 `xorm:"INDEX(IDX_category_uid_deleted_type_parent_category_id_order) NOT NULL"`
Name string `xorm:"VARCHAR(32) NOT NULL"` Name string `xorm:"VARCHAR(32) NOT NULL"`
DisplayOrder int `xorm:"INDEX(IDX_category_uid_deleted_type_parent_category_id_order) NOT NULL"` DisplayOrder int32 `xorm:"INDEX(IDX_category_uid_deleted_type_parent_category_id_order) NOT NULL"`
Icon int64 `xorm:"NOT NULL"` Icon int64 `xorm:"NOT NULL"`
Color string `xorm:"VARCHAR(6) NOT NULL"` Color string `xorm:"VARCHAR(6) NOT NULL"`
Hidden bool `xorm:"NOT NULL"` Hidden bool `xorm:"NOT NULL"`
@@ -91,7 +91,7 @@ type TransactionCategoryMoveRequest struct {
// TransactionCategoryNewDisplayOrderRequest represents a data pair of id and display order // TransactionCategoryNewDisplayOrderRequest represents a data pair of id and display order
type TransactionCategoryNewDisplayOrderRequest struct { type TransactionCategoryNewDisplayOrderRequest struct {
Id int64 `json:"id,string" binding:"required,min=1"` Id int64 `json:"id,string" binding:"required,min=1"`
DisplayOrder int `json:"displayOrder"` DisplayOrder int32 `json:"displayOrder"`
} }
// TransactionCategoryDeleteRequest represents all parameters of transaction category deleting request // TransactionCategoryDeleteRequest represents all parameters of transaction category deleting request
@@ -108,7 +108,7 @@ type TransactionCategoryInfoResponse struct {
Icon int64 `json:"icon,string"` Icon int64 `json:"icon,string"`
Color string `json:"color"` Color string `json:"color"`
Comment string `json:"comment"` Comment string `json:"comment"`
DisplayOrder int `json:"displayOrder"` DisplayOrder int32 `json:"displayOrder"`
Hidden bool `json:"hidden"` Hidden bool `json:"hidden"`
SubCategories TransactionCategoryInfoResponseSlice `json:"subCategories,omitempty"` SubCategories TransactionCategoryInfoResponseSlice `json:"subCategories,omitempty"`
} }
+3 -3
View File
@@ -6,7 +6,7 @@ type TransactionTag struct {
Uid int64 `xorm:"INDEX(IDX_tag_uid_deleted_name) NOT NULL"` Uid int64 `xorm:"INDEX(IDX_tag_uid_deleted_name) NOT NULL"`
Deleted bool `xorm:"INDEX(IDX_tag_uid_deleted_name) NOT NULL"` Deleted bool `xorm:"INDEX(IDX_tag_uid_deleted_name) NOT NULL"`
Name string `xorm:"INDEX(IDX_tag_uid_deleted_name) VARCHAR(32) NOT NULL"` Name string `xorm:"INDEX(IDX_tag_uid_deleted_name) VARCHAR(32) NOT NULL"`
DisplayOrder int `xorm:"NOT NULL"` DisplayOrder int32 `xorm:"NOT NULL"`
Hidden bool `xorm:"NOT NULL"` Hidden bool `xorm:"NOT NULL"`
CreatedUnixTime int64 CreatedUnixTime int64
UpdatedUnixTime int64 UpdatedUnixTime int64
@@ -43,7 +43,7 @@ type TransactionTagMoveRequest struct {
// TransactionTagNewDisplayOrderRequest represents a data pair of id and display order // TransactionTagNewDisplayOrderRequest represents a data pair of id and display order
type TransactionTagNewDisplayOrderRequest struct { type TransactionTagNewDisplayOrderRequest struct {
Id int64 `json:"id,string" binding:"required,min=1"` Id int64 `json:"id,string" binding:"required,min=1"`
DisplayOrder int `json:"displayOrder"` DisplayOrder int32 `json:"displayOrder"`
} }
// TransactionTagDeleteRequest represents all parameters of transaction tag deleting request // TransactionTagDeleteRequest represents all parameters of transaction tag deleting request
@@ -55,7 +55,7 @@ type TransactionTagDeleteRequest struct {
type TransactionTagInfoResponse struct { type TransactionTagInfoResponse struct {
Id int64 `json:"id,string"` Id int64 `json:"id,string"`
Name string `json:"name"` Name string `json:"name"`
DisplayOrder int `json:"displayOrder"` DisplayOrder int32 `json:"displayOrder"`
Hidden bool `json:"hidden"` Hidden bool `json:"hidden"`
} }
+6
View File
@@ -94,6 +94,7 @@ type User struct {
Password string `xorm:"VARCHAR(64) NOT NULL"` Password string `xorm:"VARCHAR(64) NOT NULL"`
Salt string `xorm:"VARCHAR(10) NOT NULL"` Salt string `xorm:"VARCHAR(10) NOT NULL"`
DefaultCurrency string `xorm:"VARCHAR(3) NOT NULL"` DefaultCurrency string `xorm:"VARCHAR(3) NOT NULL"`
DefaultAccountId int64
FirstDayOfWeek WeekDay `xorm:"TINYINT NOT NULL"` FirstDayOfWeek WeekDay `xorm:"TINYINT NOT NULL"`
TransactionEditScope TransactionEditScope `xorm:"TINYINT NOT NULL"` TransactionEditScope TransactionEditScope `xorm:"TINYINT NOT NULL"`
Deleted bool `xorm:"NOT NULL"` Deleted bool `xorm:"NOT NULL"`
@@ -110,6 +111,7 @@ type UserBasicInfo struct {
Email string `json:"email"` Email string `json:"email"`
Nickname string `json:"nickname"` Nickname string `json:"nickname"`
DefaultCurrency string `json:"defaultCurrency"` DefaultCurrency string `json:"defaultCurrency"`
DefaultAccountId int64 `json:"defaultAccountId,string"`
FirstDayOfWeek WeekDay `json:"firstDayOfWeek"` FirstDayOfWeek WeekDay `json:"firstDayOfWeek"`
TransactionEditScope TransactionEditScope `json:"transactionEditScope"` TransactionEditScope TransactionEditScope `json:"transactionEditScope"`
} }
@@ -137,6 +139,7 @@ type UserProfileUpdateRequest struct {
Password string `json:"password" binding:"omitempty,min=6,max=128"` Password string `json:"password" binding:"omitempty,min=6,max=128"`
OldPassword string `json:"oldPassword" binding:"omitempty,min=6,max=128"` OldPassword string `json:"oldPassword" binding:"omitempty,min=6,max=128"`
DefaultCurrency string `json:"defaultCurrency" binding:"omitempty,len=3,validCurrency"` DefaultCurrency string `json:"defaultCurrency" binding:"omitempty,len=3,validCurrency"`
DefaultAccountId int64 `json:"defaultAccountId,string" binding:"omitempty,min=1"`
FirstDayOfWeek *WeekDay `json:"firstDayOfWeek" binding:"omitempty,min=0,max=6"` FirstDayOfWeek *WeekDay `json:"firstDayOfWeek" binding:"omitempty,min=0,max=6"`
TransactionEditScope *TransactionEditScope `json:"transactionEditScope" binding:"omitempty,min=0,max=7"` TransactionEditScope *TransactionEditScope `json:"transactionEditScope" binding:"omitempty,min=0,max=7"`
} }
@@ -153,6 +156,7 @@ type UserProfileResponse struct {
Email string `json:"email"` Email string `json:"email"`
Nickname string `json:"nickname"` Nickname string `json:"nickname"`
DefaultCurrency string `json:"defaultCurrency"` DefaultCurrency string `json:"defaultCurrency"`
DefaultAccountId int64 `json:"defaultAccountId,string"`
FirstDayOfWeek WeekDay `json:"firstDayOfWeek"` FirstDayOfWeek WeekDay `json:"firstDayOfWeek"`
TransactionEditScope TransactionEditScope `json:"transactionEditScope"` TransactionEditScope TransactionEditScope `json:"transactionEditScope"`
LastLoginAt int64 `json:"lastLoginAt"` LastLoginAt int64 `json:"lastLoginAt"`
@@ -207,6 +211,7 @@ func (u *User) ToUserBasicInfo() *UserBasicInfo {
Email: u.Email, Email: u.Email,
Nickname: u.Nickname, Nickname: u.Nickname,
DefaultCurrency: u.DefaultCurrency, DefaultCurrency: u.DefaultCurrency,
DefaultAccountId: u.DefaultAccountId,
FirstDayOfWeek: u.FirstDayOfWeek, FirstDayOfWeek: u.FirstDayOfWeek,
TransactionEditScope: u.TransactionEditScope, TransactionEditScope: u.TransactionEditScope,
} }
@@ -219,6 +224,7 @@ func (u *User) ToUserProfileResponse() *UserProfileResponse {
Email: u.Email, Email: u.Email,
Nickname: u.Nickname, Nickname: u.Nickname,
DefaultCurrency: u.DefaultCurrency, DefaultCurrency: u.DefaultCurrency,
DefaultAccountId: u.DefaultAccountId,
FirstDayOfWeek: u.FirstDayOfWeek, FirstDayOfWeek: u.FirstDayOfWeek,
TransactionEditScope: u.TransactionEditScope, TransactionEditScope: u.TransactionEditScope,
LastLoginAt: u.LastLoginUnixTime, LastLoginAt: u.LastLoginUnixTime,
+29 -2
View File
@@ -30,6 +30,17 @@ var (
} }
) )
// GetTotalAccountCountByUid returns total account count of user
func (s *AccountService) GetTotalAccountCountByUid(uid int64) (int64, error) {
if uid <= 0 {
return 0, errs.ErrUserIdInvalid
}
count, err := s.UserDataDB(uid).Where("uid=? AND deleted=?", uid, false).Count(&models.Account{})
return count, err
}
// GetAllAccountsByUid returns all account models of user // GetAllAccountsByUid returns all account models of user
func (s *AccountService) GetAllAccountsByUid(uid int64) ([]*models.Account, error) { func (s *AccountService) GetAllAccountsByUid(uid int64) ([]*models.Account, error) {
if uid <= 0 { if uid <= 0 {
@@ -58,6 +69,22 @@ func (s *AccountService) GetAccountAndSubAccountsByAccountId(uid int64, accountI
return accounts, err return accounts, err
} }
// GetSubAccountsByAccountId returns sub account models according to account id
func (s *AccountService) GetSubAccountsByAccountId(uid int64, accountId int64) ([]*models.Account, error) {
if uid <= 0 {
return nil, errs.ErrUserIdInvalid
}
if accountId <= 0 {
return nil, errs.ErrAccountIdInvalid
}
var accounts []*models.Account
err := s.UserDataDB(uid).Where("uid=? AND deleted=? AND parent_account_id=?", uid, false, accountId).OrderBy("display_order asc").Find(&accounts)
return accounts, err
}
// GetAccountsByAccountIds returns account models according to account ids // GetAccountsByAccountIds returns account models according to account ids
func (s *AccountService) GetAccountsByAccountIds(uid int64, accountIds []int64) (map[int64]*models.Account, error) { func (s *AccountService) GetAccountsByAccountIds(uid int64, accountIds []int64) (map[int64]*models.Account, error) {
if uid <= 0 { if uid <= 0 {
@@ -80,7 +107,7 @@ func (s *AccountService) GetAccountsByAccountIds(uid int64, accountIds []int64)
} }
// GetMaxDisplayOrder returns the max display order according to account category // GetMaxDisplayOrder returns the max display order according to account category
func (s *AccountService) GetMaxDisplayOrder(uid int64, category models.AccountCategory) (int, error) { func (s *AccountService) GetMaxDisplayOrder(uid int64, category models.AccountCategory) (int32, error) {
if uid <= 0 { if uid <= 0 {
return 0, errs.ErrUserIdInvalid return 0, errs.ErrUserIdInvalid
} }
@@ -100,7 +127,7 @@ func (s *AccountService) GetMaxDisplayOrder(uid int64, category models.AccountCa
} }
// GetMaxSubAccountDisplayOrder returns the max display order of sub account according to account category and parent account id // GetMaxSubAccountDisplayOrder returns the max display order of sub account according to account category and parent account id
func (s *AccountService) GetMaxSubAccountDisplayOrder(uid int64, category models.AccountCategory, parentAccountId int64) (int, error) { func (s *AccountService) GetMaxSubAccountDisplayOrder(uid int64, category models.AccountCategory, parentAccountId int64) (int32, error) {
if uid <= 0 { if uid <= 0 {
return 0, errs.ErrUserIdInvalid return 0, errs.ErrUserIdInvalid
} }
+5
View File
@@ -45,3 +45,8 @@ type ServiceUsingUuid struct {
func (s *ServiceUsingUuid) GenerateUuid(uuidType uuid.UuidType) int64 { func (s *ServiceUsingUuid) GenerateUuid(uuidType uuid.UuidType) int64 {
return s.container.GenerateUuid(uuidType) return s.container.GenerateUuid(uuidType)
} }
// GenerateUuids generates new uuids according to given uuid type and count
func (s *ServiceUsingUuid) GenerateUuids(uuidType uuid.UuidType, count uint8) []int64 {
return s.container.GenerateUuids(uuidType, count)
}
+2 -2
View File
@@ -6,8 +6,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/dgrijalva/jwt-go" "github.com/golang-jwt/jwt/v4"
"github.com/dgrijalva/jwt-go/request" "github.com/golang-jwt/jwt/v4/request"
"xorm.io/xorm" "xorm.io/xorm"
"github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/core"
+13 -2
View File
@@ -29,6 +29,17 @@ var (
} }
) )
// GetTotalCategoryCountByUid returns total category count of user
func (s *TransactionCategoryService) GetTotalCategoryCountByUid(uid int64) (int64, error) {
if uid <= 0 {
return 0, errs.ErrUserIdInvalid
}
count, err := s.UserDataDB(uid).Where("uid=? AND deleted=?", uid, false).Count(&models.TransactionCategory{})
return count, err
}
// GetAllCategoriesByUid returns all transaction category models of user // GetAllCategoriesByUid returns all transaction category models of user
func (s *TransactionCategoryService) GetAllCategoriesByUid(uid int64, categoryType models.TransactionCategoryType, parentCategoryId int64) ([]*models.TransactionCategory, error) { func (s *TransactionCategoryService) GetAllCategoriesByUid(uid int64, categoryType models.TransactionCategoryType, parentCategoryId int64) ([]*models.TransactionCategory, error) {
if uid <= 0 { if uid <= 0 {
@@ -100,7 +111,7 @@ func (s *TransactionCategoryService) GetCategoriesByCategoryIds(uid int64, categ
} }
// GetMaxDisplayOrder returns the max display order according to transaction category type // GetMaxDisplayOrder returns the max display order according to transaction category type
func (s *TransactionCategoryService) GetMaxDisplayOrder(uid int64, categoryType models.TransactionCategoryType) (int, error) { func (s *TransactionCategoryService) GetMaxDisplayOrder(uid int64, categoryType models.TransactionCategoryType) (int32, error) {
if uid <= 0 { if uid <= 0 {
return 0, errs.ErrUserIdInvalid return 0, errs.ErrUserIdInvalid
} }
@@ -120,7 +131,7 @@ func (s *TransactionCategoryService) GetMaxDisplayOrder(uid int64, categoryType
} }
// GetMaxSubCategoryDisplayOrder returns the max display order of sub transaction category according to transaction category type and parent transaction category id // GetMaxSubCategoryDisplayOrder returns the max display order of sub transaction category according to transaction category type and parent transaction category id
func (s *TransactionCategoryService) GetMaxSubCategoryDisplayOrder(uid int64, categoryType models.TransactionCategoryType, parentCategoryId int64) (int, error) { func (s *TransactionCategoryService) GetMaxSubCategoryDisplayOrder(uid int64, categoryType models.TransactionCategoryType, parentCategoryId int64) (int32, error) {
if uid <= 0 { if uid <= 0 {
return 0, errs.ErrUserIdInvalid return 0, errs.ErrUserIdInvalid
} }
+12 -1
View File
@@ -29,6 +29,17 @@ var (
} }
) )
// GetTotalTagCountByUid returns total tag count of user
func (s *TransactionTagService) GetTotalTagCountByUid(uid int64) (int64, error) {
if uid <= 0 {
return 0, errs.ErrUserIdInvalid
}
count, err := s.UserDataDB(uid).Where("uid=? AND deleted=?", uid, false).Count(&models.TransactionTag{})
return count, err
}
// GetAllTagsByUid returns all transaction tag models of user // GetAllTagsByUid returns all transaction tag models of user
func (s *TransactionTagService) GetAllTagsByUid(uid int64) ([]*models.TransactionTag, error) { func (s *TransactionTagService) GetAllTagsByUid(uid int64) ([]*models.TransactionTag, error) {
if uid <= 0 { if uid <= 0 {
@@ -85,7 +96,7 @@ func (s *TransactionTagService) GetTagsByTagIds(uid int64, tagIds []int64) (map[
} }
// GetMaxDisplayOrder returns the max display order // GetMaxDisplayOrder returns the max display order
func (s *TransactionTagService) GetMaxDisplayOrder(uid int64) (int, error) { func (s *TransactionTagService) GetMaxDisplayOrder(uid int64) (int32, error) {
if uid <= 0 { if uid <= 0 {
return 0, errs.ErrUserIdInvalid return 0, errs.ErrUserIdInvalid
} }
+61 -28
View File
@@ -32,8 +32,19 @@ var (
} }
) )
// GetTotalTransactionCountByUid returns total transaction count of user
func (s *TransactionService) GetTotalTransactionCountByUid(uid int64) (int64, error) {
if uid <= 0 {
return 0, errs.ErrUserIdInvalid
}
count, err := s.UserDataDB(uid).Where("uid=? AND deleted=?", uid, false).Count(&models.Transaction{})
return count, err
}
// GetAllTransactions returns all transactions // GetAllTransactions returns all transactions
func (s *TransactionService) GetAllTransactions(uid int64, pageCount int, noDuplicated bool) ([]*models.Transaction, error) { func (s *TransactionService) GetAllTransactions(uid int64, pageCount int32, noDuplicated bool) ([]*models.Transaction, error) {
maxTransactionTime := utils.GetMaxTransactionTimeFromUnixTime(time.Now().Unix()) maxTransactionTime := utils.GetMaxTransactionTimeFromUnixTime(time.Now().Unix())
var allTransactions []*models.Transaction var allTransactions []*models.Transaction
@@ -46,7 +57,7 @@ func (s *TransactionService) GetAllTransactions(uid int64, pageCount int, noDupl
allTransactions = append(allTransactions, transactions...) allTransactions = append(allTransactions, transactions...)
if len(transactions) < pageCount { if len(transactions) < int(pageCount) {
maxTransactionTime = 0 maxTransactionTime = 0
break break
} }
@@ -58,12 +69,12 @@ func (s *TransactionService) GetAllTransactions(uid int64, pageCount int, noDupl
} }
// GetAllTransactionsByMaxTime returns all transactions before given time // GetAllTransactionsByMaxTime returns all transactions before given time
func (s *TransactionService) GetAllTransactionsByMaxTime(uid int64, maxTransactionTime int64, count int, noDuplicated bool) ([]*models.Transaction, error) { func (s *TransactionService) GetAllTransactionsByMaxTime(uid int64, maxTransactionTime int64, count int32, noDuplicated bool) ([]*models.Transaction, error) {
return s.GetTransactionsByMaxTime(uid, maxTransactionTime, 0, 0, nil, 0, "", count, noDuplicated) return s.GetTransactionsByMaxTime(uid, maxTransactionTime, 0, 0, nil, nil, "", count, noDuplicated)
} }
// GetTransactionsByMaxTime returns transactions before given time // GetTransactionsByMaxTime returns transactions before given time
func (s *TransactionService) GetTransactionsByMaxTime(uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountId int64, keyword string, count int, noDuplicated bool) ([]*models.Transaction, error) { func (s *TransactionService) GetTransactionsByMaxTime(uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, keyword string, count int32, noDuplicated bool) ([]*models.Transaction, error) {
if uid <= 0 { if uid <= 0 {
return nil, errs.ErrUserIdInvalid return nil, errs.ErrUserIdInvalid
} }
@@ -75,14 +86,14 @@ func (s *TransactionService) GetTransactionsByMaxTime(uid int64, maxTransactionT
var transactions []*models.Transaction var transactions []*models.Transaction
var err error var err error
condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountId, keyword, noDuplicated) condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountIds, keyword, noDuplicated)
err = s.UserDataDB(uid).Where(condition, conditionParams...).Limit(count, 0).OrderBy("transaction_time desc").Find(&transactions) err = s.UserDataDB(uid).Where(condition, conditionParams...).Limit(int(count), 0).OrderBy("transaction_time desc").Find(&transactions)
return transactions, err return transactions, err
} }
// GetTransactionsInMonthByPage returns transactions in given year and month // GetTransactionsInMonthByPage returns transactions in given year and month
func (s *TransactionService) GetTransactionsInMonthByPage(uid int64, year int, month int, transactionType models.TransactionDbType, categoryIds []int64, accountId int64, keyword string, page int, count int, utcOffset int16) ([]*models.Transaction, error) { func (s *TransactionService) GetTransactionsInMonthByPage(uid int64, year int32, month int32, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, keyword string, page int32, count int32, utcOffset int16) ([]*models.Transaction, error) {
if uid <= 0 { if uid <= 0 {
return nil, errs.ErrUserIdInvalid return nil, errs.ErrUserIdInvalid
} }
@@ -108,8 +119,8 @@ func (s *TransactionService) GetTransactionsInMonthByPage(uid int64, year int, m
var transactions []*models.Transaction var transactions []*models.Transaction
condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountId, keyword, true) condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountIds, keyword, true)
err = s.UserDataDB(uid).Where(condition, conditionParams...).Limit(count, count*(page-1)).OrderBy("transaction_time desc").Find(&transactions) err = s.UserDataDB(uid).Where(condition, conditionParams...).Limit(int(count), int(count*(page-1))).OrderBy("transaction_time desc").Find(&transactions)
return transactions, err return transactions, err
} }
@@ -138,11 +149,11 @@ func (s *TransactionService) GetTransactionByTransactionId(uid int64, transactio
// GetAllTransactionCount returns total count of transactions // GetAllTransactionCount returns total count of transactions
func (s *TransactionService) GetAllTransactionCount(uid int64) (int64, error) { func (s *TransactionService) GetAllTransactionCount(uid int64) (int64, error) {
return s.GetTransactionCount(uid, 0, 0, 0, nil, 0, "") return s.GetTransactionCount(uid, 0, 0, 0, nil, nil, "")
} }
// GetMonthTransactionCount returns total count of transactions in given year and month // GetMonthTransactionCount returns total count of transactions in given year and month
func (s *TransactionService) GetMonthTransactionCount(uid int64, year int, month int, transactionType models.TransactionDbType, categoryIds []int64, accountId int64, keyword string, utcOffset int16) (int64, error) { func (s *TransactionService) GetMonthTransactionCount(uid int64, year int32, month int32, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, keyword string, utcOffset int16) (int64, error) {
if uid <= 0 { if uid <= 0 {
return 0, errs.ErrUserIdInvalid return 0, errs.ErrUserIdInvalid
} }
@@ -158,16 +169,16 @@ func (s *TransactionService) GetMonthTransactionCount(uid int64, year int, month
minTransactionTime := utils.GetMinTransactionTimeFromUnixTime(startTime.Unix()) minTransactionTime := utils.GetMinTransactionTimeFromUnixTime(startTime.Unix())
maxTransactionTime := utils.GetMinTransactionTimeFromUnixTime(endTime.Unix()) - 1 maxTransactionTime := utils.GetMinTransactionTimeFromUnixTime(endTime.Unix()) - 1
return s.GetTransactionCount(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountId, keyword) return s.GetTransactionCount(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountIds, keyword)
} }
// GetTransactionCount returns count of transactions // GetTransactionCount returns count of transactions
func (s *TransactionService) GetTransactionCount(uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountId int64, keyword string) (int64, error) { func (s *TransactionService) GetTransactionCount(uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, keyword string) (int64, error) {
if uid <= 0 { if uid <= 0 {
return 0, errs.ErrUserIdInvalid return 0, errs.ErrUserIdInvalid
} }
condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountId, keyword, true) condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountIds, keyword, true)
return s.UserDataDB(uid).Where(condition, conditionParams...).Count(&models.Transaction{}) return s.UserDataDB(uid).Where(condition, conditionParams...).Count(&models.Transaction{})
} }
@@ -186,7 +197,19 @@ func (s *TransactionService) CreateTransaction(transaction *models.Transaction,
now := time.Now().Unix() now := time.Now().Unix()
transaction.TransactionId = s.GenerateUuid(uuid.UUID_TYPE_TRANSACTION) needUuidCount := 1
if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_OUT || transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_IN {
needUuidCount = 2
}
uuids := s.GenerateUuids(uuid.UUID_TYPE_TRANSACTION, uint8(needUuidCount))
transaction.TransactionId = uuids[0]
if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_OUT || transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_IN {
transaction.RelatedId = uuids[1]
}
transaction.TransactionTime = utils.GetMinTransactionTimeFromUnixTime(utils.GetUnixTimeFromTransactionTime(transaction.TransactionTime)) transaction.TransactionTime = utils.GetMinTransactionTimeFromUnixTime(utils.GetUnixTimeFromTransactionTime(transaction.TransactionTime))
transaction.CreatedUnixTime = now transaction.CreatedUnixTime = now
@@ -256,8 +279,7 @@ func (s *TransactionService) CreateTransaction(transaction *models.Transaction,
var relatedTransaction *models.Transaction var relatedTransaction *models.Transaction
if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_OUT || transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_IN { if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_OUT || transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_IN {
relatedTransaction = s.GetRelatedTransferTransaction(transaction, s.GenerateUuid(uuid.UUID_TYPE_TRANSACTION)) relatedTransaction = s.GetRelatedTransferTransaction(transaction)
transaction.RelatedId = relatedTransaction.TransactionId
} }
createdRows, err := sess.Insert(transaction) createdRows, err := sess.Insert(transaction)
@@ -537,7 +559,7 @@ func (s *TransactionService) ModifyTransaction(transaction *models.Transaction,
} }
if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_OUT || transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_IN { if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_OUT || transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_IN {
relatedTransaction := s.GetRelatedTransferTransaction(transaction, transaction.RelatedId) relatedTransaction := s.GetRelatedTransferTransaction(transaction)
if utils.GetUnixTimeFromTransactionTime(transaction.TransactionTime) != utils.GetUnixTimeFromTransactionTime(relatedTransaction.TransactionTime) { if utils.GetUnixTimeFromTransactionTime(transaction.TransactionTime) != utils.GetUnixTimeFromTransactionTime(relatedTransaction.TransactionTime) {
return errs.ErrTooMuchTransactionInOneSecond return errs.ErrTooMuchTransactionInOneSecond
@@ -905,7 +927,7 @@ func (s *TransactionService) DeleteAllTransactions(uid int64) error {
} }
// GetRelatedTransferTransaction returns the related transaction for transfer transaction // GetRelatedTransferTransaction returns the related transaction for transfer transaction
func (s *TransactionService) GetRelatedTransferTransaction(originalTransaction *models.Transaction, relatedTransactionId int64) *models.Transaction { func (s *TransactionService) GetRelatedTransferTransaction(originalTransaction *models.Transaction) *models.Transaction {
var relatedType models.TransactionDbType var relatedType models.TransactionDbType
var relatedTransactionTime int64 var relatedTransactionTime int64
@@ -920,7 +942,7 @@ func (s *TransactionService) GetRelatedTransferTransaction(originalTransaction *
} }
relatedTransaction := &models.Transaction{ relatedTransaction := &models.Transaction{
TransactionId: relatedTransactionId, TransactionId: originalTransaction.RelatedId,
Uid: originalTransaction.Uid, Uid: originalTransaction.Uid,
Deleted: originalTransaction.Deleted, Deleted: originalTransaction.Deleted,
Type: relatedType, Type: relatedType,
@@ -933,6 +955,7 @@ func (s *TransactionService) GetRelatedTransferTransaction(originalTransaction *
RelatedAccountId: originalTransaction.AccountId, RelatedAccountId: originalTransaction.AccountId,
RelatedAccountAmount: originalTransaction.Amount, RelatedAccountAmount: originalTransaction.Amount,
Comment: originalTransaction.Comment, Comment: originalTransaction.Comment,
CreatedIp: originalTransaction.CreatedIp,
CreatedUnixTime: originalTransaction.CreatedUnixTime, CreatedUnixTime: originalTransaction.CreatedUnixTime,
UpdatedUnixTime: originalTransaction.UpdatedUnixTime, UpdatedUnixTime: originalTransaction.UpdatedUnixTime,
DeletedUnixTime: originalTransaction.DeletedUnixTime, DeletedUnixTime: originalTransaction.DeletedUnixTime,
@@ -951,7 +974,7 @@ func (s *TransactionService) GetAccountsTotalIncomeAndExpense(uid int64, startUn
endTransactionTime := utils.GetMaxTransactionTimeFromUnixTime(endUnixTime) endTransactionTime := utils.GetMaxTransactionTimeFromUnixTime(endUnixTime)
var transactionTotalAmounts []*models.Transaction var transactionTotalAmounts []*models.Transaction
err := s.UserDataDB(uid).Select("uid, type, account_id, SUM(amount) as amount").Where("uid=? AND deleted=? AND (type=? OR type=?) AND transaction_time>=? AND transaction_time<=?", uid, false, models.TRANSACTION_DB_TYPE_INCOME, models.TRANSACTION_DB_TYPE_EXPENSE, startTransactionTime, endTransactionTime).GroupBy("type, account_id").Find(&transactionTotalAmounts) err := s.UserDataDB(uid).Select("type, account_id, SUM(amount) as amount").Where("uid=? AND deleted=? AND (type=? OR type=?) AND transaction_time>=? AND transaction_time<=?", uid, false, models.TRANSACTION_DB_TYPE_INCOME, models.TRANSACTION_DB_TYPE_EXPENSE, startTransactionTime, endTransactionTime).GroupBy("type, account_id").Find(&transactionTotalAmounts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@@ -1085,7 +1108,7 @@ func (s *TransactionService) GetTransactionMapByList(transactions []*models.Tran
return transactionMap return transactionMap
} }
func (s *TransactionService) getTransactionQueryCondition(uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountId int64, keyword string, noDuplicated bool) (string, []interface{}) { func (s *TransactionService) getTransactionQueryCondition(uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, keyword string, noDuplicated bool) (string, []interface{}) {
condition := "uid=? AND deleted=?" condition := "uid=? AND deleted=?"
conditionParams := make([]interface{}, 0, 16) conditionParams := make([]interface{}, 0, 16)
conditionParams = append(conditionParams, uid) conditionParams = append(conditionParams, uid)
@@ -1105,7 +1128,7 @@ func (s *TransactionService) getTransactionQueryCondition(uid int64, maxTransact
condition = condition + " AND type=?" condition = condition + " AND type=?"
conditionParams = append(conditionParams, transactionType) conditionParams = append(conditionParams, transactionType)
} else if transactionType == models.TRANSACTION_DB_TYPE_TRANSFER_OUT || transactionType == models.TRANSACTION_DB_TYPE_TRANSFER_IN { } else if transactionType == models.TRANSACTION_DB_TYPE_TRANSFER_OUT || transactionType == models.TRANSACTION_DB_TYPE_TRANSFER_IN {
if accountId == 0 { if len(accountIds) == 0 {
condition = condition + " AND type=?" condition = condition + " AND type=?"
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_OUT) conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_OUT)
} else { } else {
@@ -1114,7 +1137,7 @@ func (s *TransactionService) getTransactionQueryCondition(uid int64, maxTransact
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_IN) conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_IN)
} }
} else { } else {
if noDuplicated && accountId == 0 { if noDuplicated && len(accountIds) == 0 {
condition = condition + " AND (type=? OR type=? OR type=? OR type=?)" condition = condition + " AND (type=? OR type=? OR type=? OR type=?)"
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_MODIFY_BALANCE) conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_MODIFY_BALANCE)
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_INCOME) conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_INCOME)
@@ -1138,9 +1161,19 @@ func (s *TransactionService) getTransactionQueryCondition(uid int64, maxTransact
condition = condition + " AND category_id IN (" + conditions.String() + ")" condition = condition + " AND category_id IN (" + conditions.String() + ")"
} }
if accountId > 0 { if len(accountIds) > 0 {
condition = condition + " AND account_id=?" var conditions strings.Builder
conditionParams = append(conditionParams, accountId)
for i := 0; i < len(accountIds); i++ {
if i > 0 {
conditions.WriteString(",")
}
conditions.WriteString("?")
conditionParams = append(conditionParams, accountIds[i])
}
condition = condition + " AND account_id IN (" + conditions.String() + ")"
} }
if keyword != "" { if keyword != "" {
+1 -1
View File
@@ -159,7 +159,7 @@ func (s *TwoFactorAuthorizationService) GenerateTwoFactorRecoveryCodes() ([]stri
recoveryCodes := make([]string, twoFactorRecoveryCodeCount) recoveryCodes := make([]string, twoFactorRecoveryCodeCount)
for i := 0; i < twoFactorRecoveryCodeCount; i++ { for i := 0; i < twoFactorRecoveryCodeCount; i++ {
recoveryCode, err := utils.GetRandomNumberOrLetter(twoFactorRecoveryCodeLength) recoveryCode, err := utils.GetRandomNumberOrLowercaseLetter(twoFactorRecoveryCodeLength)
if err != nil { if err != nil {
return nil, err return nil, err
+4
View File
@@ -190,6 +190,10 @@ func (s *UserService) UpdateUser(user *models.User) (keyProfileUpdated bool, err
updateCols = append(updateCols, "default_currency") updateCols = append(updateCols, "default_currency")
} }
if user.DefaultAccountId > 0 {
updateCols = append(updateCols, "default_account_id")
}
if models.WEEKDAY_SUNDAY <= user.FirstDayOfWeek && user.FirstDayOfWeek <= models.WEEKDAY_SATURDAY { if models.WEEKDAY_SUNDAY <= user.FirstDayOfWeek && user.FirstDayOfWeek <= models.WEEKDAY_SATURDAY {
updateCols = append(updateCols, "first_day_of_week") updateCols = append(updateCols, "first_day_of_week")
} }
+79 -29
View File
@@ -75,23 +75,23 @@ const (
defaultAppName string = "ezBookkeeping" defaultAppName string = "ezBookkeeping"
defaultHttpAddr string = "0.0.0.0" defaultHttpAddr string = "0.0.0.0"
defaultHttpPort int = 8080 defaultHttpPort uint16 = 8080
defaultDomain string = "localhost" defaultDomain string = "localhost"
defaultDatabaseHost string = "127.0.0.1:3306" defaultDatabaseHost string = "127.0.0.1:3306"
defaultDatabaseName string = "ezbookkeeping" defaultDatabaseName string = "ezbookkeeping"
defaultDatabaseMaxIdleConn int = 2 defaultDatabaseMaxIdleConn uint16 = 2
defaultDatabaseMaxOpenConn int = 0 defaultDatabaseMaxOpenConn uint16 = 0
defaultDatabaseConnMaxLifetime int = 14400 defaultDatabaseConnMaxLifetime uint32 = 14400
defaultLogMode string = "console" defaultLogMode string = "console"
defaultLoglevel Level = LOGLEVEL_INFO defaultLoglevel Level = LOGLEVEL_INFO
defaultSecretKey string = "ezbookkeeping" defaultSecretKey string = "ezbookkeeping"
defaultTokenExpiredTime int = 604800 // 7 days defaultTokenExpiredTime uint32 = 604800 // 7 days
defaultTemporaryTokenExpiredTime int = 300 // 5 minutes defaultTemporaryTokenExpiredTime uint32 = 300 // 5 minutes
defaultExchangeRatesDataRequestTimeout int = 10000 // 10 seconds defaultExchangeRatesDataRequestTimeout uint32 = 10000 // 10 seconds
) )
// DatabaseConfig represents the database setting config // DatabaseConfig represents the database setting config
@@ -106,9 +106,9 @@ type DatabaseConfig struct {
DatabasePath string DatabasePath string
MaxIdleConnection int MaxIdleConnection uint16
MaxOpenConnection int MaxOpenConnection uint16
ConnectionMaxLifeTime int ConnectionMaxLifeTime uint32
} }
// Config represents the global setting config // Config represents the global setting config
@@ -121,7 +121,7 @@ type Config struct {
// Server // Server
Protocol Scheme Protocol Scheme
HttpAddr string HttpAddr string
HttpPort int HttpPort uint16
Domain string Domain string
RootUrl string RootUrl string
@@ -156,9 +156,9 @@ type Config struct {
// Secret // Secret
SecretKey string SecretKey string
EnableTwoFactor bool EnableTwoFactor bool
TokenExpiredTime int TokenExpiredTime uint32
TokenExpiredTimeDuration time.Duration TokenExpiredTimeDuration time.Duration
TemporaryTokenExpiredTime int TemporaryTokenExpiredTime uint32
TemporaryTokenExpiredTimeDuration time.Duration TemporaryTokenExpiredTimeDuration time.Duration
EnableRequestIdHeader bool EnableRequestIdHeader bool
@@ -170,7 +170,7 @@ type Config struct {
// Exchange Rates // Exchange Rates
ExchangeRatesDataSource string ExchangeRatesDataSource string
ExchangeRatesRequestTimeout int ExchangeRatesRequestTimeout uint32
} }
// LoadConfiguration loads setting config from given config file path // LoadConfiguration loads setting config from given config file path
@@ -281,12 +281,12 @@ func loadServerConfiguration(config *Config, configFile *ini.File, sectionName s
config.Protocol = SCHEME_HTTP config.Protocol = SCHEME_HTTP
config.HttpAddr = getConfigItemStringValue(configFile, sectionName, "http_addr", defaultHttpAddr) config.HttpAddr = getConfigItemStringValue(configFile, sectionName, "http_addr", defaultHttpAddr)
config.HttpPort = getConfigItemIntValue(configFile, sectionName, "http_port", defaultHttpPort) config.HttpPort = getConfigItemUint16Value(configFile, sectionName, "http_port", defaultHttpPort)
} else if getConfigItemStringValue(configFile, sectionName, "protocol") == "https" { } else if getConfigItemStringValue(configFile, sectionName, "protocol") == "https" {
config.Protocol = SCHEME_HTTPS config.Protocol = SCHEME_HTTPS
config.HttpAddr = getConfigItemStringValue(configFile, sectionName, "http_addr", defaultHttpAddr) config.HttpAddr = getConfigItemStringValue(configFile, sectionName, "http_addr", defaultHttpAddr)
config.HttpPort = getConfigItemIntValue(configFile, sectionName, "http_port", defaultHttpPort) config.HttpPort = getConfigItemUint16Value(configFile, sectionName, "http_port", defaultHttpPort)
config.CertFile = getConfigItemStringValue(configFile, sectionName, "cert_file") config.CertFile = getConfigItemStringValue(configFile, sectionName, "cert_file")
config.CertKeyFile = getConfigItemStringValue(configFile, sectionName, "cert_key_file") config.CertKeyFile = getConfigItemStringValue(configFile, sectionName, "cert_key_file")
@@ -339,9 +339,9 @@ func loadDatabaseConfiguration(config *Config, configFile *ini.File, sectionName
dbConfig.DatabasePath = finalStaticDBPath dbConfig.DatabasePath = finalStaticDBPath
} }
dbConfig.MaxIdleConnection = getConfigItemIntValue(configFile, sectionName, "max_idle_conn", defaultDatabaseMaxIdleConn) dbConfig.MaxIdleConnection = getConfigItemUint16Value(configFile, sectionName, "max_idle_conn", defaultDatabaseMaxIdleConn)
dbConfig.MaxOpenConnection = getConfigItemIntValue(configFile, sectionName, "max_open_conn", defaultDatabaseMaxOpenConn) dbConfig.MaxOpenConnection = getConfigItemUint16Value(configFile, sectionName, "max_open_conn", defaultDatabaseMaxOpenConn)
dbConfig.ConnectionMaxLifeTime = getConfigItemIntValue(configFile, sectionName, "conn_max_lifetime", defaultDatabaseConnMaxLifetime) dbConfig.ConnectionMaxLifeTime = getConfigItemUint32Value(configFile, sectionName, "conn_max_lifetime", defaultDatabaseConnMaxLifetime)
config.DatabaseConfig = dbConfig config.DatabaseConfig = dbConfig
config.EnableQueryLog = getConfigItemBoolValue(configFile, sectionName, "log_query", false) config.EnableQueryLog = getConfigItemBoolValue(configFile, sectionName, "log_query", false)
@@ -383,7 +383,7 @@ func loadUuidConfiguration(config *Config, configFile *ini.File, sectionName str
return errs.ErrInvalidUuidMode return errs.ErrInvalidUuidMode
} }
config.UuidServerId = uint8(getConfigItemIntValue(configFile, sectionName, "server_id", 0)) config.UuidServerId = getConfigItemUint8Value(configFile, sectionName, "server_id", 0)
return nil return nil
} }
@@ -392,10 +392,10 @@ func loadSecurityConfiguration(config *Config, configFile *ini.File, sectionName
config.SecretKey = getConfigItemStringValue(configFile, sectionName, "secret_key", defaultSecretKey) config.SecretKey = getConfigItemStringValue(configFile, sectionName, "secret_key", defaultSecretKey)
config.EnableTwoFactor = getConfigItemBoolValue(configFile, sectionName, "enable_two_factor", true) config.EnableTwoFactor = getConfigItemBoolValue(configFile, sectionName, "enable_two_factor", true)
config.TokenExpiredTime = getConfigItemIntValue(configFile, sectionName, "token_expired_time", defaultTokenExpiredTime) config.TokenExpiredTime = getConfigItemUint32Value(configFile, sectionName, "token_expired_time", defaultTokenExpiredTime)
config.TokenExpiredTimeDuration = time.Duration(config.TokenExpiredTime) * time.Second config.TokenExpiredTimeDuration = time.Duration(config.TokenExpiredTime) * time.Second
config.TemporaryTokenExpiredTime = getConfigItemIntValue(configFile, sectionName, "temporary_token_expired_time", defaultTemporaryTokenExpiredTime) config.TemporaryTokenExpiredTime = getConfigItemUint32Value(configFile, sectionName, "temporary_token_expired_time", defaultTemporaryTokenExpiredTime)
config.TemporaryTokenExpiredTimeDuration = time.Duration(config.TemporaryTokenExpiredTime) * time.Second config.TemporaryTokenExpiredTimeDuration = time.Duration(config.TemporaryTokenExpiredTime) * time.Second
config.EnableRequestIdHeader = getConfigItemBoolValue(configFile, sectionName, "request_id_header", true) config.EnableRequestIdHeader = getConfigItemBoolValue(configFile, sectionName, "request_id_header", true)
@@ -430,7 +430,7 @@ func loadExchangeRatesConfiguration(config *Config, configFile *ini.File, sectio
return errs.ErrInvalidExchangeRatesDataSource return errs.ErrInvalidExchangeRatesDataSource
} }
config.ExchangeRatesRequestTimeout = getConfigItemIntValue(configFile, sectionName, "request_timeout", defaultExchangeRatesDataRequestTimeout) config.ExchangeRatesRequestTimeout = getConfigItemUint32Value(configFile, sectionName, "request_timeout", defaultExchangeRatesDataRequestTimeout)
return nil return nil
} }
@@ -482,23 +482,73 @@ func getConfigItemStringValue(configFile *ini.File, sectionName string, itemName
} }
} }
func getConfigItemIntValue(configFile *ini.File, sectionName string, itemName string, defaultValue ...int) int { func getConfigItemUint8Value(configFile *ini.File, sectionName string, itemName string, defaultValue uint8) uint8 {
environmentKey := getEnvironmentKey(sectionName, itemName) environmentKey := getEnvironmentKey(sectionName, itemName)
environmentValue := os.Getenv(environmentKey) environmentValue := os.Getenv(environmentKey)
if len(environmentValue) > 0 { if len(environmentValue) > 0 {
value, err := strconv.ParseInt(environmentValue, 0, 64) value, err := strconv.ParseUint(environmentValue, 10, 8)
if err == nil { if err == nil {
return int(value) return uint8(value)
} }
} }
section := configFile.Section(sectionName) section := configFile.Section(sectionName)
return section.Key(itemName).MustInt(defaultValue...) value, err := strconv.ParseUint(section.Key(itemName).String(), 10, 8)
if err == nil {
return uint8(value)
}
return defaultValue
} }
func getConfigItemBoolValue(configFile *ini.File, sectionName string, itemName string, defaultValue ...bool) bool { func getConfigItemUint16Value(configFile *ini.File, sectionName string, itemName string, defaultValue uint16) uint16 {
environmentKey := getEnvironmentKey(sectionName, itemName)
environmentValue := os.Getenv(environmentKey)
if len(environmentValue) > 0 {
value, err := strconv.ParseUint(environmentValue, 10, 16)
if err == nil {
return uint16(value)
}
}
section := configFile.Section(sectionName)
value, err := strconv.ParseUint(section.Key(itemName).String(), 10, 16)
if err == nil {
return uint16(value)
}
return defaultValue
}
func getConfigItemUint32Value(configFile *ini.File, sectionName string, itemName string, defaultValue uint32) uint32 {
environmentKey := getEnvironmentKey(sectionName, itemName)
environmentValue := os.Getenv(environmentKey)
if len(environmentValue) > 0 {
value, err := strconv.ParseUint(environmentValue, 10, 32)
if err == nil {
return uint32(value)
}
}
section := configFile.Section(sectionName)
value, err := strconv.ParseUint(section.Key(itemName).String(), 10, 32)
if err == nil {
return uint32(value)
}
return defaultValue
}
func getConfigItemBoolValue(configFile *ini.File, sectionName string, itemName string, defaultValue bool) bool {
environmentKey := getEnvironmentKey(sectionName, itemName) environmentKey := getEnvironmentKey(sectionName, itemName)
environmentValue := os.Getenv(environmentKey) environmentValue := os.Getenv(environmentKey)
@@ -511,7 +561,7 @@ func getConfigItemBoolValue(configFile *ini.File, sectionName string, itemName s
} }
section := configFile.Section(sectionName) section := configFile.Section(sectionName)
return section.Key(itemName).MustBool(defaultValue...) return section.Key(itemName).MustBool(defaultValue)
} }
func getEnvironmentKey(sectionName string, itemName string) string { func getEnvironmentKey(sectionName string, itemName string) string {
+2
View File
@@ -7,6 +7,8 @@ type ConfigContainer struct {
// Initialize a config container singleton instance // Initialize a config container singleton instance
var ( var (
Version string
CommitHash string
Container = &ConfigContainer{} Container = &ConfigContainer{}
) )
+18 -7
View File
@@ -2,20 +2,20 @@ package utils
import "strconv" import "strconv"
// Int32ToString returns the textual representation of this number // IntToString returns the textual representation of this number
func Int32ToString(num int) string { func IntToString(num int) string {
return strconv.Itoa(num) return strconv.Itoa(num)
} }
// StringToInt32 parses a textual representation of the number to int32 // StringToInt parses a textual representation of the number to int
func StringToInt32(str string) (int, error) { func StringToInt(str string) (int, error) {
return strconv.Atoi(str) return strconv.Atoi(str)
} }
// StringTryToInt32 parses a textual representation of the number to int32 if str is valid, // StringTryToInt parses a textual representation of the number to int if str is valid,
// or returns the default value // or returns the default value
func StringTryToInt32(str string, defaultValue int) int { func StringTryToInt(str string, defaultValue int) int {
num, err := StringToInt32(str) num, err := StringToInt(str)
if err != nil { if err != nil {
return defaultValue return defaultValue
@@ -24,6 +24,17 @@ func StringTryToInt32(str string, defaultValue int) int {
return num return num
} }
// StringToInt32 parses a textual representation of the number to int32
func StringToInt32(str string) (int32, error) {
val, err := strconv.ParseInt(str, 10, 32)
if err != nil {
return 0, err
}
return int32(val), nil
}
// Int64ToString returns the textual representation of this number // Int64ToString returns the textual representation of this number
func Int64ToString(num int64) string { func Int64ToString(num int64) string {
return strconv.FormatInt(num, 10) return strconv.FormatInt(num, 10)
+28 -5
View File
@@ -6,19 +6,42 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestInt32ToString(t *testing.T) { func TestIntToString(t *testing.T) {
expectedValue := "-123456789" expectedValue := "-123456789"
actualValue := Int32ToString(-123456789) actualValue := IntToString(-123456789)
assert.Equal(t, expectedValue, actualValue) assert.Equal(t, expectedValue, actualValue)
} }
func TestStringToInt32(t *testing.T) { func TestStringToInt(t *testing.T) {
expectedValue := -123456789 expectedValue := -123456789
actualValue, err := StringToInt("-123456789")
assert.Equal(t, nil, err)
assert.Equal(t, expectedValue, actualValue)
}
func TestStringToInt_InvalidNumber(t *testing.T) {
_, err := StringToInt("")
assert.NotEqual(t, nil, err)
_, err = StringToInt("null")
assert.NotEqual(t, nil, err)
}
func TestStringToInt32(t *testing.T) {
expectedValue := int32(-123456789)
actualValue, err := StringToInt32("-123456789") actualValue, err := StringToInt32("-123456789")
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
assert.Equal(t, expectedValue, actualValue) assert.Equal(t, expectedValue, actualValue)
} }
func TestStringToInt32_OutOfRange(t *testing.T) {
_, err := StringToInt32("2147483648")
assert.NotEqual(t, nil, err)
_, err = StringToInt32("-2147483649")
assert.NotEqual(t, nil, err)
}
func TestStringToInt32_InvalidNumber(t *testing.T) { func TestStringToInt32_InvalidNumber(t *testing.T) {
_, err := StringToInt32("") _, err := StringToInt32("")
assert.NotEqual(t, nil, err) assert.NotEqual(t, nil, err)
@@ -29,10 +52,10 @@ func TestStringToInt32_InvalidNumber(t *testing.T) {
func TestStringTryToInt32_InvalidNumber(t *testing.T) { func TestStringTryToInt32_InvalidNumber(t *testing.T) {
expectedValue := -1 expectedValue := -1
actualValue := StringTryToInt32("", -1) actualValue := StringTryToInt("", -1)
assert.Equal(t, expectedValue, actualValue) assert.Equal(t, expectedValue, actualValue)
actualValue = StringTryToInt32("null", -1) actualValue = StringTryToInt("null", -1)
assert.Equal(t, expectedValue, actualValue) assert.Equal(t, expectedValue, actualValue)
} }
+2 -2
View File
@@ -102,13 +102,13 @@ func ParseFromTimezoneOffset(tzOffset string) (*time.Location, error) {
return nil, errs.ErrFormatInvalid return nil, errs.ErrFormatInvalid
} }
hourAbsOffset, err := StringToInt32(offsets[0]) hourAbsOffset, err := StringToInt(offsets[0])
if err != nil { if err != nil {
return nil, err return nil, err
} }
minuteAbsOffset, err := StringToInt32(offsets[1]) minuteAbsOffset, err := StringToInt(offsets[1])
if err != nil { if err != nil {
return nil, err return nil, err
+20 -1
View File
@@ -17,9 +17,11 @@ import (
const ( const (
availableCharacters = "!#$&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~" availableCharacters = "!#$&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~"
availableNumberAndLetters = "0123456789abcdefghijklmnopqrstuvwxyz" availableNumberAndLetters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
availableNumberAndLowercaseLetters = "0123456789abcdefghijklmnopqrstuvwxyz"
availableCharactersLength = len(availableCharacters) availableCharactersLength = len(availableCharacters)
availableNumberAndLettersLength = len(availableNumberAndLetters) availableNumberAndLettersLength = len(availableNumberAndLetters)
availableNumberAndLowercaseLettersLength = len(availableNumberAndLowercaseLetters)
) )
// SubString returns part of the source string according to start index and length // SubString returns part of the source string according to start index and length
@@ -107,6 +109,23 @@ func GetRandomNumberOrLetter(n int) (string, error) {
return string(result), nil return string(result), nil
} }
// GetRandomNumberOrLowercaseLetter returns a random string which only contains number or letter characters
func GetRandomNumberOrLowercaseLetter(n int) (string, error) {
var result = make([]byte, n)
for i := 0; i < n; i++ {
index, err := GetRandomInteger(availableNumberAndLowercaseLettersLength)
if err != nil {
return "", err
}
result[i] = availableNumberAndLowercaseLetters[index]
}
return string(result), nil
}
// MD5Encode returns a hashed string by md5 // MD5Encode returns a hashed string by md5
func MD5Encode(data []byte) []byte { func MD5Encode(data []byte) []byte {
m := md5.New() m := md5.New()
+5
View File
@@ -83,6 +83,11 @@ func TestGetRandomNumberOrLetter(t *testing.T) {
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
assert.Len(t, actualValue, 10) assert.Len(t, actualValue, 10)
} }
func TestGetRandomNumberOrLowercaseLetter(t *testing.T) {
actualValue, err := GetRandomNumberOrLowercaseLetter(10)
assert.Equal(t, nil, err)
assert.Len(t, actualValue, 10)
}
func TestMD5Encode(t *testing.T) { func TestMD5Encode(t *testing.T) {
str := "foobar" str := "foobar"
+36 -16
View File
@@ -48,40 +48,51 @@ func NewInternalUuidGenerator(config *settings.Config) (*InternalUuidGenerator,
return generator, nil return generator, nil
} }
// GenerateUuid returns a new uuid // GenerateUuid generates a new uuid
func (u *InternalUuidGenerator) GenerateUuid(idType UuidType) int64 { func (u *InternalUuidGenerator) GenerateUuid(idType UuidType) int64 {
uuids := u.GenerateUuids(idType, 1)
return uuids[0]
}
// GenerateUuids generates new uuids
func (u *InternalUuidGenerator) GenerateUuids(idType UuidType, count uint8) []int64 {
// 63bits = unixTime(32bits) + uuidType(4bits) + uuidServerId(8bits) + sequentialNumber(19bits) // 63bits = unixTime(32bits) + uuidType(4bits) + uuidServerId(8bits) + sequentialNumber(19bits)
uuids := make([]int64, count)
if count < 1 {
return uuids
}
var unixTime uint64 var unixTime uint64
var newSeqId uint64 var newFirstSeqId uint64
var newLastSeqId uint64
uuidType := uint8(idType) uuidType := uint8(idType)
for { for {
unixTime = uint64(time.Now().Unix()) unixTime = uint64(time.Now().Unix())
newSeqId = atomic.AddUint64(&u.uuidSeqNumbers[uuidType], 1) newLastSeqId = atomic.AddUint64(&u.uuidSeqNumbers[uuidType], uint64(count))
if newSeqId>>seqNumberIdBits == unixTime { if newLastSeqId>>seqNumberIdBits == unixTime {
newFirstSeqId = newLastSeqId - uint64(count-1)
break break
} }
currentSeqId := newSeqId currentSeqId := newLastSeqId
newSeqId = unixTime << seqNumberIdBits newFirstSeqId = unixTime << seqNumberIdBits
newLastSeqId = newFirstSeqId + uint64(count-1)
if atomic.CompareAndSwapUint64(&u.uuidSeqNumbers[uuidType], currentSeqId, newSeqId) { if atomic.CompareAndSwapUint64(&u.uuidSeqNumbers[uuidType], currentSeqId, newLastSeqId) {
break break
} }
} }
seqId := newSeqId & seqNumberIdMask for i := 0; i < int(count); i++ {
seqId := (newFirstSeqId + uint64(i)) & seqNumberIdMask
uuids[i] = u.assembleUuid(unixTime, uuidType, seqId)
}
unixTimePart := (int64(unixTime) & internalUuidUnixTimeMask) << (internalUuidTypeBits + internalUuidServerIdBits + internalUuidSeqIdBits) return uuids
uuidTypePart := (int64(uuidType) & internalUuidTypeMask) << (internalUuidServerIdBits + internalUuidSeqIdBits)
uuidServerIdPart := (int64(u.uuidServerId) & internalUuidServerIdMask) << internalUuidSeqIdBits
seqIdPart := int64(seqId) & internalUuidSeqIdMask
uuid := unixTimePart | uuidTypePart | uuidServerIdPart | seqIdPart
return uuid
} }
// ParseUuidInfo returns a info struct which contains all information in uuid // ParseUuidInfo returns a info struct which contains all information in uuid
@@ -104,3 +115,12 @@ func (u *InternalUuidGenerator) ParseUuidInfo(uuid int64) *InternalUuidInfo {
SequentialId: seqId, SequentialId: seqId,
} }
} }
func (u *InternalUuidGenerator) assembleUuid(unixTime uint64, uuidType uint8, seqId uint64) int64 {
unixTimePart := (int64(unixTime) & internalUuidUnixTimeMask) << (internalUuidTypeBits + internalUuidServerIdBits + internalUuidSeqIdBits)
uuidTypePart := (int64(uuidType) & internalUuidTypeMask) << (internalUuidServerIdBits + internalUuidSeqIdBits)
uuidServerIdPart := (int64(u.uuidServerId) & internalUuidServerIdMask) << internalUuidSeqIdBits
seqIdPart := int64(seqId) & internalUuidSeqIdMask
return unixTimePart | uuidTypePart | uuidServerIdPart | seqIdPart
}
+128 -4
View File
@@ -54,7 +54,7 @@ func TestGenerateUuid_MultiType(t *testing.T) {
assert.Equal(t, uint32(expectedSeqId), actualSeqId) assert.Equal(t, uint32(expectedSeqId), actualSeqId)
} }
func TestGenerateUuid_1000Times(t *testing.T) { func TestGenerateUuid_2000TimesIn2Seconds(t *testing.T) {
generator, _ := NewInternalUuidGenerator(&settings.Config{UuidServerId: 2}) generator, _ := NewInternalUuidGenerator(&settings.Config{UuidServerId: 2})
expectedUnixTime := time.Now().Unix() expectedUnixTime := time.Now().Unix()
@@ -79,17 +79,18 @@ func TestGenerateUuid_1000Times(t *testing.T) {
} }
func TestGenerateUuid_1000000TimesConcurrent(t *testing.T) { func TestGenerateUuid_1000000TimesConcurrent(t *testing.T) {
concurrentCount := 50
generator, _ := NewInternalUuidGenerator(&settings.Config{UuidServerId: 3}) generator, _ := NewInternalUuidGenerator(&settings.Config{UuidServerId: 3})
var mutex sync.Mutex var mutex sync.Mutex
var generatedIds sync.Map var generatedIds sync.Map
var waitGroup sync.WaitGroup var waitGroup sync.WaitGroup
for i := 0; i < 50; i++ { for routineIndex := 0; routineIndex < concurrentCount; routineIndex++ {
go func() { go func() {
waitGroup.Add(1) waitGroup.Add(1)
for j := 0; j < 40000; j++ { for cycle := 0; cycle < 40000; cycle++ {
if j%10000 == 0 { // echo server can only generate 500,000 (50 * 10000) uuids in one second if cycle%10000 == 0 { // each server can only generate 500,000 (50 * 10000) uuids in one second
time.Sleep(1000 * time.Millisecond) time.Sleep(1000 * time.Millisecond)
} }
@@ -120,3 +121,126 @@ func TestGenerateUuid_1000000TimesConcurrent(t *testing.T) {
waitGroup.Wait() waitGroup.Wait()
} }
func TestGenerateUuids_Count0(t *testing.T) {
expectedUuidServerId := uint8(90)
expectedUuidType := UUID_TYPE_TRANSACTION
generator, _ := NewInternalUuidGenerator(&settings.Config{UuidServerId: expectedUuidServerId})
uuids := generator.GenerateUuids(expectedUuidType, 0)
assert.NotEqual(t, nil, uuids)
assert.Equal(t, 0, len(uuids))
}
func TestGenerateUuids_Count255(t *testing.T) {
expectedUnixTime := time.Now().Unix()
expectedUuidServerId := uint8(90)
expectedUuidType := UUID_TYPE_TRANSACTION
expectedUuidCount := uint8(255)
generator, _ := NewInternalUuidGenerator(&settings.Config{UuidServerId: expectedUuidServerId})
uuids := generator.GenerateUuids(expectedUuidType, expectedUuidCount)
for i := 0; i < int(expectedUuidCount); i++ {
uuidInfo := generator.ParseUuidInfo(uuids[i])
actualUnixTime := uuidInfo.UnixTime
assert.Equal(t, uint32(expectedUnixTime), actualUnixTime)
actualUuidServerId := uuidInfo.UuidServerId
assert.Equal(t, expectedUuidServerId, actualUuidServerId)
actualUuidType := uuidInfo.UuidType
assert.Equal(t, uint8(expectedUuidType), actualUuidType)
expectedSeqId := i
actualSeqId := uuidInfo.SequentialId
assert.Equal(t, uint32(expectedSeqId), actualSeqId)
}
assert.Equal(t, int(expectedUuidCount), len(uuids))
}
func TestGenerateUuids_30TimesIn3Seconds(t *testing.T) {
expectedUuidServerId := uint8(90)
expectedUuidType := UUID_TYPE_TRANSACTION
expectedUuidCount := uint8(255)
generator, _ := NewInternalUuidGenerator(&settings.Config{UuidServerId: expectedUuidServerId})
for cycle := 0; cycle < 30; cycle++ {
expectedUnixTime := time.Now().Unix()
uuids := generator.GenerateUuids(expectedUuidType, expectedUuidCount)
var firstSeqId uint32
for i := 0; i < int(expectedUuidCount); i++ {
uuidInfo := generator.ParseUuidInfo(uuids[i])
actualUnixTime := uuidInfo.UnixTime
assert.Equal(t, uint32(expectedUnixTime), actualUnixTime)
actualUuidServerId := uuidInfo.UuidServerId
assert.Equal(t, expectedUuidServerId, actualUuidServerId)
actualUuidType := uuidInfo.UuidType
assert.Equal(t, uint8(expectedUuidType), actualUuidType)
if i == 0 {
firstSeqId = uuidInfo.SequentialId
} else {
expectedSeqId := firstSeqId + uint32(i)
actualSeqId := uuidInfo.SequentialId
assert.Equal(t, expectedSeqId, actualSeqId)
}
}
time.Sleep(100 * time.Millisecond)
}
}
func TestGenerateUuids_1000000TimesConcurrent(t *testing.T) {
concurrentCount := 50
expectedUuidCount := uint8(100)
generator, _ := NewInternalUuidGenerator(&settings.Config{UuidServerId: 3})
var mutex sync.Mutex
var generatedIds sync.Map
var waitGroup sync.WaitGroup
for routineIndex := 0; routineIndex < concurrentCount; routineIndex++ {
go func() {
waitGroup.Add(1)
for cycle := 0; cycle < 400; cycle++ {
if cycle%100 == 0 { // each server can only generate 500,000 (50 * 10000) uuids in one second
time.Sleep(1000 * time.Millisecond)
}
expectedUnixTime := time.Now().Unix()
uuids := generator.GenerateUuids(UUID_TYPE_USER, expectedUuidCount)
for i := 0; i < int(expectedUuidCount); i++ {
uuidInfo := generator.ParseUuidInfo(uuids[i])
if uint32(expectedUnixTime) != uuidInfo.UnixTime {
mutex.Lock()
assert.Equal(t, uint32(expectedUnixTime), uuidInfo.UnixTime)
mutex.Unlock()
}
if existedUnixTime, exists := generatedIds.Load(uuids[i]); exists {
mutex.Lock()
assert.Fail(t, fmt.Sprintf("uuid \"%d\" conflicts, seq id is %d, existed unixtime is %d, current unix time is %d", uuids[i], uuidInfo.SequentialId, existedUnixTime, uuidInfo.UnixTime))
mutex.Unlock()
}
generatedIds.Store(uuids[i], uuidInfo.UnixTime)
}
}
waitGroup.Done()
}()
}
waitGroup.Wait()
}
+5
View File
@@ -31,3 +31,8 @@ func InitializeUuidGenerator(config *settings.Config) error {
func (u *UuidContainer) GenerateUuid(uuidType UuidType) int64 { func (u *UuidContainer) GenerateUuid(uuidType UuidType) int64 {
return u.Current.GenerateUuid(uuidType) return u.Current.GenerateUuid(uuidType)
} }
// GenerateUuids returns new uuids by the current uuid generator
func (u *UuidContainer) GenerateUuids(uuidType UuidType, count uint8) []int64 {
return u.Current.GenerateUuids(uuidType, count)
}
+1
View File
@@ -3,4 +3,5 @@ package uuid
// UuidGenerator is common uuid generator interface // UuidGenerator is common uuid generator interface
type UuidGenerator interface { type UuidGenerator interface {
GenerateUuid(uuidType UuidType) int64 GenerateUuid(uuidType UuidType) int64
GenerateUuids(uuidType UuidType, count uint8) []int64
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

+42
View File
@@ -126,6 +126,20 @@ body {
width: 100%; width: 100%;
} }
.smaller {
font-size: 10px;
}
.readonly {
pointer-events: none !important;
}
.segmented.readonly .button:not(.button-active) > span,
.list.readonly .item-content .item-title.item-label,
.list.readonly .item-content .item-title > .item-header {
opacity: 0.55 !important;
}
/** Replacing the default style of framework7 **/ /** Replacing the default style of framework7 **/
:root { :root {
--f7-theme-color: #c67e48; --f7-theme-color: #c67e48;
@@ -140,6 +154,10 @@ body {
--default-icon-color: var(--f7-text-color); --default-icon-color: var(--f7-text-color);
} }
.ios .theme-dark, .ios.theme-dark {
--f7-list-item-header-text-color: inherit !important;
}
i.icon.la, i.icon.las, i.icon.lab { i.icon.la, i.icon.las, i.icon.lab {
font-size: 28px; font-size: 28px;
} }
@@ -279,6 +297,30 @@ i.icon.la, i.icon.las, i.icon.lab {
padding-bottom: var(--f7-list-item-padding-vertical); padding-bottom: var(--f7-list-item-padding-vertical);
} }
.nested-list-item.has-child-list-item .item-link.active-state {
background-color: transparent;
}
.nested-list-item.has-child-list-item .item-link .item-inner {
padding-right: 0;
}
.nested-list-item.has-child-list-item .item-link .item-inner:before {
color: transparent;
}
.nested-list-item.has-child-list-item .item-link.active-state .item-inner .nested-list-item-child .item-link.active-state {
background-color: var(--f7-list-link-pressed-bg-color);
}
.nested-list-item.has-child-list-item .item-link .item-inner .nested-list-item-child .item-link .item-inner {
padding-right: calc(var(--f7-list-chevron-icon-area) + var(--f7-list-item-padding-horizontal) + var(--f7-safe-area-right));
}
.nested-list-item.has-child-list-item .item-link .item-inner .nested-list-item-child .item-link .item-inner:before {
color: var(--f7-list-chevron-icon-color);
}
.nested-list-item .nested-list-item-title { .nested-list-item .nested-list-item-title {
align-self: center; align-self: center;
margin-left: var(--f7-list-item-media-margin); margin-left: var(--f7-list-item-media-margin);
+1 -1
View File
@@ -260,7 +260,7 @@ export default {
} }
.pie-chart { .pie-chart {
margin: 24px 24px 0 24px; margin: 0 24px 0 24px;
} }
.pie-chart-toolbox-container { .pie-chart-toolbox-container {
+13 -4
View File
@@ -45,12 +45,21 @@ const allChartDataTypes = {
const defaultChartDataType = allChartDataTypes.ExpenseByPrimaryCategory.type; const defaultChartDataType = allChartDataTypes.ExpenseByPrimaryCategory.type;
const allSortingTypes = { const allSortingTypes = {
ByAmount: 0, Amount: {
ByDisplayOrder: 1, type: 0,
ByName: 2 name: 'Amount'
},
DisplayOrder: {
type: 1,
name: 'Display Order'
},
Name: {
type: 2,
name: 'Name'
}
}; };
const defaultSortingType = allSortingTypes.ByAmount; const defaultSortingType = allSortingTypes.Amount.type;
export default { export default {
allChartTypes: allChartTypes, allChartTypes: allChartTypes,
+1 -1
View File
@@ -1,4 +1,4 @@
// https://github.com/nodatime/nodatime/blob/master/data/cldr/windowsZones-38-1.xml // Reference: https://github.com/nodatime/nodatime/blob/master/data/cldr/windowsZones-38-1.xml
const allAvailableTimezones = [ const allAvailableTimezones = [
// UTC-12:00 // UTC-12:00
{ {
+3 -1
View File
@@ -2,7 +2,7 @@ import currency from '../consts/currency.js';
import settings from '../lib/settings.js'; import settings from '../lib/settings.js';
import utils from '../lib/utils.js'; import utils from '../lib/utils.js';
export default function ({i18n}, value, currencyCode) { export default function ({i18n}, value, currencyCode, notConvertValue) {
if (!utils.isNumber(value) && !utils.isString(value)) { if (!utils.isNumber(value) && !utils.isString(value)) {
return value; return value;
} }
@@ -11,6 +11,7 @@ export default function ({i18n}, value, currencyCode) {
value = value.toString(); value = value.toString();
} }
if (!notConvertValue) {
const hasIncompleteFlag = utils.isString(value) && value.charAt(value.length - 1) === '+'; const hasIncompleteFlag = utils.isString(value) && value.charAt(value.length - 1) === '+';
if (hasIncompleteFlag) { if (hasIncompleteFlag) {
@@ -22,6 +23,7 @@ export default function ({i18n}, value, currencyCode) {
if (hasIncompleteFlag) { if (hasIncompleteFlag) {
value = value + '+'; value = value + '+';
} }
}
const currencyDisplayMode = settings.getCurrencyDisplayMode(); const currencyDisplayMode = settings.getCurrencyDisplayMode();
+8 -22
View File
@@ -1,32 +1,18 @@
export default function (oldRate, currentCurrency, allExchangeRates) { export default function (rate) {
const exchangeRateMap = {}; const rateStr = rate.toString();
for (let i = 0; i < allExchangeRates.length; i++) { if (rateStr.indexOf('.') < 0) {
const exchangeRate = allExchangeRates[i]; return rateStr;
exchangeRateMap[exchangeRate.currency] = exchangeRate;
}
const toCurrencyExchangeRate = exchangeRateMap[currentCurrency];
if (!toCurrencyExchangeRate) {
return '';
}
const newRate = parseFloat(oldRate) / parseFloat(toCurrencyExchangeRate.rate);
const newRateStr = newRate.toString();
if (newRateStr.indexOf('.') < 0) {
return newRateStr;
} else { } else {
let firstNonZeroPos = 0; let firstNonZeroPos = 0;
for (let i = 0; i < newRateStr.length; i++) { for (let i = 0; i < rateStr.length; i++) {
if (newRateStr.charAt(i) !== '.' && newRateStr.charAt(i) !== '0') { if (rateStr.charAt(i) !== '.' && rateStr.charAt(i) !== '0') {
firstNonZeroPos = Math.min(i + 4, newRateStr.length); firstNonZeroPos = Math.min(i + 4, rateStr.length);
break; break;
} }
} }
return newRateStr.substr(0, Math.max(6, Math.max(firstNonZeroPos, newRateStr.indexOf('.') + 2))); return rateStr.substr(0, Math.max(6, Math.max(firstNonZeroPos, rateStr.indexOf('.') + 2)));
} }
} }
+8 -1
View File
@@ -133,13 +133,14 @@ export default {
getProfile: () => { getProfile: () => {
return axios.get('v1/users/profile/get.json'); return axios.get('v1/users/profile/get.json');
}, },
updateProfile: ({ email, nickname, password, oldPassword, defaultCurrency, firstDayOfWeek, transactionEditScope }) => { updateProfile: ({ email, nickname, password, oldPassword, defaultCurrency, defaultAccountId, firstDayOfWeek, transactionEditScope }) => {
return axios.post('v1/users/profile/update.json', { return axios.post('v1/users/profile/update.json', {
email, email,
nickname, nickname,
password, password,
oldPassword, oldPassword,
defaultCurrency, defaultCurrency,
defaultAccountId,
firstDayOfWeek, firstDayOfWeek,
transactionEditScope transactionEditScope
}); });
@@ -166,6 +167,12 @@ export default {
password password
}); });
}, },
getUserDataStatistics: () => {
return axios.get('v1/data/statistics.json');
},
getExportedUserData: () => {
return axios.get('v1/data/export.csv');
},
clearData: ({ password }) => { clearData: ({ password }) => {
return axios.post('v1/data/clear.json', { return axios.post('v1/data/clear.json', {
password password
+3 -3
View File
@@ -24,7 +24,7 @@ const defaultSettings = {
defaultDataRangeType: statisticsConstants.defaultDataRangeType, defaultDataRangeType: statisticsConstants.defaultDataRangeType,
defaultAccountFilter: {}, defaultAccountFilter: {},
defaultTransactionCategoryFilter: {}, defaultTransactionCategoryFilter: {},
sortingType: statisticsConstants.defaultSortingType defaultSortingType: statisticsConstants.defaultSortingType
}, },
animate: true, animate: true,
autoDarkMode: true autoDarkMode: true
@@ -160,8 +160,8 @@ export default {
setStatisticsDefaultAccountFilter: value => setSubOption('statistics', 'defaultAccountFilter', value), setStatisticsDefaultAccountFilter: value => setSubOption('statistics', 'defaultAccountFilter', value),
getStatisticsDefaultTransactionCategoryFilter: () => getSubOption('statistics', 'defaultTransactionCategoryFilter'), getStatisticsDefaultTransactionCategoryFilter: () => getSubOption('statistics', 'defaultTransactionCategoryFilter'),
setStatisticsDefaultTransactionCategoryFilter: value => setSubOption('statistics', 'defaultTransactionCategoryFilter', value), setStatisticsDefaultTransactionCategoryFilter: value => setSubOption('statistics', 'defaultTransactionCategoryFilter', value),
getStatisticsSortingType: () => getSubOption('statistics', 'sortingType'), getStatisticsSortingType: () => getSubOption('statistics', 'defaultSortingType'),
setStatisticsSortingType: value => setSubOption('statistics', 'sortingType', value), setStatisticsSortingType: value => setSubOption('statistics', 'defaultSortingType', value),
isEnableAnimate: () => getOption('animate'), isEnableAnimate: () => getOption('animate'),
setEnableAnimate: value => setOption('animate', value), setEnableAnimate: value => setOption('animate', value),
isEnableAutoDarkMode: () => getOption('autoDarkMode'), isEnableAutoDarkMode: () => getOption('autoDarkMode'),
+93 -2
View File
@@ -4,6 +4,8 @@ import uaParser from 'ua-parser-js';
import dateTimeConstants from '../consts/datetime.js'; import dateTimeConstants from '../consts/datetime.js';
import accountConstants from '../consts/account.js'; import accountConstants from '../consts/account.js';
import categoryConstants from '../consts/category.js';
import transactionConstants from '../consts/transaction.js';
import settings from './settings.js'; import settings from './settings.js';
function isFunction(val) { function isFunction(val) {
@@ -34,6 +36,57 @@ function isBoolean(val) {
return typeof(val) === 'boolean'; return typeof(val) === 'boolean';
} }
function isEquals(obj1, obj2) {
if (obj1 === obj2) {
return true;
}
if (isArray(obj1) && isArray(obj2)) {
if (obj1.length !== obj2.length) {
return false;
}
for (let i = 0; i < obj1.length; i++) {
if (!isEquals(obj1[i], obj2[i])) {
return false;
}
}
return true;
} else if (isObject(obj1) && isObject(obj2)) {
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) {
return false;
}
const keyExistsMap2 = {};
for (let i = 0; i < keys2.length; i++) {
const key = keys2[i];
keyExistsMap2[key] = true;
}
for (let i = 0; i < keys1.length; i++) {
const key = keys1[i];
if (!keyExistsMap2[key]) {
return false;
}
if (!isEquals(obj1[key], obj2[key])) {
return false;
}
}
return true;
} else {
return obj1 === obj2;
}
}
function getUtcOffsetMinutesByUtcOffset(utcOffset) { function getUtcOffsetMinutesByUtcOffset(utcOffset) {
if (!utcOffset) { if (!utcOffset) {
return 0; return 0;
@@ -271,10 +324,10 @@ function getDateRangeByDateType(dateType, firstDayOfWeek) {
maxTime = getUnixTimeBeforeUnixTime(getTodayLastUnixTime(), 1, 'days'); maxTime = getUnixTimeBeforeUnixTime(getTodayLastUnixTime(), 1, 'days');
minTime = getUnixTimeBeforeUnixTime(getTodayFirstUnixTime(), 1, 'days'); minTime = getUnixTimeBeforeUnixTime(getTodayFirstUnixTime(), 1, 'days');
} else if (dateType === dateTimeConstants.allDateRanges.LastSevenDays.type) { // Last 7 days } else if (dateType === dateTimeConstants.allDateRanges.LastSevenDays.type) { // Last 7 days
maxTime = getUnixTimeBeforeUnixTime(getTodayLastUnixTime(), 1, 'days'); maxTime = getTodayLastUnixTime();
minTime = getUnixTimeBeforeUnixTime(getTodayFirstUnixTime(), 6, 'days'); minTime = getUnixTimeBeforeUnixTime(getTodayFirstUnixTime(), 6, 'days');
} else if (dateType === dateTimeConstants.allDateRanges.LastThirtyDays.type) { // Last 30 days } else if (dateType === dateTimeConstants.allDateRanges.LastThirtyDays.type) { // Last 30 days
maxTime = getUnixTimeBeforeUnixTime(getTodayLastUnixTime(), 1, 'days'); maxTime = getTodayLastUnixTime();
minTime = getUnixTimeBeforeUnixTime(getTodayFirstUnixTime(), 29, 'days'); minTime = getUnixTimeBeforeUnixTime(getTodayFirstUnixTime(), 29, 'days');
} else if (dateType === dateTimeConstants.allDateRanges.ThisWeek.type) { // This week } else if (dateType === dateTimeConstants.allDateRanges.ThisWeek.type) { // This week
maxTime = getThisWeekLastUnixTime(firstDayOfWeek); maxTime = getThisWeekLastUnixTime(firstDayOfWeek);
@@ -508,6 +561,16 @@ function stringCurrencyToNumeric(str) {
} }
} }
function getExchangedAmount(amount, fromRate, toRate) {
const exchangeRate = parseFloat(toRate) / parseFloat(fromRate);
if (!isNumber(exchangeRate)) {
return null;
}
return amount * exchangeRate;
}
function base64encode(arrayBuffer) { function base64encode(arrayBuffer) {
if (!arrayBuffer || arrayBuffer.length === 0) { if (!arrayBuffer || arrayBuffer.length === 0) {
return null; return null;
@@ -549,6 +612,30 @@ function parseUserAgent(ua) {
}; };
} }
function transactionTypeToCategroyType(transactionType) {
if (transactionType === transactionConstants.allTransactionTypes.Income) {
return categoryConstants.allCategoryTypes.Income;
} else if (transactionType === transactionConstants.allTransactionTypes.Expense) {
return categoryConstants.allCategoryTypes.Expense;
} else if (transactionType === transactionConstants.allTransactionTypes.Transfer) {
return categoryConstants.allCategoryTypes.Transfer;
} else {
return null;
}
}
function categroyTypeToTransactionType(categoryType) {
if (categoryType === categoryConstants.allCategoryTypes.Income) {
return transactionConstants.allTransactionTypes.Income;
} else if (categoryType === categoryConstants.allCategoryTypes.Expense) {
return transactionConstants.allTransactionTypes.Expense;
} else if (categoryType === categoryConstants.allCategoryTypes.Transfer) {
return transactionConstants.allTransactionTypes.Transfer;
} else {
return null;
}
}
function getCategoryInfo(categoryId) { function getCategoryInfo(categoryId) {
for (let i = 0; i < accountConstants.allCategories.length; i++) { for (let i = 0; i < accountConstants.allCategories.length; i++) {
if (accountConstants.allCategories[i].id === categoryId) { if (accountConstants.allCategories[i].id === categoryId) {
@@ -641,6 +728,7 @@ export default {
isString, isString,
isNumber, isNumber,
isBoolean, isBoolean,
isEquals,
getUtcOffsetMinutesByUtcOffset, getUtcOffsetMinutesByUtcOffset,
getUtcOffsetByUtcOffsetMinutes, getUtcOffsetByUtcOffsetMinutes,
getTimezoneOffset, getTimezoneOffset,
@@ -684,11 +772,14 @@ export default {
appendThousandsSeparator, appendThousandsSeparator,
numericCurrencyToString, numericCurrencyToString,
stringCurrencyToNumeric, stringCurrencyToNumeric,
getExchangedAmount,
base64encode, base64encode,
arrayBufferToString, arrayBufferToString,
stringToArrayBuffer, stringToArrayBuffer,
generateRandomString, generateRandomString,
parseUserAgent, parseUserAgent,
transactionTypeToCategroyType,
categroyTypeToTransactionType,
getCategoryInfo, getCategoryInfo,
getCategorizedAccounts, getCategorizedAccounts,
getAllFilteredAccountsBalance, getAllFilteredAccountsBalance,

Some files were not shown because too many files have changed in this diff Show More