From 57556f18b730ce932c0092beeaa32976cfa54952 Mon Sep 17 00:00:00 2001 From: shaipeng Date: Sat, 8 Oct 2022 18:16:49 +0800 Subject: [PATCH 01/13] =?UTF-8?q?=E4=BD=BF=E7=94=A8viper=E8=AF=BB=E5=8F=96?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E4=BF=A1=E6=81=AF=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?docker=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env/product | 9 + .env/staging | 9 + .gitignore | 1 - Dockerfile | 16 ++ app/controller/admin/controller.go | 8 +- app/controller/admin/system.go | 34 +-- app/controller/home/controller.go | 8 +- app/database/mysql.go | 17 +- config/config.toml | 69 +++++ docker-compose.yaml | 67 +++++ go.mod | 21 +- go.sum | 433 +++++++++++++++++++++++++++++ main.go | 3 +- middleware/jwt.go | 3 +- pkg/response/response.go | 2 +- pkg/utils/setting.go | 137 +++++++-- pkg/utils/util.go | 3 +- public/data/elk-blog.sql | 5 + routers/routers.go | 4 +- sql/elk-blog.sql | 292 +++++++++++++++++++ 20 files changed, 1074 insertions(+), 67 deletions(-) create mode 100644 .env/product create mode 100644 .env/staging create mode 100644 Dockerfile create mode 100644 config/config.toml create mode 100644 docker-compose.yaml create mode 100644 sql/elk-blog.sql diff --git a/.env/product b/.env/product new file mode 100644 index 0000000..775e3ae --- /dev/null +++ b/.env/product @@ -0,0 +1,9 @@ +MYSQL_ROOT_PASSWORD=123456 +DB_USER=root +DB_PASSWORD=123456 +DB_HOST=db +DB_PORT=3306 +DB_NAME=elk-blog +DB_PREFIX=tk_ +SERVER_PORT=8080 +ENVIRONMENT=local \ No newline at end of file diff --git a/.env/staging b/.env/staging new file mode 100644 index 0000000..775e3ae --- /dev/null +++ b/.env/staging @@ -0,0 +1,9 @@ +MYSQL_ROOT_PASSWORD=123456 +DB_USER=root +DB_PASSWORD=123456 +DB_HOST=db +DB_PORT=3306 +DB_NAME=elk-blog +DB_PREFIX=tk_ +SERVER_PORT=8080 +ENVIRONMENT=local \ No newline at end of file diff --git a/.gitignore b/.gitignore index b2af0c6..8b8f908 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,6 @@ publish* config/env.ini main tmp -.env .DS_Store .history diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..daa233f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM golang:latest +ENV GOOS=linux GOARCH=amd64 GO111MODULE=auto GOPROXY=https://goproxy.cn,direct +ENV WORKDIR /app +RUN mkdir ${WORKDIR} +WORKDIR ${WORKDIR} +COPY . $WORKDIR +ADD go.mod $WORKDIR +ADD go.sum $WORKDIR + +RUN go mod tidy +RUN #go build main.go +RUN go get -d github.com/githubnemo/CompileDaemon + +EXPOSE 8080 +ENTRYPOINT ["go version"] +#ENTRYPOINT ["/bo/bin/CompileDaemon", "--build='go build main.go'", "--command=./main"] \ No newline at end of file diff --git a/app/controller/admin/controller.go b/app/controller/admin/controller.go index f267f74..d3cead2 100644 --- a/app/controller/admin/controller.go +++ b/app/controller/admin/controller.go @@ -18,7 +18,7 @@ type Controller struct { this ControllerInterface // 实例 } -var Site = utils.Site +var Site = utils.Config.Site func (ctrl *Controller) Init(this ControllerInterface) error { ctrl.this = this @@ -28,14 +28,16 @@ func (ctrl *Controller) Init(this ControllerInterface) error { return nil } -/** +/* +* action调用前回调 */ func (ctrl *Controller) beforeAction(c *gin.Context) error { return nil } -/** +/* +* action调用后回调 */ func (ctrl *Controller) afterAction(c *gin.Context) error { diff --git a/app/controller/admin/system.go b/app/controller/admin/system.go index 7c922be..8b06355 100644 --- a/app/controller/admin/system.go +++ b/app/controller/admin/system.go @@ -4,6 +4,8 @@ import ( "gitee.com/jikey/elk-blog/pkg/response" "gitee.com/jikey/elk-blog/pkg/utils" "github.com/gin-gonic/gin" + "github.com/spf13/viper" + "log" ) type System struct { @@ -22,7 +24,7 @@ func (s *System) SettingList(c *gin.Context) { data := make(map[string]interface{}) utils.SetSite() - data["rows"] = utils.Site + data["rows"] = utils.Config.Site response.Success(c, data) } @@ -30,8 +32,6 @@ func (s *System) SettingList(c *gin.Context) { // SettingUpdate 修改系统设置 func (s *System) SettingUpdate(c *gin.Context) { var siteMap utils.SiteMap - cfg := utils.Config - site := cfg.Section("site") if err := c.ShouldBind(&siteMap); err != nil { c.JSON(400, gin.H{ @@ -40,24 +40,24 @@ func (s *System) SettingUpdate(c *gin.Context) { return } - site.Key("domain").SetValue(siteMap.Domain) - site.Key("title").SetValue(siteMap.Title) - site.Key("keyword").SetValue(siteMap.Keyword) - site.Key("description").SetValue(siteMap.Description) - site.Key("email").SetValue(siteMap.Email) - site.Key("contact").SetValue(siteMap.Contact) - site.Key("company").SetValue(siteMap.Company) - site.Key("phone").SetValue(siteMap.Phone) - site.Key("icp").SetValue(siteMap.Icp) - site.Key("address").SetValue(siteMap.Address) - site.Key("tpl").SetValue(siteMap.Tpl) + viper.Set("site.domain", siteMap.Domain) + viper.Set("site.title", siteMap.Title) + viper.Set("site.keyword", siteMap.Keyword) + viper.Set("site.description", siteMap.Description) + viper.Set("site.email", siteMap.Email) + viper.Set("site.contact", siteMap.Contact) + viper.Set("site.company", siteMap.Company) + viper.Set("site.phone", siteMap.Phone) + viper.Set("site.icp", siteMap.Icp) + viper.Set("site.address", siteMap.Address) + viper.Set("site.tpl", siteMap.Tpl) // ini.ReflectFrom(cfg, &siteMap) - - if err := cfg.SaveTo("config/env.ini"); err != nil { + err := viper.WriteConfig() + if err != nil { + log.Fatal("write config failed: ", err) return } - response.Success(c, siteMap) } diff --git a/app/controller/home/controller.go b/app/controller/home/controller.go index e5c1396..0ba90fe 100644 --- a/app/controller/home/controller.go +++ b/app/controller/home/controller.go @@ -21,7 +21,7 @@ type Controller struct { this ControllerInterface // 实例 } -var Site = utils.Site +var Site = utils.Config.Site func (ctrl *Controller) Init(this ControllerInterface) error { ctrl.this = this @@ -32,14 +32,16 @@ func (ctrl *Controller) Init(this ControllerInterface) error { return nil } -/** +/* +* action调用前回调 */ func (ctrl *Controller) beforeAction(context *gin.Context) error { return nil } -/** +/* +* action调用后回调 */ func (ctrl *Controller) afterAction(context *gin.Context) error { diff --git a/app/database/mysql.go b/app/database/mysql.go index 30dc97f..556d5fc 100644 --- a/app/database/mysql.go +++ b/app/database/mysql.go @@ -15,7 +15,8 @@ func init() { dbSetup() } -/** +/* +* 数据库初始化 */ func dbSetup() { @@ -26,14 +27,14 @@ func dbSetup() { dbType, dbName, user, password, host, tablePrefix string ) - sec := utils.Config.Section("database") + sec := utils.Config.Database - dbType = sec.Key("type").String() - dbName = sec.Key("dbname").String() - user = sec.Key("user").String() - password = sec.Key("password").String() - host = sec.Key("host").String() - tablePrefix = sec.Key("table_prefix").String() + dbType = sec.Type + dbName = sec.DbName + user = sec.User + password = sec.Password + host = sec.Host + tablePrefix = sec.TablePrefix Mysql, err = gorm.Open( dbType, diff --git a/config/config.toml b/config/config.toml new file mode 100644 index 0000000..85fd274 --- /dev/null +++ b/config/config.toml @@ -0,0 +1,69 @@ +[app] +env = 'dev' +log_level = 'DEBUG' +cookie_secret = 'ZJVAfAwEnR' +data_path = 'data/max_online_num' +page_size = 10 +key = '' + +[server] +host = '127.0.0.1' +port = ':8080' +reader_timeout = 60 +write_timeout = 60 + +[database] +type = 'mysql' +# docker 部署时,host要填写db, 与docker-compose中MySQL的名称一致 +host = 'db' +port = '3306' +user = 'root' +password = '123456' +dbname = 'elk-blog' +charset = 'utf8mb4' +table_prefix = "tk_" +# 最大空闲连接数 +max_idle = 2 +# 最大打开连接数 +max_conn = 10 + + +[xorm] +show_sql = true +# 0-debug, 1-info, 2-warning, 3-error, 4-off, 5-unknow +log_level = 0 + +[security] +# 退订邮件使用的 token key +# faDBMc +unsubscribe_token_key = 'i2ZPUr3YvdX' +# 注册激活邮件使用的 sign salt +activate_sign_salt = 'uaUGhP0KHcZPQVyk8N' + +# 过滤广告 +[sensitive] +# 标题关键词 +title = '' +# 内容关键词 +content = '' + +# 搜索配置 +[search] +engine_url = '' + +# 站点信息 +[site] +domain = 'http://127.0.0.1:8080' +title = '麋鹿博客' +keyword = 'Elk设计网页设计网站设计' +description = '设计师糜鹿个人网站,分享设计,分享人生,提供优质的网页设计、UI设计、APP用户体验改善、UE设计等各项设计服务!' +blogTitle = '糜鹿设计' +blogKeywords = 'Elk设计网页设计网站设计' +blogDescription = '设计师糜鹿个人网站,分享设计,分享人生,提供优质的网页设计、UI设计、APP用户体验改善、UE设计等各项设计服务!' +email = 'elk@qq.com' +contact = 'Elk' +company = 'Elk' +phone = '123456' +icp = '哥在香港' +address = '中国 • 上海' +tpl = 'green' diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..136020f --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,67 @@ +version: '2.0' + +services: + redis: + image: 'redis:6' + # command: redis-server --requirepass yourpassword + ports: + - '16379:6379' + networks: + - main + container_name: el-redis + + db: + image: mysql:8.0.21 + # 容器名(以后的控制都通过这个) + hostname: db + container_name: mysql + # 重启策略 + restart: always + env_file: + - .env/staging + ports: + - "3306:3306" + environment: + TZ: Asia/Shanghai + MYSQL_ROOT_PASSWORD: 123456 + MYSQL_USER: root + MYSQL_PASSWORD: 123456 + MYSQL_DATABASE: elk-blog + volumes: + - /var/lib/mysql:/var/lib/mysql + # 配置挂载 +# - /root/mysql/conf/:/etc/mysql/conf.d/ + # 初始化目录挂载,注意此处我只跑了这个挂载,只是为了说明其他配置不应该数据初始化 + - /opt/mysql/init/:/docker-entrypoint-initdb.d/ + command: + # 将mysql8.0默认密码策略 修改为 原先 策略 (mysql8.0对其默认策略做了更改 会导致密码无法匹配) + --default-authentication-plugin=mysql_native_password + --character-set-server=utf8mb4 + --collation-server=utf8mb4_general_ci + --explicit_defaults_for_timestamp=true + --lower_case_table_names=1 + + app: + build: + context: . + dockerfile: Dockerfile + command: sh -c "go get -d github.com/githubnemo/CompileDaemon && CompileDaemon --build='go build main.go' --command=./main" + container_name: elk-blog + expose: + - "8080" + ports: + - "8080:8080" + volumes: + - /var/elk-blog:/app + depends_on: + - db + links: + - "db:database" + logging: + driver: "json-file" + options: + max-size: "300m" + max-file: "3" + restart: on-failure +networks: + main: \ No newline at end of file diff --git a/go.mod b/go.mod index 478aecb..a53787a 100644 --- a/go.mod +++ b/go.mod @@ -1,42 +1,52 @@ module gitee.com/jikey/elk-blog -go 1.18 +go 1.17 require ( github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3 github.com/gin-gonic/gin v1.8.1 github.com/go-sql-driver/mysql v1.6.0 + github.com/golang-jwt/jwt/v4 v4.4.2 github.com/jinzhu/gorm v1.9.16 github.com/mojocn/base64Captcha v1.3.5 github.com/nleeper/goment v1.4.4 github.com/shirou/gopsutil v3.21.11+incompatible github.com/sirupsen/logrus v1.8.1 + github.com/spf13/cast v1.5.0 github.com/vjeantet/jodaTime v1.0.0 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d - gopkg.in/ini.v1 v1.66.6 + gopkg.in/ini.v1 v1.67.0 ) require ( + github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-playground/validator/v10 v10.11.0 // indirect github.com/goccy/go-json v0.9.8 // indirect - github.com/golang-jwt/jwt/v4 v4.4.2 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/google/go-cmp v0.5.8 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.4 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/lib/pq v1.10.3 // indirect + github.com/magiconair/properties v1.8.6 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect + github.com/mitchellh/mapstructure v1.5.0 // 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.2 // indirect - github.com/spf13/cast v1.5.0 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pelletier/go-toml/v2 v2.0.5 // indirect + github.com/spf13/afero v1.8.2 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.13.0 // indirect + github.com/subosito/gotenv v1.4.1 // indirect github.com/tklauser/go-sysconf v0.3.10 // indirect github.com/tklauser/numcpus v0.4.0 // indirect github.com/tkuchiki/go-timezone v0.2.2 // indirect @@ -48,4 +58,5 @@ require ( golang.org/x/text v0.3.7 // indirect google.golang.org/protobuf v1.28.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index b49cca7..c650a36 100644 --- a/go.sum +++ b/go.sum @@ -1,19 +1,79 @@ +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= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM= github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3 h1:fmFk0Wt3bBxxwZnu48jqMdaOR/IZ4vdtJFuaFV8MpIE= github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3/go.mod h1:bJWSKrZyQvfTnb2OudyUjurSG4/edverV7n82+K3JiM= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= 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-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= @@ -35,11 +95,71 @@ github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZ github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/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.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/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.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +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/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o= github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= @@ -49,6 +169,10 @@ github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas= github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 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/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= 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= @@ -62,11 +186,15 @@ github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ic github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg= github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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= @@ -77,11 +205,19 @@ github.com/mojocn/base64Captcha v1.3.5/go.mod h1:/tTTXn4WTpX9CfrmipqRytCpJ27Uw3G github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nleeper/goment v1.4.4 h1:GlMTpxvhueljArSunzYjN9Ri4SOmpn0Vh2hg2z/IIl8= github.com/nleeper/goment v1.4.4/go.mod h1:zDl5bAyDhqxwQKAvkSXMRLOdCowrdZz53ofRJc4VhTo= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw= github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI= +github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= +github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= 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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +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= @@ -89,17 +225,31 @@ github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKl github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= +github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU= +github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw= github.com/stretchr/objx v0.1.0/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/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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 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.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.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= +github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= @@ -112,44 +262,315 @@ github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0 github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/vjeantet/jodaTime v1.0.0 h1:Fq2K9UCsbTFtKbHpe/L7C57XnSgbZ5z+gyGpn7cTE3s= github.com/vjeantet/jodaTime v1.0.0/go.mod h1:gA+i8InPfZxL1ToHaDpzi6QT/npjl3uPlcV4cxDNerI= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= 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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20220617043117-41969df76e82 h1:KpZB5pUSBvrHltNEdK/tw0xlPeD13M6M6aGP32gKqiw= golang.org/x/image v0.0.0-20220617043117-41969df76e82/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY= +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-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/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-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ= golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +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-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/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-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b h1:2n253B2r0pYSmEV+UNCQoPfU/FiaizQEK5Gu4Bq4JE8= golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +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.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-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-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/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-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= @@ -161,6 +582,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI= gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +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/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -169,3 +592,13 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/main.go b/main.go index 8eb5d13..d004b2a 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( // "gitee.com/jikey/elk-blog/app/service" "gitee.com/jikey/elk-blog/app/database" + "gitee.com/jikey/elk-blog/pkg/utils" "gitee.com/jikey/elk-blog/routers" "github.com/sirupsen/logrus" "time" @@ -15,7 +16,7 @@ func init() { time.Local = timelocal router := routers.RouterApp() - _ = router.Run(":4000") + _ = router.Run(utils.Config.Server.Port) // 设置日志级别 logrus.SetLevel(logrus.DebugLevel) diff --git a/middleware/jwt.go b/middleware/jwt.go index c312c3b..425c225 100644 --- a/middleware/jwt.go +++ b/middleware/jwt.go @@ -75,7 +75,8 @@ func JWTAuth() gin.HandlerFunc { func NewJWT() *JWT { return &JWT{ - SignKey: []byte(utils.Config.Section("app").Key("key").MustString("")), + //SignKey: []byte(utils.Config.Section("app").Key("key").MustString("")), + SignKey: []byte(utils.Config.App.Key), MaxRefresh: time.Duration(10) * time.Minute, } } diff --git a/pkg/response/response.go b/pkg/response/response.go index 7725f89..be27682 100644 --- a/pkg/response/response.go +++ b/pkg/response/response.go @@ -117,7 +117,7 @@ func HTML(c *gin.Context, path string, data interface{}) { // Render 渲染 func Render(c *gin.Context, path string, data interface{}) { - tpl := utils.Site.Tpl + tpl := utils.Config.Site.Tpl if tpl == "" { tpl = "home" diff --git a/pkg/utils/setting.go b/pkg/utils/setting.go index 59e952d..c3a74ef 100644 --- a/pkg/utils/setting.go +++ b/pkg/utils/setting.go @@ -1,31 +1,98 @@ package utils import ( - "gopkg.in/ini.v1" + "github.com/spf13/viper" + "os" + + //"gopkg.in/ini.v1" "log" ) var ( - Config *ini.File + //Config *ini.File // PageSize RunMode string PageSize int - Site *SiteMap + //Site *SiteMap ) +// AllConfig 读取配置文件config +type AllConfig struct { + Redis string + Database DatabaseConfig + App AppConfig + Site SiteMap + Server ServerConfig + Security SecurityConfig + Xorm XormConfig + Sensitive SensitiveConfig + Search SearchConfig +} + +type DatabaseConfig struct { + Type string + Host string + Port string + User string + Password string + DbName string + Charset string + TablePrefix string `toml:"table_prefix" mapstructure:"table_prefix"` + MaxIdle int `toml:"max_idle" mapstructure:"max_idle"` + MaxConn int `toml:"max_conn" mapstructure:"max_conn"` +} + +type AppConfig struct { + Env string + LogLevel string + CookieSecret string + DataPath string + PageSize int + Key string +} + +type ServerConfig struct { + Host string + Port string + ReaderTimeout int + WriteTimeout int +} +type SecurityConfig struct { + UnsubscribeTokenKey string + ActivateSignSalt string +} + +type XormConfig struct { + ShowSql bool + LogLevel int +} +type SensitiveConfig struct { + Title string + Content string +} +type SearchConfig struct { + EngineUrl string +} + type SiteMap struct { - Domain string `ini:"domain"` - Title string `ini:"title"` - Slogon string `ini:"slogon"` - Keyword string `ini:"keyword"` - Description string `ini:"description"` - Email string `ini:"email"` - Contact string `ini:"contact"` - Company string `ini:"company"` - Phone string `ini:"phone"` - Icp string `ini:"icp"` - Address string `ini:"address"` - Tpl string `ini:"tpl"` + Domain string + Title string + Keyword string + Description string + Slogon Slogon + Email string + Contact string + Company string + Phone string + Icp string + Address string + Tpl string +} + +type Slogon struct { + blogTitle string + blogKeywords string + blogDescription string } func init() { @@ -35,27 +102,49 @@ func init() { SetSite() } +var Config AllConfig + // LoadInI 载入配置 func LoadInI() { var err error - Config, err = ini.Load("config/env.ini") - // Config, err = ini.Load("env.ini") + path, _ := os.Getwd() + cfg := viper.New() + cfg.SetConfigName("config") // 配置文件的文件名,没有扩展名,如 .yaml, .toml 这样的扩展名 + cfg.SetConfigType("toml") // 设置扩展名。在这里设置文件的扩展名。另外,如果配置文件的名称没有扩展名,则需要配置这个选项 + //viper.AddConfigPath("/etc/appname/") // 查找配置文件所在路径 + //viper.AddConfigPath("$HOME/.appname") // 多次调用AddConfigPath,可以添加多个搜索路径 + cfg.AddConfigPath(path + "./config") // 还可以在工作目录中搜索配置文件 + err = cfg.ReadInConfig() // 搜索并读取配置文件 + + if err != nil { // 处理错误 + //panic(fmt.Errorf("Fatal error config file: %s \n", err)) + log.Fatalf("Fatal error config file: %v", err) + } + err = cfg.Unmarshal(&Config) if err != nil { - log.Fatalf("Fail to parse 'conf/env.ini': %v", err) + return } + viper.WatchConfig() + //将配置文件绑定到config上 + //Config, err = ini.Load("config/env.ini") + //// Config, err = ini.Load("env.ini") + //if err != nil { + // log.Fatalf("Fail to parse 'conf/env.ini': %v", err) + //} } func SetApp() { - sec := Config.Section("app") - PageSize = sec.Key("page_size").MustInt(10) + //sec := config.App + PageSize = viper.GetInt("app.page_size") } func SetMeta() { - sec := Config.Section("site") - _ = sec.Key("keyword").MustString("") + //sec := Config.Section("site") + _ = viper.GetString("site.keyword") } func SetSite() { - Site = &SiteMap{} - _ = Config.Section("site").MapTo(Site) + //Site = &SiteMap{} + //Site := config.Site + //_ = Config.Section("site").MapTo(Site) } diff --git a/pkg/utils/util.go b/pkg/utils/util.go index 85bd00b..2aad69f 100644 --- a/pkg/utils/util.go +++ b/pkg/utils/util.go @@ -12,7 +12,8 @@ import ( // IsEnv 检测环境 func IsEnv(eType string) bool { - return Config.Section("app").Key("env").MustString("") == eType + //return Config.Section("app").Key("env").MustString("") == eType + return Config.App.Env == eType } // IsProd 是否是生产环境 diff --git a/public/data/elk-blog.sql b/public/data/elk-blog.sql index e0a0039..e7c7c9d 100644 --- a/public/data/elk-blog.sql +++ b/public/data/elk-blog.sql @@ -13,6 +13,11 @@ File Encoding : 65001 Date: 2022-07-30 08:21:33 */ +-- create database elk-blog +create database `elk-blog` default character set utf8mb4 collate utf8mb4_general_ci; + +use elk-blog; + SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- diff --git a/routers/routers.go b/routers/routers.go index f2d10f9..44bffce 100644 --- a/routers/routers.go +++ b/routers/routers.go @@ -13,10 +13,10 @@ import ( ) func RouterApp() *gin.Engine { - gin.SetMode(gin.ReleaseMode) + //gin.SetMode(gin.ReleaseMode) + gin.SetMode(gin.DebugMode) router := gin.Default() - // 模板引擎 router.HTMLRender = utils.NewRender("views/") diff --git a/sql/elk-blog.sql b/sql/elk-blog.sql new file mode 100644 index 0000000..219eee3 --- /dev/null +++ b/sql/elk-blog.sql @@ -0,0 +1,292 @@ +/* +Navicat MySQL Data Transfer + +Source Server : localhost +Source Server Version : 50726 +Source Host : localhost:3306 +Source Database : elk-blog + +Target Server Type : MYSQL +Target Server Version : 50726 +File Encoding : 65001 + +Date: 2022-07-30 08:21:33 +*/ + +-- create database elk-blog +create database `elk-blog` default character set utf8mb4 collate utf8mb4_general_ci if not exists `elk-blog`; + +use elk-blog; + +SET FOREIGN_KEY_CHECKS=0; + +-- ---------------------------- +-- Table structure for tk_about +-- ---------------------------- +DROP TABLE IF EXISTS `tk_about`; +CREATE TABLE `tk_about` ( + `id` int(10) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Table structure for tk_banner +-- ---------------------------- +DROP TABLE IF EXISTS `tk_banner`; +CREATE TABLE `tk_banner` ( + `id` int(8) unsigned NOT NULL AUTO_INCREMENT, + `modelId` int(10) NOT NULL, + `smallimg` varchar(100) NOT NULL, + `title` varchar(100) NOT NULL, + `link` varchar(100) NOT NULL, + `ord` int(8) DEFAULT NULL, + `status` tinyint(1) DEFAULT '1', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=40 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; + +-- ---------------------------- +-- Table structure for tk_blog +-- ---------------------------- +DROP TABLE IF EXISTS `tk_blog`; +CREATE TABLE `tk_blog` ( + `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, + `catid` smallint(5) unsigned DEFAULT NULL, + `title` varchar(80) DEFAULT NULL, + `content` text, + `md` text, + `keywords` varchar(100) DEFAULT NULL, + `smallimg` varchar(100) DEFAULT NULL, + `description` varchar(200) DEFAULT NULL, + `ctime` varchar(30) DEFAULT NULL, + `username` char(20) DEFAULT NULL, + `author` varchar(30) DEFAULT NULL, + `listorder` smallint(5) unsigned DEFAULT '0', + `posid` tinyint(4) NOT NULL DEFAULT '0', + `ord` tinyint(3) DEFAULT NULL, + `views` int(10) DEFAULT NULL COMMENT '浏览量', + `likes` int(10) DEFAULT NULL COMMENT '点赞', + `status` tinyint(4) DEFAULT '0', + `create_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=103 DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Table structure for tk_category +-- ---------------------------- +DROP TABLE IF EXISTS `tk_category`; +CREATE TABLE `tk_category` ( + `colId` smallint(5) unsigned NOT NULL AUTO_INCREMENT, + `colPid` smallint(5) NOT NULL, + `typeid` smallint(3) NOT NULL DEFAULT '0', + `modelid` smallint(5) NOT NULL, + `model` varchar(20) NOT NULL, + `picId` smallint(5) DEFAULT NULL, + `colPath` varchar(100) NOT NULL, + `colTitle` varchar(100) NOT NULL, + `thumb` varchar(150) DEFAULT NULL, + `asmenu` tinyint(1) DEFAULT NULL, + `description` varchar(200) NOT NULL, + `status` tinyint(2) DEFAULT NULL, + `ord` smallint(3) DEFAULT NULL, + PRIMARY KEY (`colId`) +) ENGINE=MyISAM AUTO_INCREMENT=204 DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Records of tk_category +-- ---------------------------- +INSERT INTO `tk_category` VALUES ('1', '0', '0', '1', 'Design', '0', '0', 'Design', '', '1', '设计1', '1', '0'); +INSERT INTO `tk_category` VALUES ('2', '0', '0', '2', 'About', '0', '0', 'About', '', '1', '关于我们', '1', '0'); +INSERT INTO `tk_category` VALUES ('3', '0', '0', '3', 'Contact', '0', '0', 'Contact', '', '1', '联系我', '1', '0'); +INSERT INTO `tk_category` VALUES ('4', '0', '0', '4', 'Blog', '0', '0', 'Blog', '', '1', '博客', '1', '0'); +INSERT INTO `tk_category` VALUES ('5', '1', '0', '1', 'Design', '0', '0-1', 'GUI444', '', '0', '

ios android

', '1', '1'); +INSERT INTO `tk_category` VALUES ('6', '1', '0', '1', 'Design', '0', '0-1', 'WEB', '', '0', 'WEB', '1', '4'); +INSERT INTO `tk_category` VALUES ('7', '1', '0', '1', 'Design', '0', '0-1', 'PAINT', '', '0', 'PAINT', '1', '3'); +INSERT INTO `tk_category` VALUES ('17', '4', '0', '4', 'Blog', '0', '0-4', '轻慢摄影', '', '0', '轻慢摄影', '0', '0'); +INSERT INTO `tk_category` VALUES ('14', '4', '0', '4', 'Blog', '0', '0-4', '快乐绘画', '', '0', '快乐绘画', '0', '0'); +INSERT INTO `tk_category` VALUES ('15', '4', '0', '4', 'Blog', '0', '0-4', '收藏点滴', '', '0', '收藏点滴', '0', '0'); +INSERT INTO `tk_category` VALUES ('18', '1', '0', '1', 'Design', '0', '0-1', 'App', '', '0', '', '0', '2'); +INSERT INTO `tk_category` VALUES ('184', '1', '0', '1', 'Design', '0', '0-1', 'logo', '', '0', '', '0', '5'); +INSERT INTO `tk_category` VALUES ('185', '4', '0', '4', 'Blog', '0', '0-4', '设计理论', '', '0', '设计理论', '0', '0'); +INSERT INTO `tk_category` VALUES ('188', '4', '0', '4', 'Blog', null, '0-4', '好看风云', null, null, '好看风云', null, '6'); + + +-- ---------------------------- +-- Table structure for tk_comment +-- ---------------------------- +DROP TABLE IF EXISTS `tk_comment`; +CREATE TABLE `tk_comment` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `pid` int(10) DEFAULT NULL, + `path` varchar(100) DEFAULT NULL, + `username` varchar(40) DEFAULT NULL, + `nid` mediumint(8) unsigned DEFAULT NULL, + `bid` mediumint(8) unsigned DEFAULT NULL, + `email` varchar(50) DEFAULT NULL, + `author` varchar(40) DEFAULT NULL, + `module` varchar(20) DEFAULT NULL, + `headimg` varchar(250) DEFAULT NULL, + `url` varchar(200) DEFAULT NULL, + `ip` varchar(15) DEFAULT NULL, + `verify` varchar(32) DEFAULT NULL, + `content` text, + `isreply` tinyint(1) DEFAULT '0', + `ord` tinyint(5) DEFAULT NULL, + `status` tinyint(1) DEFAULT '1', + `create_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=119 DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Table structure for tk_contact +-- ---------------------------- +DROP TABLE IF EXISTS `tk_contact`; +CREATE TABLE `tk_contact` ( + `id` int(10) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Table structure for tk_design +-- ---------------------------- +DROP TABLE IF EXISTS `tk_design`; +CREATE TABLE `tk_design` ( + `id` int(8) unsigned NOT NULL AUTO_INCREMENT, + `colId` smallint(5) NOT NULL, + `title` varchar(80) NOT NULL COMMENT '标题', + `content` text NOT NULL COMMENT '内容', + `smallimg` varchar(100) NOT NULL, + `ctime` varchar(30) NOT NULL COMMENT '创建时间', + `commentnum` int(10) NOT NULL DEFAULT '1' COMMENT '评论数量', + `status` tinyint(1) NOT NULL DEFAULT '1', + `likes` int(10) NOT NULL DEFAULT '1' COMMENT '喜欢数量', + `author` varchar(30) NOT NULL, + `inputtime` int(30) NOT NULL, + `posid` tinyint(2) NOT NULL DEFAULT '0', + `ord` int(10) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`id`,`author`) +) ENGINE=MyISAM AUTO_INCREMENT=61 DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Table structure for tk_link +-- ---------------------------- +DROP TABLE IF EXISTS `tk_link`; +CREATE TABLE `tk_link` ( + `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, + `linktype` tinyint(1) DEFAULT NULL, + `title` varchar(50) DEFAULT NULL, + `url` varchar(255) DEFAULT NULL, + `logo` varchar(255) DEFAULT NULL, + `status` tinyint(1) DEFAULT '1', + `ord` tinyint(5) DEFAULT '0', + `introduce` text, + `contact` varchar(30) DEFAULT NULL, + `create_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=26 DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Table structure for tk_message +-- ---------------------------- +DROP TABLE IF EXISTS `tk_message`; +CREATE TABLE `tk_message` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `pid` int(10) DEFAULT NULL, + `email` varchar(50) DEFAULT NULL, + `path` varchar(100) DEFAULT NULL, + `username` varchar(30) DEFAULT NULL, + `ip` varchar(15) DEFAULT NULL, + `headimg` varchar(250) DEFAULT NULL, + `url` varchar(200) DEFAULT NULL, + `content` text NOT NULL, + `verify` varchar(32) DEFAULT NULL, + `isreply` tinyint(1) DEFAULT NULL, + `ord` tinyint(1) DEFAULT NULL, + `status` tinyint(1) DEFAULT NULL, + `create_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=54 DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Table structure for tk_node +-- ---------------------------- +DROP TABLE IF EXISTS `tk_node`; +CREATE TABLE `tk_node` ( + `id` smallint(6) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(20) DEFAULT NULL, + `title` varchar(20) DEFAULT NULL, + `status` tinyint(1) DEFAULT NULL, + `remark` varchar(50) DEFAULT NULL, + `sort` smallint(6) unsigned DEFAULT NULL, + `pid` smallint(6) unsigned DEFAULT NULL, + `level` tinyint(1) unsigned DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Table structure for tk_password_resets +-- ---------------------------- +DROP TABLE IF EXISTS `tk_password_resets`; +CREATE TABLE `tk_password_resets` ( + `email` varchar(255) NOT NULL, + `token` varchar(255) NOT NULL, + `created_at` timestamp NULL DEFAULT NULL, + KEY `tk_password_resets_email_index` (`email`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Table structure for tk_role +-- ---------------------------- +DROP TABLE IF EXISTS `tk_role`; +CREATE TABLE `tk_role` ( + `id` smallint(6) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(20) DEFAULT NULL, + `pid` smallint(6) DEFAULT NULL, + `status` tinyint(1) unsigned DEFAULT NULL, + `remark` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Table structure for tk_role_user +-- ---------------------------- +DROP TABLE IF EXISTS `tk_role_user`; +CREATE TABLE `tk_role_user` ( + `role_id` mediumint(9) unsigned NOT NULL, + `user_id` char(32) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Table structure for tk_user +-- ---------------------------- +DROP TABLE IF EXISTS `tk_user`; +CREATE TABLE `tk_user` ( + `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, + `username` varchar(64) DEFAULT NULL, + `sex` tinyint(2) DEFAULT NULL, + `avatar` varchar(200) DEFAULT NULL, + `nickname` varchar(100) DEFAULT NULL, + `description` varchar(100) DEFAULT NULL, + `password` char(255) DEFAULT NULL, + `loginip` varchar(20) DEFAULT NULL, + `logintime` varchar(50) DEFAULT NULL, + `verify` varchar(32) DEFAULT NULL, + `email` varchar(50) DEFAULT NULL, + `isadmin` tinyint(1) DEFAULT NULL, + `status` tinyint(1) DEFAULT NULL, + `address` varchar(255) DEFAULT NULL, + `create_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Records of tk_user +-- ---------------------------- +INSERT INTO `tk_user` VALUES ('1', 'admin', '1', '', '杰克', '大风起兮云飞扬,威加海内兮归故乡\r\n', '$2a$14$ePl.tGVMczS/DrvMXNl77u3R4U0SBWXhoOZu8GYe2bqwUckRHRrzC', null, null, null, 'jikeytang@163.com', null, null, '中国 • 上海市 • 浦东新区', '2022-07-05 13:42:22', '2022-07-05 13:42:24'); +INSERT INTO `tk_user` VALUES ('2', 'test', null, '', null, null, '$2a$14$otb9WpTUmSulfMlc526hhe5IeTqFGM5P5hhc1YjT20Pl9j5UGxgvy', null, null, null, null, null, null, null, null, null); -- Gitee From 7c42a486d157503aa99526078b5e467e31d0e9f6 Mon Sep 17 00:00:00 2001 From: shaipeng Date: Sun, 9 Oct 2022 15:58:29 +0800 Subject: [PATCH 02/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BD=BF=E7=94=A8docke?= =?UTF-8?q?r=E5=88=9B=E5=BB=BA=E9=95=9C=E5=83=8F=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 58 ++++++++++++++++++++++++++++++++++---------- Dockerfile-mysql | 2 ++ config/config.toml | 2 +- docker-compose.yaml | 10 ++++---- pkg/utils/setting.go | 4 +-- 5 files changed, 55 insertions(+), 21 deletions(-) create mode 100644 Dockerfile-mysql diff --git a/Dockerfile b/Dockerfile index daa233f..64dc349 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,16 +1,48 @@ -FROM golang:latest -ENV GOOS=linux GOARCH=amd64 GO111MODULE=auto GOPROXY=https://goproxy.cn,direct -ENV WORKDIR /app -RUN mkdir ${WORKDIR} -WORKDIR ${WORKDIR} -COPY . $WORKDIR -ADD go.mod $WORKDIR -ADD go.sum $WORKDIR - +FROM golang:1.17 as golang +# 为我们的镜像设置必要的环境变量 +ENV GO111MODULE=on \ + CGO_ENABLED=0 \ + GOOS=linux \ + GOARCH=amd64 \ + GOPROXY=https://goproxy.cn,direct +# 设置/www,进入容器就会直接进入到这个目录下,而不是进入到默认根目录下面 +ADD . /www +# 进入工作目录 +WORKDIR /www +# 复制项目中的 go.mod 和 go.sum文件并下载依赖信息 +COPY go.mod . +COPY go.sum . RUN go mod tidy -RUN #go build main.go -RUN go get -d github.com/githubnemo/CompileDaemon +# 将代码复制到容器中 +COPY . . +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-w -s' -o ginserver main.go + +# 主要是为了下一步的 scratch 拉取 ca-certificates 根证书 +FROM alpine:3.14 as alpine + +RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \ + && apk update && apk add ca-certificates + +FROM ubuntu:18.04 +# 配置项目环境(根据自己情况来) +ENV GO_PROFILE=pro +ENV GIN_MODE=release + +# 暴露服务端口 EXPOSE 8080 -ENTRYPOINT ["go version"] -#ENTRYPOINT ["/bo/bin/CompileDaemon", "--build='go build main.go'", "--command=./main"] \ No newline at end of file + +WORKDIR /www + +# 复制打包的 Go 文件到系统用户可执行程序目录下 +COPY --from=golang /www/ginserver . +COPY --from=golang /www/public ./public +COPY --from=golang /www/config ./config +COPY --from=golang /www/views ./views +# 为所有标准证书颁发机构添加了根证书 +COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ +RUN chmod a+x ginserver + +# 容器启动时运行的命令 +#ENTRYPOINT ["./ginserver"] +CMD ["./ginserver"] \ No newline at end of file diff --git a/Dockerfile-mysql b/Dockerfile-mysql new file mode 100644 index 0000000..c5d1fa5 --- /dev/null +++ b/Dockerfile-mysql @@ -0,0 +1,2 @@ +FROM mysql:8.0.21 +COPY sql/*.sql /docker-entrypoint-initdb.d/ \ No newline at end of file diff --git a/config/config.toml b/config/config.toml index 85fd274..8f24e40 100644 --- a/config/config.toml +++ b/config/config.toml @@ -14,7 +14,7 @@ write_timeout = 60 [database] type = 'mysql' -# docker 部署时,host要填写db, 与docker-compose中MySQL的名称一致 +# docker 部署时,host要填写宿主机的ip host = 'db' port = '3306' user = 'root' diff --git a/docker-compose.yaml b/docker-compose.yaml index 136020f..d97189f 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -11,7 +11,10 @@ services: container_name: el-redis db: - image: mysql:8.0.21 + build: + context: . + dockerfile: Dockerfile-mysql +# image: mysql:8.0.21 # 容器名(以后的控制都通过这个) hostname: db container_name: mysql @@ -45,18 +48,15 @@ services: build: context: . dockerfile: Dockerfile - command: sh -c "go get -d github.com/githubnemo/CompileDaemon && CompileDaemon --build='go build main.go' --command=./main" container_name: elk-blog expose: - "8080" ports: - "8080:8080" volumes: - - /var/elk-blog:/app + - /var/elk-blog:/www depends_on: - db - links: - - "db:database" logging: driver: "json-file" options: diff --git a/pkg/utils/setting.go b/pkg/utils/setting.go index c3a74ef..0831860 100644 --- a/pkg/utils/setting.go +++ b/pkg/utils/setting.go @@ -113,8 +113,8 @@ func LoadInI() { cfg.SetConfigType("toml") // 设置扩展名。在这里设置文件的扩展名。另外,如果配置文件的名称没有扩展名,则需要配置这个选项 //viper.AddConfigPath("/etc/appname/") // 查找配置文件所在路径 //viper.AddConfigPath("$HOME/.appname") // 多次调用AddConfigPath,可以添加多个搜索路径 - cfg.AddConfigPath(path + "./config") // 还可以在工作目录中搜索配置文件 - err = cfg.ReadInConfig() // 搜索并读取配置文件 + cfg.AddConfigPath(path + "/config") // 还可以在工作目录中搜索配置文件 + err = cfg.ReadInConfig() // 搜索并读取配置文件 if err != nil { // 处理错误 //panic(fmt.Errorf("Fatal error config file: %s \n", err)) -- Gitee From 308c9cc1efa55800d570be5b89083c1289836f5a Mon Sep 17 00:00:00 2001 From: shaipeng Date: Wed, 26 Oct 2022 17:39:31 +0800 Subject: [PATCH 03/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BD=BF=E7=94=A8docke?= =?UTF-8?q?r=E5=88=9B=E5=BB=BA=E9=95=9C=E5=83=8F=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/mysql/Dockerfile | 2 + sql/elk-blog.sql => deploy/mysql/init.sql | 18 +--- deploy/mysql/mysqld.cnf | 111 ++++++++++++++++++++++ deploy/redis/Dockerfile | 4 + deploy/redis/redis.conf | 9 ++ docker-compose.yaml | 21 ++-- pkg/utils/setting.go | 1 + 7 files changed, 141 insertions(+), 25 deletions(-) create mode 100644 deploy/mysql/Dockerfile rename sql/elk-blog.sql => deploy/mysql/init.sql (97%) create mode 100644 deploy/mysql/mysqld.cnf create mode 100644 deploy/redis/Dockerfile create mode 100644 deploy/redis/redis.conf diff --git a/deploy/mysql/Dockerfile b/deploy/mysql/Dockerfile new file mode 100644 index 0000000..67e3a9a --- /dev/null +++ b/deploy/mysql/Dockerfile @@ -0,0 +1,2 @@ +FROM mysql:5.7 +ADD mysqld.cnf /etc/mysql/mysql.conf.d/mysqld.cnf \ No newline at end of file diff --git a/sql/elk-blog.sql b/deploy/mysql/init.sql similarity index 97% rename from sql/elk-blog.sql rename to deploy/mysql/init.sql index 219eee3..53fb6c1 100644 --- a/sql/elk-blog.sql +++ b/deploy/mysql/init.sql @@ -1,21 +1,7 @@ -/* -Navicat MySQL Data Transfer -Source Server : localhost -Source Server Version : 50726 -Source Host : localhost:3306 -Source Database : elk-blog - -Target Server Type : MYSQL -Target Server Version : 50726 -File Encoding : 65001 - -Date: 2022-07-30 08:21:33 -*/ - --- create database elk-blog create database `elk-blog` default character set utf8mb4 collate utf8mb4_general_ci if not exists `elk-blog`; - +grant all PRIVILEGES on test.* to test@'%' identified by '123456'; +flush privileges; use elk-blog; SET FOREIGN_KEY_CHECKS=0; diff --git a/deploy/mysql/mysqld.cnf b/deploy/mysql/mysqld.cnf new file mode 100644 index 0000000..a673926 --- /dev/null +++ b/deploy/mysql/mysqld.cnf @@ -0,0 +1,111 @@ +[client] +port=3306 +socket = /var/run/mysqld/mysqld.sock +[mysql] +no-auto-rehash +auto-rehash +default-character-set=utf8mb4 +[mysqld] +###basic settings +server-id = 2 +pid-file = /var/run/mysqld/mysqld.pid +socket = /var/run/mysqld/mysqld.sock +datadir = /var/lib/mysql +#log-error = /var/lib/mysql/error.log +# By default we only accept connections from localhost +#bind-address = 127.0.0.1 +# Disabling symbolic-links is recommended to prevent assorted security risks +symbolic-links=0 +character-set-server = utf8mb4 +sql_mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" +default-storage-engine=INNODB +transaction_isolation = READ-COMMITTED +auto_increment_offset = 1 +connect_timeout = 20 +max_connections = 3500 +wait_timeout=86400 +interactive_timeout=86400 +interactive_timeout = 7200 +log_bin_trust_function_creators = 1 +wait_timeout = 7200 +sort_buffer_size = 32M +join_buffer_size = 128M +max_allowed_packet = 1024M +tmp_table_size = 2097152 +explicit_defaults_for_timestamp = 1 +read_buffer_size = 16M +read_rnd_buffer_size = 32M +query_cache_type = 1 +query_cache_size = 2M +table_open_cache = 1500 +table_definition_cache = 1000 +thread_cache_size = 768 +back_log = 3000 +open_files_limit = 65536 +skip-name-resolve +########log settings######## +log-output=FILE +general_log = ON +general_log_file=/var/lib/mysql/general.log +slow_query_log = ON +slow_query_log_file=/var/lib/mysql/slowquery.log +long_query_time=10 +#log-error=/var/lib/mysql/error.log +log_queries_not_using_indexes = OFF +log_throttle_queries_not_using_indexes = 0 +#expire_logs_days = 120 +min_examined_row_limit = 100 +########innodb settings######## +innodb_io_capacity = 4000 +innodb_io_capacity_max = 8000 +innodb_buffer_pool_size = 6144M +innodb_file_per_table = on +innodb_buffer_pool_instances = 20 +innodb_buffer_pool_load_at_startup = 1 +innodb_buffer_pool_dump_at_shutdown = 1 +innodb_log_file_size = 300M +innodb_log_files_in_group = 2 +innodb_log_buffer_size = 16M +innodb_undo_logs = 128 +#innodb_undo_tablespaces = 3 +#innodb_undo_log_truncate = 1 +#innodb_max_undo_log_size = 2G +innodb_flush_method = O_DIRECT +innodb_flush_neighbors = 1 +innodb_purge_threads = 4 +innodb_large_prefix = 1 +innodb_thread_concurrency = 64 +innodb_print_all_deadlocks = 1 +innodb_strict_mode = 1 +innodb_sort_buffer_size = 64M +innodb_flush_log_at_trx_commit=1 +innodb_autoextend_increment=64 +innodb_concurrency_tickets=5000 +innodb_old_blocks_time=1000 +innodb_open_files=65536 +innodb_stats_on_metadata=0 +innodb_file_per_table=1 +innodb_checksum_algorithm=0 +#innodb_data_file_path=ibdata1:60M;ibdata2:60M;autoextend:max:1G +innodb_data_file_path = ibdata1:12M:autoextend +#innodb_temp_data_file_path = ibtmp1:500M:autoextend:max:20G +#innodb_buffer_pool_dump_pct = 40 +#innodb_page_cleaners = 4 +#innodb_purge_rseg_truncate_frequency = 128 +binlog_gtid_simple_recovery=1 +#log_timestamps=system +############## +delayed_insert_limit = 100 +delayed_insert_timeout = 300 +delayed_queue_size = 1000 +delay_key_write = ON +disconnect_on_expired_password = ON +div_precision_increment = 4 +end_markers_in_json = OFF +eq_range_index_dive_limit = 10 +innodb_adaptive_flushing = ON +innodb_adaptive_hash_index = ON +innodb_adaptive_max_sleep_delay = 150000 +#innodb_additional_mem_pool_size = 2097152 +innodb_autoextend_increment = 64 +innodb_autoinc_lock_mode = 1 \ No newline at end of file diff --git a/deploy/redis/Dockerfile b/deploy/redis/Dockerfile new file mode 100644 index 0000000..a28b3b1 --- /dev/null +++ b/deploy/redis/Dockerfile @@ -0,0 +1,4 @@ +FROM redis:4.0.10 +COPY redis.conf /usr/local/etc/redis/redis.conf +EXPOSE 6379 +ENTRYPOINT [ "redis-server", "/usr/local/etc/redis/redis.conf"] \ No newline at end of file diff --git a/deploy/redis/redis.conf b/deploy/redis/redis.conf new file mode 100644 index 0000000..f999666 --- /dev/null +++ b/deploy/redis/redis.conf @@ -0,0 +1,9 @@ +port 6379 +dir /data +pidfile /data/redis.pid +logfile "/data/redis.log" +repl-disable-tcp-nodelay yes +no-appendfsync-on-rewrite yes +maxmemory 248m +maxmemory-policy allkeys-lru +requirepass abcd1234 \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index d97189f..6be5bbe 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,8 +1,11 @@ -version: '2.0' +version: '2.2' services: redis: - image: 'redis:6' +# image: 'redis:6' + build: + context: ./deploy/redis + dockerfile: Dockerfile # command: redis-server --requirepass yourpassword ports: - '16379:6379' @@ -12,8 +15,8 @@ services: db: build: - context: . - dockerfile: Dockerfile-mysql + context: ./deploy/mysql + dockerfile: Dockerfile # image: mysql:8.0.21 # 容器名(以后的控制都通过这个) hostname: db @@ -27,15 +30,15 @@ services: environment: TZ: Asia/Shanghai MYSQL_ROOT_PASSWORD: 123456 - MYSQL_USER: root - MYSQL_PASSWORD: 123456 - MYSQL_DATABASE: elk-blog +# MYSQL_USER: root +# MYSQL_PASSWORD: 123456 +# MYSQL_DATABASE: elk-blog volumes: - - /var/lib/mysql:/var/lib/mysql + - /var/mysql/data:/var/lib/mysql # 配置挂载 # - /root/mysql/conf/:/etc/mysql/conf.d/ # 初始化目录挂载,注意此处我只跑了这个挂载,只是为了说明其他配置不应该数据初始化 - - /opt/mysql/init/:/docker-entrypoint-initdb.d/ + - /var/mysql/init/:/docker-entrypoint-initdb.d/ command: # 将mysql8.0默认密码策略 修改为 原先 策略 (mysql8.0对其默认策略做了更改 会导致密码无法匹配) --default-authentication-plugin=mysql_native_password diff --git a/pkg/utils/setting.go b/pkg/utils/setting.go index 0831860..e00046c 100644 --- a/pkg/utils/setting.go +++ b/pkg/utils/setting.go @@ -113,6 +113,7 @@ func LoadInI() { cfg.SetConfigType("toml") // 设置扩展名。在这里设置文件的扩展名。另外,如果配置文件的名称没有扩展名,则需要配置这个选项 //viper.AddConfigPath("/etc/appname/") // 查找配置文件所在路径 //viper.AddConfigPath("$HOME/.appname") // 多次调用AddConfigPath,可以添加多个搜索路径 + //cfg.AddConfigPath(path + "/config") // 还可以在工作目录中搜索配置文件 cfg.AddConfigPath(path + "/config") // 还可以在工作目录中搜索配置文件 err = cfg.ReadInConfig() // 搜索并读取配置文件 -- Gitee From d56f4d87bbf780c54e7d7fefc4dd33ffdf10b239 Mon Sep 17 00:00:00 2001 From: shaipeng Date: Fri, 18 Nov 2022 17:58:42 +0800 Subject: [PATCH 04/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=AF=94=E8=BE=83?= =?UTF-8?q?=E5=A4=9A=EF=BC=8C=E8=BF=98=E6=9C=89=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 2 +- app/controller/admin/banner.go | 4 +- app/controller/admin/blog.go | 4 +- app/controller/admin/comment.go | 4 +- app/controller/admin/controller.go | 4 +- app/controller/admin/link.go | 4 +- app/controller/admin/message.go | 62 ++++++++++++------------ app/controller/admin/system.go | 8 ++-- app/controller/admin/user.go | 4 +- app/controller/home/blog.go | 23 ++++----- app/controller/home/comment.go | 4 +- app/controller/home/controller.go | 4 +- app/controller/home/message.go | 3 +- app/database/mysql.go | 77 ------------------------------ app/model/base.go | 45 ----------------- app/model/blog.go | 25 +++++----- app/service/banner.go | 2 +- app/service/blog.go | 2 +- app/service/category.go | 2 +- app/service/comment.go | 2 +- app/service/link.go | 2 +- app/service/message.go | 2 +- app/service/user.go | 2 +- config/config.toml | 2 +- config/env.example.ini | 65 ------------------------- deploy/mysql/init.sql | 3 +- docker-compose.yaml | 8 ++-- main.go | 13 +++-- middleware/jwt.go | 3 +- pkg/response/response.go | 3 +- pkg/{utils => setting}/setting.go | 18 ++++--- pkg/utils/util.go | 3 +- routers/routers.go | 2 +- 33 files changed, 119 insertions(+), 292 deletions(-) delete mode 100644 app/database/mysql.go delete mode 100644 app/model/base.go delete mode 100644 config/env.example.ini rename pkg/{utils => setting}/setting.go (95%) diff --git a/Dockerfile b/Dockerfile index 64dc349..b12fd28 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ COPY go.sum . RUN go mod tidy # 将代码复制到容器中 COPY . . -RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-w -s' -o ginserver main.go +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-w -s' -installsuffix 'public' -o ginserver main.go # 主要是为了下一步的 scratch 拉取 ca-certificates 根证书 FROM alpine:3.14 as alpine diff --git a/app/controller/admin/banner.go b/app/controller/admin/banner.go index 5449d8b..da9cf86 100644 --- a/app/controller/admin/banner.go +++ b/app/controller/admin/banner.go @@ -80,8 +80,8 @@ func (b *Banner) Update(c *gin.Context) { response.Success(c, banner) } -// Destory 删除 -func (b *Banner) Destory(c *gin.Context) { +// Destroy 删除 +func (b *Banner) Destroy(c *gin.Context) { id := c.PostForm("id") service.Banner.Delete(id) diff --git a/app/controller/admin/blog.go b/app/controller/admin/blog.go index 446a93c..2278f54 100644 --- a/app/controller/admin/blog.go +++ b/app/controller/admin/blog.go @@ -5,7 +5,7 @@ import ( "gitee.com/jikey/elk-blog/app/service" "gitee.com/jikey/elk-blog/pkg/e" "gitee.com/jikey/elk-blog/pkg/response" - "gitee.com/jikey/elk-blog/pkg/utils" + "gitee.com/jikey/elk-blog/pkg/setting" "github.com/flosch/pongo2" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" @@ -33,7 +33,7 @@ func (b *Blog) List(c *gin.Context) { title := c.Query("title") maps := "title like '%" + title + "%'" - data["rows"] = service.Blog.BlogList(pageNum, utils.PageSize, maps) + data["rows"] = service.Blog.BlogList(pageNum, setting.PageSize, maps) data["total"] = service.Blog.GetBlogTotal(maps) response.Success(c, data, "列表返回成功了呀!") diff --git a/app/controller/admin/comment.go b/app/controller/admin/comment.go index 79518e9..c75b87d 100644 --- a/app/controller/admin/comment.go +++ b/app/controller/admin/comment.go @@ -5,7 +5,7 @@ import ( "gitee.com/jikey/elk-blog/app/service" "gitee.com/jikey/elk-blog/pkg/e" "gitee.com/jikey/elk-blog/pkg/response" - "gitee.com/jikey/elk-blog/pkg/utils" + "gitee.com/jikey/elk-blog/pkg/setting" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" "strconv" @@ -33,7 +33,7 @@ func (m *Comment) List(c *gin.Context) { maps += " and content like '%" + title + "%'" } - list := service.Comment.List(pageNum, utils.PageSize, maps) + list := service.Comment.List(pageNum, setting.PageSize, maps) data["rows"] = list data["total"] = service.Comment.Total(maps) diff --git a/app/controller/admin/controller.go b/app/controller/admin/controller.go index d3cead2..5b1f2a2 100644 --- a/app/controller/admin/controller.go +++ b/app/controller/admin/controller.go @@ -1,7 +1,7 @@ package admin import ( - "gitee.com/jikey/elk-blog/pkg/utils" + "gitee.com/jikey/elk-blog/pkg/setting" "github.com/gin-gonic/gin" "reflect" "strings" @@ -18,7 +18,7 @@ type Controller struct { this ControllerInterface // 实例 } -var Site = utils.Config.Site +var Site = setting.Config.Site func (ctrl *Controller) Init(this ControllerInterface) error { ctrl.this = this diff --git a/app/controller/admin/link.go b/app/controller/admin/link.go index d6807e0..6aca49e 100644 --- a/app/controller/admin/link.go +++ b/app/controller/admin/link.go @@ -5,7 +5,7 @@ import ( "gitee.com/jikey/elk-blog/app/service" "gitee.com/jikey/elk-blog/pkg/e" "gitee.com/jikey/elk-blog/pkg/response" - "gitee.com/jikey/elk-blog/pkg/utils" + "gitee.com/jikey/elk-blog/pkg/setting" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" "strconv" @@ -29,7 +29,7 @@ func (l *Link) List(c *gin.Context) { title := c.Query("title") maps := "title like '%" + title + "%'" - data["rows"] = service.Link.List(pageNum, utils.PageSize, maps) + data["rows"] = service.Link.List(pageNum, setting.PageSize, maps) data["total"] = service.Link.Total(maps) response.Success(c, data) diff --git a/app/controller/admin/message.go b/app/controller/admin/message.go index 6c04dc0..d3bb25d 100644 --- a/app/controller/admin/message.go +++ b/app/controller/admin/message.go @@ -5,7 +5,7 @@ import ( "gitee.com/jikey/elk-blog/app/service" "gitee.com/jikey/elk-blog/pkg/e" "gitee.com/jikey/elk-blog/pkg/response" - "gitee.com/jikey/elk-blog/pkg/utils" + "gitee.com/jikey/elk-blog/pkg/setting" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" "strconv" @@ -13,59 +13,59 @@ import ( ) type Message struct { - Base + Base } func (m *Message) Index(c *gin.Context) { - data := make(map[string]interface{}) - response.HTML(c, "message/index", data) + data := make(map[string]interface{}) + response.HTML(c, "message/index", data) } // List 列表 func (m *Message) List(c *gin.Context) { - data := make(map[string]interface{}) + data := make(map[string]interface{}) - pageNum, _ := strconv.Atoi(c.Query("page")) + pageNum, _ := strconv.Atoi(c.Query("page")) - title := c.Query("content") - maps := "content like '%" + title + "%'" + title := c.Query("content") + maps := "content like '%" + title + "%'" - data["rows"] = service.Message.List(pageNum, utils.PageSize, maps) - data["total"] = service.Message.Total(maps) + data["rows"] = service.Message.List(pageNum, setting.PageSize, maps) + data["total"] = service.Message.Total(maps) - response.Success(c, data) + response.Success(c, data) } // Insert 新增保存 func (m *Message) Insert(c *gin.Context) { - banner := &model.Message{} + banner := &model.Message{} - if err := c.ShouldBind(&banner); err != nil { - c.JSON(400, gin.H{ - "err": err.Error(), - }) - return - } + if err := c.ShouldBind(&banner); err != nil { + c.JSON(400, gin.H{ + "err": err.Error(), + }) + return + } - err := service.Message.Create(banner) + err := service.Message.Create(banner) - if err != nil { - logrus.Error("修改失败", err) - response.Fail(c, e.ErrorUpdate) - return - } + if err != nil { + logrus.Error("修改失败", err) + response.Fail(c, e.ErrorUpdate) + return + } - response.Success(c, banner) + response.Success(c, banner) } // Destory 删除 func (m *Message) Destory(c *gin.Context) { - id := strings.Split(c.PostForm("id"), ",") + id := strings.Split(c.PostForm("id"), ",") - if row := service.Message.Delete(id); row > 0 { - response.Success(c, id) - return - } + if row := service.Message.Delete(id); row > 0 { + response.Success(c, id) + return + } - response.Fail(c, e.ErrorDelete) + response.Fail(c, e.ErrorDelete) } diff --git a/app/controller/admin/system.go b/app/controller/admin/system.go index 8b06355..4ce8f64 100644 --- a/app/controller/admin/system.go +++ b/app/controller/admin/system.go @@ -2,7 +2,7 @@ package admin import ( "gitee.com/jikey/elk-blog/pkg/response" - "gitee.com/jikey/elk-blog/pkg/utils" + "gitee.com/jikey/elk-blog/pkg/setting" "github.com/gin-gonic/gin" "github.com/spf13/viper" "log" @@ -23,15 +23,15 @@ func (s *System) Setting(c *gin.Context) { func (s *System) SettingList(c *gin.Context) { data := make(map[string]interface{}) - utils.SetSite() - data["rows"] = utils.Config.Site + setting.SetSite() + data["rows"] = setting.Config.Site response.Success(c, data) } // SettingUpdate 修改系统设置 func (s *System) SettingUpdate(c *gin.Context) { - var siteMap utils.SiteMap + var siteMap setting.SiteMap if err := c.ShouldBind(&siteMap); err != nil { c.JSON(400, gin.H{ diff --git a/app/controller/admin/user.go b/app/controller/admin/user.go index 74f8b6f..3c3a040 100644 --- a/app/controller/admin/user.go +++ b/app/controller/admin/user.go @@ -6,7 +6,7 @@ import ( "gitee.com/jikey/elk-blog/app/service" "gitee.com/jikey/elk-blog/pkg/e" "gitee.com/jikey/elk-blog/pkg/response" - "gitee.com/jikey/elk-blog/pkg/utils" + "gitee.com/jikey/elk-blog/pkg/setting" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" "strconv" @@ -50,7 +50,7 @@ func (u *User) List(c *gin.Context) { username := c.Query("username") maps := "username like '%" + username + "%'" - rows, total := service.User.List(pageNum, utils.PageSize, maps) + rows, total := service.User.List(pageNum, setting.PageSize, maps) fmt.Println("rows: ", rows) data["rows"] = rows diff --git a/app/controller/home/blog.go b/app/controller/home/blog.go index ede4569..73c5164 100644 --- a/app/controller/home/blog.go +++ b/app/controller/home/blog.go @@ -5,6 +5,7 @@ import ( "gitee.com/jikey/elk-blog/app/model" "gitee.com/jikey/elk-blog/app/service" "gitee.com/jikey/elk-blog/pkg/response" + "gitee.com/jikey/elk-blog/pkg/setting" "gitee.com/jikey/elk-blog/pkg/utils" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" @@ -36,13 +37,13 @@ func (b *Blog) Index(c *gin.Context) { maps := "(tk_blog.status = 1) AND (title like '%" + keywords + "%')" // 获取分页数据 - page := utils.NewPagination(c.Request, service.Blog.GetBlogTotal(maps), utils.PageSize) + page := utils.NewPagination(c.Request, service.Blog.GetBlogTotal(maps), setting.PageSize) data["page"] = template.HTML(page.Pages()) data["menu"] = Elk["Menu"] data["blogCategory"] = Elk["BlogCategory"] data["archiveList"] = service.Blog.BlogArchiveList() - data["list"] = service.Blog.BlogList(pageNum, utils.PageSize, maps) + data["list"] = service.Blog.BlogList(pageNum, setting.PageSize, maps) data["link"] = service.Link.List(1, 100, "") data["site"] = Site data["active"] = "blog" @@ -64,10 +65,10 @@ func (b *Blog) Detail(c *gin.Context) { data["blogCategory"] = Elk["BlogCategory"] data["archiveList"] = service.Blog.BlogArchiveList() - data["commentList"] = service.Comment.List(pageNum, utils.PageSize, maps) + data["commentList"] = service.Comment.List(pageNum, setting.PageSize, maps) data["commentTotal"] = service.Comment.Total(maps) - data["prev"] = service.Blog.GetPrevNextBlog(detail.Createtime, "prev") - data["next"] = service.Blog.GetPrevNextBlog(detail.Createtime, "next") + data["prev"] = service.Blog.GetPrevNextBlog(detail.CreateTime, "prev") + data["next"] = service.Blog.GetPrevNextBlog(detail.CreateTime, "next") data["link"] = service.Link.List(1, 100, "") data["site"] = Site @@ -85,12 +86,12 @@ func (b *Blog) Archive(c *gin.Context) { id := c.Param("id") // 获取分页数据 - page := utils.NewPagination(c.Request, total, utils.PageSize) + page := utils.NewPagination(c.Request, total, setting.PageSize) data["page"] = template.HTML(page.Pages()) data["blogCategory"] = Elk["BlogCategory"] data["archiveList"] = service.Blog.BlogArchiveList() - data["list"] = service.Blog.GetArchive(pageNum, utils.PageSize, id) + data["list"] = service.Blog.GetArchive(pageNum, setting.PageSize, id) data["link"] = service.Link.List(1, 100, "") data["site"] = Site data["active"] = "blog" @@ -109,12 +110,12 @@ func (b *Blog) Category(c *gin.Context) { maps["catid"] = id // 获取分页数据 - page := utils.NewPagination(c.Request, service.Blog.GetBlogTotal(maps), utils.PageSize) + page := utils.NewPagination(c.Request, service.Blog.GetBlogTotal(maps), setting.PageSize) data["page"] = template.HTML(page.Pages()) data["blogCategory"] = Elk["BlogCategory"] data["archiveList"] = service.Blog.BlogArchiveList() - data["list"] = service.Blog.BlogList(pageNum, utils.PageSize, maps) + data["list"] = service.Blog.BlogList(pageNum, setting.PageSize, maps) data["link"] = service.Link.List(1, 100, "") data["site"] = Site data["active"] = "blog" @@ -142,10 +143,10 @@ func (b *Blog) Search(c *gin.Context) { maps["title"] = keywords // 获取分页数据 - page := utils.NewPagination(c.Request, service.Blog.GetBlogTotal(maps), utils.PageSize) + page := utils.NewPagination(c.Request, service.Blog.GetBlogTotal(maps), setting.PageSize) data["page"] = template.HTML(page.Pages()) - data["list"] = service.Blog.BlogList(pageNum, utils.PageSize, maps) + data["list"] = service.Blog.BlogList(pageNum, setting.PageSize, maps) data["site"] = Site data["active"] = "blog" diff --git a/app/controller/home/comment.go b/app/controller/home/comment.go index a7b12cb..f8f4996 100644 --- a/app/controller/home/comment.go +++ b/app/controller/home/comment.go @@ -5,7 +5,7 @@ import ( "gitee.com/jikey/elk-blog/app/service" "gitee.com/jikey/elk-blog/pkg/e" "gitee.com/jikey/elk-blog/pkg/response" - "gitee.com/jikey/elk-blog/pkg/utils" + "gitee.com/jikey/elk-blog/pkg/setting" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" "strconv" @@ -24,7 +24,7 @@ func (m *Comment) List(c *gin.Context) { title := c.Query("content") maps := "content like '%" + title + "%'" - data["rows"] = service.Comment.List(pageNum, utils.PageSize, maps) + data["rows"] = service.Comment.List(pageNum, setting.PageSize, maps) data["total"] = service.Comment.Total(maps) response.Success(c, data) diff --git a/app/controller/home/controller.go b/app/controller/home/controller.go index 0ba90fe..dd226ed 100644 --- a/app/controller/home/controller.go +++ b/app/controller/home/controller.go @@ -2,7 +2,7 @@ package home import ( "gitee.com/jikey/elk-blog/app/service" - "gitee.com/jikey/elk-blog/pkg/utils" + "gitee.com/jikey/elk-blog/pkg/setting" "github.com/gin-gonic/gin" "reflect" "strings" @@ -21,7 +21,7 @@ type Controller struct { this ControllerInterface // 实例 } -var Site = utils.Config.Site +var Site = setting.Config.Site func (ctrl *Controller) Init(this ControllerInterface) error { ctrl.this = this diff --git a/app/controller/home/message.go b/app/controller/home/message.go index 9f6bc2f..8d148b6 100644 --- a/app/controller/home/message.go +++ b/app/controller/home/message.go @@ -5,6 +5,7 @@ import ( "gitee.com/jikey/elk-blog/app/service" "gitee.com/jikey/elk-blog/pkg/e" "gitee.com/jikey/elk-blog/pkg/response" + "gitee.com/jikey/elk-blog/pkg/setting" "gitee.com/jikey/elk-blog/pkg/utils" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" @@ -23,7 +24,7 @@ func (message *Message) Index(c *gin.Context) { maps := make(map[string]interface{}) // 获取分页数据 - page := utils.NewPagination(c.Request, service.Message.Total(maps), utils.PageSize) + page := utils.NewPagination(c.Request, service.Message.Total(maps), setting.PageSize) data["page"] = template.HTML(page.Pages()) data["list"] = service.Message.List(pageNum, 3000, maps) data["link"] = service.Link.List(1, 100, "") diff --git a/app/database/mysql.go b/app/database/mysql.go deleted file mode 100644 index 556d5fc..0000000 --- a/app/database/mysql.go +++ /dev/null @@ -1,77 +0,0 @@ -package database - -import ( - "fmt" - "gitee.com/jikey/elk-blog/pkg/utils" - _ "github.com/go-sql-driver/mysql" - "github.com/jinzhu/gorm" - "log" - "time" -) - -var Mysql *gorm.DB - -func init() { - dbSetup() -} - -/* -* -数据库初始化 -*/ -func dbSetup() { - // dsn := "root:88888888@/elk-blog?charset=utf8&parseTime=True&loc=Local" - - var ( - err error - dbType, dbName, user, password, host, tablePrefix string - ) - - sec := utils.Config.Database - - dbType = sec.Type - dbName = sec.DbName - user = sec.User - password = sec.Password - host = sec.Host - tablePrefix = sec.TablePrefix - - Mysql, err = gorm.Open( - dbType, - fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8", - user, - password, - host, - dbName, - )) - - // defer Mysql.Close() - - if err != nil { - panic(err) - } - - // 设置默认表名的命名规则 - gorm.DefaultTableNameHandler = func(Mysql *gorm.DB, defaultTableName string) string { - return tablePrefix + defaultTableName - } - Mysql.SingularTable(true) // 全局禁用表名复数 - Mysql.DB().SetMaxIdleConns(25) // 设置最大空闲连接数 - Mysql.DB().SetMaxOpenConns(100) // 设置最大连接数 - Mysql.DB().SetConnMaxLifetime(5 * time.Minute) // 设置每个链接的过期时间 - - // 启用Logger,显示详细日志 - Mysql.LogMode(true) - - // 调试单个操作,显示此操作的详细日志 - // Mysql.Debug().Where("name = ?", "jinzhu").First(&User{}) -} - -func CloseDB() { - defer func() { - err := Mysql.Close() - if err != nil { - log.Fatal(err) - } - }() -} diff --git a/app/model/base.go b/app/model/base.go deleted file mode 100644 index ada5568..0000000 --- a/app/model/base.go +++ /dev/null @@ -1,45 +0,0 @@ -package model - -import ( - "gitee.com/jikey/elk-blog/pkg/utils" - "github.com/jinzhu/gorm" - "github.com/spf13/cast" -) - -// BaseModel 基础model -type BaseModel struct { - Id int `gorm:"primary_key;autoIncrement;column:id" json:"id,omitempty"` - Createtime string `gorm:"column:create_time" json:"create_time,omitempty" form:"create_time"` - Updatetime string `gorm:"column:update_time" json:"update_time,omitempty" form:"update_time"` -} - -func (v *BaseModel) BeforeCreate(scope *gorm.Scope) error { - err := scope.SetColumn("create_time", utils.NowTime()) - - if err != nil { - return err - } - - err2 := scope.SetColumn("update_time", utils.NowTime()) - - if err != nil { - return err2 - } - - return nil -} - -func (v *BaseModel) BeforeUpdate(scope *gorm.Scope) error { - err := scope.SetColumn("update_time", utils.NowTime()) - - if err != nil { - return err - } - - return nil -} - -// StringID 获取 ID 的字符串格式 -func (v *BaseModel) StringID() string { - return cast.ToString(v.Id) -} diff --git a/app/model/blog.go b/app/model/blog.go index 4033b08..cf2e98d 100644 --- a/app/model/blog.go +++ b/app/model/blog.go @@ -6,18 +6,19 @@ import ( type Blog struct { BaseModel - Title string `gorm:"column:title" json:"title" form:"title"` - Content string `gorm:"column:content" json:"content" form:"content"` - Md string `gorm:"column:md" json:"md" form:"md"` - Description string `gorm:"column:description" json:"description" form:"description"` - Catid int `gorm:"column:catid" json:"catid" form:"catid"` - Status int `gorm:"column:status" json:"status" form:"status"` - Likes int `gorm:"column:likes" json:"likes" form:"likes"` - Views int `gorm:"column:views" json:"views" form:"views"` - Avatar string `gorm:"column:avatar;type:varchar(200)" json:"avatar"` - Author string `gorm:"column:author" json:"author" form:"author"` - Total string `gorm:"-"` - ColTitle string `gorm:"column:colTitle" json:"colTitle"` + Category Category `gorm:"foreignkey:Catid"` + Title string `gorm:"column:title" json:"title" form:"title"` + Content string `gorm:"column:content" json:"content" form:"content"` + Md string `gorm:"column:md" json:"md" form:"md"` + Description string `gorm:"column:description" json:"description" form:"description"` + Catid int `gorm:"column:catid" json:"catid" form:"catid"` + Status int `gorm:"column:status" json:"status" form:"status"` + Likes int `gorm:"column:likes" json:"likes" form:"likes"` + Views int `gorm:"column:views" json:"views" form:"views"` + Avatar string `gorm:"column:avatar;type:varchar(200)" json:"avatar"` + Author string `gorm:"column:author" json:"author" form:"author"` + Total string `gorm:"-"` + ColTitle string `gorm:"column:colTitle" json:"colTitle"` } func (b *Blog) IsValid() (err error) { diff --git a/app/service/banner.go b/app/service/banner.go index fbffefb..d403cd0 100644 --- a/app/service/banner.go +++ b/app/service/banner.go @@ -1,8 +1,8 @@ package service import ( - db "gitee.com/jikey/elk-blog/app/database" "gitee.com/jikey/elk-blog/app/model" + db "gitee.com/jikey/elk-blog/app/model" ) type banner struct { diff --git a/app/service/blog.go b/app/service/blog.go index 14ea0f5..b6df516 100644 --- a/app/service/blog.go +++ b/app/service/blog.go @@ -2,8 +2,8 @@ package service import ( "fmt" - db "gitee.com/jikey/elk-blog/app/database" "gitee.com/jikey/elk-blog/app/model" + db "gitee.com/jikey/elk-blog/app/model" "github.com/jinzhu/gorm" "github.com/spf13/cast" ) diff --git a/app/service/category.go b/app/service/category.go index be8e38c..d1ebb6e 100644 --- a/app/service/category.go +++ b/app/service/category.go @@ -1,8 +1,8 @@ package service import ( - db "gitee.com/jikey/elk-blog/app/database" "gitee.com/jikey/elk-blog/app/model" + db "gitee.com/jikey/elk-blog/app/model" ) type category struct { diff --git a/app/service/comment.go b/app/service/comment.go index e7b9d78..6e01e10 100644 --- a/app/service/comment.go +++ b/app/service/comment.go @@ -1,8 +1,8 @@ package service import ( - db "gitee.com/jikey/elk-blog/app/database" "gitee.com/jikey/elk-blog/app/model" + db "gitee.com/jikey/elk-blog/app/model" ) type comment struct { diff --git a/app/service/link.go b/app/service/link.go index 913d9b2..d3040e7 100644 --- a/app/service/link.go +++ b/app/service/link.go @@ -1,8 +1,8 @@ package service import ( - db "gitee.com/jikey/elk-blog/app/database" "gitee.com/jikey/elk-blog/app/model" + db "gitee.com/jikey/elk-blog/app/model" ) type link struct { diff --git a/app/service/message.go b/app/service/message.go index a4a4b5a..a807557 100644 --- a/app/service/message.go +++ b/app/service/message.go @@ -1,8 +1,8 @@ package service import ( - db "gitee.com/jikey/elk-blog/app/database" "gitee.com/jikey/elk-blog/app/model" + db "gitee.com/jikey/elk-blog/app/model" ) type message struct { diff --git a/app/service/user.go b/app/service/user.go index 64a5db0..326debe 100644 --- a/app/service/user.go +++ b/app/service/user.go @@ -3,8 +3,8 @@ package service import ( "errors" "fmt" - db "gitee.com/jikey/elk-blog/app/database" "gitee.com/jikey/elk-blog/app/model" + db "gitee.com/jikey/elk-blog/app/model" "golang.org/x/crypto/bcrypt" ) diff --git a/config/config.toml b/config/config.toml index 8f24e40..fe25771 100644 --- a/config/config.toml +++ b/config/config.toml @@ -15,7 +15,7 @@ write_timeout = 60 [database] type = 'mysql' # docker 部署时,host要填写宿主机的ip -host = 'db' +host = '127.0.0.1' port = '3306' user = 'root' password = '123456' diff --git a/config/env.example.ini b/config/env.example.ini deleted file mode 100644 index 779cde2..0000000 --- a/config/env.example.ini +++ /dev/null @@ -1,65 +0,0 @@ -[app] -env = dev -log_level = DEBUG -cookie_secret = ZJVAfAwEnR -data_path = data/max_online_num -page_size = 10 - -[server] -host = -port = 6000 -reader_timeout = 60 -write_timeout = 60 - -[database] -type = mysql -host = 192.168.31.165 -port = 3306 -user = root -password = root -dbname = elk-blog -charset = utf8 -; 最大空闲连接数 -max_idle = 2 -; 最大打开连接数 -max_conn = 10 -table_prefix = tk_ - -[xorm] -show_sql = true -; 0-debug, 1-info, 2-warning, 3-error, 4-off, 5-unknow -log_level = 0 - -[security] -; 退订邮件使用的 token key -unsubscribe_token_key = i2ZPUr3YvdX#faDBMc -; 注册激活邮件使用的 sign salt -activate_sign_salt = uaUGhP0KHcZPQVyk8N - -; 过滤广告 -[sensitive] -; 标题关键词 -title = -; 内容关键词 -content = - -; 搜索配置 -[search] -engine_url = - -; 站点信息 -[site] -domain = http://elk.vyan.top -title = 麋鹿博客 -keyword = Elk设计网页设计网站设计 -description = 设计师糜鹿个人网站,分享设计,分享人生,提供优质的网页设计、UI设计、APP用户体验改善、UE设计等各项设计服务! -blogTitle = 糜鹿设计 -blogKeywords = Elk设计网页设计网站设计 -blogDescription = 设计师糜鹿个人网站,分享设计,分享人生,提供优质的网页设计、UI设计、APP用户体验改善、UE设计等各项设计服务! -email = elk@qq.com -contact = Elk -company = Elk -phone = 123456 -icp = 哥在香港 -address = 中国 • 上海 -tpl = green \ No newline at end of file diff --git a/deploy/mysql/init.sql b/deploy/mysql/init.sql index 53fb6c1..10ecabe 100644 --- a/deploy/mysql/init.sql +++ b/deploy/mysql/init.sql @@ -1,6 +1,5 @@ - create database `elk-blog` default character set utf8mb4 collate utf8mb4_general_ci if not exists `elk-blog`; -grant all PRIVILEGES on test.* to test@'%' identified by '123456'; +GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION; flush privileges; use elk-blog; diff --git a/docker-compose.yaml b/docker-compose.yaml index 6be5bbe..00e20f2 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -29,16 +29,16 @@ services: - "3306:3306" environment: TZ: Asia/Shanghai - MYSQL_ROOT_PASSWORD: 123456 + MYSQL_ROOT_PASSWORD: abcd1234 # MYSQL_USER: root # MYSQL_PASSWORD: 123456 # MYSQL_DATABASE: elk-blog volumes: - - /var/mysql/data:/var/lib/mysql + - /root/mysql/data:/var/lib/mysql # 配置挂载 # - /root/mysql/conf/:/etc/mysql/conf.d/ # 初始化目录挂载,注意此处我只跑了这个挂载,只是为了说明其他配置不应该数据初始化 - - /var/mysql/init/:/docker-entrypoint-initdb.d/ + - /root/mysql/init/:/docker-entrypoint-initdb.d/ command: # 将mysql8.0默认密码策略 修改为 原先 策略 (mysql8.0对其默认策略做了更改 会导致密码无法匹配) --default-authentication-plugin=mysql_native_password @@ -57,7 +57,7 @@ services: ports: - "8080:8080" volumes: - - /var/elk-blog:/www + - /root/elk-blog:/www depends_on: - db logging: diff --git a/main.go b/main.go index d004b2a..1bae743 100644 --- a/main.go +++ b/main.go @@ -2,8 +2,8 @@ package main import ( // "gitee.com/jikey/elk-blog/app/service" - "gitee.com/jikey/elk-blog/app/database" - "gitee.com/jikey/elk-blog/pkg/utils" + "gitee.com/jikey/elk-blog/app/model" + "gitee.com/jikey/elk-blog/pkg/setting" "gitee.com/jikey/elk-blog/routers" "github.com/sirupsen/logrus" "time" @@ -11,12 +11,17 @@ import ( // 初始化应用 func init() { + setting.LoadInI() + setting.SetApp() + setting.SetMeta() + setting.SetSite() + model.Setup() // 设置时区 timelocal, _ := time.LoadLocation("Asia/Shanghai") time.Local = timelocal router := routers.RouterApp() - _ = router.Run(utils.Config.Server.Port) + _ = router.Run(setting.Config.Server.Port) // 设置日志级别 logrus.SetLevel(logrus.DebugLevel) @@ -24,5 +29,5 @@ func init() { } func main() { - database.CloseDB() + model.CloseDB() } diff --git a/middleware/jwt.go b/middleware/jwt.go index 425c225..3a4d73c 100644 --- a/middleware/jwt.go +++ b/middleware/jwt.go @@ -4,6 +4,7 @@ import ( "errors" "gitee.com/jikey/elk-blog/pkg/e" "gitee.com/jikey/elk-blog/pkg/response" + "gitee.com/jikey/elk-blog/pkg/setting" "gitee.com/jikey/elk-blog/pkg/utils" "github.com/gin-gonic/gin" jwtgo "github.com/golang-jwt/jwt/v4" @@ -76,7 +77,7 @@ func JWTAuth() gin.HandlerFunc { func NewJWT() *JWT { return &JWT{ //SignKey: []byte(utils.Config.Section("app").Key("key").MustString("")), - SignKey: []byte(utils.Config.App.Key), + SignKey: []byte(setting.Config.App.Key), MaxRefresh: time.Duration(10) * time.Minute, } } diff --git a/pkg/response/response.go b/pkg/response/response.go index be27682..109a34c 100644 --- a/pkg/response/response.go +++ b/pkg/response/response.go @@ -3,6 +3,7 @@ package response import ( "fmt" "gitee.com/jikey/elk-blog/pkg/e" + "gitee.com/jikey/elk-blog/pkg/setting" "gitee.com/jikey/elk-blog/pkg/utils" "github.com/flosch/pongo2" "github.com/gin-gonic/gin" @@ -117,7 +118,7 @@ func HTML(c *gin.Context, path string, data interface{}) { // Render 渲染 func Render(c *gin.Context, path string, data interface{}) { - tpl := utils.Config.Site.Tpl + tpl := setting.Config.Site.Tpl if tpl == "" { tpl = "home" diff --git a/pkg/utils/setting.go b/pkg/setting/setting.go similarity index 95% rename from pkg/utils/setting.go rename to pkg/setting/setting.go index e00046c..e26b4d5 100644 --- a/pkg/utils/setting.go +++ b/pkg/setting/setting.go @@ -1,6 +1,7 @@ -package utils +package setting import ( + "fmt" "github.com/spf13/viper" "os" @@ -42,6 +43,8 @@ type DatabaseConfig struct { MaxConn int `toml:"max_conn" mapstructure:"max_conn"` } +var DatabaseSetting = &DatabaseConfig{} + type AppConfig struct { Env string LogLevel string @@ -95,12 +98,12 @@ type Slogon struct { blogDescription string } -func init() { - LoadInI() - SetApp() - SetMeta() - SetSite() -} +//func init() { +// LoadInI() +// SetApp() +// SetMeta() +// SetSite() +//} var Config AllConfig @@ -114,6 +117,7 @@ func LoadInI() { //viper.AddConfigPath("/etc/appname/") // 查找配置文件所在路径 //viper.AddConfigPath("$HOME/.appname") // 多次调用AddConfigPath,可以添加多个搜索路径 //cfg.AddConfigPath(path + "/config") // 还可以在工作目录中搜索配置文件 + fmt.Println(path + "/config") cfg.AddConfigPath(path + "/config") // 还可以在工作目录中搜索配置文件 err = cfg.ReadInConfig() // 搜索并读取配置文件 diff --git a/pkg/utils/util.go b/pkg/utils/util.go index 2aad69f..5394608 100644 --- a/pkg/utils/util.go +++ b/pkg/utils/util.go @@ -2,6 +2,7 @@ package utils import ( "bytes" + "gitee.com/jikey/elk-blog/pkg/setting" "github.com/gin-gonic/gin" mathrand "math/rand" "net/http" @@ -13,7 +14,7 @@ import ( // IsEnv 检测环境 func IsEnv(eType string) bool { //return Config.Section("app").Key("env").MustString("") == eType - return Config.App.Env == eType + return setting.Config.App.Env == eType } // IsProd 是否是生产环境 diff --git a/routers/routers.go b/routers/routers.go index 44bffce..dcd9061 100644 --- a/routers/routers.go +++ b/routers/routers.go @@ -73,7 +73,7 @@ func RouterApp() *gin.Engine { back.GET("banner/list", bannerController.List) back.POST("banner/insert", bannerController.Insert) back.PUT("banner/update", bannerController.Update) - back.POST("banner/delete", bannerController.Destory) + back.POST("banner/delete", bannerController.Destroy) // System管理 systemController := new(admin.System) -- Gitee From 3b809dfcd9d33790cd077ed1c11ea4ca1fe20040 Mon Sep 17 00:00:00 2001 From: shaipeng Date: Mon, 21 Nov 2022 13:58:42 +0800 Subject: [PATCH 05/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=AF=94=E8=BE=83?= =?UTF-8?q?=E5=A4=9A=EF=BC=8C=E8=BF=98=E6=9C=89=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/model/model.go | 156 ++++++++++++++++++++++++++++++++ main.go | 5 - pkg/setting/setting.go | 21 +++-- {config => setting}/config.toml | 0 4 files changed, 168 insertions(+), 14 deletions(-) create mode 100644 app/model/model.go rename {config => setting}/config.toml (100%) diff --git a/app/model/model.go b/app/model/model.go new file mode 100644 index 0000000..6387e56 --- /dev/null +++ b/app/model/model.go @@ -0,0 +1,156 @@ +package model + +import ( + "fmt" + "github.com/spf13/cast" + "log" + + "github.com/jinzhu/gorm" + _ "github.com/jinzhu/gorm/dialects/mysql" + + "gitee.com/jikey/elk-blog/pkg/setting" + "time" +) + +var Mysql *gorm.DB + +type BaseModel struct { + Id int `gorm:"primary_key;autoIncrement;column:id" json:"id,omitempty"` + DeletedOn int `json:"deleted_on"` + CreateTime string `gorm:"column:create_time" json:"create_time,omitempty" form:"create_time"` + UpdateTime string `gorm:"column:update_time" json:"update_time,omitempty" form:"update_time"` +} + +// Setup initializes the database instance +func init() { + var err error + Mysql, err = gorm.Open(setting.Config.Database.Type, fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", + setting.Config.Database.User, + setting.Config.Database.Password, + setting.Config.Database.Host, + setting.Config.Database.DbName)) + + if err != nil { + log.Fatalf("models.Setup err: %v", err) + } + + gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string { + return setting.DatabaseSetting.TablePrefix + defaultTableName + } + + Mysql.SingularTable(true) + Mysql.Callback().Create().Replace("gorm:update_time_stamp", updateTimeStampForCreateCallback) + Mysql.Callback().Update().Replace("gorm:update_time_stamp", updateTimeStampForUpdateCallback) + Mysql.Callback().Delete().Replace("gorm:delete", deleteCallback) + Mysql.DB().SetMaxIdleConns(25) // 设置最大空闲连接数 + Mysql.DB().SetMaxOpenConns(100) // 设置最大连接数 + Mysql.DB().SetConnMaxLifetime(5 * time.Minute) // 设置每个链接的过期时间 + + // 启用Logger,显示详细日志 + Mysql.LogMode(true) +} + +// CloseDB closes database connection (unnecessary) +func CloseDB() { + defer func(Mysql *gorm.DB) { + err := Mysql.Close() + if err != nil { + log.Fatal(err) + } + }(Mysql) +} + +// updateTimeStampForCreateCallback will set `CreatedOn`, `ModifiedOn` when creating +func updateTimeStampForCreateCallback(scope *gorm.Scope) { + if !scope.HasError() { + //nowTime := time.Now().Unix() + nowTime := time.Now().Format("2006-01-02 15:04:05") + if createTimeField, ok := scope.FieldByName("CreateTime"); ok { + if createTimeField.IsBlank { + createTimeField.Set(nowTime) + } + } + + if modifyTimeField, ok := scope.FieldByName("UpdateTime"); ok { + if modifyTimeField.IsBlank { + modifyTimeField.Set(nowTime) + } + } + } +} + +// updateTimeStampForUpdateCallback will set `ModifiedOn` when updating +func updateTimeStampForUpdateCallback(scope *gorm.Scope) { + if _, ok := scope.Get("gorm:update_column"); !ok { + scope.SetColumn("UpdateTime", time.Now().Format("2006-01-02 15:04:05")) + } +} + +// deleteCallback will set `DeletedOn` where deleting +func deleteCallback(scope *gorm.Scope) { + if !scope.HasError() { + var extraOption string + if str, ok := scope.Get("gorm:delete_option"); ok { + extraOption = fmt.Sprint(str) + } + + deletedOnField, hasDeletedOnField := scope.FieldByName("DeletedOn") + + if !scope.Search.Unscoped && hasDeletedOnField { + scope.Raw(fmt.Sprintf( + "UPDATE %v SET %v=%v%v%v", + scope.QuotedTableName(), + scope.Quote(deletedOnField.DBName), + scope.AddToVars(time.Now().Format("2006-01-02 15:04:05")), + addExtraSpaceIfExist(scope.CombinedConditionSql()), + addExtraSpaceIfExist(extraOption), + )).Exec() + } else { + scope.Raw(fmt.Sprintf( + "DELETE FROM %v%v%v", + scope.QuotedTableName(), + addExtraSpaceIfExist(scope.CombinedConditionSql()), + addExtraSpaceIfExist(extraOption), + )).Exec() + } + } +} + +// addExtraSpaceIfExist adds a separator +func addExtraSpaceIfExist(str string) string { + if str != "" { + return " " + str + } + return "" +} + +func (v *BaseModel) BeforeCreate(scope *gorm.Scope) error { + err := scope.SetColumn("create_time", time.Now().Format("2006-01-02 15:04:05")) + + if err != nil { + return err + } + + err2 := scope.SetColumn("update_time", time.Now().Format("2006-01-02 15:04:05")) + + if err != nil { + return err2 + } + + return nil +} + +func (v *BaseModel) BeforeUpdate(scope *gorm.Scope) error { + err := scope.SetColumn("update_time", time.Now().Format("2006-01-02 15:04:05")) + + if err != nil { + return err + } + + return nil +} + +// StringID 获取 ID 的字符串格式 +func (v *BaseModel) StringID() string { + return cast.ToString(v.Id) +} diff --git a/main.go b/main.go index 1bae743..afeae19 100644 --- a/main.go +++ b/main.go @@ -11,11 +11,6 @@ import ( // 初始化应用 func init() { - setting.LoadInI() - setting.SetApp() - setting.SetMeta() - setting.SetSite() - model.Setup() // 设置时区 timelocal, _ := time.LoadLocation("Asia/Shanghai") time.Local = timelocal diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index e26b4d5..6d9655b 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/spf13/viper" "os" + "path/filepath" //"gopkg.in/ini.v1" "log" @@ -98,12 +99,12 @@ type Slogon struct { blogDescription string } -//func init() { -// LoadInI() -// SetApp() -// SetMeta() -// SetSite() -//} +func init() { + LoadInI() + SetApp() + SetMeta() + SetSite() +} var Config AllConfig @@ -117,9 +118,11 @@ func LoadInI() { //viper.AddConfigPath("/etc/appname/") // 查找配置文件所在路径 //viper.AddConfigPath("$HOME/.appname") // 多次调用AddConfigPath,可以添加多个搜索路径 //cfg.AddConfigPath(path + "/config") // 还可以在工作目录中搜索配置文件 - fmt.Println(path + "/config") - cfg.AddConfigPath(path + "/config") // 还可以在工作目录中搜索配置文件 - err = cfg.ReadInConfig() // 搜索并读取配置文件 + //cfg.AddConfigPath(path + "/config") // 还可以在工作目录中搜索配置文件 + path_ := filepath.Join(path, "/setting") + fmt.Println(path_) + cfg.AddConfigPath(path_) // 还可以在工作目录中搜索配置文件 + err = cfg.ReadInConfig() // 搜索并读取配置文件 if err != nil { // 处理错误 //panic(fmt.Errorf("Fatal error config file: %s \n", err)) diff --git a/config/config.toml b/setting/config.toml similarity index 100% rename from config/config.toml rename to setting/config.toml -- Gitee From d86df36c3c4a3ca1bdc86b49af19055309e3d7a3 Mon Sep 17 00:00:00 2001 From: shaipeng Date: Mon, 21 Nov 2022 18:14:32 +0800 Subject: [PATCH 06/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=AF=94=E8=BE=83?= =?UTF-8?q?=E5=A4=9A=EF=BC=8C=E8=BF=98=E6=9C=89=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 3 ++- app/model/blog.go | 15 ++++++++------- app/model/model.go | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index b12fd28..7070b4b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -41,7 +41,8 @@ COPY --from=golang /www/config ./config COPY --from=golang /www/views ./views # 为所有标准证书颁发机构添加了根证书 COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ -RUN chmod a+x ginserver +RUN chown -R root /www/ginserver +RUN chmod a+x /www/ginserver # 容器启动时运行的命令 #ENTRYPOINT ["./ginserver"] diff --git a/app/model/blog.go b/app/model/blog.go index cf2e98d..f983cd5 100644 --- a/app/model/blog.go +++ b/app/model/blog.go @@ -12,13 +12,14 @@ type Blog struct { Md string `gorm:"column:md" json:"md" form:"md"` Description string `gorm:"column:description" json:"description" form:"description"` Catid int `gorm:"column:catid" json:"catid" form:"catid"` - Status int `gorm:"column:status" json:"status" form:"status"` - Likes int `gorm:"column:likes" json:"likes" form:"likes"` - Views int `gorm:"column:views" json:"views" form:"views"` - Avatar string `gorm:"column:avatar;type:varchar(200)" json:"avatar"` - Author string `gorm:"column:author" json:"author" form:"author"` - Total string `gorm:"-"` - ColTitle string `gorm:"column:colTitle" json:"colTitle"` + //CategoryId int `gorm:"column:category_id" json:"category_id" form:"category_id"` + Status int `gorm:"column:status" json:"status" form:"status"` + Likes int `gorm:"column:likes" json:"likes" form:"likes"` + Views int `gorm:"column:views" json:"views" form:"views"` + Avatar string `gorm:"column:avatar;type:varchar(200)" json:"avatar"` + Author string `gorm:"column:author" json:"author" form:"author"` + Total string `gorm:"-"` + ColTitle string `gorm:"column:colTitle" json:"colTitle"` } func (b *Blog) IsValid() (err error) { diff --git a/app/model/model.go b/app/model/model.go index 6387e56..7fd76f7 100644 --- a/app/model/model.go +++ b/app/model/model.go @@ -35,7 +35,7 @@ func init() { } gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string { - return setting.DatabaseSetting.TablePrefix + defaultTableName + return setting.Config.Database.TablePrefix + defaultTableName } Mysql.SingularTable(true) -- Gitee From 365179ce1966a7a312713a6a53f2ecd6e294d1d1 Mon Sep 17 00:00:00 2001 From: shaipeng Date: Wed, 23 Nov 2022 10:20:57 +0800 Subject: [PATCH 07/13] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=94=B9docker=E9=83=A8=E7=BD=B2=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 19 ++++++------------- app/model/blog.go | 15 ++++++++------- deploy/mysql/init.sql | 33 +++++++++++++++++++-------------- docker-compose.yaml | 6 +++--- views/admin/blog/edit.html | 4 ++++ views/admin/blog/md.html | 7 +++++++ 6 files changed, 47 insertions(+), 37 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7070b4b..14f5027 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,12 +17,6 @@ RUN go mod tidy COPY . . RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-w -s' -installsuffix 'public' -o ginserver main.go -# 主要是为了下一步的 scratch 拉取 ca-certificates 根证书 -FROM alpine:3.14 as alpine - -RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \ - && apk update && apk add ca-certificates - FROM ubuntu:18.04 # 配置项目环境(根据自己情况来) @@ -32,18 +26,17 @@ ENV GIN_MODE=release # 暴露服务端口 EXPOSE 8080 -WORKDIR /www +WORKDIR /app # 复制打包的 Go 文件到系统用户可执行程序目录下 COPY --from=golang /www/ginserver . COPY --from=golang /www/public ./public COPY --from=golang /www/config ./config COPY --from=golang /www/views ./views -# 为所有标准证书颁发机构添加了根证书 -COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ -RUN chown -R root /www/ginserver -RUN chmod a+x /www/ginserver + +RUN chown -R root /app/ginserver +RUN chmod +x /app/ginserver # 容器启动时运行的命令 -#ENTRYPOINT ["./ginserver"] -CMD ["./ginserver"] \ No newline at end of file +ENTRYPOINT ["/app/ginserver"] +#CMD ["/app/ginserver"] \ No newline at end of file diff --git a/app/model/blog.go b/app/model/blog.go index f983cd5..88d2f02 100644 --- a/app/model/blog.go +++ b/app/model/blog.go @@ -13,13 +13,14 @@ type Blog struct { Description string `gorm:"column:description" json:"description" form:"description"` Catid int `gorm:"column:catid" json:"catid" form:"catid"` //CategoryId int `gorm:"column:category_id" json:"category_id" form:"category_id"` - Status int `gorm:"column:status" json:"status" form:"status"` - Likes int `gorm:"column:likes" json:"likes" form:"likes"` - Views int `gorm:"column:views" json:"views" form:"views"` - Avatar string `gorm:"column:avatar;type:varchar(200)" json:"avatar"` - Author string `gorm:"column:author" json:"author" form:"author"` - Total string `gorm:"-"` - ColTitle string `gorm:"column:colTitle" json:"colTitle"` + Status int `gorm:"column:status" json:"status" form:"status"` + Likes int `gorm:"column:likes" json:"likes" form:"likes"` + Views int `gorm:"column:views" json:"views" form:"views"` + Avatar string `gorm:"column:avatar;type:varchar(200)" json:"avatar"` + Author string `gorm:"column:author" json:"author" form:"author"` + Total string `gorm:"-"` + SourceUrl string `gorm:"column:source_url;type:varchar(200)" json:"source_url"` + ColTitle string `gorm:"column:colTitle" json:"colTitle"` } func (b *Blog) IsValid() (err error) { diff --git a/deploy/mysql/init.sql b/deploy/mysql/init.sql index 10ecabe..7c543de 100644 --- a/deploy/mysql/init.sql +++ b/deploy/mysql/init.sql @@ -11,8 +11,12 @@ SET FOREIGN_KEY_CHECKS=0; DROP TABLE IF EXISTS `tk_about`; CREATE TABLE `tk_about` ( `id` int(10) NOT NULL, + `content` text, + `status` tinyint(1) DEFAULT '1', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Table structure for tk_banner @@ -29,7 +33,7 @@ CREATE TABLE `tk_banner` ( `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=40 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; +) ENGINE=MyISAM AUTO_INCREMENT=40 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC; -- ---------------------------- -- Table structure for tk_blog @@ -52,11 +56,12 @@ CREATE TABLE `tk_blog` ( `ord` tinyint(3) DEFAULT NULL, `views` int(10) DEFAULT NULL COMMENT '浏览量', `likes` int(10) DEFAULT NULL COMMENT '点赞', + `source_url` varchar(200) DEFAULT NULL, `status` tinyint(4) DEFAULT '0', `create_time` datetime DEFAULT NULL, `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=103 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=103 DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Table structure for tk_category @@ -77,7 +82,7 @@ CREATE TABLE `tk_category` ( `status` tinyint(2) DEFAULT NULL, `ord` smallint(3) DEFAULT NULL, PRIMARY KEY (`colId`) -) ENGINE=MyISAM AUTO_INCREMENT=204 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=204 DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Records of tk_category @@ -123,7 +128,7 @@ CREATE TABLE `tk_comment` ( `create_time` datetime DEFAULT NULL, `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=119 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=119 DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Table structure for tk_contact @@ -132,7 +137,7 @@ DROP TABLE IF EXISTS `tk_contact`; CREATE TABLE `tk_contact` ( `id` int(10) NOT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Table structure for tk_design @@ -153,7 +158,7 @@ CREATE TABLE `tk_design` ( `posid` tinyint(2) NOT NULL DEFAULT '0', `ord` int(10) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`id`,`author`) -) ENGINE=MyISAM AUTO_INCREMENT=61 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=61 DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Table structure for tk_link @@ -172,7 +177,7 @@ CREATE TABLE `tk_link` ( `create_time` datetime DEFAULT NULL, `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=26 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Table structure for tk_message @@ -195,7 +200,7 @@ CREATE TABLE `tk_message` ( `create_time` datetime DEFAULT NULL, `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=54 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=54 DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Table structure for tk_node @@ -211,7 +216,7 @@ CREATE TABLE `tk_node` ( `pid` smallint(6) unsigned DEFAULT NULL, `level` tinyint(1) unsigned DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Table structure for tk_password_resets @@ -222,7 +227,7 @@ CREATE TABLE `tk_password_resets` ( `token` varchar(255) NOT NULL, `created_at` timestamp NULL DEFAULT NULL, KEY `tk_password_resets_email_index` (`email`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Table structure for tk_role @@ -235,7 +240,7 @@ CREATE TABLE `tk_role` ( `status` tinyint(1) unsigned DEFAULT NULL, `remark` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Table structure for tk_role_user @@ -244,7 +249,7 @@ DROP TABLE IF EXISTS `tk_role_user`; CREATE TABLE `tk_role_user` ( `role_id` mediumint(9) unsigned NOT NULL, `user_id` char(32) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=utf8; +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Table structure for tk_user @@ -268,7 +273,7 @@ CREATE TABLE `tk_user` ( `create_time` datetime DEFAULT NULL, `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4; -- ---------------------------- -- Records of tk_user diff --git a/docker-compose.yaml b/docker-compose.yaml index 00e20f2..fd52c7f 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -34,11 +34,11 @@ services: # MYSQL_PASSWORD: 123456 # MYSQL_DATABASE: elk-blog volumes: - - /root/mysql/data:/var/lib/mysql + - /var/mysql/data:/var/lib/mysql # 配置挂载 # - /root/mysql/conf/:/etc/mysql/conf.d/ # 初始化目录挂载,注意此处我只跑了这个挂载,只是为了说明其他配置不应该数据初始化 - - /root/mysql/init/:/docker-entrypoint-initdb.d/ + - /var/mysql/init/:/docker-entrypoint-initdb.d/ command: # 将mysql8.0默认密码策略 修改为 原先 策略 (mysql8.0对其默认策略做了更改 会导致密码无法匹配) --default-authentication-plugin=mysql_native_password @@ -57,7 +57,7 @@ services: ports: - "8080:8080" volumes: - - /root/elk-blog:/www + - /var/elk-blog:/app depends_on: - db logging: diff --git a/views/admin/blog/edit.html b/views/admin/blog/edit.html index 77ff31f..ef4c640 100644 --- a/views/admin/blog/edit.html +++ b/views/admin/blog/edit.html @@ -8,6 +8,9 @@ + + + @@ -80,6 +83,7 @@ catid: '', content: '', status: 1, + source_url: '', }, rules: { title: [ diff --git a/views/admin/blog/md.html b/views/admin/blog/md.html index 2aeeefe..515f53c 100644 --- a/views/admin/blog/md.html +++ b/views/admin/blog/md.html @@ -89,6 +89,12 @@ + + + + + + @@ -113,6 +119,7 @@ content: '', catid: '', status: 1, + source_url: '', }, rules: { title: [ -- Gitee From 29e1de67d4ed0ea56017cab99e15fb2a7c016430 Mon Sep 17 00:00:00 2001 From: geewe Date: Sun, 15 Jan 2023 14:40:13 +0800 Subject: [PATCH 08/13] =?UTF-8?q?1=E3=80=81=E7=B3=BB=E7=BB=9F=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E4=BD=BF=E7=94=A8=E7=AE=A1=E7=90=86=E5=90=8E=E5=8F=B0?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=EF=BC=8C=E5=8C=85=E6=8B=AC=E8=AF=84=E8=AE=BA?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=EF=BC=8C=E8=BD=AE=E6=92=AD=E5=9B=BE=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=202=E3=80=81=E5=85=B3=E4=BA=8E=E6=88=91=EF=BC=8C?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E6=95=B0=E6=8D=AE=E5=BA=93=E4=BF=9D=E5=AD=98?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E6=95=B0=E6=8D=AE=203=E3=80=81=E5=88=9B?= =?UTF-8?q?=E5=BB=BAdocker=E9=83=A8=E7=BD=B2=E7=9B=B8=E5=85=B3=E6=96=87?= =?UTF-8?q?=E4=BB=B6=204=E3=80=81=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=94=B9=E4=B8=BAtoml=E6=96=87=E4=BB=B6=EF=BC=8C=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E6=97=A0=E6=B3=95=E9=83=BD=E9=85=8D=E7=BD=AE=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE=E9=A2=98=205?= =?UTF-8?q?=E3=80=81=E4=BF=AE=E6=94=B9blog=E4=B8=BAarticle=EF=BC=8C?= =?UTF-8?q?=E6=98=AF=E7=B3=BB=E7=BB=9F=E6=9B=B4=E4=B8=BA=E9=80=9A=E7=94=A8?= =?UTF-8?q?=EF=BC=88=E5=8F=AF=E4=BB=A5=E4=BD=9C=E4=B8=BA=E5=85=B6=E4=BB=96?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E7=9A=84=E5=BC=80=E5=8F=91=E7=9A=84=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=EF=BC=89=206=E3=80=81=E4=BF=AE=E6=94=B9=E9=83=A8?= =?UTF-8?q?=E5=88=86=E9=A1=B5=E9=9D=A2=E7=9A=84=E6=A0=B7=E5=BC=8F=207?= =?UTF-8?q?=E3=80=81=E6=B7=BB=E5=8A=A0=E5=9B=BE=E7=89=87=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E5=88=B0=E9=98=BF=E9=87=8C=E4=BA=91oss=208=E3=80=81=E5=9B=BE?= =?UTF-8?q?=E5=83=8F=E4=BD=BF=E7=94=A8cravatar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 23 +- README.md | 6 +- app/controller/admin/about.go | 59 +++ app/controller/admin/{blog.go => article.go} | 63 +-- app/controller/admin/category.go | 2 +- app/controller/admin/system.go | 34 +- app/controller/admin/upload.go | 87 +++- app/controller/home/about.go | 3 +- app/controller/home/{blog.go => article.go} | 105 ++--- app/controller/home/category.go | 6 +- app/controller/home/controller.go | 2 +- app/controller/home/index.go | 11 +- app/controller/home/message.go | 6 +- app/model/about.go | 6 + app/model/{blog.go => article.go} | 4 +- app/model/model.go | 3 +- app/model/system.go | 19 + app/model/user.go | 3 +- app/service/about.go | 44 ++ app/service/{blog.go => article.go} | 68 +-- app/service/category.go | 4 +- app/service/system.go | 57 +++ deploy/mysql/init.sql | 445 ++++++++++--------- docker-compose.yaml | 24 +- go.mod | 9 +- go.sum | 378 +++++++++++++++- middleware/cors.go | 18 +- middleware/jwt.go | 2 +- old-Dockerfile | 42 ++ pkg/setting/setting.go | 17 +- pkg/utils/upload.go | 168 +++++++ public/admin/js/admin.js | 4 +- public/common/api/init.json | 14 +- public/common/images/favicon.ico | Bin 67646 -> 67646 bytes public/common/images/favicon1.ico | Bin 0 -> 67646 bytes public/common/js/app.js | 2 +- public/common/js/page.js | 5 +- public/green/css/app.css | 3 +- public/green/images/ico.png | Bin 0 -> 25599 bytes public/home/images/aboutme/me.jpg | Bin 0 -> 38512 bytes public/ico.png | Bin 0 -> 25599 bytes routers/routers.go | 40 +- setting/config.toml | 31 +- test/abc.jpg | Bin 0 -> 38512 bytes test/test_a.go | 52 +++ test/test_b.go | 55 +++ test/test_c.go | 34 ++ views/admin/about/index.html | 79 ++++ views/admin/{blog => article}/edit.html | 16 +- views/admin/{blog => article}/index.html | 20 +- views/admin/{blog => article}/md.html | 10 +- views/admin/auth/login.html | 6 +- views/admin/components/tinymce.html | 21 +- views/admin/index/index.html | 5 +- views/admin/index/welcome.html | 2 +- views/admin/layouts/master.html | 4 +- views/admin/system/setting.html | 129 ++++-- views/defaulted/article/detail.html | 178 ++++++++ views/defaulted/article/index.html | 57 +++ views/defaulted/article/search.html | 14 + views/defaulted/category/index.html | 2 +- views/defaulted/common/_blog_sider.html | 2 +- views/defaulted/layouts/_footer.html | 2 +- views/green/about/index.html | 2 +- views/green/{blog => article}/detail.html | 36 +- views/green/{blog => article}/index.html | 10 +- views/green/{blog => article}/search.html | 0 views/green/category/index.html | 10 +- views/green/common/_blog_sider.html | 12 +- views/green/index/index.html | 10 +- views/green/layouts/_footer.html | 5 +- views/green/layouts/_header.html | 4 +- views/green/layouts/blog-layouts.html | 2 +- views/green/message/index.html | 4 +- views/home/archive/index.html | 2 +- views/home/article/detail.html | 160 +++++++ views/home/article/index.html | 58 +++ views/home/article/search.html | 15 + views/home/category/index.html | 2 +- views/home/common/_blog_sider.html | 6 +- views/home/index/index.html | 4 +- views/home/layouts/_footer.html | 2 +- views/home/layouts/_header.html | 4 +- views/home/message/index.html | 2 +- 84 files changed, 2289 insertions(+), 566 deletions(-) create mode 100644 app/controller/admin/about.go rename app/controller/admin/{blog.go => article.go} (50%) rename app/controller/home/{blog.go => article.go} (46%) create mode 100644 app/model/about.go rename app/model/{blog.go => article.go} (94%) create mode 100644 app/model/system.go create mode 100644 app/service/about.go rename app/service/{blog.go => article.go} (39%) create mode 100644 app/service/system.go create mode 100644 old-Dockerfile create mode 100644 pkg/utils/upload.go create mode 100644 public/common/images/favicon1.ico create mode 100644 public/green/images/ico.png create mode 100644 public/home/images/aboutme/me.jpg create mode 100644 public/ico.png create mode 100644 test/abc.jpg create mode 100644 test/test_a.go create mode 100644 test/test_b.go create mode 100644 test/test_c.go create mode 100644 views/admin/about/index.html rename views/admin/{blog => article}/edit.html (96%) rename views/admin/{blog => article}/index.html (95%) rename views/admin/{blog => article}/md.html (97%) create mode 100644 views/defaulted/article/detail.html create mode 100644 views/defaulted/article/index.html create mode 100644 views/defaulted/article/search.html rename views/green/{blog => article}/detail.html (89%) rename views/green/{blog => article}/index.html (92%) rename views/green/{blog => article}/search.html (100%) create mode 100644 views/home/article/detail.html create mode 100644 views/home/article/index.html create mode 100644 views/home/article/search.html diff --git a/Dockerfile b/Dockerfile index 14f5027..428cab2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,17 +5,14 @@ ENV GO111MODULE=on \ GOOS=linux \ GOARCH=amd64 \ GOPROXY=https://goproxy.cn,direct -# 设置/www,进入容器就会直接进入到这个目录下,而不是进入到默认根目录下面 -ADD . /www # 进入工作目录 -WORKDIR /www +WORKDIR /blog +ADD . . # 复制项目中的 go.mod 和 go.sum文件并下载依赖信息 COPY go.mod . COPY go.sum . RUN go mod tidy -# 将代码复制到容器中 -COPY . . -RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-w -s' -installsuffix 'public' -o ginserver main.go +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-w -s' -installsuffix 'public' -o main . FROM ubuntu:18.04 @@ -29,14 +26,14 @@ EXPOSE 8080 WORKDIR /app # 复制打包的 Go 文件到系统用户可执行程序目录下 -COPY --from=golang /www/ginserver . -COPY --from=golang /www/public ./public -COPY --from=golang /www/config ./config -COPY --from=golang /www/views ./views +COPY --from=golang /blog/main . +COPY --from=golang /blog/public ./public +COPY --from=golang /blog/setting ./setting +COPY --from=golang /blog/views ./views -RUN chown -R root /app/ginserver -RUN chmod +x /app/ginserver +RUN chown -R root /app +RUN chmod +x main # 容器启动时运行的命令 -ENTRYPOINT ["/app/ginserver"] +ENTRYPOINT ["./main"] #CMD ["/app/ginserver"] \ No newline at end of file diff --git a/README.md b/README.md index 59160e8..b6ad1bc 100644 --- a/README.md +++ b/README.md @@ -233,13 +233,13 @@ $ air 前台入口: ``` -http://localhost:4000/ +http://localhost:8080/ ``` 后台入口: ``` -http://localhost:4000/admin/login +http://localhost:8080/admin/login ``` -初始用户名:`admin`,密码:`admin` +初始用户名:`admin`,密码:`admin123$` #### 2.3 `Goland` 的配置 diff --git a/app/controller/admin/about.go b/app/controller/admin/about.go new file mode 100644 index 0000000..a458d40 --- /dev/null +++ b/app/controller/admin/about.go @@ -0,0 +1,59 @@ +package admin + +import ( + "gitee.com/jikey/elk-blog/app/model" + "gitee.com/jikey/elk-blog/app/service" + "gitee.com/jikey/elk-blog/pkg/e" + "gitee.com/jikey/elk-blog/pkg/response" + "github.com/flosch/pongo2" + "github.com/gin-gonic/gin" + "github.com/sirupsen/logrus" + "strconv" +) + +type About struct { + Base +} + +// Index 文章新增、编辑 +func (b *About) Index(c *gin.Context) { + c.HTML(200, "admin/about/index.html", pongo2.Context{ + "title": "Welcome11222!", + "greet": "hello", + "obj": "world", + }) +} + +// Detail 详情 +func (b *About) Detail(c *gin.Context) { + data := make(map[string]interface{}) + + id, _ := strconv.Atoi(c.Query("id")) + data["rows"], _ = service.About.AboutDetail(id) + + response.Success(c, data) +} + +// Update 修改 +func (b *About) Update(c *gin.Context) { + blog := &model.About{} + id_ := c.DefaultPostForm("id", strconv.Itoa(1)) + if err := c.ShouldBind(&blog); err != nil { + c.JSON(400, gin.H{ + "err": err.Error(), + }) + return + } + + //id := strconv.Itoa(id_) + blog.BaseModel.Id, _ = strconv.Atoi(id_) + err := service.About.Update(id_, blog) + + if err != nil { + logrus.Error("修改失败", err) + response.Fail(c, e.ErrorUpdate) + return + } + + response.Success(c, blog) +} diff --git a/app/controller/admin/blog.go b/app/controller/admin/article.go similarity index 50% rename from app/controller/admin/blog.go rename to app/controller/admin/article.go index 2278f54..98a5ac8 100644 --- a/app/controller/admin/blog.go +++ b/app/controller/admin/article.go @@ -6,18 +6,19 @@ import ( "gitee.com/jikey/elk-blog/pkg/e" "gitee.com/jikey/elk-blog/pkg/response" "gitee.com/jikey/elk-blog/pkg/setting" + "gitee.com/jikey/elk-blog/pkg/utils" "github.com/flosch/pongo2" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" "strconv" ) -type Blog struct { +type Article struct { Base } -func (b *Blog) Index(c *gin.Context) { - c.HTML(200, "admin/blog/index.html", pongo2.Context{ +func (b *Article) Index(c *gin.Context) { + c.HTML(200, "admin/Article/index.html", pongo2.Context{ "title": "Welcome11222!", "greet": "hello", "obj": "world", @@ -25,65 +26,65 @@ func (b *Blog) Index(c *gin.Context) { } // List 列表 -func (b *Blog) List(c *gin.Context) { +func (b *Article) List(c *gin.Context) { data := make(map[string]interface{}) - pageNum, _ := strconv.Atoi(c.Query("page")) + pageNum, _ := strconv.Atoi(c.DefaultQuery("page", "1")) title := c.Query("title") maps := "title like '%" + title + "%'" - data["rows"] = service.Blog.BlogList(pageNum, setting.PageSize, maps) - data["total"] = service.Blog.GetBlogTotal(maps) + data["rows"] = service.Article.ArticleList(pageNum, setting.Config.App.PageSize, maps) + data["total"] = service.Article.GetArticleTotal(maps) response.Success(c, data, "列表返回成功了呀!") } // Detail 详情 -func (b *Blog) Detail(c *gin.Context) { +func (b *Article) Detail(c *gin.Context) { data := make(map[string]interface{}) id, _ := strconv.Atoi(c.Param("id")) - data["rows"], _ = service.Blog.BlogDetail(id) + data["rows"], _ = service.Article.ArticleDetail(id) response.Success(c, data) } // Category 种类渲染页面 -func (b *Blog) Category(c *gin.Context) { +func (b *Article) Category(c *gin.Context) { response.HTML(c, "category/index", nil) } // CategoryList 获取列表数据 -func (b *Blog) CategoryList(c *gin.Context) { +func (b *Article) CategoryList(c *gin.Context) { data := make(map[string]interface{}) - data["rows"] = service.Category.GetBlogCategoryList("4") + data["rows"] = service.Category.GetArticleCategoryList("4") response.Success(c, data) } // Edit 文章新增、编辑 -func (b *Blog) Edit(c *gin.Context) { - response.HTML(c, "blog/edit", nil) +func (b *Article) Edit(c *gin.Context) { + response.HTML(c, "Article/edit", nil) } // EditMd markdown文章新增、编辑 -func (b *Blog) EditMd(c *gin.Context) { - response.HTML(c, "blog/md", nil) +func (b *Article) EditMd(c *gin.Context) { + response.HTML(c, "Article/md", nil) } // Insert 新增保存 -func (b *Blog) Insert(c *gin.Context) { - blog := &model.Blog{} +func (b *Article) Insert(c *gin.Context) { + Article := &model.Article{} - if err := c.ShouldBind(&blog); err != nil { + if err := c.ShouldBind(&Article); err != nil { c.JSON(400, gin.H{ "err": err.Error(), }) return } - - err := service.Blog.Create(blog) + Article.Content = utils.RepImages(Article.Content) + err := service.Article.Create(Article) if err != nil { logrus.Error("修改失败", err) @@ -91,22 +92,22 @@ func (b *Blog) Insert(c *gin.Context) { return } - response.Success(c, blog) + response.Success(c, Article) } // Update 修改 -func (b *Blog) Update(c *gin.Context) { - blog := &model.Blog{} +func (b *Article) Update(c *gin.Context) { + Article := &model.Article{} - if err := c.ShouldBind(&blog); err != nil { + if err := c.ShouldBind(&Article); err != nil { c.JSON(400, gin.H{ "err": err.Error(), }) return } - id := strconv.Itoa(blog.Id) - err := service.Blog.Update(id, blog) + id := strconv.Itoa(Article.Id) + err := service.Article.Update(id, Article) if err != nil { logrus.Error("修改失败", err) @@ -114,13 +115,13 @@ func (b *Blog) Update(c *gin.Context) { return } - response.Success(c, blog) + response.Success(c, Article) } -// Destory 删除 -func (b *Blog) Destory(c *gin.Context) { +// Destroy 删除 +func (b *Article) Destroy(c *gin.Context) { id := c.PostForm("id") - service.Blog.Delete(id) + service.Article.Delete(id) response.Success(c, id) } diff --git a/app/controller/admin/category.go b/app/controller/admin/category.go index 23d2dee..1c52254 100644 --- a/app/controller/admin/category.go +++ b/app/controller/admin/category.go @@ -27,7 +27,7 @@ func (cat *Category) Index(c *gin.Context) { func (cat *Category) List(c *gin.Context) { data := make(map[string]interface{}) - data["rows"] = service.Category.GetBlogCategoryList("4") + data["rows"] = service.Category.GetArticleCategoryList("4") response.Success(c, data) } diff --git a/app/controller/admin/system.go b/app/controller/admin/system.go index 4ce8f64..4aebc38 100644 --- a/app/controller/admin/system.go +++ b/app/controller/admin/system.go @@ -1,11 +1,16 @@ package admin import ( + "gitee.com/jikey/elk-blog/app/model" + "gitee.com/jikey/elk-blog/app/service" + "gitee.com/jikey/elk-blog/pkg/e" "gitee.com/jikey/elk-blog/pkg/response" "gitee.com/jikey/elk-blog/pkg/setting" "github.com/gin-gonic/gin" + "github.com/sirupsen/logrus" "github.com/spf13/viper" "log" + "strconv" ) type System struct { @@ -23,14 +28,39 @@ func (s *System) Setting(c *gin.Context) { func (s *System) SettingList(c *gin.Context) { data := make(map[string]interface{}) - setting.SetSite() - data["rows"] = setting.Config.Site + //setting.SetSite() + //data["rows"] = setting.Config.Site + + data["rows"] = service.System.GetSystem(1) response.Success(c, data) } // SettingUpdate 修改系统设置 func (s *System) SettingUpdate(c *gin.Context) { + system := &model.System{} + + if err := c.ShouldBind(&system); err != nil { + c.JSON(400, gin.H{ + "err": err.Error(), + }) + return + } + + systemId := strconv.Itoa(system.Id) + err := service.System.Update(systemId, system) + + if err != nil { + logrus.Error("修改失败: ", err) + response.Fail(c, e.ErrorUpdate) + return + } + + response.Success(c, system) +} + +// SettingUpdate 修改系统设置 +func (s *System) SettingUpdateOld(c *gin.Context) { var siteMap setting.SiteMap if err := c.ShouldBind(&siteMap); err != nil { diff --git a/app/controller/admin/upload.go b/app/controller/admin/upload.go index fc3b8a0..18a124a 100644 --- a/app/controller/admin/upload.go +++ b/app/controller/admin/upload.go @@ -4,16 +4,19 @@ import ( "fmt" "gitee.com/jikey/elk-blog/app/model" "gitee.com/jikey/elk-blog/pkg/response" + "gitee.com/jikey/elk-blog/pkg/setting" "gitee.com/jikey/elk-blog/pkg/utils" "github.com/gin-gonic/gin" "github.com/nleeper/goment" "github.com/sirupsen/logrus" "mime/multipart" + "net/http" "os" "path/filepath" + "time" ) -// UploadImage 上传图片 +// UploadImage 上传图片,可以上传到本地或者上传到oss func UploadImage(c *gin.Context) { file, err := c.FormFile("file") data := make(map[string]interface{}) @@ -22,17 +25,44 @@ func UploadImage(c *gin.Context) { response.Fail(c, 201, "上传图片出错了") return } + filePath := "" + if setting.Config.App.UploadOss { + res, msg := uploadOss(file) + if !res { + response.Fail(c, 201, msg) + return + } + filePath = msg + } else { + filePath, err = uploadLocal(c, file) + if err != nil { + response.Fail(c, 201, "上传图片出错了") + return + } + } + + data["location"] = filePath + + //response.Success(c, data) + c.JSON(http.StatusOK, data) + return +} - // 增加时间文件不易重复,且可追溯 +// renameFileName 重命名文件名 +func renameFileName(file *multipart.FileHeader) string { + return utils.RandomString(16) + filepath.Ext(file.Filename) +} + +func uploadLocal(c *gin.Context, file *multipart.FileHeader) (string, error) { g, _ := goment.New() - dirName := fmt.Sprintf("public/uploads/blog/%s/%s/", g.Format("YYYYMMDD"), model.CurrentUserID(c)) + dirName := fmt.Sprintf("public/uploads/article/%s/%s/", g.Format("YYYYMMDD"), model.CurrentUserID(c)) // 如果没有path文件目录就创建一个 if _, err := os.Stat(dirName); err != nil { if !os.IsExist(err) { err2 := os.MkdirAll(dirName, os.ModePerm) if err2 != nil { - return + return "", err } logrus.Info("创建文件夹:" + dirName) @@ -42,20 +72,49 @@ func UploadImage(c *gin.Context) { filePath := dirName + renameFileName(file) // 上传到指定目录 - err = c.SaveUploadedFile(file, filePath) + err := c.SaveUploadedFile(file, filePath) if err != nil { - response.Fail(c, 201, err.Error()) - return + return "", err + } + return filePath, nil +} + +func uploadOss(file *multipart.FileHeader) (bool, string) { + fileExt := filepath.Ext(file.Filename) + allowExts := []string{".jpg", ".png", ".gif", ".jpeg"} + allowFlag := false + for _, ext := range allowExts { + if ext == fileExt { + allowFlag = true + break + } + } + if !allowFlag { + return false, "不允许的类型" } - data["path"] = filePath + now := time.Now() + //文件存放路径 + //fileDir := fmt.Sprintf("articles/%s", now.Format("200601")) + //fileDir := fmt.Sprintf("article") - response.Success(c, data) - return -} + //文件名称 + timeStamp := now.Unix() + //fileName := fmt.Sprintf("%d%s", timeStamp, fileExt) + // 文件key + //fileKey := filepath.Join(fileDir, fileName) + fileKey := fmt.Sprintf("article/%d%s", timeStamp, fileExt) -// renameFileName 重命名文件名 -func renameFileName(file *multipart.FileHeader) string { - return utils.RandomString(16) + filepath.Ext(file.Filename) + src, err := file.Open() + if err != nil { + return false, "上传失败" + } + defer src.Close() + + res, err := utils.OssUpload(fileKey, src) + if err != nil { + return false, "上传失败" + } + return true, res } diff --git a/app/controller/home/about.go b/app/controller/home/about.go index a3d26d8..8a77c5e 100644 --- a/app/controller/home/about.go +++ b/app/controller/home/about.go @@ -1,6 +1,7 @@ package home import ( + "gitee.com/jikey/elk-blog/app/service" "gitee.com/jikey/elk-blog/pkg/response" "github.com/gin-gonic/gin" ) @@ -11,7 +12,7 @@ type About struct { func (about *About) Index(c *gin.Context) { data := make(map[string]interface{}) - data["site"] = Site + data["site"] = service.System.GetSystem(1) data["active"] = "about" response.Render(c, "about/index", data) diff --git a/app/controller/home/blog.go b/app/controller/home/article.go similarity index 46% rename from app/controller/home/blog.go rename to app/controller/home/article.go index 73c5164..87d6a7c 100644 --- a/app/controller/home/blog.go +++ b/app/controller/home/article.go @@ -13,46 +13,47 @@ import ( "strconv" ) -type Blog struct { +type Article struct { Controller } func init() { - blog := &Blog{} - _ = blog.Init(blog) - blog.Menu() + Article := &Article{} + _ = Article.Init(Article) + Article.Menu() Elk = make(map[interface{}]interface{}) - Elk["Menu"] = blog.Data["Menu"] - Elk["BlogCategory"] = blog.Data["BlogCategory"] - Elk["ArchiveList"] = blog.Data["ArchiveList"] + Elk["Menu"] = Article.Data["Menu"] + Elk["ArticleCategory"] = Article.Data["ArticleCategory"] + Elk["ArchiveList"] = Article.Data["ArchiveList"] } // Index 首页 -func (b *Blog) Index(c *gin.Context) { +func (b *Article) Index(c *gin.Context) { data := make(map[string]interface{}) - pageNum, _ := strconv.Atoi(c.Query("page")) + pageNum, _ := strconv.Atoi(c.DefaultQuery("page", "1")) keywords := c.Query("keywords") - maps := "(tk_blog.status = 1) AND (title like '%" + keywords + "%')" + maps := "(tk_article.status = 1) AND (title like '%" + keywords + "%')" // 获取分页数据 - page := utils.NewPagination(c.Request, service.Blog.GetBlogTotal(maps), setting.PageSize) + page := utils.NewPagination(c.Request, service.Article.GetArticleTotal(maps), setting.Config.App.PageSize) data["page"] = template.HTML(page.Pages()) data["menu"] = Elk["Menu"] - data["blogCategory"] = Elk["BlogCategory"] - data["archiveList"] = service.Blog.BlogArchiveList() - data["list"] = service.Blog.BlogList(pageNum, setting.PageSize, maps) + data["articleCategory"] = Elk["ArticleCategory"] + data["archiveList"] = service.Article.ArticleArchiveList() + data["list"] = service.Article.ArticleList(pageNum, setting.Config.App.PageSize, maps) data["link"] = service.Link.List(1, 100, "") - data["site"] = Site - data["active"] = "blog" + //data["site"] = Site + data["site"] = service.System.GetSystem(1) + data["active"] = "article" - response.Render(c, "blog/index", data) + response.Render(c, "article/index", data) } // Detail 详情 -func (b *Blog) Detail(c *gin.Context) { +func (b *Article) Detail(c *gin.Context) { data := make(map[string]interface{}) id, _ := strconv.Atoi(c.Param("id")) @@ -60,25 +61,25 @@ func (b *Blog) Detail(c *gin.Context) { maps := "bid=" + c.Param("id") - detail, _ := service.Blog.BlogDetail(id) - data["blog"] = detail - data["blogCategory"] = Elk["BlogCategory"] - data["archiveList"] = service.Blog.BlogArchiveList() + detail, _ := service.Article.ArticleDetail(id) + data["article"] = detail + data["articleCategory"] = Elk["ArticleCategory"] + data["archiveList"] = service.Article.ArticleArchiveList() data["commentList"] = service.Comment.List(pageNum, setting.PageSize, maps) data["commentTotal"] = service.Comment.Total(maps) - data["prev"] = service.Blog.GetPrevNextBlog(detail.CreateTime, "prev") - data["next"] = service.Blog.GetPrevNextBlog(detail.CreateTime, "next") + data["prev"] = service.Article.GetPrevNextArticle(detail.CreateTime, "prev") + data["next"] = service.Article.GetPrevNextArticle(detail.CreateTime, "next") data["link"] = service.Link.List(1, 100, "") - data["site"] = Site - data["active"] = "blog" + data["site"] = service.System.GetSystem(1) + data["active"] = "article" - response.Render(c, "blog/detail", data) + response.Render(c, "article/detail", data) } // Archive 归档 -func (b *Blog) Archive(c *gin.Context) { +func (b *Article) Archive(c *gin.Context) { data := make(map[string]interface{}) pageNum, _ := strconv.Atoi(c.Query("page")) @@ -89,18 +90,18 @@ func (b *Blog) Archive(c *gin.Context) { page := utils.NewPagination(c.Request, total, setting.PageSize) data["page"] = template.HTML(page.Pages()) - data["blogCategory"] = Elk["BlogCategory"] - data["archiveList"] = service.Blog.BlogArchiveList() - data["list"] = service.Blog.GetArchive(pageNum, setting.PageSize, id) + data["articleCategory"] = Elk["ArticleCategory"] + data["archiveList"] = service.Article.ArticleArchiveList() + data["list"] = service.Article.GetArchive(pageNum, setting.PageSize, id) data["link"] = service.Link.List(1, 100, "") - data["site"] = Site - data["active"] = "blog" + data["site"] = service.System.GetSystem(1) + data["active"] = "article" response.Render(c, "archive/index", data) } // Category 分类 -func (b *Blog) Category(c *gin.Context) { +func (b *Article) Category(c *gin.Context) { data := make(map[string]interface{}) maps := make(map[string]interface{}) @@ -110,21 +111,21 @@ func (b *Blog) Category(c *gin.Context) { maps["catid"] = id // 获取分页数据 - page := utils.NewPagination(c.Request, service.Blog.GetBlogTotal(maps), setting.PageSize) + page := utils.NewPagination(c.Request, service.Article.GetArticleTotal(maps), setting.PageSize) data["page"] = template.HTML(page.Pages()) - data["blogCategory"] = Elk["BlogCategory"] - data["archiveList"] = service.Blog.BlogArchiveList() - data["list"] = service.Blog.BlogList(pageNum, setting.PageSize, maps) + data["articleCategory"] = Elk["ArticleCategory"] + data["archiveList"] = service.Article.ArticleArchiveList() + data["list"] = service.Article.ArticleList(pageNum, setting.PageSize, maps) data["link"] = service.Link.List(1, 100, "") - data["site"] = Site - data["active"] = "blog" + data["site"] = service.System.GetSystem(1) + data["active"] = "article" response.Render(c, "category/index", data) } // Search 搜索 -func (b *Blog) Search(c *gin.Context) { +func (b *Article) Search(c *gin.Context) { data := make(map[string]interface{}) maps := make(map[string]interface{}) @@ -143,31 +144,31 @@ func (b *Blog) Search(c *gin.Context) { maps["title"] = keywords // 获取分页数据 - page := utils.NewPagination(c.Request, service.Blog.GetBlogTotal(maps), setting.PageSize) + page := utils.NewPagination(c.Request, service.Article.GetArticleTotal(maps), setting.PageSize) data["page"] = template.HTML(page.Pages()) - data["list"] = service.Blog.BlogList(pageNum, setting.PageSize, maps) - data["site"] = Site - data["active"] = "blog" + data["list"] = service.Article.ArticleList(pageNum, setting.PageSize, maps) + data["site"] = service.System.GetSystem(1) + data["active"] = "article" - response.Render(c, "blog/search", data) + response.Render(c, "article/search", data) } // Likes 点赞 -func (b *Blog) Likes(c *gin.Context) { +func (b *Article) Likes(c *gin.Context) { id := c.Param("id") - blog := &model.Blog{} + Article := &model.Article{} - if err := c.ShouldBind(&blog); err != nil { + if err := c.ShouldBind(&Article); err != nil { c.JSON(400, gin.H{ "err": err.Error(), }) return } - fmt.Println("blog", blog.Likes) + fmt.Println("Article", Article.Likes) - service.Blog.UpdateField(id, "likes", blog.Likes) + service.Article.UpdateField(id, "likes", Article.Likes) - response.Success(c, blog.Likes) + response.Success(c, Article.Likes) } diff --git a/app/controller/home/category.go b/app/controller/home/category.go index 6d7ced6..20b6ba1 100644 --- a/app/controller/home/category.go +++ b/app/controller/home/category.go @@ -13,9 +13,9 @@ type Category struct { func (category *Category) Index(c *gin.Context) { data := make(map[string]interface{}) - data["list"] = service.Blog.BlogList(1, 10, nil) + data["list"] = service.Article.ArticleList(1, 10, nil) data["link"] = service.Link.List(1, 100, "") - data["site"] = Site + data["site"] = service.System.GetSystem(1) - response.Render(c, "blog/index", data) + response.Render(c, "article/index", data) } diff --git a/app/controller/home/controller.go b/app/controller/home/controller.go index dd226ed..9dc4bc8 100644 --- a/app/controller/home/controller.go +++ b/app/controller/home/controller.go @@ -50,5 +50,5 @@ func (ctrl *Controller) afterAction(context *gin.Context) error { func (ctrl *Controller) Menu() { ctrl.Data["Menu"] = "menu" - ctrl.Data["BlogCategory"] = service.Category.GetBlogCategoryList("4") + ctrl.Data["ArticleCategory"] = service.Category.GetArticleCategoryList("4") } diff --git a/app/controller/home/index.go b/app/controller/home/index.go index 4a164bc..323dfd5 100644 --- a/app/controller/home/index.go +++ b/app/controller/home/index.go @@ -21,20 +21,21 @@ func init() { index.Menu() Elk = make(map[interface{}]interface{}) Elk["Menu"] = index.Data["Menu"] - Elk["BlogCategory"] = index.Data["BlogCategory"] + Elk["ArticleCategory"] = index.Data["ArticleCategory"] } func (index *Index) Index(c *gin.Context) { data := make(map[string]interface{}) - data["site"] = Site + data["site"] = service.System.GetSystem(1) + //data["site"] = Site data["active"] = "index" data["advs"] = service.Banner.List("") data["link"] = service.Link.List(1, 100, "") - data["archiveList"] = service.Blog.BlogArchiveList() - data["blogList"] = service.Blog.BlogList(1, 10, "tk_blog.status = 1") + data["archiveList"] = service.Article.ArticleArchiveList() + data["articleList"] = service.Article.ArticleList(1, 10, "tk_article.status = 1") data["menu"] = index.Data["Menu"] - data["blogCategory"] = Elk["BlogCategory"] + data["articleCategory"] = Elk["ArticleCategory"] data["time"] = utils.GetTime() response.Render(c, "index/index", data) diff --git a/app/controller/home/message.go b/app/controller/home/message.go index 8d148b6..9ef6abd 100644 --- a/app/controller/home/message.go +++ b/app/controller/home/message.go @@ -28,9 +28,9 @@ func (message *Message) Index(c *gin.Context) { data["page"] = template.HTML(page.Pages()) data["list"] = service.Message.List(pageNum, 3000, maps) data["link"] = service.Link.List(1, 100, "") - data["archiveList"] = service.Blog.BlogArchiveList() - data["blogCategory"] = Elk["BlogCategory"] - data["site"] = Site + data["archiveList"] = service.Article.ArticleArchiveList() + data["articleCategory"] = Elk["ArticleCategory"] + data["site"] = service.System.GetSystem(1) data["active"] = "message" response.Render(c, "message/index", data) diff --git a/app/model/about.go b/app/model/about.go new file mode 100644 index 0000000..bbb0011 --- /dev/null +++ b/app/model/about.go @@ -0,0 +1,6 @@ +package model + +type About struct { + BaseModel + Content string `gorm:"column:content" json:"content" form:"content"` +} diff --git a/app/model/blog.go b/app/model/article.go similarity index 94% rename from app/model/blog.go rename to app/model/article.go index 88d2f02..d8252e7 100644 --- a/app/model/blog.go +++ b/app/model/article.go @@ -4,7 +4,7 @@ import ( "errors" ) -type Blog struct { +type Article struct { BaseModel Category Category `gorm:"foreignkey:Catid"` Title string `gorm:"column:title" json:"title" form:"title"` @@ -23,7 +23,7 @@ type Blog struct { ColTitle string `gorm:"column:colTitle" json:"colTitle"` } -func (b *Blog) IsValid() (err error) { +func (b *Article) IsValid() (err error) { if b.Title == "" { err = errors.New("标题不能为空") } diff --git a/app/model/model.go b/app/model/model.go index 7fd76f7..b448132 100644 --- a/app/model/model.go +++ b/app/model/model.go @@ -15,8 +15,7 @@ import ( var Mysql *gorm.DB type BaseModel struct { - Id int `gorm:"primary_key;autoIncrement;column:id" json:"id,omitempty"` - DeletedOn int `json:"deleted_on"` + Id int `gorm:"primary_key;autoIncrement;column:id" json:"id,omitempty" form:"id"` CreateTime string `gorm:"column:create_time" json:"create_time,omitempty" form:"create_time"` UpdateTime string `gorm:"column:update_time" json:"update_time,omitempty" form:"update_time"` } diff --git a/app/model/system.go b/app/model/system.go new file mode 100644 index 0000000..19f58a1 --- /dev/null +++ b/app/model/system.go @@ -0,0 +1,19 @@ +package model + +type System struct { + BaseModel + Domain string `gorm:"column:domain" json:"domain" form:"domain"` + SiteName string `gorm:"column:site_name" json:"site_name" form:"site_name"` + Description string `gorm:"column:description" json:"description" form:"description"` + Keyword string `gorm:"column:keyword" json:"keyword" form:"keyword"` + Email string `gorm:"column:email" json:"email" form:"email"` + Contact string `gorm:"column:contact" json:"contact" form:"contact"` + Company string `gorm:"column:company" json:"company" form:"company"` + Record string `gorm:"column:record" json:"record" form:"record"` + Phone string `gorm:"column:phone" json:"phone" form:"phone"` + Icp string `gorm:"column:icp" json:"icp" form:"icp"` + Address string `gorm:"column:address" json:"address" form:"address"` + Tpl string `gorm:"column:tpl" json:"tpl" form:"tpl"` + AllowComment bool `gorm:"column:allow_comment" json:"allow_comment" form:"allow_comment"` + ShowBanner bool `gorm:"column:show_banner" json:"show_banner" form:"show_banner"` +} diff --git a/app/model/user.go b/app/model/user.go index e5376cd..a6e96ee 100644 --- a/app/model/user.go +++ b/app/model/user.go @@ -26,7 +26,8 @@ type User struct { Address string `gorm:"column:address;type:varchar(255)" json:"address"` } -/** +/* +* 校验用户名 */ func (u *User) checkName() (err error) { diff --git a/app/service/about.go b/app/service/about.go new file mode 100644 index 0000000..0965b8e --- /dev/null +++ b/app/service/about.go @@ -0,0 +1,44 @@ +package service + +import ( + "gitee.com/jikey/elk-blog/app/model" + db "gitee.com/jikey/elk-blog/app/model" +) + +type about struct { +} + +var About *about + +// GetBy 查询 +func (b *about) GetBy(field, value string) (blog []model.About) { + db.Mysql.Where("? = ?", field, value).First(&blog) + return +} + +// AboutDetail 获取 about 详情 +func (b *about) AboutDetail(id int) (mblog model.About, err error) { + err = db.Mysql.First(&mblog, id).Error + db.Mysql.Model(&mblog).Where("id = ?", id) + return +} + +// Create 新增 +func (b *about) Create(model *model.About) (err error) { + err = db.Mysql.Omit("ColTitle").Create(model).Error + + return err +} + +// Update 修改 +func (b *about) Update(id string, model *model.About) (err error) { + err = db.Mysql.Model(&model).Where("id = ? ", id).Updates(model).Error + + return err +} + +// UpdateField 修改某一字段 +func (b *about) UpdateField(id string, key string, value interface{}) { + mBlog := &model.About{} + db.Mysql.Model(&mBlog).Where("id = ?", id).Update(key, value) +} diff --git a/app/service/blog.go b/app/service/article.go similarity index 39% rename from app/service/blog.go rename to app/service/article.go index b6df516..432b0d0 100644 --- a/app/service/blog.go +++ b/app/service/article.go @@ -8,87 +8,87 @@ import ( "github.com/spf13/cast" ) -type blog struct { +type article struct { } -var Blog *blog +var Article *article -// BlogList 获取 blog 列表 -func (b *blog) BlogList(PageNum int, PageSize int, maps interface{}) (blog []model.Blog) { - condition := "left join tk_category on tk_category.colId = tk_blog.catid" - db.Mysql.Where(maps).Offset((PageNum - 1) * PageSize).Limit(PageSize).Order("ord asc, id desc").Select("tk_blog.*, tk_category.colTitle").Joins(condition).Find(&blog) +// ArticleList 获取 article 列表 +func (b *article) ArticleList(PageNum int, PageSize int, maps interface{}) (article []model.Article) { + condition := "left join tk_category on tk_category.colId = tk_article.catid" + db.Mysql.Where(maps).Offset((PageNum - 1) * PageSize).Limit(PageSize).Order("ord asc, id desc").Select("tk_article.*, tk_category.colTitle").Joins(condition).Find(&article) return } // GetBy 查询 -func (b *blog) GetBy(field, value string) (blog []model.Blog) { - db.Mysql.Where("? = ?", field, value).First(&blog) +func (b *article) GetBy(field, value string) (article []model.Article) { + db.Mysql.Where("? = ?", field, value).First(&article) return } // GetArchiveList 获取归档列表 -func (b *blog) GetArchiveList(PageNum int, PageSize int, maps interface{}) (blog []model.Blog) { - db.Mysql.Where(maps).Offset((PageNum - 1) * PageSize).Limit(PageSize).Order("ord asc, id desc").Find(&blog) +func (b *article) GetArchiveList(PageNum int, PageSize int, maps interface{}) (article []model.Article) { + db.Mysql.Where(maps).Offset((PageNum - 1) * PageSize).Limit(PageSize).Order("ord asc, id desc").Find(&article) return } -// BlogDetail 获取 blog 详情 -func (b *blog) BlogDetail(id int) (mblog model.Blog, err error) { - err = db.Mysql.First(&mblog, id).Error - db.Mysql.Model(&mblog).Where("id = ?", id).UpdateColumn("views", gorm.Expr("views + ?", 1)) +// ArticleDetail 获取 article 详情 +func (b *article) ArticleDetail(id int) (marticle model.Article, err error) { + err = db.Mysql.First(&marticle, id).Error + db.Mysql.Model(&marticle).Where("id = ?", id).UpdateColumn("views", gorm.Expr("views + ?", 1)) return } -// GetBlogTotal 获取 blog 总记录数 -func (b *blog) GetBlogTotal(maps interface{}) (count int) { - db.Mysql.Model(&blog{}).Where(maps).Count(&count) +// GetArticleTotal 获取 article 总记录数 +func (b *article) GetArticleTotal(maps interface{}) (count int) { + db.Mysql.Model(&article{}).Where(maps).Count(&count) return } // Create 新增 -func (b *blog) Create(model *model.Blog) (err error) { +func (b *article) Create(model *model.Article) (err error) { err = db.Mysql.Omit("ColTitle").Create(model).Error return err } // Update 修改 -func (b *blog) Update(id string, model *model.Blog) (err error) { +func (b *article) Update(id string, model *model.Article) (err error) { err = db.Mysql.Model(&model).Where("id = ? ", id).Omit("ColTitle").Updates(model).Error return err } // UpdateField 修改某一字段 -func (b *blog) UpdateField(id string, key string, value interface{}) { - mBlog := &model.Blog{} - db.Mysql.Model(&mBlog).Where("id = ?", id).Update(key, value) +func (b *article) UpdateField(id string, key string, value interface{}) { + marticle := &model.Article{} + db.Mysql.Model(&marticle).Where("id = ?", id).Update(key, value) } // Delete 删除 -func (b *blog) Delete(id string) bool { - db.Mysql.Where("id = ?", id).Delete(&blog{}) +func (b *article) Delete(id string) bool { + db.Mysql.Where("id = ?", id).Delete(&article{}) return true } -// BlogArchiveList 归档列表 -func (b *blog) BlogArchiveList() (archive []model.Archive) { - sql := "select count(DATE_FORMAT(create_time, '%Y-%m')) as Count, DATE_FORMAT(create_time, '%Y-%m') as Time, create_time as CreateTime from tk_blog group by Time order by Time desc" +// ArticleArchiveList 归档列表 +func (b *article) ArticleArchiveList() (archive []model.Archive) { + sql := "select count(DATE_FORMAT(create_time, '%Y-%m')) as Count, DATE_FORMAT(create_time, '%Y-%m') as Time, create_time as CreateTime from tk_article group by Time order by Time desc" db.Mysql.Raw(sql).Scan(&archive) return } // GetArchive 归档列表 -func (b *blog) GetArchive(PageNum int, PageSize int, ctime string) (blog []model.Blog) { - db.Mysql.Where("create_time like ?", "%"+ctime+"%").Offset((PageNum - 1) * PageSize).Limit(PageSize).Order("ord asc, id desc").Find(&blog) +func (b *article) GetArchive(PageNum int, PageSize int, ctime string) (article []model.Article) { + db.Mysql.Where("create_time like ?", "%"+ctime+"%").Offset((PageNum - 1) * PageSize).Limit(PageSize).Order("ord asc, id desc").Find(&article) return } -// GetPrevNextBlog 获取上一篇下一篇 -func (b *blog) GetPrevNextBlog(ctime string, dir string) (link string) { - blog := &model.Blog{} +// GetPrevNextArticle 获取上一篇下一篇 +func (b *article) GetPrevNextArticle(ctime string, dir string) (link string) { + article := &model.Article{} var maps, order string if dir == "prev" { @@ -101,9 +101,9 @@ func (b *blog) GetPrevNextBlog(ctime string, dir string) (link string) { order = "desc" } - db.Mysql.Where(maps).Order("ord asc,create_time " + order).First(&blog) + db.Mysql.Where(maps).Order("ord asc,create_time " + order).First(&article) - link = fmt.Sprintf("%s", cast.ToString(blog.Id), blog.Title) + link = fmt.Sprintf("%s", cast.ToString(article.Id), article.Title) return } diff --git a/app/service/category.go b/app/service/category.go index d1ebb6e..f90272e 100644 --- a/app/service/category.go +++ b/app/service/category.go @@ -10,8 +10,8 @@ type category struct { var Category *category -// GetBlogCategoryList 获取 Blog 分类列表 -func (c *category) GetBlogCategoryList(modelId string) (category []*model.Category) { +// GetArticleCategoryList 获取 Article 分类列表 +func (c *category) GetArticleCategoryList(modelId string) (category []*model.Category) { // var Total []int db.Mysql.Select("concat(colPath,'-', colId) as bPath, colPid, colId, colTitle, description, ord, model, modelid").Where("modelid = ?", modelId).Order("ord ASC").Find(&category) diff --git a/app/service/system.go b/app/service/system.go new file mode 100644 index 0000000..18c657b --- /dev/null +++ b/app/service/system.go @@ -0,0 +1,57 @@ +package service + +import ( + "encoding/json" + "gitee.com/jikey/elk-blog/app/model" + db "gitee.com/jikey/elk-blog/app/model" +) + +type system struct { +} + +var System *system + +// GetSystemList 获取 Article 分类列表 +func (c *system) GetSystemList(systemId int) (systems []*model.System) { + // var Total []int + + db.Mysql.Select("*").Where("id = ? ", systemId).Order("id ASC").Find(&systems) + // db.Mysql.Model(&category).Select("count(*) as Total").Pluck("Total", &Total) + + return +} + +// GetSystem 获取 System +func (c *system) GetSystem(systemId int) (system model.System) { + // var Total []int + + db.Mysql.Where("id = ? ", systemId).First(&system) + // db.Mysql.Model(&category).Select("count(*) as Total").Pluck("Total", &Total) + + return +} + +// Create 新增 +func (c *system) Create(model *model.System) (err error) { + err = db.Mysql.Create(model).Error + + return err +} + +// Update 修改 +func (c *system) Update(systemId string, model *model.System) (err error) { + data, _ := json.Marshal(&model) + m := make(map[string]interface{}) + json.Unmarshal(data, &m) + // 使用map更新含0值字段,使用struct无法更新 + err = db.Mysql.Model(&model).Where("Id = ? ", systemId).Updates(m).Error + + return err +} + +// Delete 删除 +func (c *system) Delete(id int) (rowsAffected int64) { + result := db.Mysql.Where("Id = ?", id).Delete(&system{}) + + return result.RowsAffected +} diff --git a/deploy/mysql/init.sql b/deploy/mysql/init.sql index 7c543de..7f8e642 100644 --- a/deploy/mysql/init.sql +++ b/deploy/mysql/init.sql @@ -1,282 +1,315 @@ -create database `elk-blog` default character set utf8mb4 collate utf8mb4_general_ci if not exists `elk-blog`; +create database `elk-blog` default character set utf8mb4 collate utf8mb4_general_ci if not exists `juzizhou`; GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION; flush privileges; -use elk-blog; +use juzizhou; -SET FOREIGN_KEY_CHECKS=0; +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for tk_about -- ---------------------------- DROP TABLE IF EXISTS `tk_about`; -CREATE TABLE `tk_about` ( - `id` int(10) NOT NULL, - `content` text, - `status` tinyint(1) DEFAULT '1', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; +CREATE TABLE `tk_about` ( + `id` int(10) NOT NULL, + `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, + `status` tinyint(1) NULL DEFAULT 1, + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_time` datetime(0) NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = MyISAM CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for tk_article +-- ---------------------------- +DROP TABLE IF EXISTS `tk_article`; +CREATE TABLE `tk_article` ( + `id` smallint(5) UNSIGNED NOT NULL AUTO_INCREMENT, + `catid` smallint(5) UNSIGNED NULL DEFAULT NULL, + `title` varchar(80) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, + `md` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, + `keywords` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `smallimg` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `ctime` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `username` char(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `author` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `listorder` smallint(5) UNSIGNED NULL DEFAULT 0, + `posid` tinyint(4) NOT NULL DEFAULT 0, + `ord` tinyint(3) NULL DEFAULT NULL, + `views` int(10) NULL DEFAULT NULL COMMENT '浏览量', + `likes` int(10) NULL DEFAULT NULL COMMENT '点赞', + `source_url` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `avatar` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `status` tinyint(4) NULL DEFAULT 0, + `create_time` datetime(0) NULL DEFAULT NULL, + `update_time` datetime(0) NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = MyISAM AUTO_INCREMENT = 103 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for tk_banner -- ---------------------------- DROP TABLE IF EXISTS `tk_banner`; -CREATE TABLE `tk_banner` ( - `id` int(8) unsigned NOT NULL AUTO_INCREMENT, - `modelId` int(10) NOT NULL, - `smallimg` varchar(100) NOT NULL, - `title` varchar(100) NOT NULL, - `link` varchar(100) NOT NULL, - `ord` int(8) DEFAULT NULL, - `status` tinyint(1) DEFAULT '1', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=40 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC; - --- ---------------------------- --- Table structure for tk_blog --- ---------------------------- -DROP TABLE IF EXISTS `tk_blog`; -CREATE TABLE `tk_blog` ( - `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, - `catid` smallint(5) unsigned DEFAULT NULL, - `title` varchar(80) DEFAULT NULL, - `content` text, - `md` text, - `keywords` varchar(100) DEFAULT NULL, - `smallimg` varchar(100) DEFAULT NULL, - `description` varchar(200) DEFAULT NULL, - `ctime` varchar(30) DEFAULT NULL, - `username` char(20) DEFAULT NULL, - `author` varchar(30) DEFAULT NULL, - `listorder` smallint(5) unsigned DEFAULT '0', - `posid` tinyint(4) NOT NULL DEFAULT '0', - `ord` tinyint(3) DEFAULT NULL, - `views` int(10) DEFAULT NULL COMMENT '浏览量', - `likes` int(10) DEFAULT NULL COMMENT '点赞', - `source_url` varchar(200) DEFAULT NULL, - `status` tinyint(4) DEFAULT '0', - `create_time` datetime DEFAULT NULL, - `update_time` datetime DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=103 DEFAULT CHARSET=utf8mb4; +CREATE TABLE `tk_banner` ( + `id` int(8) UNSIGNED NOT NULL AUTO_INCREMENT, + `modelId` int(10) NOT NULL, + `smallimg` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `link` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `ord` int(8) NULL DEFAULT NULL, + `status` tinyint(1) NULL DEFAULT 1, + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_time` datetime(0) NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = MyISAM AUTO_INCREMENT = 40 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for tk_category -- ---------------------------- DROP TABLE IF EXISTS `tk_category`; -CREATE TABLE `tk_category` ( - `colId` smallint(5) unsigned NOT NULL AUTO_INCREMENT, - `colPid` smallint(5) NOT NULL, - `typeid` smallint(3) NOT NULL DEFAULT '0', - `modelid` smallint(5) NOT NULL, - `model` varchar(20) NOT NULL, - `picId` smallint(5) DEFAULT NULL, - `colPath` varchar(100) NOT NULL, - `colTitle` varchar(100) NOT NULL, - `thumb` varchar(150) DEFAULT NULL, - `asmenu` tinyint(1) DEFAULT NULL, - `description` varchar(200) NOT NULL, - `status` tinyint(2) DEFAULT NULL, - `ord` smallint(3) DEFAULT NULL, - PRIMARY KEY (`colId`) -) ENGINE=MyISAM AUTO_INCREMENT=204 DEFAULT CHARSET=utf8mb4; +CREATE TABLE `tk_category` ( + `colId` smallint(5) UNSIGNED NOT NULL AUTO_INCREMENT, + `colPid` smallint(5) NOT NULL, + `typeid` smallint(3) NOT NULL DEFAULT 0, + `modelid` smallint(5) NOT NULL, + `model` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `picId` smallint(5) NULL DEFAULT NULL, + `colPath` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `colTitle` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `thumb` varchar(150) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `asmenu` tinyint(1) NULL DEFAULT NULL, + `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `status` tinyint(2) NULL DEFAULT NULL, + `ord` smallint(3) NULL DEFAULT NULL, + PRIMARY KEY (`colId`) USING BTREE +) ENGINE = MyISAM AUTO_INCREMENT = 204 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of tk_category -- ---------------------------- -INSERT INTO `tk_category` VALUES ('1', '0', '0', '1', 'Design', '0', '0', 'Design', '', '1', '设计1', '1', '0'); -INSERT INTO `tk_category` VALUES ('2', '0', '0', '2', 'About', '0', '0', 'About', '', '1', '关于我们', '1', '0'); -INSERT INTO `tk_category` VALUES ('3', '0', '0', '3', 'Contact', '0', '0', 'Contact', '', '1', '联系我', '1', '0'); -INSERT INTO `tk_category` VALUES ('4', '0', '0', '4', 'Blog', '0', '0', 'Blog', '', '1', '博客', '1', '0'); -INSERT INTO `tk_category` VALUES ('5', '1', '0', '1', 'Design', '0', '0-1', 'GUI444', '', '0', '

ios android

', '1', '1'); -INSERT INTO `tk_category` VALUES ('6', '1', '0', '1', 'Design', '0', '0-1', 'WEB', '', '0', 'WEB', '1', '4'); -INSERT INTO `tk_category` VALUES ('7', '1', '0', '1', 'Design', '0', '0-1', 'PAINT', '', '0', 'PAINT', '1', '3'); -INSERT INTO `tk_category` VALUES ('17', '4', '0', '4', 'Blog', '0', '0-4', '轻慢摄影', '', '0', '轻慢摄影', '0', '0'); -INSERT INTO `tk_category` VALUES ('14', '4', '0', '4', 'Blog', '0', '0-4', '快乐绘画', '', '0', '快乐绘画', '0', '0'); -INSERT INTO `tk_category` VALUES ('15', '4', '0', '4', 'Blog', '0', '0-4', '收藏点滴', '', '0', '收藏点滴', '0', '0'); -INSERT INTO `tk_category` VALUES ('18', '1', '0', '1', 'Design', '0', '0-1', 'App', '', '0', '', '0', '2'); -INSERT INTO `tk_category` VALUES ('184', '1', '0', '1', 'Design', '0', '0-1', 'logo', '', '0', '', '0', '5'); -INSERT INTO `tk_category` VALUES ('185', '4', '0', '4', 'Blog', '0', '0-4', '设计理论', '', '0', '设计理论', '0', '0'); -INSERT INTO `tk_category` VALUES ('188', '4', '0', '4', 'Blog', null, '0-4', '好看风云', null, null, '好看风云', null, '6'); - +INSERT INTO `tk_category` VALUES (1, 0, 0, 1, 'Design', 0, '0', 'Design', '', 1, '设计1', 1, 0); +INSERT INTO `tk_category` VALUES (2, 0, 0, 2, 'About', 0, '0', 'About', '', 1, '关于我们', 1, 0); +INSERT INTO `tk_category` VALUES (3, 0, 0, 3, 'Contact', 0, '0', 'Contact', '', 1, '联系我', 1, 0); +INSERT INTO `tk_category` VALUES (4, 0, 0, 4, 'Blog', 0, '0', 'Blog', '', 1, '博客', 1, 0); +INSERT INTO `tk_category` VALUES (5, 1, 0, 1, 'Design', 0, '0-1', 'GUI444', '', 0, '

ios android

', 1, 1); +INSERT INTO `tk_category` VALUES (6, 1, 0, 1, 'Design', 0, '0-1', 'WEB', '', 0, 'WEB', 1, 4); +INSERT INTO `tk_category` VALUES (7, 1, 0, 1, 'Design', 0, '0-1', 'PAINT', '', 0, 'PAINT', 1, 3); +INSERT INTO `tk_category` VALUES (17, 4, 0, 4, 'Blog', 0, '0-4', '轻慢摄影', '', 0, '轻慢摄影', 0, 0); +INSERT INTO `tk_category` VALUES (14, 4, 0, 4, 'Blog', 0, '0-4', '快乐绘画', '', 0, '快乐绘画', 0, 0); +INSERT INTO `tk_category` VALUES (15, 4, 0, 4, 'Blog', 0, '0-4', '收藏点滴', '', 0, '收藏点滴', 0, 0); +INSERT INTO `tk_category` VALUES (18, 1, 0, 1, 'Design', 0, '0-1', 'App', '', 0, '', 0, 2); +INSERT INTO `tk_category` VALUES (184, 1, 0, 1, 'Design', 0, '0-1', 'logo', '', 0, '', 0, 5); +INSERT INTO `tk_category` VALUES (185, 4, 0, 4, 'Blog', 0, '0-4', '设计理论', '', 0, '设计理论', 0, 0); +INSERT INTO `tk_category` VALUES (188, 4, 0, 4, 'Blog', NULL, '0-4', '好看风云', NULL, NULL, '好看风云', NULL, 6); -- ---------------------------- -- Table structure for tk_comment -- ---------------------------- DROP TABLE IF EXISTS `tk_comment`; -CREATE TABLE `tk_comment` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `pid` int(10) DEFAULT NULL, - `path` varchar(100) DEFAULT NULL, - `username` varchar(40) DEFAULT NULL, - `nid` mediumint(8) unsigned DEFAULT NULL, - `bid` mediumint(8) unsigned DEFAULT NULL, - `email` varchar(50) DEFAULT NULL, - `author` varchar(40) DEFAULT NULL, - `module` varchar(20) DEFAULT NULL, - `headimg` varchar(250) DEFAULT NULL, - `url` varchar(200) DEFAULT NULL, - `ip` varchar(15) DEFAULT NULL, - `verify` varchar(32) DEFAULT NULL, - `content` text, - `isreply` tinyint(1) DEFAULT '0', - `ord` tinyint(5) DEFAULT NULL, - `status` tinyint(1) DEFAULT '1', - `create_time` datetime DEFAULT NULL, - `update_time` datetime DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=119 DEFAULT CHARSET=utf8mb4; +CREATE TABLE `tk_comment` ( + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `pid` int(10) NULL DEFAULT NULL, + `path` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `username` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `nid` mediumint(8) UNSIGNED NULL DEFAULT NULL, + `bid` mediumint(8) UNSIGNED NULL DEFAULT NULL, + `email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `author` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `module` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `headimg` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `url` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `ip` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `verify` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, + `isreply` tinyint(1) NULL DEFAULT 0, + `ord` tinyint(5) NULL DEFAULT NULL, + `status` tinyint(1) NULL DEFAULT 1, + `create_time` datetime(0) NULL DEFAULT NULL, + `update_time` datetime(0) NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = MyISAM AUTO_INCREMENT = 119 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for tk_contact -- ---------------------------- DROP TABLE IF EXISTS `tk_contact`; -CREATE TABLE `tk_contact` ( - `id` int(10) NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; +CREATE TABLE `tk_contact` ( + `id` int(10) NOT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = MyISAM CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Fixed; -- ---------------------------- -- Table structure for tk_design -- ---------------------------- DROP TABLE IF EXISTS `tk_design`; -CREATE TABLE `tk_design` ( - `id` int(8) unsigned NOT NULL AUTO_INCREMENT, - `colId` smallint(5) NOT NULL, - `title` varchar(80) NOT NULL COMMENT '标题', - `content` text NOT NULL COMMENT '内容', - `smallimg` varchar(100) NOT NULL, - `ctime` varchar(30) NOT NULL COMMENT '创建时间', - `commentnum` int(10) NOT NULL DEFAULT '1' COMMENT '评论数量', - `status` tinyint(1) NOT NULL DEFAULT '1', - `likes` int(10) NOT NULL DEFAULT '1' COMMENT '喜欢数量', - `author` varchar(30) NOT NULL, - `inputtime` int(30) NOT NULL, - `posid` tinyint(2) NOT NULL DEFAULT '0', - `ord` int(10) unsigned NOT NULL DEFAULT '0', - PRIMARY KEY (`id`,`author`) -) ENGINE=MyISAM AUTO_INCREMENT=61 DEFAULT CHARSET=utf8mb4; +CREATE TABLE `tk_design` ( + `id` int(8) UNSIGNED NOT NULL AUTO_INCREMENT, + `colId` smallint(5) NOT NULL, + `title` varchar(80) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '标题', + `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '内容', + `smallimg` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `ctime` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '创建时间', + `commentnum` int(10) NOT NULL DEFAULT 1 COMMENT '评论数量', + `status` tinyint(1) NOT NULL DEFAULT 1, + `likes` int(10) NOT NULL DEFAULT 1 COMMENT '喜欢数量', + `author` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `inputtime` int(30) NOT NULL, + `posid` tinyint(2) NOT NULL DEFAULT 0, + `ord` int(10) UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`id`, `author`) USING BTREE +) ENGINE = MyISAM AUTO_INCREMENT = 61 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for tk_link -- ---------------------------- DROP TABLE IF EXISTS `tk_link`; -CREATE TABLE `tk_link` ( - `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, - `linktype` tinyint(1) DEFAULT NULL, - `title` varchar(50) DEFAULT NULL, - `url` varchar(255) DEFAULT NULL, - `logo` varchar(255) DEFAULT NULL, - `status` tinyint(1) DEFAULT '1', - `ord` tinyint(5) DEFAULT '0', - `introduce` text, - `contact` varchar(30) DEFAULT NULL, - `create_time` datetime DEFAULT NULL, - `update_time` datetime DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb4; +CREATE TABLE `tk_link` ( + `id` smallint(5) UNSIGNED NOT NULL AUTO_INCREMENT, + `linktype` tinyint(1) NULL DEFAULT NULL, + `title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `logo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `status` tinyint(1) NULL DEFAULT 1, + `ord` tinyint(5) NULL DEFAULT 0, + `introduce` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, + `contact` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `create_time` datetime(0) NULL DEFAULT NULL, + `update_time` datetime(0) NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = MyISAM AUTO_INCREMENT = 26 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for tk_message -- ---------------------------- DROP TABLE IF EXISTS `tk_message`; -CREATE TABLE `tk_message` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `pid` int(10) DEFAULT NULL, - `email` varchar(50) DEFAULT NULL, - `path` varchar(100) DEFAULT NULL, - `username` varchar(30) DEFAULT NULL, - `ip` varchar(15) DEFAULT NULL, - `headimg` varchar(250) DEFAULT NULL, - `url` varchar(200) DEFAULT NULL, - `content` text NOT NULL, - `verify` varchar(32) DEFAULT NULL, - `isreply` tinyint(1) DEFAULT NULL, - `ord` tinyint(1) DEFAULT NULL, - `status` tinyint(1) DEFAULT NULL, - `create_time` datetime DEFAULT NULL, - `update_time` datetime DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=54 DEFAULT CHARSET=utf8mb4; +CREATE TABLE `tk_message` ( + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `pid` int(10) NULL DEFAULT NULL, + `email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `path` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `ip` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `headimg` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `url` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `verify` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `isreply` tinyint(1) NULL DEFAULT NULL, + `ord` tinyint(1) NULL DEFAULT NULL, + `status` tinyint(1) NULL DEFAULT NULL, + `create_time` datetime(0) NULL DEFAULT NULL, + `update_time` datetime(0) NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = MyISAM AUTO_INCREMENT = 54 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for tk_node -- ---------------------------- DROP TABLE IF EXISTS `tk_node`; -CREATE TABLE `tk_node` ( - `id` smallint(6) unsigned NOT NULL AUTO_INCREMENT, - `name` varchar(20) DEFAULT NULL, - `title` varchar(20) DEFAULT NULL, - `status` tinyint(1) DEFAULT NULL, - `remark` varchar(50) DEFAULT NULL, - `sort` smallint(6) unsigned DEFAULT NULL, - `pid` smallint(6) unsigned DEFAULT NULL, - `level` tinyint(1) unsigned DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4; +CREATE TABLE `tk_node` ( + `id` smallint(6) UNSIGNED NOT NULL AUTO_INCREMENT, + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `title` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `status` tinyint(1) NULL DEFAULT NULL, + `remark` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `sort` smallint(6) UNSIGNED NULL DEFAULT NULL, + `pid` smallint(6) UNSIGNED NULL DEFAULT NULL, + `level` tinyint(1) UNSIGNED NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = MyISAM AUTO_INCREMENT = 12 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for tk_password_resets -- ---------------------------- DROP TABLE IF EXISTS `tk_password_resets`; -CREATE TABLE `tk_password_resets` ( - `email` varchar(255) NOT NULL, - `token` varchar(255) NOT NULL, - `created_at` timestamp NULL DEFAULT NULL, - KEY `tk_password_resets_email_index` (`email`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +CREATE TABLE `tk_password_resets` ( + `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `token` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `created_at` timestamp(0) NULL DEFAULT NULL, + INDEX `tk_password_resets_email_index`(`email`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for tk_role -- ---------------------------- DROP TABLE IF EXISTS `tk_role`; -CREATE TABLE `tk_role` ( - `id` smallint(6) unsigned NOT NULL AUTO_INCREMENT, - `name` varchar(20) DEFAULT NULL, - `pid` smallint(6) DEFAULT NULL, - `status` tinyint(1) unsigned DEFAULT NULL, - `remark` varchar(255) DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; +CREATE TABLE `tk_role` ( + `id` smallint(6) UNSIGNED NOT NULL AUTO_INCREMENT, + `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `pid` smallint(6) NULL DEFAULT NULL, + `status` tinyint(1) UNSIGNED NULL DEFAULT NULL, + `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for tk_role_user -- ---------------------------- DROP TABLE IF EXISTS `tk_role_user`; -CREATE TABLE `tk_role_user` ( - `role_id` mediumint(9) unsigned NOT NULL, - `user_id` char(32) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; +CREATE TABLE `tk_role_user` ( + `role_id` mediumint(9) UNSIGNED NOT NULL, + `user_id` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL +) ENGINE = MyISAM CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Fixed; + +-- ---------------------------- +-- Table structure for tk_system +-- ---------------------------- +DROP TABLE IF EXISTS `tk_system`; +CREATE TABLE `tk_system` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `domain` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `site_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `description` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `keyword` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `email` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `contact` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `company` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `record` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `phone` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `icp` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `address` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `tpl` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '1', + `allow_comment` tinyint(2) NULL DEFAULT 0, + `show_banner` tinyint(2) NULL DEFAULT 0, + `status` tinyint(4) NULL DEFAULT 0, + `create_time` datetime(0) NULL DEFAULT NULL, + `update_time` datetime(0) NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = MyISAM AUTO_INCREMENT = 103 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of tk_system +-- ---------------------------- +INSERT INTO `tk_system` VALUES (1, '127.0.0.1:8080', '橘子洲', '橘子洲', '橘子洲', 'akira@163.com', 'alex', '橘子洲', '', '15911006066', '橘子洲', '橘子洲', 'green', 0, 0, 0, NULL, '2023-01-15 14:18:37'); -- ---------------------------- -- Table structure for tk_user -- ---------------------------- DROP TABLE IF EXISTS `tk_user`; -CREATE TABLE `tk_user` ( - `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, - `username` varchar(64) DEFAULT NULL, - `sex` tinyint(2) DEFAULT NULL, - `avatar` varchar(200) DEFAULT NULL, - `nickname` varchar(100) DEFAULT NULL, - `description` varchar(100) DEFAULT NULL, - `password` char(255) DEFAULT NULL, - `loginip` varchar(20) DEFAULT NULL, - `logintime` varchar(50) DEFAULT NULL, - `verify` varchar(32) DEFAULT NULL, - `email` varchar(50) DEFAULT NULL, - `isadmin` tinyint(1) DEFAULT NULL, - `status` tinyint(1) DEFAULT NULL, - `address` varchar(255) DEFAULT NULL, - `create_time` datetime DEFAULT NULL, - `update_time` datetime DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4; +CREATE TABLE `tk_user` ( + `id` smallint(5) UNSIGNED NOT NULL AUTO_INCREMENT, + `username` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `sex` tinyint(2) NULL DEFAULT NULL, + `avatar` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `nickname` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `description` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `password` char(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `loginip` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `logintime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `verify` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `isadmin` tinyint(1) NULL DEFAULT NULL, + `status` tinyint(1) NULL DEFAULT NULL, + `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `create_time` datetime(0) NULL DEFAULT NULL, + `update_time` datetime(0) NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = MyISAM AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of tk_user -- ---------------------------- -INSERT INTO `tk_user` VALUES ('1', 'admin', '1', '', '杰克', '大风起兮云飞扬,威加海内兮归故乡\r\n', '$2a$14$ePl.tGVMczS/DrvMXNl77u3R4U0SBWXhoOZu8GYe2bqwUckRHRrzC', null, null, null, 'jikeytang@163.com', null, null, '中国 • 上海市 • 浦东新区', '2022-07-05 13:42:22', '2022-07-05 13:42:24'); -INSERT INTO `tk_user` VALUES ('2', 'test', null, '', null, null, '$2a$14$otb9WpTUmSulfMlc526hhe5IeTqFGM5P5hhc1YjT20Pl9j5UGxgvy', null, null, null, null, null, null, null, null, null); +INSERT INTO `tk_user` VALUES (1, 'admin', 1, '', '杰克', '大风起兮云飞扬,威加海内兮归故乡\r\n', '$2a$14$W7LKAr1AId3eYmtIiAtFeeLYhPuRldxziwORiuu2roiN2ojwD36xy', NULL, NULL, NULL, 'jikeytang@163.com', NULL, NULL, '中国 • 上海市 • 浦东新区', '2022-07-05 13:42:22', '2022-07-05 13:42:24'); + +SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index fd52c7f..fcbc6eb 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -14,13 +14,14 @@ services: container_name: el-redis db: - build: - context: ./deploy/mysql - dockerfile: Dockerfile + image: mariadb:10.3 +# build: +# context: ./deploy/mysql +# dockerfile: Dockerfile # image: mysql:8.0.21 # 容器名(以后的控制都通过这个) hostname: db - container_name: mysql + container_name: database # 重启策略 restart: always env_file: @@ -29,35 +30,24 @@ services: - "3306:3306" environment: TZ: Asia/Shanghai - MYSQL_ROOT_PASSWORD: abcd1234 -# MYSQL_USER: root -# MYSQL_PASSWORD: 123456 -# MYSQL_DATABASE: elk-blog volumes: - /var/mysql/data:/var/lib/mysql # 配置挂载 # - /root/mysql/conf/:/etc/mysql/conf.d/ # 初始化目录挂载,注意此处我只跑了这个挂载,只是为了说明其他配置不应该数据初始化 - /var/mysql/init/:/docker-entrypoint-initdb.d/ - command: - # 将mysql8.0默认密码策略 修改为 原先 策略 (mysql8.0对其默认策略做了更改 会导致密码无法匹配) - --default-authentication-plugin=mysql_native_password - --character-set-server=utf8mb4 - --collation-server=utf8mb4_general_ci - --explicit_defaults_for_timestamp=true - --lower_case_table_names=1 app: build: context: . dockerfile: Dockerfile - container_name: elk-blog + container_name: juzizhou expose: - "8080" ports: - "8080:8080" volumes: - - /var/elk-blog:/app + - /var/juzizhou:/app depends_on: - db logging: diff --git a/go.mod b/go.mod index a53787a..529ca34 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module gitee.com/jikey/elk-blog go 1.17 require ( + github.com/aliyun/aliyun-oss-go-sdk v2.2.6+incompatible github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3 github.com/gin-gonic/gin v1.8.1 - github.com/go-sql-driver/mysql v1.6.0 github.com/golang-jwt/jwt/v4 v4.4.2 github.com/jinzhu/gorm v1.9.16 github.com/mojocn/base64Captcha v1.3.5 @@ -13,9 +13,9 @@ require ( github.com/shirou/gopsutil v3.21.11+incompatible github.com/sirupsen/logrus v1.8.1 github.com/spf13/cast v1.5.0 + github.com/spf13/viper v1.13.0 github.com/vjeantet/jodaTime v1.0.0 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d - gopkg.in/ini.v1 v1.67.0 ) require ( @@ -25,9 +25,9 @@ require ( github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-playground/validator/v10 v10.11.0 // indirect + github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/goccy/go-json v0.9.8 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect - github.com/google/go-cmp v0.5.8 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.4 // indirect @@ -45,7 +45,6 @@ require ( github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.13.0 // indirect github.com/subosito/gotenv v1.4.1 // indirect github.com/tklauser/go-sysconf v0.3.10 // indirect github.com/tklauser/numcpus v0.4.0 // indirect @@ -56,7 +55,9 @@ require ( golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b // indirect golang.org/x/text v0.3.7 // indirect + golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect google.golang.org/protobuf v1.28.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index c650a36..9d98919 100644 --- a/go.sum +++ b/go.sum @@ -17,14 +17,32 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -38,35 +56,76 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= +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/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/aliyun/aliyun-oss-go-sdk v2.2.6+incompatible h1:KXeJoM1wo9I/6xPTyt6qCxoSZnmASiAjlrr0dyTUKt8= +github.com/aliyun/aliyun-oss-go-sdk v2.2.6+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM= github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3 h1:fmFk0Wt3bBxxwZnu48jqMdaOR/IZ4vdtJFuaFV8MpIE= github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3/go.mod h1:bJWSKrZyQvfTnb2OudyUjurSG4/edverV7n82+K3JiM= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 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-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= @@ -74,6 +133,12 @@ github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +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/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +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-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= @@ -82,13 +147,19 @@ github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2BOGlCyvTqsp/xIw= github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.9.8 h1:DxXB6MLd6yyel7CLph8EwNIonUtVZd3Ue5iRcL4DQCE= github.com/goccy/go-json v0.9.8/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= @@ -99,6 +170,7 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -106,6 +178,8 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -121,6 +195,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/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= @@ -131,14 +208,18 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -149,15 +230,52 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= +github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1/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-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +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/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= +github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o= @@ -167,13 +285,25 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas= github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/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/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/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.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +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.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 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= @@ -188,43 +318,96 @@ github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg= github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/go-homedir v1.1.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/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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 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/mojocn/base64Captcha v1.3.5 h1:Qeilr7Ta6eDtG4S+tQuZ5+hO+QHbiGAJdi4PfoagaA0= github.com/mojocn/base64Captcha v1.3.5/go.mod h1:/tTTXn4WTpX9CfrmipqRytCpJ27Uw3G6I7NcP2WwcmY= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nleeper/goment v1.4.4 h1:GlMTpxvhueljArSunzYjN9Ri4SOmpn0Vh2hg2z/IIl8= github.com/nleeper/goment v1.4.4/go.mod h1:zDl5bAyDhqxwQKAvkSXMRLOdCowrdZz53ofRJc4VhTo= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw= -github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI= +github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= 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/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/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.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/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/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= @@ -236,6 +419,7 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU= github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw= 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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -245,8 +429,8 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 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.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= @@ -257,6 +441,8 @@ github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hM github.com/tkuchiki/go-timezone v0.2.0/go.mod h1:b1Ean9v2UXtxSq4TZF0i/TU9NuoWa9hOzOKoGCV2zqY= github.com/tkuchiki/go-timezone v0.2.2 h1:MdHR65KwgVTwWFQrota4SKzc4L5EfuH5SdZZGtk/P2Q= github.com/tkuchiki/go-timezone v0.2.2/go.mod h1:oFweWxYl35C/s7HMVZXiA19Jr9Y0qJHMaG/J2TES4LY= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= @@ -266,24 +452,38 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= +go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU= +go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/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-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -312,6 +512,7 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -322,9 +523,11 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -332,9 +535,11 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -351,10 +556,22 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ= golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -366,6 +583,17 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= 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= @@ -376,22 +604,35 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/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-20181116152217-5ac8a444bdc5/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-20190312061237-fead79001313/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-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -402,6 +643,8 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -409,28 +652,56 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/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-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/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-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b h1:2n253B2r0pYSmEV+UNCQoPfU/FiaizQEK5Gu4Bq4JE8= golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -445,6 +716,7 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -469,6 +741,7 @@ golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= @@ -477,12 +750,20 @@ golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -502,6 +783,26 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.81.0/go.mod h1:FA6Mb/bZxj706H2j+j2d6mHEEaHBmbbWnkfvmorOCko= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -532,6 +833,7 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= @@ -544,7 +846,48 @@ google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -558,9 +901,24 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -572,20 +930,27 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= google.golang.org/protobuf v1.28.0/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 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI= -gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 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/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.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -602,3 +967,4 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/middleware/cors.go b/middleware/cors.go index 88473b6..de4165e 100644 --- a/middleware/cors.go +++ b/middleware/cors.go @@ -10,11 +10,19 @@ func Cors() gin.HandlerFunc { return func(c *gin.Context) { method := c.Request.Method origin := c.Request.Header.Get("Origin") - c.Header("Access-Control-Allow-Origin", origin) - c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id") - c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS,DELETE,PUT") - c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type") - c.Header("Access-Control-Allow-Credentials", "true") + //c.Header("Access-Control-Allow-Origin", origin) + //c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id") + //c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS,DELETE,PUT") + //c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type") + //c.Header("Access-Control-Allow-Credentials", "true") + + if origin != "" { + c.Header("Access-Control-Allow-Origin", "*") // 可将将 * 替换为指定的域名 + c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE") + c.Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization") + c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type") + c.Header("Access-Control-Allow-Credentials", "true") + } // 放行所有OPTIONS方法 if method == "OPTIONS" { diff --git a/middleware/jwt.go b/middleware/jwt.go index 3a4d73c..cc1c4bc 100644 --- a/middleware/jwt.go +++ b/middleware/jwt.go @@ -37,7 +37,7 @@ var ( // JWTAuth jwt中间件 func JWTAuth() gin.HandlerFunc { return func(c *gin.Context) { - tokenHeader, err := c.Cookie("milu.blog.token") + tokenHeader, err := c.Cookie("milu.article.token") if tokenHeader == "" { // response.Fail(c, e.AuthTokenNoEmpty) diff --git a/old-Dockerfile b/old-Dockerfile new file mode 100644 index 0000000..a306c83 --- /dev/null +++ b/old-Dockerfile @@ -0,0 +1,42 @@ +FROM golang:1.17 as golang +# 为我们的镜像设置必要的环境变量 +ENV GO111MODULE=on \ + CGO_ENABLED=0 \ + GOOS=linux \ + GOARCH=amd64 \ + GOPROXY=https://goproxy.cn,direct +# 设置/www,进入容器就会直接进入到这个目录下,而不是进入到默认根目录下面 +ADD . /www +# 进入工作目录 +WORKDIR /www +# 复制项目中的 go.mod 和 go.sum文件并下载依赖信息 +COPY go.mod . +COPY go.sum . +RUN go mod tidy +# 将代码复制到容器中 +COPY . . +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-w -s' -installsuffix 'public' -o ginserver main.go + +FROM ubuntu:18.04 + +# 配置项目环境(根据自己情况来) +ENV GO_PROFILE=pro +ENV GIN_MODE=release + +# 暴露服务端口 +EXPOSE 8080 + +WORKDIR /app + +# 复制打包的 Go 文件到系统用户可执行程序目录下 +COPY --from=golang /www/ginserver /app +COPY --from=golang /www/public /app/public +COPY --from=golang /www/setting /app/setting +COPY --from=golang /www/views /app/views + +RUN chown -R root /app/ginserver +RUN chmod +x /app/ginserver + +# 容器启动时运行的命令 +ENTRYPOINT ["/app/ginserver"] +#CMD ["/app/ginserver"] \ No newline at end of file diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index 6d9655b..6a524de 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -29,6 +29,7 @@ type AllConfig struct { Xorm XormConfig Sensitive SensitiveConfig Search SearchConfig + Aliyun AliyunConfig } type DatabaseConfig struct { @@ -44,15 +45,24 @@ type DatabaseConfig struct { MaxConn int `toml:"max_conn" mapstructure:"max_conn"` } -var DatabaseSetting = &DatabaseConfig{} +type AliyunConfig struct { + AccessKey string `toml:"access_key" mapstructure:"access_key"` + SecretAccessKey string `toml:"secret_access_key" mapstructure:"secret_access_key"` + BucketName string `toml:"bucket_name" mapstructure:"bucket_name"` + Endpoint string + InnerNet string `toml:"inner_net" mapstructure:"inner_net"` + OuterNet string `toml:"outer_net" mapstructure:"outer_net"` + AliyunNet string `toml:"aliyun_net" mapstructure:"aliyun_net"` +} type AppConfig struct { Env string LogLevel string CookieSecret string DataPath string - PageSize int + PageSize int `toml:"page_size" mapstructure:"page_size"` Key string + UploadOss bool `toml:"upload_oss" mapstructure:"upload_oss"` } type ServerConfig struct { @@ -87,6 +97,7 @@ type SiteMap struct { Email string Contact string Company string + Record string Phone string Icp string Address string @@ -143,7 +154,7 @@ func LoadInI() { func SetApp() { //sec := config.App - PageSize = viper.GetInt("app.page_size") + PageSize = Config.App.PageSize } func SetMeta() { diff --git a/pkg/utils/upload.go b/pkg/utils/upload.go new file mode 100644 index 0000000..f8756d1 --- /dev/null +++ b/pkg/utils/upload.go @@ -0,0 +1,168 @@ +package utils + +import ( + "fmt" + "gitee.com/jikey/elk-blog/pkg/setting" + "github.com/aliyun/aliyun-oss-go-sdk/oss" + "github.com/gin-gonic/gin" + "io" + "net/http" + "os" + "path/filepath" + "regexp" + "strconv" + "strings" + "sync" + "time" +) + +var ( + long = 0 + ti1 = int64(0) + once sync.Once + client *oss.Client + err error +) + +func Uploads(str []interface{}) []interface{} { + for k, v := range str { + str[k] = Upload(v.(string)) + } + return str +} + +// 使用sync.Once来保证oss.New函数只调用一次,避免重复创建OSSClient实例。 +func getOssClient() *oss.Client { + once.Do(func() { + // 创建OSSClient实例。 + client, err = oss.New(setting.Config.Aliyun.Endpoint, + setting.Config.Aliyun.AccessKey, + setting.Config.Aliyun.SecretAccessKey) + if err != nil { + fmt.Println("Error:", err) + os.Exit(-1) + } + fmt.Println("create ossClient") + }) + fmt.Println("get ossClient") + return client +} + +func Upload(url string) string { + // 创建OSSClient实例。 + client = getOssClient() + t1 := time.Now().Unix() + if ti1 != t1 { //如果时间戳不一样,那么归零 + long = 0 + } + ti1 = t1 + long++ + obj := fmt.Sprintf("article/%d%d.png", t1, long) + // 获取存储空间。 + bucket, err := client.Bucket(setting.Config.Aliyun.BucketName) + if err != nil { + fmt.Println("Error:", err) + os.Exit(-1) + } + res, _ := http.Get(url) + // 上传Byte数组。 + //err = bucket.PutObject(obj, bytes.NewReader(ReadImgData(url))) + err = bucket.PutObject(obj, io.Reader(res.Body)) + if err != nil { + fmt.Println("Error:", err) + os.Exit(-1) + } + return setting.Config.Aliyun.InnerNet + obj +} + +// ReadImgData 获取C的图片数据 +func ReadImgData(url string) []byte { + resp, err := http.Get(url) + if err != nil { + panic(err) + } + defer resp.Body.Close() + pix, err := io.ReadAll(resp.Body) + if err != nil { + panic(err) + } + return pix +} + +// RepImages 上传给定内容中非本站的图片,并替换为上传的图片链接 https://zhuanlan.zhihu.com/p/74047342 +func RepImages(htmls string) string { + var imgRE = regexp.MustCompile(`]+\bsrc=["']([^"']+)["']`) + imgs := imgRE.FindAllStringSubmatch(htmls, -1) + out := make([]string, len(imgs)) + myImage := "" + resHtml := htmls + //var result = make(chan string) + for i := range out { + if !strings.HasPrefix(imgs[i][1], "https://static.juzizhou.net") { + fmt.Println(imgs[i][1]) + myImage = Upload(imgs[i][1]) + resHtml = strings.Replace(resHtml, imgs[i][1], myImage, -1) + out[i] = imgs[i][1] + fmt.Println(strconv.Itoa(i), out[i]) + } + } + fmt.Println(resHtml) + return resHtml +} + +func OssUpload(key string, file io.Reader) (string, error) { + client = getOssClient() + // 获取存储空间。 + bucket, err := client.Bucket(setting.Config.Aliyun.BucketName) + if err != nil { + return "", err + } + // 上传文件。 + err = bucket.PutObject(key, file) + if err != nil { + return "", err + } + // https://jxcatimg.oss-cn-shenzhen.aliyuncs.com/articles/202107/1626401559-1564453109_219427.jpg + return setting.Config.Aliyun.InnerNet + key, nil +} + +func OSSUploadFile(c *gin.Context) (bool, string) { + fileHeader, err := c.FormFile("file") + if err != nil { + return false, "参数有误" + } + fileExt := filepath.Ext(fileHeader.Filename) + allowExts := []string{".jpg", ".png", ".gif", ".jpeg", ".doc", ".docx", ".ppt", ".pptx", ".xls", ".xlsx", ".pdf"} + allowFlag := false + for _, ext := range allowExts { + if ext == fileExt { + allowFlag = true + break + } + } + if !allowFlag { + return false, "不允许的类型" + } + + now := time.Now() + //文件存放路径 + fileDir := fmt.Sprintf("articles/%s", now.Format("200601")) + + //文件名称 + timeStamp := now.Unix() + fileName := fmt.Sprintf("%d-%s", timeStamp, fileHeader.Filename) + // 文件key + fileKey := filepath.Join(fileDir, fileName) + + src, err := fileHeader.Open() + if err != nil { + return false, "上传失败" + } + defer src.Close() + + res, err := OssUpload(fileKey, src) + if err != nil { + return false, "上传失败" + } + return true, res +} diff --git a/public/admin/js/admin.js b/public/admin/js/admin.js index 09218d5..c1ac284 100644 --- a/public/admin/js/admin.js +++ b/public/admin/js/admin.js @@ -11,14 +11,14 @@ this.info() }, info: function () { - var user = JSON.parse(app.atob(localStorage.getItem('milu.blog.user'))) + var user = JSON.parse(app.atob(localStorage.getItem('milu.article.user'))) if (user) { this.data.user = user } }, getUserInfo: function () { - return JSON.parse(app.atob(localStorage.getItem('milu.blog.user'))) && '' + return JSON.parse(app.atob(localStorage.getItem('milu.article.user'))) && '' }, /** * 构造树型结构数据 diff --git a/public/common/api/init.json b/public/common/api/init.json index 998781f..3806a69 100644 --- a/public/common/api/init.json +++ b/public/common/api/init.json @@ -25,25 +25,25 @@ "title": "发表文章", "icon": "fa fa-pencil", "target": "_blank", - "href": "blog/edit" + "href": "article/edit" }, { "title": "发表MD", "icon": "fa fa-maxcdn", "target": "_blank", - "href": "blog/edit/md" + "href": "article/edit/md" }, { "title": "文章管理", "icon": "fa fa-list-alt", "target": "_self", - "href": "blog" + "href": "article" }, { "title": "类别管理", "icon": "fa fa-navicon", "target": "_self", - "href": "blog/category" + "href": "article/category" }, { "title": "Banner管理", @@ -69,6 +69,12 @@ "target": "_self", "href": "users" }, + { + "title": "关于我", + "icon": "fa fa-beer", + "target": "_self", + "href": "about" + }, { "title": "友情链接", "icon": "fa fa-link", diff --git a/public/common/images/favicon.ico b/public/common/images/favicon.ico index 16b87024939c2e4121273b77f336a6a63bbe99a2..80de41f20199f1e7c96f203d3390c330603115dc 100644 GIT binary patch literal 67646 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 diff --git a/public/common/images/favicon1.ico b/public/common/images/favicon1.ico new file mode 100644 index 0000000000000000000000000000000000000000..16b87024939c2e4121273b77f336a6a63bbe99a2 GIT binary patch literal 67646 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 literal 0 HcmV?d00001 diff --git a/public/common/js/app.js b/public/common/js/app.js index 3dbbd53..2e14d56 100644 --- a/public/common/js/app.js +++ b/public/common/js/app.js @@ -454,7 +454,7 @@ // request interceptor service.interceptors.request.use( config => { - const token = app.cookie.get('milu.blog.token') + const token = app.cookie.get('milu.article.token') token && (config.headers['Authorization'] = `Bearer ${token}`) // 让每个请求携带自定义token 请根据实际情况自行修改 diff --git a/public/common/js/page.js b/public/common/js/page.js index 5a145dc..da52f5e 100644 --- a/public/common/js/page.js +++ b/public/common/js/page.js @@ -93,7 +93,7 @@ popup: null, }, data: { - blogStoreKey: 'milu.blog.likes.ids', + blogStoreKey: 'milu.article.likes.ids', likedIds: [], }, init: function () { @@ -207,7 +207,7 @@ return } - var url = `/blog/${id}/likes`, + var url = `/article/${id}/likes`, data = { likes: ++badge } $.ajax({ @@ -216,6 +216,7 @@ dataType: 'json', data, success: function (res) { + console.log(res.msg) if (!res.code) { self.handleLikeOk(el, res?.data) } else { diff --git a/public/green/css/app.css b/public/green/css/app.css index 77f0bf1..089a907 100644 --- a/public/green/css/app.css +++ b/public/green/css/app.css @@ -225,6 +225,7 @@ a:hover, a:active{ } .app-blog-model .app-container-inner{ width:80%; + /*width:100%;*/ } .app-container-inner{ display:flex; @@ -592,7 +593,7 @@ a:hover, a:active{ /* blog detail */ .app-detail-overview{ display:flex; - justify-content:space-between; + justify-content:center; align-items:center; } .app-detail-title{ diff --git a/public/green/images/ico.png b/public/green/images/ico.png new file mode 100644 index 0000000000000000000000000000000000000000..4f24ac61f7e9ae1876905f67422296682cc2c203 GIT binary patch literal 25599 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 literal 0 HcmV?d00001 diff --git a/public/home/images/aboutme/me.jpg b/public/home/images/aboutme/me.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6e12a045829a2811549f4c17903fd4f9cdc2cbb0 GIT binary patch literal 38512 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 Fe*=20pQ8W( literal 0 HcmV?d00001 diff --git a/public/ico.png b/public/ico.png new file mode 100644 index 0000000000000000000000000000000000000000..4f24ac61f7e9ae1876905f67422296682cc2c203 GIT binary patch literal 25599 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 literal 0 HcmV?d00001 diff --git a/routers/routers.go b/routers/routers.go index dcd9061..48e5735 100644 --- a/routers/routers.go +++ b/routers/routers.go @@ -47,17 +47,17 @@ func RouterApp() *gin.Engine { back.POST("upload/image", admin.UploadImage) // 文章管理 - blogController := new(admin.Blog) - back.GET("blog", blogController.Index) - back.GET("blog/category", blogController.Category) - back.GET("blog/category/list", blogController.CategoryList) - back.GET("blog/list", blogController.List) - back.GET("blog/edit", blogController.Edit) - back.GET("blog/:id", blogController.Detail) - back.GET("blog/edit/md", blogController.EditMd) - back.POST("blog/insert", blogController.Insert) - back.PUT("blog/update", blogController.Update) - back.POST("blog/delete", blogController.Destory) + articleController := new(admin.Article) + back.GET("article", articleController.Index) + back.GET("article/category", articleController.Category) + back.GET("article/category/list", articleController.CategoryList) + back.GET("article/list", articleController.List) + back.GET("article/:id", articleController.Detail) + back.GET("article/edit", articleController.Edit) + back.GET("article/edit/md", articleController.EditMd) + back.POST("article/insert", articleController.Insert) + back.PUT("article/update", articleController.Update) + back.POST("article/delete", articleController.Destroy) // 分类管理 categoryController := new(admin.Category) @@ -116,6 +116,12 @@ func RouterApp() *gin.Engine { back.POST("user/insert", userController.Insert) back.PUT("user/update", userController.Update) back.POST("user/delete", userController.Destory) + + // 用户管理 + aboutController := new(admin.About) + back.GET("about", aboutController.Index) + back.PUT("about/update", aboutController.Update) + back.GET("about/info", aboutController.Detail) } // 前台页面 @@ -130,13 +136,13 @@ func RouterApp() *gin.Engine { front.GET("/verify", homeController.GetVerify) // 博客 - blogController := new(home.Blog) - front.GET("/blog", blogController.Index) - front.GET("/blog/:id", blogController.Detail) - front.GET("/blog/archive/:id", blogController.Archive) - front.GET("/blog/category/:id", blogController.Category) + blogController := new(home.Article) + front.GET("/article", blogController.Index) + front.GET("/article/:id", blogController.Detail) + front.GET("/article/archive/:id", blogController.Archive) + front.GET("/article/category/:id", blogController.Category) front.GET("/search", blogController.Index) - front.POST("/blog/:id/likes", blogController.Likes) + front.POST("/article/:id/likes", blogController.Likes) // 标签 tagsController := new(home.Tags) diff --git a/setting/config.toml b/setting/config.toml index fe25771..1cef993 100644 --- a/setting/config.toml +++ b/setting/config.toml @@ -5,6 +5,7 @@ cookie_secret = 'ZJVAfAwEnR' data_path = 'data/max_online_num' page_size = 10 key = '' +upload_oss = true [server] host = '127.0.0.1' @@ -14,7 +15,7 @@ write_timeout = 60 [database] type = 'mysql' -# docker 部署时,host要填写宿主机的ip +# docker 部署时,host要填写宿主机的ip https://codeantenna.com/a/CuMmEL1ebL host = '127.0.0.1' port = '3306' user = 'root' @@ -51,19 +52,29 @@ content = '' [search] engine_url = '' +[aliyun] +access_key = "access_key" +secret_access_key = "secret_access_key" +bucket_name = "bucket_name" +endpoint = "https://oss-cn-beijing.aliyuncs.com" +inner_net = "https://static.domain.net/" +outer_net = "https://domain.oss-cn-beijing.aliyuncs.com/" +aliyun_net = "http://domain.oss-cn-beijing.aliyuncs.com/" + # 站点信息 [site] domain = 'http://127.0.0.1:8080' -title = '麋鹿博客' -keyword = 'Elk设计网页设计网站设计' -description = '设计师糜鹿个人网站,分享设计,分享人生,提供优质的网页设计、UI设计、APP用户体验改善、UE设计等各项设计服务!' +title = '糜鹿博客' +keyword = 'Alex设计网页设计网站设计' +description = '设计师糜鹿个人网站,分享设计,分享人生!' blogTitle = '糜鹿设计' -blogKeywords = 'Elk设计网页设计网站设计' -blogDescription = '设计师糜鹿个人网站,分享设计,分享人生,提供优质的网页设计、UI设计、APP用户体验改善、UE设计等各项设计服务!' -email = 'elk@qq.com' -contact = 'Elk' -company = 'Elk' +blogKeywords = '糜鹿设计网页设计网站设计' +blogDescription = '设计师糜鹿个人网站,分享设计,分享人生!' +email = 'iAlex@tom.com' +contact = 'Alex' +company = 'Alex' +record = '陕ICP备14007359号' phone = '123456' icp = '哥在香港' -address = '中国 • 上海' +address = '中国 • 西安' tpl = 'green' diff --git a/test/abc.jpg b/test/abc.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6e12a045829a2811549f4c17903fd4f9cdc2cbb0 GIT binary patch literal 38512 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 Fe*=20pQ8W( literal 0 HcmV?d00001 diff --git a/test/test_a.go b/test/test_a.go new file mode 100644 index 0000000..3ecf1dc --- /dev/null +++ b/test/test_a.go @@ -0,0 +1,52 @@ +package main + +import ( + "fmt" + "github.com/sirupsen/logrus" + "golang.org/x/crypto/bcrypt" + "regexp" + "strconv" + "strings" +) + +// BcryptHash 使用 bcrypt 对密码进行加密 +func BcryptHash(password string) string { + // GenerateFromPassword 的第二个参数是 cost 值。建议大于 12,数值越大耗费时间越长 + bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14) + logrus.Error(err) + + return string(bytes) +} + +// BcryptCheck 对比明文密码和数据库的哈希值 +func BcryptCheck(password, hash string) bool { + err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) + return err == nil +} + +// BcryptIsHashed 判断字符串是否是哈希过的数据 +func BcryptIsHashed(str string) bool { + // bcrypt 加密后的长度等于 60 + return len(str) == 60 +} + +func RepImages(htmls string) { + var imgRE = regexp.MustCompile(`]+\bsrc=["']([^"']+)["']`) + imgs := imgRE.FindAllStringSubmatch(htmls, -1) + out := make([]string, len(imgs)) + myImage := "https://static.juzizhou.net/1111111111111111.jpg" + resHtml := htmls + for i := range out { + if strings.HasPrefix(imgs[i][1], "https://static.juzizhou.net") { + resHtml = strings.Replace(resHtml, imgs[i][1], myImage, -1) + out[i] = imgs[i][1] + fmt.Println(strconv.Itoa(i), out[i]) + } + } + fmt.Println(resHtml) +} + +func main() { + a := BcryptHash("admin123$") + fmt.Print(a) +} diff --git a/test/test_b.go b/test/test_b.go new file mode 100644 index 0000000..42d4910 --- /dev/null +++ b/test/test_b.go @@ -0,0 +1,55 @@ +package main + +import ( + "fmt" + "path/filepath" + "sync" + "time" +) + +// 婷婷的淘宝客户端和web端都会指向婷婷这一个人 +type Woman struct { + name string +} + +var ( + once sync.Once + ting *Woman + ti1 = int64(0) + long = 0 +) + +func getTing() *Woman { + once.Do(func() { + ting = new(Woman) + ting.name = "tingting" + fmt.Println("newtingting") + }) + fmt.Println("gettingting") + return ting +} + +func main() { + for i := 0; i < 3; i++ { + _ = getTing() + } + now := time.Now() + fileExt := ".jpg" + //文件存放路径 + fileDir := fmt.Sprintf("articles") + + //文件名称 + timeStamp := now.Unix() + fileName := fmt.Sprintf("%d%s", timeStamp, fileExt) + // 文件key + fileKey := filepath.Join(fileDir, fileName) + fmt.Println(fileKey) + t1 := time.Now().Unix() + if ti1 != t1 { //如果时间戳不一样,那么归零 + long = 0 + } + ti1 = t1 + long++ + obj := fmt.Sprintf("article/%d%d.png", t1, long) + fmt.Println(obj) +} diff --git a/test/test_c.go b/test/test_c.go new file mode 100644 index 0000000..997016b --- /dev/null +++ b/test/test_c.go @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + "github.com/aliyun/aliyun-oss-go-sdk/oss" + "os" +) + +func main() { + // 创建OSSClient实例。 + // yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。 + // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。 + client, err := oss.New("https://oss-cn-beijing.aliyuncs.com", + "", "") + if err != nil { + fmt.Println("Error:", err) + os.Exit(-1) + } + + // 填写存储空间名称,例如examplebucket。 + bucket, err := client.Bucket("juzizhou") + if err != nil { + fmt.Println("Error:", err) + os.Exit(-1) + } + + // 依次填写Object的完整路径(例如exampledir/exampleobject.txt)和本地文件的完整路径(例如D:\\localpath\\examplefile.txt)。 + err = bucket.PutObjectFromFile("article/abc.jpg", "E:\\GolandProjects\\juzizhou\\test\\abc.jpg") + if err != nil { + fmt.Println("Error:", err) + os.Exit(-1) + } + fmt.Println("https://static.domain.net/article/abc.jpg") +} diff --git a/views/admin/about/index.html b/views/admin/about/index.html new file mode 100644 index 0000000..cb677f7 --- /dev/null +++ b/views/admin/about/index.html @@ -0,0 +1,79 @@ +{% include "../common/_app_css.html" %} +

+ +
+ 关于我 +
+ + + + + + 取消 + 确认 + + +
+
+{% include "../common/_app_js.html" %} +{% block importJs %} + +{% endblock %} +{% include "../components/tinymce.html" %} +{% include "../components/table-tool-bar.html" %} + diff --git a/views/admin/blog/edit.html b/views/admin/article/edit.html similarity index 96% rename from views/admin/blog/edit.html rename to views/admin/article/edit.html index ef4c640..842f39e 100644 --- a/views/admin/blog/edit.html +++ b/views/admin/article/edit.html @@ -117,12 +117,12 @@ addNew() { // this.editVisible = true // this.dialogStatus = 'create' - window.open('blog/edit') + window.open('article/edit') }, getCategoryList() { app.request({ method: 'get', - url: 'blog/category/list', + url: 'article/category/list', params: this.queryForm, }).then((res) => { const rows = res?.data?.rows @@ -135,7 +135,7 @@ getDetail() { app.request({ method: 'get', - url: `blog/${this.id}`, + url: `article/${this.id}`, }).then((res) => { this.modelForm = res?.data?.rows @@ -148,7 +148,7 @@ this.tableLoading = true app.request({ method: 'get', - url: 'blog/list', + url: 'article/list', params: this.queryForm, }).then((res) => { this.tableData = res?.data?.rows @@ -204,7 +204,7 @@ app.request({ method: 'post', - url: 'blog/delete', + url: 'article/delete', data: app.stringify({ id }) }).then((res) => { !res?.code && this.refreshData() @@ -235,7 +235,7 @@ if (valid) { app.request({ method: 'post', - url: 'blog/insert', + url: 'article/insert', data: this.modelForm, }).then(() => { this.editVisible = false @@ -262,7 +262,7 @@ onUpdate() { app.request({ method: 'put', - url: 'blog/update', + url: 'article/update', data: this.modelForm, }).then(() => { this.editVisible = false @@ -291,7 +291,7 @@ done && done() }, toMarkdown() { - window.open('/admin/blog/edit/md') + window.open('/admin/article/edit/md') } } }) diff --git a/views/admin/blog/index.html b/views/admin/article/index.html similarity index 95% rename from views/admin/blog/index.html rename to views/admin/article/index.html index 61d0e49..359d94b 100644 --- a/views/admin/blog/index.html +++ b/views/admin/article/index.html @@ -31,7 +31,7 @@ @@ -127,15 +127,15 @@ addNew() { this.editVisible = true this.dialogStatus = 'create' - window.open('blog/edit') + window.open('article/edit') }, addNewMd() { - window.open('blog/edit/md') + window.open('article/edit/md') }, getCategoryList() { app.request({ method: 'get', - url: 'blog/category/list', + url: 'article/category/list', params: this.queryForm, }).then((res) => { this.categoryList = res?.data?.rows @@ -145,7 +145,7 @@ this.tableLoading = true app.request({ method: 'get', - url: 'blog/list', + url: 'article/list', params: this.queryForm, }).then((res) => { this.tableData = res?.data?.rows @@ -169,8 +169,8 @@ this.editVisible = true this.dialogStatus = 'update' this.modelForm = row - // const url = `blog/edit?id=${row.id}${isMd}` - const url = row.md ? `blog/edit/md?id=${row.id}` : `blog/edit?id=${row.id}` + // const url = `article/edit?id=${row.id}${isMd}` + const url = row.md ? `article/edit/md?id=${row.id}` : `article/edit?id=${row.id}` window.open(url) }, @@ -204,7 +204,7 @@ app.request({ method: 'post', - url: 'blog/delete', + url: 'article/delete', data: app.stringify({ id }) }).then((res) => { !res?.code && this.refreshData() @@ -231,7 +231,7 @@ if (valid) { app.request({ method: 'post', - url: 'blog/insert', + url: 'article/insert', data: this.modelForm, }).then(() => { this.editVisible = false @@ -258,7 +258,7 @@ onUpdate() { app.request({ method: 'put', - url: 'blog/update', + url: 'article/update', data: this.modelForm, }).then(() => { this.editVisible = false diff --git a/views/admin/blog/md.html b/views/admin/article/md.html similarity index 97% rename from views/admin/blog/md.html rename to views/admin/article/md.html index 515f53c..8d38eb4 100644 --- a/views/admin/blog/md.html +++ b/views/admin/article/md.html @@ -152,7 +152,7 @@ getDetail() { app.request({ method: 'get', - url: `blog/${this.id}`, + url: `article/${this.id}`, }).then((res) => { this.modelForm = res?.data?.rows this.input = this.modelForm.md @@ -165,7 +165,7 @@ getCategoryList() { app.request({ method: 'get', - url: 'blog/category/list', + url: 'article/category/list', params: this.queryForm, }).then((res) => { const rows = res?.data?.rows @@ -190,7 +190,7 @@ if (valid) { app.request({ method: 'post', - url: 'blog/insert', + url: 'article/insert', data: this.modelForm, }).then(() => { this.handleClose() @@ -215,7 +215,7 @@ onUpdate() { app.request({ method: 'put', - url: 'blog/update', + url: 'article/update', data: this.modelForm, }).then(() => { this.editVisible = false @@ -233,7 +233,7 @@ this.drawer = !this.drawer }, toEditor() { - window.open('/admin/blog/edit') + window.open('/admin/article/edit') }, handleClose(done) { this.$refs.modelForm && this.$refs.modelForm.resetFields() diff --git a/views/admin/auth/login.html b/views/admin/auth/login.html index d17a3e5..2e0cb3a 100644 --- a/views/admin/auth/login.html +++ b/views/admin/auth/login.html @@ -22,7 +22,7 @@
- +
{# {{/*
*/}} #} @@ -65,8 +65,8 @@ if (res.code === 20103) { var toPath = '/admin/' - res.data.token && app.cookie.set('milu.blog.token', res.data.token, 1, toPath) - res.data.user && localStorage.setItem('milu.blog.user', app.btoa(res.data.user)) + res.data.token && app.cookie.set('milu.article.token', res.data.token, 1, toPath) + res.data.user && localStorage.setItem('milu.article.user', app.btoa(res.data.user)) layer.msg('登录成功', function () { location.href = toPath diff --git a/views/admin/components/tinymce.html b/views/admin/components/tinymce.html index 31969c1..503bd75 100644 --- a/views/admin/components/tinymce.html +++ b/views/admin/components/tinymce.html @@ -89,6 +89,7 @@ imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'], default_link_target: '_blank', link_title: false, + images_upload_url: '/admin/upload/image', nonbreaking_force_tab: true, // inserting nonbreaking space   need Nonbreaking Space Plugin init_instance_callback: editor => { if (_this.value) { @@ -116,7 +117,25 @@ editor.on('focus', function () { editor.setContent(_this.value) }) - } + }, + images_upload_handler(blobInfo, success, failure, progress) { + progress(0); + const token = _this.$store.getters.token; + getToken(token).then(response => { + const url = response.data.qiniu_url; + const formData = new FormData(); + formData.append('token', response.data.qiniu_token); + formData.append('key', response.data.qiniu_key); + formData.append('file', blobInfo.blob(), url); + upload(formData).then(() => { + success(url); + progress(100); + }) + }).catch(err => { + failure('出现未知问题,刷新页面,或者联系程序员') + console.log(err); + }); + }, // 整合七牛上传 // images_dataimg_filter(img) { // setTimeout(() => { diff --git a/views/admin/index/index.html b/views/admin/index/index.html index 492b0d6..713c1e4 100644 --- a/views/admin/index/index.html +++ b/views/admin/index/index.html @@ -21,11 +21,12 @@
快捷操作
新增作品 - 新增博文 + 新增博文 新增作品分类 新增博客分类 作品评论 - 博客评论 + 博客评论 + 关于我 留言管理 友情链接 广告管理 diff --git a/views/admin/index/welcome.html b/views/admin/index/welcome.html index 75894b9..6fbe6a6 100644 --- a/views/admin/index/welcome.html +++ b/views/admin/index/welcome.html @@ -19,7 +19,7 @@
快捷操作
- 新增文章 + 新增文章 新增分类 文章评论 留言管理 diff --git a/views/admin/layouts/master.html b/views/admin/layouts/master.html index 7c2e226..943ac45 100644 --- a/views/admin/layouts/master.html +++ b/views/admin/layouts/master.html @@ -103,7 +103,7 @@ this.bind() }, info: function () { - var user = JSON.parse(app.atob(localStorage.getItem('milu.blog.user'))) + var user = JSON.parse(app.atob(localStorage.getItem('milu.article.user'))) if (user) { $('#js-top-username').text(user.nickname) @@ -114,7 +114,7 @@ $('.login-out').on("click", function () { layer.msg('成功退出', { time: 1200 }, function () { window.location.href = '/admin/login' - app.cookie.remove('milu.blog.token') + app.cookie.remove('milu.article.token') }); }); }, diff --git a/views/admin/system/setting.html b/views/admin/system/setting.html index 6b307b4..2cffb2f 100644 --- a/views/admin/system/setting.html +++ b/views/admin/system/setting.html @@ -5,40 +5,93 @@ 网站信息设置
- - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - + - + 取消 @@ -55,13 +108,25 @@ return { loading: false, modelForm: { - tpl: 'default', + domain: '', + phone:'', + contact:'', + icp:'green', + tpl: null, }, tplOptions: [ { value: 'home', label: '默认主题' }, { value: 'defaulted', label: '极简主题' }, { value: 'green', label: '绿色主题' }, ], + commentOptions: [ + {value: true, label:'允许评论'}, + {value: false, label: '暂停评论'} + ], + bannerOptions: [ + {value: true, label:'显示轮播'}, + {value: false, label: '隐藏轮播'} + ] } }, created() { @@ -73,7 +138,9 @@ method: 'get', url: 'system/setting/list', }).then((res) => { - this.modelForm = res?.data?.rows + console.log(res.data.rows) + // this.modelForm = res?.data?.rows[0] + this.modelForm = res.data.rows setTimeout(() => { this.loading = false diff --git a/views/defaulted/article/detail.html b/views/defaulted/article/detail.html new file mode 100644 index 0000000..1c87596 --- /dev/null +++ b/views/defaulted/article/detail.html @@ -0,0 +1,178 @@ +{% extends "../layouts/master.html" %} + +{% block title %}Index{% endblock %} + +{% block head %} +{% endblock %} + +{% block content %} +
+
+

{{ data.blog.Title }}

+
+
+
+
+ +
+
+
管理员
+
+
1 评论
+ / + + / +
{{ data.blog.Views }} 阅读
+ / +
{{ data.blog.Content | length }} 字
+
+
+
+
+ {{ data.blog.Createtime | slice:"8:10" }} + {{ data.blog.Createtime | slice:":7" }} +
+
+
+
{{ data.blog.Content | safe }}
+
+ + + +
+
+ {% if(data.prev) %} + <<{{ data.prev | safe }} + {% else %} + 暂无上一篇 + {% endif %} +
+
+ {% if(data.next) %} + {{ data.next | safe }}>> + {% else %} + 暂无下一篇 + {% endif %} +
+
+ + +
+
+
+
+
+
+
+ 头像 +
+
+
+
    +
  • + + * +
  • +
  • + + * + 了解Gravatar + +
  • +
  • + +
  • +
  • + + * +
  • +
  • + + 点击刷新验证码 +
  • +
  • + + + + +
  • +
+
+
+
+
+ + +
+
    + {% for vo in data.commentList %} +
  • +
    + + Daxun + +
    +
    +
    +
    +

    {{ vo.Username }}

    +
    +
    + +
    +
    +
    {{ vo.Content | safe | escape }}
    + {% if vo.Child %} + {% for reply in vo.Child %} +
    +
    +
    +
    +
    +

    {{ reply.Username }}

    +
    +
    + + +
    +
    + {% autoescape off %} +
    {{ reply.Content }}
    + {% endautoescape %} +
    +
    + {% endfor %} + {% endif %} +
    +
  • + {% empty %} +
    暂无数据
    + {% endfor %} +
+
+ +
+ + + +
+{% endblock %} \ No newline at end of file diff --git a/views/defaulted/article/index.html b/views/defaulted/article/index.html new file mode 100644 index 0000000..500469f --- /dev/null +++ b/views/defaulted/article/index.html @@ -0,0 +1,57 @@ +{% extends "../layouts/blog-layouts.html" %} + +{% block title %}博客{% endblock %} + +{% block head %} +{% endblock %} + +{% block content %} +
+ {% for vo in data.list %} +
+ +
+
{{ vo.Description | safe | slice:":150" }}
+
+
+
+
+
{{ vo.Createtime | slice:":10" }}
+ / +
0 评论
+ / + + / +
{{ vo.Views }} 阅读
+
+ +
+
+
+ {% empty %} +
+
+ + + + + + + + + +
+
暂无数据
+
+ {% endfor %} +
+ {{ data.page | safe }} +
+
+{% endblock %} \ No newline at end of file diff --git a/views/defaulted/article/search.html b/views/defaulted/article/search.html new file mode 100644 index 0000000..825757e --- /dev/null +++ b/views/defaulted/article/search.html @@ -0,0 +1,14 @@ +{% extends "../layouts/master.html" %} + +{% block title %}搜索{% endblock %} + +{% block head %} +{% endblock %} + +{% block content %} +
+
+ search +
+
+{% endblock %} \ No newline at end of file diff --git a/views/defaulted/category/index.html b/views/defaulted/category/index.html index 5ac4604..1deb384 100644 --- a/views/defaulted/category/index.html +++ b/views/defaulted/category/index.html @@ -10,7 +10,7 @@ {% for vo in data.list %}