Merge branch 'release/1.1.3'

This commit is contained in:
LinkinStars 2023-09-06 16:25:17 +08:00
commit 818af49f27
61 changed files with 648 additions and 577 deletions

View File

@ -1,6 +1,6 @@
.PHONY: build clean ui .PHONY: build clean ui
VERSION=1.1.2 VERSION=1.1.3
BIN=answer BIN=answer
DIR_SRC=./cmd/answer DIR_SRC=./cmd/answer
DOCKER_CMD=docker DOCKER_CMD=docker

View File

@ -130,10 +130,10 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
userExternalLoginRepo := user_external_login.NewUserExternalLoginRepo(dataData) userExternalLoginRepo := user_external_login.NewUserExternalLoginRepo(dataData)
userExternalLoginService := user_external_login2.NewUserExternalLoginService(userRepo, userCommon, userExternalLoginRepo, emailService, siteInfoCommonService, userActiveActivityRepo) userExternalLoginService := user_external_login2.NewUserExternalLoginService(userRepo, userCommon, userExternalLoginRepo, emailService, siteInfoCommonService, userActiveActivityRepo)
userNotificationConfigRepo := user_notification_config.NewUserNotificationConfigRepo(dataData) userNotificationConfigRepo := user_notification_config.NewUserNotificationConfigRepo(dataData)
userService := service.NewUserService(userRepo, userActiveActivityRepo, activityRepo, emailService, authService, siteInfoCommonService, userRoleRelService, userCommon, userExternalLoginService, userNotificationConfigRepo) userNotificationConfigService := user_notification_config2.NewUserNotificationConfigService(userRepo, userNotificationConfigRepo)
userService := service.NewUserService(userRepo, userActiveActivityRepo, activityRepo, emailService, authService, siteInfoCommonService, userRoleRelService, userCommon, userExternalLoginService, userNotificationConfigRepo, userNotificationConfigService)
captchaRepo := captcha.NewCaptchaRepo(dataData) captchaRepo := captcha.NewCaptchaRepo(dataData)
captchaService := action.NewCaptchaService(captchaRepo) captchaService := action.NewCaptchaService(captchaRepo)
userNotificationConfigService := user_notification_config2.NewUserNotificationConfigService(userRepo, userNotificationConfigRepo)
userController := controller.NewUserController(authService, userService, captchaService, emailService, siteInfoCommonService, userNotificationConfigService) userController := controller.NewUserController(authService, userService, captchaService, emailService, siteInfoCommonService, userNotificationConfigService)
commentRepo := comment.NewCommentRepo(dataData, uniqueIDRepo) commentRepo := comment.NewCommentRepo(dataData, uniqueIDRepo)
commentCommonRepo := comment.NewCommentCommonRepo(dataData, uniqueIDRepo) commentCommonRepo := comment.NewCommentCommonRepo(dataData, uniqueIDRepo)
@ -184,7 +184,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
questionController := controller.NewQuestionController(questionService, answerService, rankService, siteInfoCommonService, captchaService) questionController := controller.NewQuestionController(questionService, answerService, rankService, siteInfoCommonService, captchaService)
answerController := controller.NewAnswerController(answerService, rankService, captchaService) answerController := controller.NewAnswerController(answerService, rankService, captchaService)
searchParser := search_parser.NewSearchParser(tagCommonService, userCommon) searchParser := search_parser.NewSearchParser(tagCommonService, userCommon)
searchRepo := search_common.NewSearchRepo(dataData, uniqueIDRepo, userCommon) searchRepo := search_common.NewSearchRepo(dataData, uniqueIDRepo, userCommon, tagCommonService)
searchService := service.NewSearchService(searchParser, searchRepo) searchService := service.NewSearchService(searchParser, searchRepo)
searchController := controller.NewSearchController(searchService, captchaService) searchController := controller.NewSearchController(searchService, captchaService)
serviceRevisionService := service.NewRevisionService(revisionRepo, userCommon, questionCommon, answerService, objService, questionRepo, answerRepo, tagRepo, tagCommonService, notificationQueueService, activityQueueService) serviceRevisionService := service.NewRevisionService(revisionRepo, userCommon, questionCommon, answerService, objService, questionRepo, answerRepo, tagRepo, tagCommonService, notificationQueueService, activityQueueService)

36
go.mod
View File

@ -25,7 +25,7 @@ require (
github.com/lib/pq v1.10.7 github.com/lib/pq v1.10.7
github.com/microcosm-cc/bluemonday v1.0.21 github.com/microcosm-cc/bluemonday v1.0.21
github.com/mojocn/base64Captcha v1.3.5 github.com/mojocn/base64Captcha v1.3.5
github.com/ory/dockertest/v3 v3.9.1 github.com/ory/dockertest/v3 v3.10.0
github.com/robfig/cron/v3 v3.0.1 github.com/robfig/cron/v3 v3.0.1
github.com/scottleedavis/go-exif-remove v0.0.0-20230314195146-7e059d593405 github.com/scottleedavis/go-exif-remove v0.0.0-20230314195146-7e059d593405
github.com/segmentfault/pacman v1.0.5-0.20230822083413-c0075a2d401f github.com/segmentfault/pacman v1.0.5-0.20230822083413-c0075a2d401f
@ -41,8 +41,8 @@ require (
github.com/swaggo/swag v1.16.1 github.com/swaggo/swag v1.16.1
github.com/tidwall/gjson v1.14.4 github.com/tidwall/gjson v1.14.4
github.com/yuin/goldmark v1.4.13 github.com/yuin/goldmark v1.4.13
golang.org/x/crypto v0.11.0 golang.org/x/crypto v0.13.0
golang.org/x/net v0.12.0 golang.org/x/net v0.15.0
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
modernc.org/sqlite v1.24.0 modernc.org/sqlite v1.24.0
@ -51,22 +51,22 @@ require (
) )
require ( require (
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/KyleBanks/depth v1.2.1 // indirect github.com/KyleBanks/depth v1.2.1 // indirect
github.com/LinkinStars/go-i18n/v2 v2.2.2 // indirect github.com/LinkinStars/go-i18n/v2 v2.2.2 // indirect
github.com/Microsoft/go-winio v0.5.2 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect github.com/andybalholm/brotli v1.0.4 // indirect
github.com/aymerick/douceur v0.2.0 // indirect github.com/aymerick/douceur v0.2.0 // indirect
github.com/bytedance/sonic v1.9.1 // indirect github.com/bytedance/sonic v1.9.1 // indirect
github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/containerd/continuity v0.3.0 // indirect github.com/containerd/continuity v0.4.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/cli v20.10.14+incompatible // indirect github.com/docker/cli v24.0.6+incompatible // indirect
github.com/docker/docker v20.10.7+incompatible // indirect github.com/docker/docker v24.0.6+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect
github.com/dsoprea/go-exif v0.0.0-20190901173045-3ce78807c90f // indirect github.com/dsoprea/go-exif v0.0.0-20190901173045-3ce78807c90f // indirect
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20190422055009-d6f9ba25cf48 // indirect github.com/dsoprea/go-jpeg-image-structure v0.0.0-20190422055009-d6f9ba25cf48 // indirect
github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696 // indirect github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696 // indirect
@ -87,7 +87,7 @@ require (
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/gorilla/css v1.0.0 // indirect github.com/gorilla/css v1.0.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/imdario/mergo v0.3.12 // indirect github.com/imdario/mergo v0.3.16 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
@ -100,19 +100,19 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect github.com/moby/term v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/opencontainers/runc v1.1.2 // indirect github.com/opencontainers/runc v1.1.9 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/sirupsen/logrus v1.8.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/afero v1.9.2 // indirect github.com/spf13/afero v1.9.2 // indirect
github.com/spf13/cast v1.5.0 // indirect github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect
@ -124,7 +124,7 @@ require (
github.com/tidwall/pretty v1.2.0 // indirect github.com/tidwall/pretty v1.2.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect github.com/ugorji/go/codec v1.2.11 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect
go.uber.org/atomic v1.10.0 // indirect go.uber.org/atomic v1.10.0 // indirect
@ -133,9 +133,9 @@ require (
golang.org/x/arch v0.3.0 // indirect golang.org/x/arch v0.3.0 // indirect
golang.org/x/image v0.1.0 // indirect golang.org/x/image v0.1.0 // indirect
golang.org/x/mod v0.12.0 // indirect golang.org/x/mod v0.12.0 // indirect
golang.org/x/sys v0.10.0 // indirect golang.org/x/sys v0.12.0 // indirect
golang.org/x/text v0.11.0 // indirect golang.org/x/text v0.13.0 // indirect
golang.org/x/tools v0.11.0 // indirect golang.org/x/tools v0.13.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect

112
go.sum
View File

@ -39,8 +39,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
gitee.com/travelliu/dm v1.8.11192/go.mod h1:DHTzyhCrM843x9VdKVbZ+GKXGRbKM2sJ4LxihRxShkE= gitee.com/travelliu/dm v1.8.11192/go.mod h1:DHTzyhCrM843x9VdKVbZ+GKXGRbKM2sJ4LxihRxShkE=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU=
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
@ -56,8 +56,8 @@ github.com/Machiel/slugify v1.0.1 h1:EfWSlRWstMadsgzmiV7d0yVd2IFlagWH68Q+DcYCm4E
github.com/Machiel/slugify v1.0.1/go.mod h1:fTFGn5uWEynW4CUMG7sWkYXOf1UgDxyTM3DbR6Qfg3k= github.com/Machiel/slugify v1.0.1/go.mod h1:fTFGn5uWEynW4CUMG7sWkYXOf1UgDxyTM3DbR6Qfg3k=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
@ -91,7 +91,6 @@ github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZw
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 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.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
@ -103,18 +102,16 @@ github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 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/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/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/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-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
@ -123,22 +120,18 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM=
github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -146,14 +139,14 @@ github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/docker/cli v20.10.14+incompatible h1:dSBKJOVesDgHo7rbxlYjYsXe7gPzrTT+/cKQgpDAazg= github.com/docker/cli v24.0.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY=
github.com/docker/cli v20.10.14+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ= github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE=
github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dsoprea/go-exif v0.0.0-20190901173045-3ce78807c90f h1:vqfYiZ+xF0xJvl9SZ1kovmMgKjaGZIz/Hn8JDQdyd9A= github.com/dsoprea/go-exif v0.0.0-20190901173045-3ce78807c90f h1:vqfYiZ+xF0xJvl9SZ1kovmMgKjaGZIz/Hn8JDQdyd9A=
github.com/dsoprea/go-exif v0.0.0-20190901173045-3ce78807c90f/go.mod h1:DmMpU91/Ax6BAwoRkjgRCr2rmgEgS4tsmatfV7M+U+c= github.com/dsoprea/go-exif v0.0.0-20190901173045-3ce78807c90f/go.mod h1:DmMpU91/Ax6BAwoRkjgRCr2rmgEgS4tsmatfV7M+U+c=
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20190422055009-d6f9ba25cf48 h1:9zARagUAxQJjibcDy+0+koUMR6sbX38L49Bk2Vni628= github.com/dsoprea/go-jpeg-image-structure v0.0.0-20190422055009-d6f9ba25cf48 h1:9zARagUAxQJjibcDy+0+koUMR6sbX38L49Bk2Vni628=
@ -180,7 +173,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
@ -246,8 +238,6 @@ github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGF
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
@ -375,8 +365,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 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/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
@ -525,9 +515,8 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= 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/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 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/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -537,7 +526,6 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 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 h1:Qeilr7Ta6eDtG4S+tQuZ5+hO+QHbiGAJdi4PfoagaA0=
github.com/mojocn/base64Captcha v1.3.5/go.mod h1:/tTTXn4WTpX9CfrmipqRytCpJ27Uw3G6I7NcP2WwcmY= github.com/mojocn/base64Captcha v1.3.5/go.mod h1:/tTTXn4WTpX9CfrmipqRytCpJ27Uw3G6I7NcP2WwcmY=
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
@ -560,10 +548,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v1.1.2 h1:2VSZwLx5k/BfsBxMMipG/LYUnmqOD/BPkIVgQUcTlLw= github.com/opencontainers/runc v1.1.9 h1:XR0VIHTGce5eWPkaPesqTBrhW2yAcaraWfsEalNwQLM=
github.com/opencontainers/runc v1.1.2/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= github.com/opencontainers/runc v1.1.9/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50=
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
@ -572,8 +558,8 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/ory/dockertest/v3 v3.9.1 h1:v4dkG+dlu76goxMiTT2j8zV7s4oPPEppKT8K8p2f1kY= github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4=
github.com/ory/dockertest/v3 v3.9.1/go.mod h1:42Ir9hmvaAPm0Mgibk6mBPi7SFvTXxEcnztDYOJ//uM= github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg=
github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U= github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
@ -640,13 +626,8 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh
github.com/scottleedavis/go-exif-remove v0.0.0-20230314195146-7e059d593405 h1:2ieGkj4z/YPXVyQ2ayZUg3GwE1pYWd5f1RB6DzAOXKM= github.com/scottleedavis/go-exif-remove v0.0.0-20230314195146-7e059d593405 h1:2ieGkj4z/YPXVyQ2ayZUg3GwE1pYWd5f1RB6DzAOXKM=
github.com/scottleedavis/go-exif-remove v0.0.0-20230314195146-7e059d593405/go.mod h1:rIxVzVLKlBwLxO+lC+k/I4HJfRQcemg/f/76Xmmzsec= github.com/scottleedavis/go-exif-remove v0.0.0-20230314195146-7e059d593405/go.mod h1:rIxVzVLKlBwLxO+lC+k/I4HJfRQcemg/f/76Xmmzsec=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/segmentfault/pacman v1.0.5-0.20230822075009-309985fb8700 h1:VqxiuNGQg86GEKxnzmJegZR2Ufr7EVXo68mdKaf+/MQ=
github.com/segmentfault/pacman v1.0.5-0.20230822075009-309985fb8700/go.mod h1:5lNp5REd8QMThmBUvR3Fi9Y3AsOB4GRq7soCB4QLqOs=
github.com/segmentfault/pacman v1.0.5-0.20230822083413-c0075a2d401f h1:9f2Bjf6bdMvNyUop32wAGJCdp+Jdm/d6nKBYvFvkRo0= github.com/segmentfault/pacman v1.0.5-0.20230822083413-c0075a2d401f h1:9f2Bjf6bdMvNyUop32wAGJCdp+Jdm/d6nKBYvFvkRo0=
github.com/segmentfault/pacman v1.0.5-0.20230822083413-c0075a2d401f/go.mod h1:5lNp5REd8QMThmBUvR3Fi9Y3AsOB4GRq7soCB4QLqOs= github.com/segmentfault/pacman v1.0.5-0.20230822083413-c0075a2d401f/go.mod h1:5lNp5REd8QMThmBUvR3Fi9Y3AsOB4GRq7soCB4QLqOs=
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20230822075009-309985fb8700 h1:VZpexPTcr7sOxxYUGa/9cneyCESfisAhCNbaEuTpcwI=
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20230822075009-309985fb8700/go.mod h1:rmf1TCwz67dyM+AmTwSd1BxTo2AOYHj262lP93bOZbs=
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20230822083413-c0075a2d401f h1:1KHe0uN6p798E7XJZPhZkgm/hXk5CTjisCvFMqaZSKI= github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20230822083413-c0075a2d401f h1:1KHe0uN6p798E7XJZPhZkgm/hXk5CTjisCvFMqaZSKI=
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20230822083413-c0075a2d401f/go.mod h1:rmf1TCwz67dyM+AmTwSd1BxTo2AOYHj262lP93bOZbs= github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20230822083413-c0075a2d401f/go.mod h1:rmf1TCwz67dyM+AmTwSd1BxTo2AOYHj262lP93bOZbs=
github.com/segmentfault/pacman/contrib/conf/viper v0.0.0-20221018072427-a15dd1434e05 h1:BlqTgc3/MYKG6vMI2MI+6o+7P4Gy5PXlawu185wPXAk= github.com/segmentfault/pacman/contrib/conf/viper v0.0.0-20221018072427-a15dd1434e05 h1:BlqTgc3/MYKG6vMI2MI+6o+7P4Gy5PXlawu185wPXAk=
@ -664,9 +645,8 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
@ -681,7 +661,6 @@ github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUq
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 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/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 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU=
@ -717,7 +696,6 @@ github.com/swaggo/gin-swagger v1.5.3/go.mod h1:3XJKSfHjDMB5dBo/0rrTXidPmgLeqsX89
github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ= github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ=
github.com/swaggo/swag v1.16.1 h1:fTNRhKstPKxcnoKsytm4sahr8FaYzUcT7i1/3nd/fBg= github.com/swaggo/swag v1.16.1 h1:fTNRhKstPKxcnoKsytm4sahr8FaYzUcT7i1/3nd/fBg=
github.com/swaggo/swag v1.16.1/go.mod h1:9/LMvHycG3NFHfR6LwvikHv5iFvmPADQ359cKikGxto= github.com/swaggo/swag v1.16.1/go.mod h1:9/LMvHycG3NFHfR6LwvikHv5iFvmPADQ359cKikGxto=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
@ -738,10 +716,9 @@ github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZ
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
@ -777,7 +754,6 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
@ -812,8 +788,8 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/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-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -901,8 +877,8 @@ golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -942,14 +918,12 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/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-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-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/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-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -967,7 +941,6 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/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-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-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/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-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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -975,7 +948,6 @@ golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/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-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-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-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -983,24 +955,23 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/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-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-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-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-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/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-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/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-20211216021012-1d35b9e2eb4e/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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -1016,8 +987,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -1038,7 +1009,6 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/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-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-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/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-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-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@ -1085,8 +1055,8 @@ 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.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1190,7 +1160,6 @@ 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.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 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-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
@ -1230,8 +1199,7 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/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.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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo=
gotest.tools/v3 v3.2.0 h1:I0DwBVMGAx26dttAj1BtJLAkVGncrkkUXfJLC4Flt/I=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -1292,16 +1292,16 @@ ui:
page_title: CSS and HTML page_title: CSS and HTML
custom_css: custom_css:
label: Custom CSS label: Custom CSS
text: This will insert as <link> text: This will insert as &lt;link>
head: head:
label: Head label: Head
text: This will insert before </head> text: This will insert before &lt;/head>
header: header:
label: Header label: Header
text: This will insert after <body> text: This will insert after &lt;body>
footer: footer:
label: Footer label: Footer
text: This will insert before </html>. text: This will insert before &lt;/body>.
login: login:
page_title: Login page_title: Login
membership: membership:

View File

@ -1263,12 +1263,14 @@ ui:
site_name: site_name:
label: Site name label: Site name
msg: Site name cannot be empty. msg: Site name cannot be empty.
msg_max_length: Site name must be at maximum 30 characters in length.
site_url: site_url:
label: Site URL label: Site URL
text: The address of your site. text: The address of your site.
msg: msg:
empty: Site URL cannot be empty. empty: Site URL cannot be empty.
incorrect: Site URL incorrect format. incorrect: Site URL incorrect format.
max_length: Site URL must be at maximum 512 characters in length.
contact_email: contact_email:
label: Contact email label: Contact email
text: Email address of key contact responsible for this site. text: Email address of key contact responsible for this site.
@ -1283,12 +1285,15 @@ ui:
label: Name label: Name
msg: Name cannot be empty. msg: Name cannot be empty.
character: 'Must use the character set "a-z", "0-9", " - . _"' character: 'Must use the character set "a-z", "0-9", " - . _"'
msg_max_length: Name must be at maximum 30 characters in length.
admin_password: admin_password:
label: Password label: Password
text: >- text: >-
You will need this password to log in. Please store it in a secure You will need this password to log in. Please store it in a secure
location. location.
msg: Password cannot be empty. msg: Password cannot be empty.
msg_min_length: Password must be at least 8 characters in length.
msg_max_length: Password must be at maximum 32 characters in length.
admin_email: admin_email:
label: Email label: Email
text: You will need this email to log in. text: You will need this email to log in.
@ -1652,16 +1657,16 @@ ui:
page_title: CSS and HTML page_title: CSS and HTML
custom_css: custom_css:
label: Custom CSS label: Custom CSS
text: This will insert as <link> text: This will insert as &lt;link>
head: head:
label: Head label: Head
text: This will insert before </head> text: This will insert before &lt;/head>
header: header:
label: Header label: Header
text: This will insert after <body> text: This will insert after &lt;body>
footer: footer:
label: Footer label: Footer
text: This will insert before </body>. text: This will insert before &lt;/body>.
sidebar: sidebar:
label: Sidebar label: Sidebar
text: This will insert in sidebar. text: This will insert in sidebar.

View File

@ -1607,16 +1607,16 @@ ui:
page_title: CSS 与 HTML page_title: CSS 与 HTML
custom_css: custom_css:
label: 自定义 CSS label: 自定义 CSS
text: 这将以 <link> 方式插入 text: 这将以 &lt;link> 方式插入
head: head:
label: 头部 label: 头部
text: 这将在 </head> 之前插入 text: 这将在 &lt;/head> 之前插入
header: header:
label: 页眉 label: 页眉
text: 这将在 <body> 之后插入 text: 这将在 &lt;body> 之后插入
footer: footer:
label: 页脚 label: 页脚
text: 这将在 </body> 之前插入. text: 这将在 &lt;/body> 之前插入.
sidebar: sidebar:
label: 侧边栏 label: 侧边栏
text: 这将插入侧边栏中。 text: 这将插入侧边栏中。

View File

@ -14,6 +14,7 @@ const (
SiteInfoCacheTime = 1 * time.Hour SiteInfoCacheTime = 1 * time.Hour
ConfigID2KEYCacheKeyPrefix = "answer:config:id:" ConfigID2KEYCacheKeyPrefix = "answer:config:id:"
ConfigKEY2ContentCacheKeyPrefix = "answer:config:key:" ConfigKEY2ContentCacheKeyPrefix = "answer:config:key:"
ConfigCacheTime = 1 * time.Hour
ConnectorUserExternalInfoCacheKey = "answer:connector:" ConnectorUserExternalInfoCacheKey = "answer:connector:"
ConnectorUserExternalInfoCacheTime = 10 * time.Minute ConnectorUserExternalInfoCacheTime = 10 * time.Minute
SiteMapQuestionCacheKeyPrefix = "answer:sitemap:question:%d" SiteMapQuestionCacheKeyPrefix = "answer:sitemap:question:%d"

View File

@ -2,15 +2,13 @@ package handler
import ( import (
"errors" "errors"
"net/http"
"strings"
"github.com/answerdev/answer/internal/base/constant" "github.com/answerdev/answer/internal/base/constant"
"github.com/answerdev/answer/internal/base/reason" "github.com/answerdev/answer/internal/base/reason"
"github.com/answerdev/answer/internal/base/validator" "github.com/answerdev/answer/internal/base/validator"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
myErrors "github.com/segmentfault/pacman/errors" myErrors "github.com/segmentfault/pacman/errors"
"github.com/segmentfault/pacman/log" "github.com/segmentfault/pacman/log"
"net/http"
) )
// HandleResponse Handle response body // HandleResponse Handle response body
@ -74,10 +72,3 @@ func BindAndCheckReturnErr(ctx *gin.Context, data interface{}) (errFields []*val
errFields, _ = validator.GetValidatorByLang(lang).Check(data) errFields, _ = validator.GetValidatorByLang(lang).Check(data)
return errFields return errFields
} }
func MsgWithParameter(msg string, list map[string]string) string {
for k, v := range list {
msg = strings.Replace(msg, "{{ "+k+" }}", v, -1)
}
return msg
}

View File

@ -319,11 +319,11 @@ func (ac *AnswerController) AnswerList(ctx *gin.Context) {
// @Accept json // @Accept json
// @Produce json // @Produce json
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Param data body schema.AnswerAcceptedReq true "AnswerAcceptedReq" // @Param data body schema.AcceptAnswerReq true "AcceptAnswerReq"
// @Success 200 {string} string "" // @Success 200 {string} string ""
// @Router /answer/api/v1/answer/acceptance [post] // @Router /answer/api/v1/answer/acceptance [post]
func (ac *AnswerController) Accepted(ctx *gin.Context) { func (ac *AnswerController) Accepted(ctx *gin.Context) {
req := &schema.AnswerAcceptedReq{} req := &schema.AcceptAnswerReq{}
if handler.BindAndCheck(ctx, req) { if handler.BindAndCheck(ctx, req) {
return return
} }
@ -341,7 +341,7 @@ func (ac *AnswerController) Accepted(ctx *gin.Context) {
return return
} }
err = ac.answerService.UpdateAccepted(ctx, req) err = ac.answerService.AcceptAnswer(ctx, req)
handler.HandleResponse(ctx, err, nil) handler.HandleResponse(ctx, err, nil)
} }

View File

@ -157,20 +157,23 @@ func (cc *CommentController) UpdateComment(ctx *gin.Context) {
} }
req.UserID = middleware.GetLoginUserIDFromContext(ctx) req.UserID = middleware.GetLoginUserIDFromContext(ctx)
req.IsAdmin = middleware.GetIsAdminFromContext(ctx)
canList, err := cc.rankService.CheckOperationPermissions(ctx, req.UserID, []string{ canList, err := cc.rankService.CheckOperationPermissions(ctx, req.UserID, []string{
permission.CommentAdd,
permission.CommentEdit, permission.CommentEdit,
permission.CommentDelete,
permission.LinkUrlLimit, permission.LinkUrlLimit,
}) })
if err != nil { if err != nil {
handler.HandleResponse(ctx, err, nil) handler.HandleResponse(ctx, err, nil)
return return
} }
linkUrlLimitUser := canList[3] req.CanEdit = canList[0] || cc.rankService.CheckOperationObjectOwner(ctx, req.UserID, req.CommentID)
req.IsAdmin = middleware.GetIsAdminFromContext(ctx) linkUrlLimitUser := canList[1]
isAdmin := middleware.GetUserIsAdminModerator(ctx) if !req.CanEdit {
if !isAdmin || !linkUrlLimitUser { handler.HandleResponse(ctx, errors.Forbidden(reason.RankFailToMeetTheCondition), nil)
return
}
if !req.IsAdmin || !linkUrlLimitUser {
captchaPass := cc.actionService.ActionRecordVerifyCaptcha(ctx, entity.CaptchaActionEdit, req.UserID, req.CaptchaID, req.CaptchaCode) captchaPass := cc.actionService.ActionRecordVerifyCaptcha(ctx, entity.CaptchaActionEdit, req.UserID, req.CaptchaID, req.CaptchaCode)
if !captchaPass { if !captchaPass {
errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{ errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{
@ -182,21 +185,8 @@ func (cc *CommentController) UpdateComment(ctx *gin.Context) {
} }
} }
req.CanAdd = canList[0]
req.CanEdit = canList[1]
req.CanDelete = canList[2]
can, err := cc.rankService.CheckOperationPermission(ctx, req.UserID, permission.CommentEdit, req.CommentID)
if err != nil {
handler.HandleResponse(ctx, err, nil)
return
}
if !can {
handler.HandleResponse(ctx, errors.Forbidden(reason.RankFailToMeetTheCondition), nil)
return
}
resp, err := cc.commentService.UpdateComment(ctx, req) resp, err := cc.commentService.UpdateComment(ctx, req)
if !isAdmin || !linkUrlLimitUser { if !req.IsAdmin || !linkUrlLimitUser {
cc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionEdit, req.UserID) cc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionEdit, req.UserID)
} }
handler.HandleResponse(ctx, err, resp) handler.HandleResponse(ctx, err, resp)

View File

@ -686,9 +686,9 @@ func (qc *QuestionController) UpdateQuestionInviteUser(ctx *gin.Context) {
handler.HandleResponse(ctx, nil, nil) handler.HandleResponse(ctx, nil, nil)
} }
// SearchByTitleLike add question title like // GetSimilarQuestions fuzzy query similar questions based on title
// @Summary add question title like // @Summary fuzzy query similar questions based on title
// @Description add question title like // @Description fuzzy query similar questions based on title
// @Tags Question // @Tags Question
// @Accept json // @Accept json
// @Produce json // @Produce json
@ -696,10 +696,9 @@ func (qc *QuestionController) UpdateQuestionInviteUser(ctx *gin.Context) {
// @Param title query string true "title" default(string) // @Param title query string true "title" default(string)
// @Success 200 {object} handler.RespBody // @Success 200 {object} handler.RespBody
// @Router /answer/api/v1/question/similar [get] // @Router /answer/api/v1/question/similar [get]
func (qc *QuestionController) SearchByTitleLike(ctx *gin.Context) { func (qc *QuestionController) GetSimilarQuestions(ctx *gin.Context) {
title := ctx.Query("title") title := ctx.Query("title")
userID := middleware.GetLoginUserIDFromContext(ctx) resp, err := qc.questionService.GetQuestionsByTitle(ctx, title)
resp, err := qc.questionService.SearchByTitleLike(ctx, title, userID)
handler.HandleResponse(ctx, err, resp) handler.HandleResponse(ctx, err, resp)
} }

View File

@ -45,7 +45,6 @@ func (tc *TagController) SearchTagLike(ctx *gin.Context) {
if handler.BindAndCheck(ctx, req) { if handler.BindAndCheck(ctx, req) {
return return
} }
req.IsAdmin = middleware.GetIsAdminFromContext(ctx)
resp, err := tc.tagCommonService.SearchTagLike(ctx, req) resp, err := tc.tagCommonService.SearchTagLike(ctx, req)
handler.HandleResponse(ctx, err, resp) handler.HandleResponse(ctx, err, resp)
} }

View File

@ -161,35 +161,41 @@ func (tc *TemplateController) QuestionList(ctx *gin.Context) {
} }
func (tc *TemplateController) QuestionInfoeRdirect(ctx *gin.Context, siteInfo *schema.TemplateSiteInfoResp, correctTitle bool) (jump bool, url string) { func (tc *TemplateController) QuestionInfoeRdirect(ctx *gin.Context, siteInfo *schema.TemplateSiteInfoResp, correctTitle bool) (jump bool, url string) {
id := ctx.Param("id") questionID := ctx.Param("id")
title := ctx.Param("title") title := ctx.Param("title")
answerID := uid.DeShortID(title)
titleIsAnswerID := false titleIsAnswerID := false
needChangeShortID := false needChangeShortID := false
objectType, err := obj.GetObjectTypeStrByObjectID(answerID)
if err == nil && objectType == constant.AnswerObjectType {
titleIsAnswerID = true
}
siteSeo, err := tc.siteInfoService.GetSiteSeo(ctx) siteSeo, err := tc.siteInfoService.GetSiteSeo(ctx)
if err != nil { if err != nil {
return false, "" return false, ""
} }
isShortID := uid.IsShortID(id) isShortID := uid.IsShortID(questionID)
if siteSeo.IsShortLink() { if siteSeo.IsShortLink() {
if !isShortID { if !isShortID {
id = uid.EnShortID(id) questionID = uid.EnShortID(questionID)
needChangeShortID = true needChangeShortID = true
} }
if titleIsAnswerID {
answerID = uid.EnShortID(answerID)
}
} else { } else {
if isShortID { if isShortID {
needChangeShortID = true needChangeShortID = true
id = uid.DeShortID(id) questionID = uid.DeShortID(questionID)
}
if titleIsAnswerID {
answerID = uid.DeShortID(answerID)
} }
} }
objectType, objectTypeerr := obj.GetObjectTypeStrByObjectID(uid.DeShortID(title)) url = fmt.Sprintf("%s/questions/%s", siteInfo.General.SiteUrl, questionID)
if objectTypeerr == nil {
if objectType == constant.AnswerObjectType {
titleIsAnswerID = true
}
}
url = fmt.Sprintf("%s/questions/%s", siteInfo.General.SiteUrl, id)
if siteInfo.SiteSeo.PermaLink == constant.PermaLinkQuestionID || siteInfo.SiteSeo.PermaLink == constant.PermaLinkQuestionIDByShortID { if siteInfo.SiteSeo.PermaLink == constant.PermaLinkQuestionID || siteInfo.SiteSeo.PermaLink == constant.PermaLinkQuestionIDByShortID {
if len(ctx.Request.URL.Query()) > 0 { if len(ctx.Request.URL.Query()) > 0 {
url = fmt.Sprintf("%s?%s", url, ctx.Request.URL.RawQuery) url = fmt.Sprintf("%s?%s", url, ctx.Request.URL.RawQuery)
@ -205,14 +211,14 @@ func (tc *TemplateController) QuestionInfoeRdirect(ctx *gin.Context, siteInfo *s
return true, url return true, url
} else { } else {
detail, err := tc.templateRenderController.QuestionDetail(ctx, id) detail, err := tc.templateRenderController.QuestionDetail(ctx, questionID)
if err != nil { if err != nil {
tc.Page404(ctx) tc.Page404(ctx)
return return
} }
url = fmt.Sprintf("%s/%s", url, htmltext.UrlTitle(detail.Title)) url = fmt.Sprintf("%s/%s", url, htmltext.UrlTitle(detail.Title))
if titleIsAnswerID { if titleIsAnswerID {
url = fmt.Sprintf("%s/%s", url, title) url = fmt.Sprintf("%s/%s", url, answerID)
} }
if len(ctx.Request.URL.Query()) > 0 { if len(ctx.Request.URL.Query()) > 0 {

View File

@ -2,6 +2,7 @@ package entity
import ( import (
"encoding/json" "encoding/json"
"github.com/segmentfault/pacman/log"
"github.com/answerdev/answer/pkg/converter" "github.com/answerdev/answer/pkg/converter"
) )
@ -33,6 +34,9 @@ func (c *Config) JsonString() string {
// GetIntValue get int value // GetIntValue get int value
func (c *Config) GetIntValue() int { func (c *Config) GetIntValue() int {
if len(c.Value) == 0 {
log.Warnf("config value is empty, key: %s, value: %s", c.Key, c.Value)
}
return converter.StringToInt(c.Value) return converter.StringToInt(c.Value)
} }

View File

@ -72,6 +72,7 @@ var migrations = []Migration{
NewMigration("v1.1.0", "add gravatar base url", updateCount, true), NewMigration("v1.1.0", "add gravatar base url", updateCount, true),
NewMigration("v1.1.1", "update the length of revision content", updateTheLengthOfRevisionContent, false), NewMigration("v1.1.1", "update the length of revision content", updateTheLengthOfRevisionContent, false),
NewMigration("v1.1.2", "add notification config", addNoticeConfig, true), NewMigration("v1.1.2", "add notification config", addNoticeConfig, true),
NewMigration("v1.1.3", "set default user notification config", setDefaultUserNotificationConfig, false),
} }
func GetMigrations() []Migration { func GetMigrations() []Migration {

View File

@ -0,0 +1,38 @@
package migrations
import (
"context"
"github.com/answerdev/answer/internal/base/constant"
"github.com/answerdev/answer/internal/entity"
"github.com/segmentfault/pacman/log"
"xorm.io/xorm"
)
func setDefaultUserNotificationConfig(ctx context.Context, x *xorm.Engine) error {
userIDs := make([]string, 0)
err := x.Context(ctx).Table("user").Select("id").Find(&userIDs)
if err != nil {
return err
}
for _, id := range userIDs {
bean := entity.UserNotificationConfig{UserID: id, Source: string(constant.InboxSource)}
exist, err := x.Context(ctx).Get(&bean)
if err != nil {
log.Error(err)
}
if exist {
continue
}
_, err = x.Context(ctx).Insert(&entity.UserNotificationConfig{
UserID: id,
Source: string(constant.InboxSource),
Channels: `[{"key":"email","enable":true}]`,
Enabled: true,
})
if err != nil {
log.Error(err)
}
}
return nil
}

View File

@ -46,15 +46,6 @@ func NewAnswerActivityRepo(
func (ar *AnswerActivityRepo) SaveAcceptAnswerActivity(ctx context.Context, op *schema.AcceptAnswerOperationInfo) ( func (ar *AnswerActivityRepo) SaveAcceptAnswerActivity(ctx context.Context, op *schema.AcceptAnswerOperationInfo) (
err error) { err error) {
// pre check
noNeedToDo, err := ar.activityPreCheck(ctx, op)
if err != nil {
return err
}
if noNeedToDo {
return nil
}
// save activity // save activity
_, err = ar.data.DB.Transaction(func(session *xorm.Session) (result any, err error) { _, err = ar.data.DB.Transaction(func(session *xorm.Session) (result any, err error) {
session = session.Context(ctx) session = session.Context(ctx)
@ -131,21 +122,6 @@ func (ar *AnswerActivityRepo) SaveCancelAcceptAnswerActivity(ctx context.Context
return nil return nil
} }
func (ar *AnswerActivityRepo) activityPreCheck(ctx context.Context, op *schema.AcceptAnswerOperationInfo) (
noNeedToDo bool, err error) {
activities, err := ar.getExistActivity(ctx, op)
if err != nil {
return false, err
}
done := 0
for _, act := range activities {
if act.Cancelled == entity.ActivityAvailable {
done++
}
}
return done == len(op.Activities), nil
}
func (ar *AnswerActivityRepo) acquireUserInfo(session *xorm.Session, userIDs []string) (map[string]*entity.User, error) { func (ar *AnswerActivityRepo) acquireUserInfo(session *xorm.Session, userIDs []string) (map[string]*entity.User, error) {
us := make([]*entity.User, 0) us := make([]*entity.User, 0)
err := session.In("id", userIDs).ForUpdate().Find(&us) err := session.In("id", userIDs).ForUpdate().Find(&us)
@ -286,18 +262,17 @@ func (ar *AnswerActivityRepo) rollbackUserRank(ctx context.Context, session *xor
func (ar *AnswerActivityRepo) getExistActivity(ctx context.Context, op *schema.AcceptAnswerOperationInfo) ([]*entity.Activity, error) { func (ar *AnswerActivityRepo) getExistActivity(ctx context.Context, op *schema.AcceptAnswerOperationInfo) ([]*entity.Activity, error) {
var activities []*entity.Activity var activities []*entity.Activity
for _, action := range op.Activities { for _, action := range op.Activities {
t := &entity.Activity{} var t []*entity.Activity
exist, err := ar.data.DB.Context(ctx). err := ar.data.DB.Context(ctx).
Where(builder.Eq{"user_id": action.ActivityUserID}). Where(builder.Eq{"user_id": action.ActivityUserID}).
And(builder.Eq{"trigger_user_id": action.TriggerUserID}).
And(builder.Eq{"activity_type": action.ActivityType}). And(builder.Eq{"activity_type": action.ActivityType}).
And(builder.Eq{"object_id": op.AnswerObjectID}). And(builder.Eq{"object_id": op.AnswerObjectID}).
Get(t) Find(&t)
if err != nil { if err != nil {
return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
} }
if exist { if len(t) > 0 {
activities = append(activities, t) activities = append(activities, t...)
} }
} }
return activities, nil return activities, nil

View File

@ -166,30 +166,29 @@ func (ar *answerRepo) GetAnswerPage(ctx context.Context, page, pageSize int, ans
return return
} }
// UpdateAccepted // UpdateAcceptedStatus update all accepted status of this question's answers
// If no answer is selected, the answer id can be 0 func (ar *answerRepo) UpdateAcceptedStatus(ctx context.Context, acceptedAnswerID string, questionID string) error {
func (ar *answerRepo) UpdateAccepted(ctx context.Context, id string, questionID string) error { acceptedAnswerID = uid.DeShortID(acceptedAnswerID)
if questionID == "" {
return nil
}
id = uid.DeShortID(id)
questionID = uid.DeShortID(questionID) questionID = uid.DeShortID(questionID)
var data entity.Answer
data.ID = id
data.Accepted = schema.AnswerAcceptedFailed // update all this question's answer accepted status to false
_, err := ar.data.DB.Context(ctx).Where("question_id =?", questionID).Cols("adopted").Update(&data) _, err := ar.data.DB.Context(ctx).Where("question_id = ?", questionID).Cols("adopted").Update(&entity.Answer{
Accepted: schema.AnswerAcceptedFailed,
})
if err != nil { if err != nil {
return err return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
} }
if id != "0" {
data.Accepted = schema.AnswerAcceptedEnable // if acceptedAnswerID is not empty, update accepted status to true
_, err = ar.data.DB.Context(ctx).Where("id = ?", id).Cols("adopted").Update(&data) if len(acceptedAnswerID) > 0 && acceptedAnswerID != "0" {
_, err = ar.data.DB.Context(ctx).Where("id = ?", acceptedAnswerID).Cols("adopted").Update(&entity.Answer{
Accepted: schema.AnswerAcceptedEnable,
})
if err != nil { if err != nil {
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
} }
} }
_ = ar.updateSearch(ctx, id) _ = ar.updateSearch(ctx, acceptedAnswerID)
return nil return nil
} }
@ -259,7 +258,7 @@ func (ar *answerRepo) SearchList(ctx context.Context, search *entity.AnswerSearc
search.PageSize = constant.DefaultPageSize search.PageSize = constant.DefaultPageSize
} }
offset := search.Page * search.PageSize offset := search.Page * search.PageSize
session := ar.data.DB.Context(ctx).Where("") session := ar.data.DB.Context(ctx)
if search.QuestionID != "" { if search.QuestionID != "" {
session = session.And("question_id = ?", search.QuestionID) session = session.And("question_id = ?", search.QuestionID)

View File

@ -2,9 +2,9 @@ package collection
import ( import (
"context" "context"
"github.com/answerdev/answer/internal/base/constant" "github.com/answerdev/answer/internal/base/constant"
"github.com/answerdev/answer/internal/base/data" "github.com/answerdev/answer/internal/base/data"
"github.com/answerdev/answer/internal/base/handler"
"github.com/answerdev/answer/internal/base/pager" "github.com/answerdev/answer/internal/base/pager"
"github.com/answerdev/answer/internal/base/reason" "github.com/answerdev/answer/internal/base/reason"
"github.com/answerdev/answer/internal/entity" "github.com/answerdev/answer/internal/entity"
@ -142,25 +142,32 @@ func (cr *collectionRepo) GetCollectionPage(ctx context.Context, page, pageSize
session = session.OrderBy("update_time desc") session = session.OrderBy("update_time desc")
total, err = pager.Help(page, pageSize, collectionList, collection, session) total, err = pager.Help(page, pageSize, collectionList, collection, session)
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
return return
} }
// SearchObjectCollected check object is collected or not // SearchObjectCollected check object is collected or not
func (cr *collectionRepo) SearchObjectCollected(ctx context.Context, userID string, objectIds []string) (map[string]bool, error) { func (cr *collectionRepo) SearchObjectCollected(ctx context.Context, userID string, objectIds []string) (map[string]bool, error) {
collectedMap := make(map[string]bool) for i := 0; i < len(objectIds); i++ {
for k, object_id := range objectIds { objectIds[i] = uid.DeShortID(objectIds[i])
objectIds[k] = uid.DeShortID(object_id)
} }
list, err := cr.SearchByObjectIDsAndUser(ctx, userID, objectIds) list, err := cr.SearchByObjectIDsAndUser(ctx, userID, objectIds)
if err != nil { if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
return collectedMap, err
} }
collectedMap := make(map[string]bool)
short := handler.GetEnableShortID(ctx)
for _, item := range list { for _, item := range list {
if short {
item.ObjectID = uid.EnShortID(item.ObjectID)
}
collectedMap[item.ObjectID] = true collectedMap[item.ObjectID] = true
} }
return collectedMap, err return collectedMap, nil
} }
// SearchList // SearchList

View File

@ -58,9 +58,13 @@ func (cr *commentRepo) RemoveComment(ctx context.Context, commentID string) (err
return return
} }
// UpdateComment update comment // UpdateCommentContent update comment
func (cr *commentRepo) UpdateComment(ctx context.Context, comment *entity.Comment) (err error) { func (cr *commentRepo) UpdateCommentContent(
_, err = cr.data.DB.Context(ctx).ID(comment.ID).Where("user_id = ?", comment.UserID).Update(comment) ctx context.Context, commentID string, originalText string, parsedText string) (err error) {
_, err = cr.data.DB.Context(ctx).ID(commentID).Update(&entity.Comment{
OriginalText: originalText,
ParsedText: parsedText,
})
if err != nil { if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
} }
@ -69,8 +73,7 @@ func (cr *commentRepo) UpdateComment(ctx context.Context, comment *entity.Commen
// GetComment get comment one // GetComment get comment one
func (cr *commentRepo) GetComment(ctx context.Context, commentID string) ( func (cr *commentRepo) GetComment(ctx context.Context, commentID string) (
comment *entity.Comment, exist bool, err error, comment *entity.Comment, exist bool, err error) {
) {
comment = &entity.Comment{} comment = &entity.Comment{}
exist, err = cr.data.DB.Context(ctx).ID(commentID).Get(comment) exist, err = cr.data.DB.Context(ctx).ID(commentID).Get(comment)
if err != nil { if err != nil {

View File

@ -28,7 +28,8 @@ func NewConfigRepo(data *data.Data) config.ConfigRepo {
func (cr configRepo) GetConfigByID(ctx context.Context, id int) (c *entity.Config, err error) { func (cr configRepo) GetConfigByID(ctx context.Context, id int) (c *entity.Config, err error) {
cacheKey := fmt.Sprintf("%s%d", constant.ConfigID2KEYCacheKeyPrefix, id) cacheKey := fmt.Sprintf("%s%d", constant.ConfigID2KEYCacheKeyPrefix, id)
if cacheData, exist, err := cr.data.Cache.GetString(ctx, cacheKey); err == nil && exist { cacheData, exist, err := cr.data.Cache.GetString(ctx, cacheKey)
if err == nil && exist && len(cacheData) > 0 {
c = &entity.Config{} c = &entity.Config{}
c.BuildByJSON([]byte(cacheData)) c.BuildByJSON([]byte(cacheData))
if c.ID > 0 { if c.ID > 0 {
@ -37,7 +38,7 @@ func (cr configRepo) GetConfigByID(ctx context.Context, id int) (c *entity.Confi
} }
c = &entity.Config{} c = &entity.Config{}
exist, err := cr.data.DB.Context(ctx).ID(id).Get(c) exist, err = cr.data.DB.Context(ctx).ID(id).Get(c)
if err != nil { if err != nil {
return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
} }
@ -46,7 +47,7 @@ func (cr configRepo) GetConfigByID(ctx context.Context, id int) (c *entity.Confi
} }
// update cache // update cache
if err := cr.data.Cache.SetString(ctx, cacheKey, c.JsonString(), -1); err != nil { if err := cr.data.Cache.SetString(ctx, cacheKey, c.JsonString(), constant.ConfigCacheTime); err != nil {
log.Error(err) log.Error(err)
} }
return c, nil return c, nil
@ -54,7 +55,8 @@ func (cr configRepo) GetConfigByID(ctx context.Context, id int) (c *entity.Confi
func (cr configRepo) GetConfigByKey(ctx context.Context, key string) (c *entity.Config, err error) { func (cr configRepo) GetConfigByKey(ctx context.Context, key string) (c *entity.Config, err error) {
cacheKey := constant.ConfigKEY2ContentCacheKeyPrefix + key cacheKey := constant.ConfigKEY2ContentCacheKeyPrefix + key
if cacheData, exist, err := cr.data.Cache.GetString(ctx, cacheKey); err == nil && exist { cacheData, exist, err := cr.data.Cache.GetString(ctx, cacheKey)
if err == nil && exist && len(cacheData) > 0 {
c = &entity.Config{} c = &entity.Config{}
c.BuildByJSON([]byte(cacheData)) c.BuildByJSON([]byte(cacheData))
if c.ID > 0 { if c.ID > 0 {
@ -63,7 +65,7 @@ func (cr configRepo) GetConfigByKey(ctx context.Context, key string) (c *entity.
} }
c = &entity.Config{Key: key} c = &entity.Config{Key: key}
exist, err := cr.data.DB.Context(ctx).Get(c) exist, err = cr.data.DB.Context(ctx).Get(c)
if err != nil { if err != nil {
return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
} }
@ -72,7 +74,7 @@ func (cr configRepo) GetConfigByKey(ctx context.Context, key string) (c *entity.
} }
// update cache // update cache
if err := cr.data.Cache.SetString(ctx, cacheKey, c.JsonString(), -1); err != nil { if err := cr.data.Cache.SetString(ctx, cacheKey, c.JsonString(), constant.ConfigCacheTime); err != nil {
log.Error(err) log.Error(err)
} }
return c, nil return c, nil
@ -99,11 +101,11 @@ func (cr configRepo) UpdateConfig(ctx context.Context, key string, value string)
cacheVal := oldConfig.JsonString() cacheVal := oldConfig.JsonString()
// update cache // update cache
if err := cr.data.Cache.SetString(ctx, if err := cr.data.Cache.SetString(ctx,
constant.ConfigKEY2ContentCacheKeyPrefix+key, cacheVal, -1); err != nil { constant.ConfigKEY2ContentCacheKeyPrefix+key, cacheVal, constant.ConfigCacheTime); err != nil {
log.Error(err) log.Error(err)
} }
if err := cr.data.Cache.SetString(ctx, if err := cr.data.Cache.SetString(ctx,
fmt.Sprintf("%s%d", constant.ConfigID2KEYCacheKeyPrefix, oldConfig.ID), cacheVal, -1); err != nil { fmt.Sprintf("%s%d", constant.ConfigID2KEYCacheKeyPrefix, oldConfig.ID), cacheVal, constant.ConfigCacheTime); err != nil {
log.Error(err) log.Error(err)
} }
return return

View File

@ -186,10 +186,15 @@ func (qr *questionRepo) GetQuestion(ctx context.Context, id string) (
return return
} }
// GetTagBySlugName get tag by slug name // GetQuestionsByTitle get question list by title
func (qr *questionRepo) SearchByTitleLike(ctx context.Context, title string) (questionList []*entity.Question, err error) { func (qr *questionRepo) GetQuestionsByTitle(ctx context.Context, title string, pageSize int) (
questionList []*entity.Question, err error) {
questionList = make([]*entity.Question, 0) questionList = make([]*entity.Question, 0)
err = qr.data.DB.Context(ctx).Table("question").Where("title like ?", "%"+title+"%").Limit(10, 0).Find(&questionList) session := qr.data.DB.Context(ctx)
session.Where("status != ?", entity.QuestionStatusDeleted)
session.Where("title like ?", "%"+title+"%")
session.Limit(pageSize)
err = session.Find(&questionList)
if err != nil { if err != nil {
return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
} }

View File

@ -65,7 +65,7 @@ func Test_commentRepo_UpdateComment(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
testCommentEntity.ParsedText = "test" testCommentEntity.ParsedText = "test"
err = commentRepo.UpdateComment(context.TODO(), testCommentEntity) err = commentRepo.UpdateCommentContent(context.TODO(), testCommentEntity, "", "")
assert.NoError(t, err) assert.NoError(t, err)
newComment, exist, err := commonCommentRepo.GetComment(context.TODO(), testCommentEntity.ID) newComment, exist, err := commonCommentRepo.GetComment(context.TODO(), testCommentEntity.ID)

View File

@ -3,6 +3,7 @@ package search_common
import ( import (
"context" "context"
"fmt" "fmt"
tagcommon "github.com/answerdev/answer/internal/service/tag_common"
"github.com/answerdev/answer/plugin" "github.com/answerdev/answer/plugin"
"strconv" "strconv"
"strings" "strings"
@ -19,7 +20,6 @@ import (
usercommon "github.com/answerdev/answer/internal/service/user_common" usercommon "github.com/answerdev/answer/internal/service/user_common"
"github.com/answerdev/answer/pkg/converter" "github.com/answerdev/answer/pkg/converter"
"github.com/answerdev/answer/pkg/obj" "github.com/answerdev/answer/pkg/obj"
"github.com/jinzhu/copier"
"github.com/segmentfault/pacman/errors" "github.com/segmentfault/pacman/errors"
"xorm.io/builder" "xorm.io/builder"
) )
@ -58,19 +58,26 @@ type searchRepo struct {
data *data.Data data *data.Data
userCommon *usercommon.UserCommon userCommon *usercommon.UserCommon
uniqueIDRepo unique.UniqueIDRepo uniqueIDRepo unique.UniqueIDRepo
tagCommon *tagcommon.TagCommonService
} }
// NewSearchRepo new repository // NewSearchRepo new repository
func NewSearchRepo(data *data.Data, uniqueIDRepo unique.UniqueIDRepo, userCommon *usercommon.UserCommon) search_common.SearchRepo { func NewSearchRepo(
data *data.Data,
uniqueIDRepo unique.UniqueIDRepo,
userCommon *usercommon.UserCommon,
tagCommon *tagcommon.TagCommonService,
) search_common.SearchRepo {
return &searchRepo{ return &searchRepo{
data: data, data: data,
uniqueIDRepo: uniqueIDRepo, uniqueIDRepo: uniqueIDRepo,
userCommon: userCommon, userCommon: userCommon,
tagCommon: tagCommon,
} }
} }
// SearchContents search question and answer data // SearchContents search question and answer data
func (sr *searchRepo) SearchContents(ctx context.Context, words []string, tagIDs []string, userID string, votes int, page, size int, order string) (resp []schema.SearchResult, total int64, err error) { func (sr *searchRepo) SearchContents(ctx context.Context, words []string, tagIDs []string, userID string, votes int, page, size int, order string) (resp []*schema.SearchResult, total int64, err error) {
words = filterWords(words) words = filterWords(words)
var ( var (
@ -210,7 +217,7 @@ func (sr *searchRepo) SearchContents(ctx context.Context, words []string, tagIDs
} }
// SearchQuestions search question data // SearchQuestions search question data
func (sr *searchRepo) SearchQuestions(ctx context.Context, words []string, tagIDs []string, notAccepted bool, views, answers int, page, size int, order string) (resp []schema.SearchResult, total int64, err error) { func (sr *searchRepo) SearchQuestions(ctx context.Context, words []string, tagIDs []string, notAccepted bool, views, answers int, page, size int, order string) (resp []*schema.SearchResult, total int64, err error) {
words = filterWords(words) words = filterWords(words)
var ( var (
qfs = qFields qfs = qFields
@ -319,7 +326,7 @@ func (sr *searchRepo) SearchQuestions(ctx context.Context, words []string, tagID
} }
// SearchAnswers search answer data // SearchAnswers search answer data
func (sr *searchRepo) SearchAnswers(ctx context.Context, words []string, tagIDs []string, accepted bool, questionID string, page, size int, order string) (resp []schema.SearchResult, total int64, err error) { func (sr *searchRepo) SearchAnswers(ctx context.Context, words []string, tagIDs []string, accepted bool, questionID string, page, size int, order string) (resp []*schema.SearchResult, total int64, err error) {
words = filterWords(words) words = filterWords(words)
var ( var (
@ -428,7 +435,7 @@ func (sr *searchRepo) parseOrder(ctx context.Context, order string) (res string)
} }
// ParseSearchPluginResult parse search plugin result // ParseSearchPluginResult parse search plugin result
func (sr *searchRepo) ParseSearchPluginResult(ctx context.Context, sres []plugin.SearchResult) (resp []schema.SearchResult, err error) { func (sr *searchRepo) ParseSearchPluginResult(ctx context.Context, sres []plugin.SearchResult) (resp []*schema.SearchResult, err error) {
var ( var (
qres []map[string][]byte qres []map[string][]byte
res = make([]map[string][]byte, 0) res = make([]map[string][]byte, 0)
@ -455,82 +462,79 @@ func (sr *searchRepo) ParseSearchPluginResult(ctx context.Context, sres []plugin
} }
// parseResult parse search result, return the data structure // parseResult parse search result, return the data structure
func (sr *searchRepo) parseResult(ctx context.Context, res []map[string][]byte) (resp []schema.SearchResult, err error) { func (sr *searchRepo) parseResult(ctx context.Context, res []map[string][]byte) (resp []*schema.SearchResult, err error) {
questionIDs := make([]string, 0)
userIDs := make([]string, 0)
resultList := make([]*schema.SearchResult, 0)
for _, r := range res { for _, r := range res {
var ( questionIDs = append(questionIDs, string(r["question_id"]))
objectKey, userIDs = append(userIDs, string(r["user_id"]))
status string tp, _ := time.ParseInLocation("2006-01-02 15:04:05", string(r["created_at"]), time.Local)
object := &schema.SearchObject{
ID: string(r["id"]),
QuestionID: string(r["question_id"]),
Title: string(r["title"]),
Excerpt: htmltext.FetchExcerpt(string(r["parsed_text"]), "...", 240),
CreatedAtParsed: tp.Unix(),
UserInfo: &schema.SearchObjectUser{
ID: string(r["user_id"]),
},
Tags: make([]*schema.TagResp, 0),
VoteCount: converter.StringToInt(string(r["vote_count"])),
Accepted: string(r["accepted"]) == "2",
AnswerCount: converter.StringToInt(string(r["answer_count"])),
}
tags []schema.TagResp objectKey, err := obj.GetObjectTypeStrByObjectID(string(r["id"]))
tagsEntity []entity.Tag
object schema.SearchObject
)
objectKey, err = obj.GetObjectTypeStrByObjectID(string(r["id"]))
if err != nil { if err != nil {
continue continue
} }
tp, _ := time.ParseInLocation("2006-01-02 15:04:05", string(r["created_at"]), time.Local)
// get user info
userInfo, _, e := sr.userCommon.GetUserBasicInfoByID(ctx, string(r["user_id"]))
if e != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
return
}
// get tags
err = sr.data.DB.Context(ctx).
Select("`display_name`,`slug_name`,`main_tag_slug_name`,`recommend`,`reserved`").
Table("tag").
Join("INNER", "tag_rel", "tag.id = tag_rel.tag_id").
Where(builder.Eq{"tag_rel.object_id": r["question_id"]}).
And(builder.Eq{"tag_rel.status": entity.TagRelStatusAvailable}).
UseBool("recommend", "reserved").
OrderBy("tag.recommend DESC, tag.reserved DESC, tag.id DESC").
Find(&tagsEntity)
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
return
}
_ = copier.Copy(&tags, tagsEntity)
switch objectKey { switch objectKey {
case "question": case "question":
for k, v := range entity.AdminQuestionSearchStatus { for k, v := range entity.AdminQuestionSearchStatus {
if v == converter.StringToInt(string(r["status"])) { if v == converter.StringToInt(string(r["status"])) {
status = k object.StatusStr = k
break break
} }
} }
case "answer": case "answer":
for k, v := range entity.AdminAnswerSearchStatus { for k, v := range entity.AdminAnswerSearchStatus {
if v == converter.StringToInt(string(r["status"])) { if v == converter.StringToInt(string(r["status"])) {
status = k object.StatusStr = k
break break
} }
} }
} }
object = schema.SearchObject{ resultList = append(resultList, &schema.SearchResult{
ID: string(r["id"]),
QuestionID: string(r["question_id"]),
Title: string(r["title"]),
Excerpt: htmltext.FetchExcerpt(string(r["parsed_text"]), "...", 240),
CreatedAtParsed: tp.Unix(),
UserInfo: userInfo,
Tags: tags,
VoteCount: converter.StringToInt(string(r["vote_count"])),
Accepted: string(r["accepted"]) == "2",
AnswerCount: converter.StringToInt(string(r["answer_count"])),
StatusStr: status,
}
resp = append(resp, schema.SearchResult{
ObjectType: objectKey, ObjectType: objectKey,
Object: object, Object: object,
}) })
} }
return
tagsMap, err := sr.tagCommon.BatchGetObjectTag(ctx, questionIDs)
if err != nil {
return nil, err
}
userInfoMap, err := sr.userCommon.BatchUserBasicInfoByID(ctx, userIDs)
if err != nil {
return nil, err
}
for _, item := range resultList {
tags, ok := tagsMap[item.Object.QuestionID]
if ok {
item.Object.Tags = tags
}
if userInfo := userInfoMap[item.Object.UserInfo.ID]; userInfo != nil {
item.Object.UserInfo.Username = userInfo.Username
item.Object.UserInfo.DisplayName = userInfo.DisplayName
item.Object.UserInfo.Rank = userInfo.Rank
item.Object.UserInfo.Status = userInfo.Status
}
}
return resultList, nil
} }
func addRelevanceField(searchFields, words, fields []string) (res []string, args []interface{}) { func addRelevanceField(searchFields, words, fields []string) (res []string, args []interface{}) {

View File

@ -3,6 +3,7 @@ package tag_common
import ( import (
"context" "context"
"fmt" "fmt"
"strings"
"github.com/answerdev/answer/internal/base/data" "github.com/answerdev/answer/internal/base/data"
"github.com/answerdev/answer/internal/base/pager" "github.com/answerdev/answer/internal/base/pager"
@ -56,19 +57,28 @@ func (tr *tagCommonRepo) GetTagBySlugName(ctx context.Context, slugName string)
} }
// GetTagListByName get tag list all like name // GetTagListByName get tag list all like name
func (tr *tagCommonRepo) GetTagListByName(ctx context.Context, name string, hasReserved bool) (tagList []*entity.Tag, err error) { func (tr *tagCommonRepo) GetTagListByName(ctx context.Context, name string, recommend, reserved bool) (tagList []*entity.Tag, err error) {
tagList = make([]*entity.Tag, 0)
cond := &entity.Tag{} cond := &entity.Tag{}
session := tr.data.DB.Context(ctx).Where("") session := tr.data.DB.Context(ctx)
if name != "" { if len(name) > 0 {
session.Where("slug_name LIKE LOWER(?) or display_name LIKE ?", name+"%", name+"%") session.Where("slug_name LIKE ? OR display_name LIKE ?", strings.ToLower(name)+"%", name+"%")
} else { }
session.UseBool("recommend") var columns []string
if recommend {
columns = append(columns, "recommend")
cond.Recommend = true cond.Recommend = true
} }
if reserved {
columns = append(columns, "reserved")
cond.Reserved = true
}
if len(columns) > 0 {
session.UseBool(columns...)
}
session.Where(builder.Eq{"status": entity.TagStatusAvailable}) session.Where(builder.Eq{"status": entity.TagStatusAvailable})
session.Asc("slug_name")
err = session.OrderBy("recommend desc,reserved desc,id desc").Find(&tagList, cond) tagList = make([]*entity.Tag, 0)
err = session.OrderBy("recommend DESC,reserved DESC,slug_name ASC").Find(&tagList, cond)
if err != nil { if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
} }

View File

@ -131,21 +131,21 @@ func (ur *userAdminRepo) GetUserPage(ctx context.Context, page, pageSize int, us
session := ur.data.DB.Context(ctx) session := ur.data.DB.Context(ctx)
switch user.Status { switch user.Status {
case entity.UserStatusDeleted: case entity.UserStatusDeleted:
session.Desc("user.deleted_at") session.Desc("`user`.deleted_at")
case entity.UserStatusSuspended: case entity.UserStatusSuspended:
session.Desc("user.suspended_at") session.Desc("`user`.suspended_at")
default: default:
session.Desc("user.created_at") session.Desc("`user`.created_at")
} }
if len(usernameOrDisplayName) > 0 { if len(usernameOrDisplayName) > 0 {
session.And(builder.Or( session.And(builder.Or(
builder.Like{"user.username", usernameOrDisplayName}, builder.Like{"`user`.username", usernameOrDisplayName},
builder.Like{"user.display_name", usernameOrDisplayName}, builder.Like{"`user`.display_name", usernameOrDisplayName},
)) ))
} }
if isStaff { if isStaff {
session.Join("INNER", "user_role_rel", "user.id = user_role_rel.user_id AND user_role_rel.role_id > 1") session.Join("INNER", "user_role_rel", "`user`.id = `user_role_rel`.user_id AND `user_role_rel`.role_id > 1")
} }
total, err = pager.Help(page, pageSize, &users, user, session) total, err = pager.Help(page, pageSize, &users, user, session)

View File

@ -22,6 +22,24 @@ func NewUserNotificationConfigRepo(data *data.Data) user_notification_config.Use
} }
} }
// Add add notification config
func (ur *userNotificationConfigRepo) Add(ctx context.Context, userIDs []string, source, channels string) (err error) {
var configs []*entity.UserNotificationConfig
for _, userID := range userIDs {
configs = append(configs, &entity.UserNotificationConfig{
UserID: userID,
Source: source,
Channels: channels,
Enabled: true,
})
}
_, err = ur.data.DB.Context(ctx).Insert(configs)
if err != nil {
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
return nil
}
// Save save notification config, if existed, update, if not exist, insert // Save save notification config, if existed, update, if not exist, insert
func (ur *userNotificationConfigRepo) Save(ctx context.Context, uc *entity.UserNotificationConfig) (err error) { func (ur *userNotificationConfigRepo) Save(ctx context.Context, uc *entity.UserNotificationConfig) (err error) {
old := &entity.UserNotificationConfig{UserID: uc.UserID, Source: uc.Source} old := &entity.UserNotificationConfig{UserID: uc.UserID, Source: uc.Source}

View File

@ -203,7 +203,7 @@ func (a *AnswerAPIRouter) RegisterAnswerAPIRouter(r *gin.RouterGroup) {
r.PUT("/question/status", a.questionController.CloseQuestion) r.PUT("/question/status", a.questionController.CloseQuestion)
r.PUT("/question/operation", a.questionController.OperationQuestion) r.PUT("/question/operation", a.questionController.OperationQuestion)
r.PUT("/question/reopen", a.questionController.ReopenQuestion) r.PUT("/question/reopen", a.questionController.ReopenQuestion)
r.GET("/question/similar", a.questionController.SearchByTitleLike) r.GET("/question/similar", a.questionController.GetSimilarQuestions)
// answer // answer
r.POST("/answer", a.answerController.Add) r.POST("/answer", a.answerController.Add)

View File

@ -108,12 +108,19 @@ type AdminAnswerInfo struct {
} `json:"question_info"` } `json:"question_info"`
} }
type AnswerAcceptedReq struct { type AcceptAnswerReq struct {
QuestionID string `json:"question_id"` QuestionID string `validate:"required,gt=0,lte=30" json:"question_id"`
AnswerID string `json:"answer_id"` AnswerID string `validate:"omitempty" json:"answer_id"`
UserID string `json:"-"` UserID string `json:"-"`
} }
func (req *AcceptAnswerReq) Check() (errFields []*validator.FormErrorField, err error) {
if len(req.AnswerID) == 0 {
req.AnswerID = "0"
}
return nil, nil
}
type AdminSetAnswerStatusRequest struct { type AdminSetAnswerStatusRequest struct {
StatusStr string `json:"status"` StatusStr string `json:"status"`
AnswerID string `json:"answer_id"` AnswerID string `json:"answer_id"`

View File

@ -58,11 +58,10 @@ type UpdateCommentReq struct {
UserID string `json:"-"` UserID string `json:"-"`
IsAdmin bool `json:"-"` IsAdmin bool `json:"-"`
CanAdd bool `json:"-"`
// whether user can edit it // whether user can edit it
CanEdit bool `json:"-"` CanEdit bool `json:"-"`
// whether user can delete it // whether user can delete it
CanDelete bool `json:"-"`
CaptchaID string `json:"captcha_id"` // captcha_id CaptchaID string `json:"captcha_id"` // captcha_id
CaptchaCode string `json:"captcha_code"` CaptchaCode string `json:"captcha_code"`
} }
@ -72,6 +71,15 @@ func (req *UpdateCommentReq) Check() (errFields []*validator.FormErrorField, err
return nil, nil return nil, nil
} }
type UpdateCommentResp struct {
// comment id
CommentID string `json:"comment_id"`
// original comment content
OriginalText string `json:"original_text"`
// parsed comment content
ParsedText string `json:"parsed_text"`
}
// GetCommentListReq get comment list all request // GetCommentListReq get comment list all request
type GetCommentListReq struct { type GetCommentListReq struct {
// user id // user id

View File

@ -90,13 +90,21 @@ type SearchObject struct {
Accepted bool `json:"accepted"` Accepted bool `json:"accepted"`
AnswerCount int `json:"answer_count"` AnswerCount int `json:"answer_count"`
// user info // user info
UserInfo *UserBasicInfo `json:"user_info"` UserInfo *SearchObjectUser `json:"user_info"`
// tags // tags
Tags []TagResp `json:"tags"` Tags []*TagResp `json:"tags"`
// Status // Status
StatusStr string `json:"status"` StatusStr string `json:"status"`
} }
type SearchObjectUser struct {
ID string `json:"id"`
Username string `json:"username"`
DisplayName string `json:"display_name"`
Rank int `json:"rank"`
Status string `json:"status"`
}
type TagResp struct { type TagResp struct {
ID string `json:"-"` ID string `json:"-"`
SlugName string `json:"slug_name"` SlugName string `json:"slug_name"`
@ -111,13 +119,13 @@ type SearchResult struct {
// object_type // object_type
ObjectType string `json:"object_type"` ObjectType string `json:"object_type"`
// this object // this object
Object SearchObject `json:"object"` Object *SearchObject `json:"object"`
} }
type SearchResp struct { type SearchResp struct {
Total int64 `json:"count"` Total int64 `json:"count"`
// search response // search response
SearchResults []SearchResult `json:"list"` SearchResults []*SearchResult `json:"list"`
} }
type SearchDescResp struct { type SearchDescResp struct {

View File

@ -34,6 +34,9 @@ func NewAnswerActivityService(
// AcceptAnswer accept answer change activity // AcceptAnswer accept answer change activity
func (as *AnswerActivityService) AcceptAnswer(ctx context.Context, func (as *AnswerActivityService) AcceptAnswer(ctx context.Context,
loginUserID, answerObjID, questionObjID, questionUserID, answerUserID string, isSelf bool) (err error) { loginUserID, answerObjID, questionObjID, questionUserID, answerUserID string, isSelf bool) (err error) {
log.Debugf("user %s want to accept answer %s[%s] for question %s[%s]", loginUserID,
answerObjID, answerUserID,
questionObjID, questionUserID)
operationInfo := as.createAcceptAnswerOperationInfo(ctx, loginUserID, operationInfo := as.createAcceptAnswerOperationInfo(ctx, loginUserID,
answerObjID, questionObjID, questionUserID, answerUserID, isSelf) answerObjID, questionObjID, questionUserID, answerUserID, isSelf)
return as.answerActivityRepo.SaveAcceptAnswerActivity(ctx, operationInfo) return as.answerActivityRepo.SaveAcceptAnswerActivity(ctx, operationInfo)

View File

@ -17,7 +17,7 @@ type AnswerRepo interface {
GetAnswer(ctx context.Context, id string) (answer *entity.Answer, exist bool, err error) GetAnswer(ctx context.Context, id string) (answer *entity.Answer, exist bool, err error)
GetAnswerList(ctx context.Context, answer *entity.Answer) (answerList []*entity.Answer, err error) GetAnswerList(ctx context.Context, answer *entity.Answer) (answerList []*entity.Answer, err error)
GetAnswerPage(ctx context.Context, page, pageSize int, answer *entity.Answer) (answerList []*entity.Answer, total int64, err error) GetAnswerPage(ctx context.Context, page, pageSize int, answer *entity.Answer) (answerList []*entity.Answer, total int64, err error)
UpdateAccepted(ctx context.Context, id string, questionID string) error UpdateAcceptedStatus(ctx context.Context, acceptedAnswerID string, questionID string) error
GetByID(ctx context.Context, id string) (*entity.Answer, bool, error) GetByID(ctx context.Context, id string) (*entity.Answer, bool, error)
GetCountByQuestionID(ctx context.Context, questionID string) (int64, error) GetCountByQuestionID(ctx context.Context, questionID string) (int64, error)
GetCountByUserID(ctx context.Context, userID string) (int64, error) GetCountByUserID(ctx context.Context, userID string) (int64, error)
@ -83,6 +83,7 @@ func (as *AnswerCommon) ShowFormat(ctx context.Context, data *entity.Answer) *sc
info.UserID = data.UserID info.UserID = data.UserID
info.UpdateUserID = data.LastEditUserID info.UpdateUserID = data.LastEditUserID
info.Status = data.Status info.Status = data.Status
info.MemberActions = make([]*schema.PermissionMemberAction, 0)
return &info return &info
} }

View File

@ -230,15 +230,13 @@ func (as *AnswerService) Insert(ctx context.Context, req *schema.AnswerAddReq) (
} }
func (as *AnswerService) Update(ctx context.Context, req *schema.AnswerUpdateReq) (string, error) { func (as *AnswerService) Update(ctx context.Context, req *schema.AnswerUpdateReq) (string, error) {
//req.NoNeedReview //true 不需要审核
var canUpdate bool var canUpdate bool
_, existUnreviewed, err := as.revisionService.ExistUnreviewedByObjectID(ctx, req.ID) _, existUnreviewed, err := as.revisionService.ExistUnreviewedByObjectID(ctx, req.ID)
if err != nil { if err != nil {
return "", err return "", err
} }
if existUnreviewed { if existUnreviewed {
err = errors.BadRequest(reason.AnswerCannotUpdate) return "", errors.BadRequest(reason.AnswerCannotUpdate)
return "", err
} }
questionInfo, exist, err := as.questionRepo.GetQuestion(ctx, req.QuestionID) questionInfo, exist, err := as.questionRepo.GetQuestion(ctx, req.QuestionID)
@ -254,12 +252,11 @@ func (as *AnswerService) Update(ctx context.Context, req *schema.AnswerUpdateReq
return "", err return "", err
} }
if !exist { if !exist {
return "", nil return "", errors.BadRequest(reason.AnswerNotFound)
} }
if answerInfo.Status == entity.AnswerStatusDeleted { if answerInfo.Status == entity.AnswerStatusDeleted {
err = errors.BadRequest(reason.AnswerCannotUpdate) return "", errors.BadRequest(reason.AnswerCannotUpdate)
return "", err
} }
//If the content is the same, ignore it //If the content is the same, ignore it
@ -267,15 +264,13 @@ func (as *AnswerService) Update(ctx context.Context, req *schema.AnswerUpdateReq
return "", nil return "", nil
} }
now := time.Now() insertData := &entity.Answer{}
insertData := new(entity.Answer)
insertData.ID = req.ID insertData.ID = req.ID
insertData.UserID = answerInfo.UserID insertData.UserID = answerInfo.UserID
insertData.QuestionID = req.QuestionID insertData.QuestionID = req.QuestionID
insertData.OriginalText = req.Content insertData.OriginalText = req.Content
insertData.ParsedText = req.HTML insertData.ParsedText = req.HTML
insertData.UpdatedAt = now insertData.UpdatedAt = time.Now()
insertData.LastEditUserID = "0" insertData.LastEditUserID = "0"
if answerInfo.UserID != req.UserID { if answerInfo.UserID != req.UserID {
insertData.LastEditUserID = req.UserID insertData.LastEditUserID = req.UserID
@ -284,7 +279,6 @@ func (as *AnswerService) Update(ctx context.Context, req *schema.AnswerUpdateReq
revisionDTO := &schema.AddRevisionDTO{ revisionDTO := &schema.AddRevisionDTO{
UserID: req.UserID, UserID: req.UserID,
ObjectID: req.ID, ObjectID: req.ID,
Title: "",
Log: req.EditSummary, Log: req.EditSummary,
} }
@ -314,7 +308,7 @@ func (as *AnswerService) Update(ctx context.Context, req *schema.AnswerUpdateReq
} }
if canUpdate { if canUpdate {
as.activityQueueService.Send(ctx, &schema.ActivityMsg{ as.activityQueueService.Send(ctx, &schema.ActivityMsg{
UserID: insertData.UserID, UserID: req.UserID,
ObjectID: insertData.ID, ObjectID: insertData.ID,
OriginalObjectID: insertData.ID, OriginalObjectID: insertData.ID,
ActivityTypeKey: constant.ActAnswerEdited, ActivityTypeKey: constant.ActAnswerEdited,
@ -325,47 +319,47 @@ func (as *AnswerService) Update(ctx context.Context, req *schema.AnswerUpdateReq
return insertData.ID, nil return insertData.ID, nil
} }
// UpdateAccepted // AcceptAnswer accept answer
func (as *AnswerService) UpdateAccepted(ctx context.Context, req *schema.AnswerAcceptedReq) error { func (as *AnswerService) AcceptAnswer(ctx context.Context, req *schema.AcceptAnswerReq) (err error) {
if req.AnswerID == "" { // find question
req.AnswerID = "0"
}
if req.UserID == "" {
return nil
}
newAnswerInfo := &entity.Answer{}
newAnswerInfoexist := false
var err error
if req.AnswerID != "0" {
newAnswerInfo, newAnswerInfoexist, err = as.answerRepo.GetByID(ctx, req.AnswerID)
if err != nil {
return err
}
newAnswerInfo.ID = uid.DeShortID(newAnswerInfo.ID)
if !newAnswerInfoexist {
return errors.BadRequest(reason.AnswerNotFound)
}
}
questionInfo, exist, err := as.questionRepo.GetQuestion(ctx, req.QuestionID) questionInfo, exist, err := as.questionRepo.GetQuestion(ctx, req.QuestionID)
if err != nil { if err != nil {
return err return err
} }
questionInfo.ID = uid.DeShortID(questionInfo.ID)
if !exist { if !exist {
return errors.BadRequest(reason.QuestionNotFound) return errors.BadRequest(reason.QuestionNotFound)
} }
// if questionInfo.UserID != req.UserID { questionInfo.ID = uid.DeShortID(questionInfo.ID)
// return fmt.Errorf("no permission to set answer")
// }
if questionInfo.AcceptedAnswerID == req.AnswerID { if questionInfo.AcceptedAnswerID == req.AnswerID {
return nil return nil
} }
// find answer
var acceptedAnswerInfo *entity.Answer
if len(req.AnswerID) > 1 {
acceptedAnswerInfo, exist, err = as.answerRepo.GetByID(ctx, req.AnswerID)
if err != nil {
return err
}
if !exist {
return errors.BadRequest(reason.AnswerNotFound)
}
acceptedAnswerInfo.ID = uid.DeShortID(acceptedAnswerInfo.ID)
}
// update answers status
if err = as.answerRepo.UpdateAcceptedStatus(ctx, req.AnswerID, req.QuestionID); err != nil {
return err
}
// update question status
err = as.questionCommon.UpdateAccepted(ctx, req.QuestionID, req.AnswerID)
if err != nil {
log.Error("UpdateLastAnswer error", err.Error())
}
var oldAnswerInfo *entity.Answer var oldAnswerInfo *entity.Answer
if len(questionInfo.AcceptedAnswerID) > 0 && questionInfo.AcceptedAnswerID != "0" { if len(questionInfo.AcceptedAnswerID) > 1 {
oldAnswerInfo, _, err = as.answerRepo.GetByID(ctx, questionInfo.AcceptedAnswerID) oldAnswerInfo, _, err = as.answerRepo.GetByID(ctx, questionInfo.AcceptedAnswerID)
if err != nil { if err != nil {
return err return err
@ -373,17 +367,7 @@ func (as *AnswerService) UpdateAccepted(ctx context.Context, req *schema.AnswerA
oldAnswerInfo.ID = uid.DeShortID(oldAnswerInfo.ID) oldAnswerInfo.ID = uid.DeShortID(oldAnswerInfo.ID)
} }
err = as.answerRepo.UpdateAccepted(ctx, req.AnswerID, req.QuestionID) as.updateAnswerRank(ctx, req.UserID, questionInfo, acceptedAnswerInfo, oldAnswerInfo)
if err != nil {
return err
}
err = as.questionCommon.UpdateAccepted(ctx, req.QuestionID, req.AnswerID)
if err != nil {
log.Error("UpdateLastAnswer error", err.Error())
}
as.updateAnswerRank(ctx, req.UserID, questionInfo, newAnswerInfo, oldAnswerInfo)
return nil return nil
} }
@ -398,9 +382,9 @@ func (as *AnswerService) updateAnswerRank(ctx context.Context, userID string,
log.Error(err) log.Error(err)
} }
} }
if newAnswerInfo.ID != "" { if newAnswerInfo != nil {
err := as.answerActivityService.AcceptAnswer(ctx, userID, newAnswerInfo.ID, err := as.answerActivityService.AcceptAnswer(ctx, userID, newAnswerInfo.ID,
questionInfo.ID, questionInfo.UserID, newAnswerInfo.UserID, newAnswerInfo.UserID == userID) questionInfo.ID, questionInfo.UserID, newAnswerInfo.UserID, newAnswerInfo.UserID == questionInfo.UserID)
if err != nil { if err != nil {
log.Error(err) log.Error(err)
} }
@ -443,12 +427,11 @@ func (as *AnswerService) Get(ctx context.Context, answerID, loginUserID string)
info.VoteStatus = as.voteRepo.GetVoteStatus(ctx, answerID, loginUserID) info.VoteStatus = as.voteRepo.GetVoteStatus(ctx, answerID, loginUserID)
CollectedMap, err := as.collectionCommon.SearchObjectCollected(ctx, loginUserID, []string{answerInfo.ID}) collectedMap, err := as.collectionCommon.SearchObjectCollected(ctx, loginUserID, []string{answerInfo.ID})
if err != nil { if err != nil {
log.Error("CollectionFunc.SearchObjectCollected error", err) return nil, nil, has, err
} }
_, ok = CollectedMap[answerInfo.ID] if len(collectedMap) > 0 {
if ok {
info.Collected = true info.Collected = true
} }
@ -529,46 +512,28 @@ func (as *AnswerService) SearchFormatInfo(ctx context.Context, answers []*entity
item := as.ShowFormat(ctx, info) item := as.ShowFormat(ctx, info)
list = append(list, item) list = append(list, item)
objectIDs = append(objectIDs, info.ID) objectIDs = append(objectIDs, info.ID)
userIDs = append(userIDs, info.UserID) userIDs = append(userIDs, info.UserID, info.LastEditUserID)
userIDs = append(userIDs, info.LastEditUserID)
if req.UserID != "" {
item.ID = uid.DeShortID(item.ID)
item.VoteStatus = as.voteRepo.GetVoteStatus(ctx, item.ID, req.UserID)
}
} }
userInfoMap, err := as.userCommon.BatchUserBasicInfoByID(ctx, userIDs) userInfoMap, err := as.userCommon.BatchUserBasicInfoByID(ctx, userIDs)
if err != nil { if err != nil {
return list, err return list, err
} }
for _, item := range list { for _, item := range list {
_, ok := userInfoMap[item.UserID] item.UserInfo = userInfoMap[item.UserID]
if ok { item.UpdateUserInfo = userInfoMap[item.UpdateUserID]
item.UserInfo = userInfoMap[item.UserID]
}
_, ok = userInfoMap[item.UpdateUserID]
if ok {
item.UpdateUserInfo = userInfoMap[item.UpdateUserID]
}
} }
if len(req.UserID) == 0 {
if req.UserID == "" {
return list, nil return list, nil
} }
searchObjectCollected, err := as.collectionCommon.SearchObjectCollected(ctx, req.UserID, objectIDs) collectedMap, err := as.collectionCommon.SearchObjectCollected(ctx, req.UserID, objectIDs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, item := range list { for _, item := range list {
_, ok := searchObjectCollected[item.ID] item.VoteStatus = as.voteRepo.GetVoteStatus(ctx, item.ID, req.UserID)
if ok { item.Collected = collectedMap[item.ID]
item.Collected = true
}
}
for _, item := range list {
item.ID = uid.EnShortID(item.ID)
item.MemberActions = permission.GetAnswerPermission(ctx, req.UserID, item.UserID, req.CanEdit, req.CanDelete) item.MemberActions = permission.GetAnswerPermission(ctx, req.UserID, item.UserID, req.CanEdit, req.CanDelete)
} }
return list, nil return list, nil

View File

@ -29,7 +29,7 @@ import (
type CommentRepo interface { type CommentRepo interface {
AddComment(ctx context.Context, comment *entity.Comment) (err error) AddComment(ctx context.Context, comment *entity.Comment) (err error)
RemoveComment(ctx context.Context, commentID string) (err error) RemoveComment(ctx context.Context, commentID string) (err error)
UpdateComment(ctx context.Context, comment *entity.Comment) (err error) UpdateCommentContent(ctx context.Context, commentID string, original string, parsedText string) (err error)
GetComment(ctx context.Context, commentID string) (comment *entity.Comment, exist bool, err error) GetComment(ctx context.Context, commentID string) (comment *entity.Comment, exist bool, err error)
GetCommentPage(ctx context.Context, commentQuery *CommentQuery) ( GetCommentPage(ctx context.Context, commentQuery *CommentQuery) (
comments []*entity.Comment, total int64, err error) comments []*entity.Comment, total int64, err error)
@ -224,39 +224,34 @@ func (cs *CommentService) RemoveComment(ctx context.Context, req *schema.RemoveC
// UpdateComment update comment // UpdateComment update comment
func (cs *CommentService) UpdateComment(ctx context.Context, req *schema.UpdateCommentReq) ( func (cs *CommentService) UpdateComment(ctx context.Context, req *schema.UpdateCommentReq) (
resp *schema.GetCommentResp, err error) { resp *schema.UpdateCommentResp, err error) {
resp = &schema.GetCommentResp{}
old, exist, err := cs.commentCommonRepo.GetComment(ctx, req.CommentID) old, exist, err := cs.commentCommonRepo.GetComment(ctx, req.CommentID)
if err != nil {
return
}
if !exist {
return resp, errors.BadRequest(reason.CommentNotFound)
}
// user can edit the comment that was posted by himself before deadline.
if !req.IsAdmin && (time.Now().After(old.CreatedAt.Add(constant.CommentEditDeadline))) {
return resp, errors.BadRequest(reason.CommentCannotEditAfterDeadline)
}
comment := &entity.Comment{}
_ = copier.Copy(comment, req)
comment.ID = req.CommentID
resp.SetFromComment(comment)
resp.MemberActions = permission.GetCommentPermission(ctx, req.UserID, resp.UserID,
time.Now(), req.CanEdit, req.CanDelete)
userInfo, exist, err := cs.userCommon.GetUserBasicInfoByID(ctx, resp.UserID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if exist { if !exist {
resp.Username = userInfo.Username return nil, errors.BadRequest(reason.CommentNotFound)
resp.UserDisplayName = userInfo.DisplayName
resp.UserAvatar = userInfo.Avatar
resp.UserStatus = userInfo.Status
} }
return resp, cs.commentRepo.UpdateComment(ctx, comment) // user can't edit the comment that was posted by others except admin
if !req.IsAdmin && req.UserID != old.UserID {
return nil, errors.BadRequest(reason.CommentNotFound)
}
// user can edit the comment that was posted by himself before deadline.
// admin can edit it at any time
if !req.IsAdmin && (time.Now().After(old.CreatedAt.Add(constant.CommentEditDeadline))) {
return nil, errors.BadRequest(reason.CommentCannotEditAfterDeadline)
}
if err = cs.commentRepo.UpdateCommentContent(ctx, old.ID, req.OriginalText, req.ParsedText); err != nil {
return nil, err
}
resp = &schema.UpdateCommentResp{
CommentID: old.ID,
OriginalText: req.OriginalText,
ParsedText: req.ParsedText,
}
return resp, nil
} }
// GetComment get comment one // GetComment get comment one

View File

@ -40,7 +40,7 @@ type QuestionRepo interface {
UpdateQuestionStatus(ctx context.Context, question *entity.Question) (err error) UpdateQuestionStatus(ctx context.Context, question *entity.Question) (err error)
UpdateQuestionStatusWithOutUpdateTime(ctx context.Context, question *entity.Question) (err error) UpdateQuestionStatusWithOutUpdateTime(ctx context.Context, question *entity.Question) (err error)
UpdateQuestionOperation(ctx context.Context, question *entity.Question) (err error) UpdateQuestionOperation(ctx context.Context, question *entity.Question) (err error)
SearchByTitleLike(ctx context.Context, title string) (questionList []*entity.Question, err error) GetQuestionsByTitle(ctx context.Context, title string, pageSize int) (questionList []*entity.Question, err error)
UpdatePvCount(ctx context.Context, questionID string) (err error) UpdatePvCount(ctx context.Context, questionID string) (err error)
UpdateAnswerCount(ctx context.Context, questionID string, num int) (err error) UpdateAnswerCount(ctx context.Context, questionID string, num int) (err error)
UpdateCollectionCount(ctx context.Context, questionID string, num int) (err error) UpdateCollectionCount(ctx context.Context, questionID string, num int) (err error)
@ -282,17 +282,13 @@ func (qs *QuestionCommon) Info(ctx context.Context, questionID string, loginUser
} }
showinfo.Answered = has showinfo.Answered = has
// login user Collected information collectedMap, err := qs.collectionCommon.SearchObjectCollected(ctx, loginUserID, []string{dbinfo.ID})
CollectedMap, err := qs.collectionCommon.SearchObjectCollected(ctx, loginUserID, []string{dbinfo.ID})
if err != nil { if err != nil {
log.Error("CollectionFunc.SearchObjectCollected", err) return nil, err
} }
_, ok = CollectedMap[dbinfo.ID] if len(collectedMap) > 0 {
if ok {
showinfo.Collected = true showinfo.Collected = true
} }
return showinfo, nil return showinfo, nil
} }
@ -406,9 +402,7 @@ func (qs *QuestionCommon) FormatQuestions(ctx context.Context, questionList []*e
item := qs.ShowFormat(ctx, questionInfo) item := qs.ShowFormat(ctx, questionInfo)
list = append(list, item) list = append(list, item)
objectIds = append(objectIds, item.ID) objectIds = append(objectIds, item.ID)
userIds = append(userIds, item.UserID) userIds = append(userIds, item.UserID, item.LastEditUserID, item.LastAnsweredUserID)
userIds = append(userIds, item.LastEditUserID)
userIds = append(userIds, item.LastAnsweredUserID)
} }
tagsMap, err := qs.tagCommon.BatchGetObjectTag(ctx, objectIds) tagsMap, err := qs.tagCommon.BatchGetObjectTag(ctx, objectIds)
if err != nil { if err != nil {
@ -421,38 +415,21 @@ func (qs *QuestionCommon) FormatQuestions(ctx context.Context, questionList []*e
} }
for _, item := range list { for _, item := range list {
_, ok := tagsMap[item.ID] item.Tags = tagsMap[item.ID]
if ok { item.UserInfo = userInfoMap[item.UserID]
item.Tags = tagsMap[item.ID] item.UpdateUserInfo = userInfoMap[item.LastEditUserID]
} item.LastAnsweredUserInfo = userInfoMap[item.LastAnsweredUserID]
_, ok = userInfoMap[item.UserID]
if ok {
item.UserInfo = userInfoMap[item.UserID]
}
_, ok = userInfoMap[item.LastEditUserID]
if ok {
item.UpdateUserInfo = userInfoMap[item.LastEditUserID]
}
_, ok = userInfoMap[item.LastAnsweredUserID]
if ok {
item.LastAnsweredUserInfo = userInfoMap[item.LastAnsweredUserID]
}
} }
if loginUserID == "" { if loginUserID == "" {
return list, nil return list, nil
} }
// //login user Collected information
CollectedMap, err := qs.collectionCommon.SearchObjectCollected(ctx, loginUserID, objectIds)
if err != nil {
log.Error("CollectionFunc.SearchObjectCollected", err)
}
collectedMap, err := qs.collectionCommon.SearchObjectCollected(ctx, loginUserID, objectIds)
if err != nil {
return nil, err
}
for _, item := range list { for _, item := range list {
_, ok := CollectedMap[item.ID] item.Collected = collectedMap[item.ID]
if ok {
item.Collected = true
}
} }
return list, nil return list, nil
} }

View File

@ -1103,14 +1103,18 @@ func (qs *QuestionService) SearchUserTopList(ctx context.Context, userName strin
return userQuestionlist, userAnswerlist, nil return userQuestionlist, userAnswerlist, nil
} }
// SearchByTitleLike // GetQuestionsByTitle get questions by title
func (qs *QuestionService) SearchByTitleLike(ctx context.Context, title string, loginUserID string) ([]*schema.QuestionBaseInfo, error) { func (qs *QuestionService) GetQuestionsByTitle(ctx context.Context, title string) (
list := make([]*schema.QuestionBaseInfo, 0) resp []*schema.QuestionBaseInfo, err error) {
dblist, err := qs.questionRepo.SearchByTitleLike(ctx, title) resp = make([]*schema.QuestionBaseInfo, 0)
if err != nil { if len(title) == 0 {
return list, err return resp, nil
} }
for _, question := range dblist { questions, err := qs.questionRepo.GetQuestionsByTitle(ctx, title, 10)
if err != nil {
return resp, err
}
for _, question := range questions {
item := &schema.QuestionBaseInfo{} item := &schema.QuestionBaseInfo{}
item.ID = question.ID item.ID = question.ID
item.Title = question.Title item.Title = question.Title
@ -1125,10 +1129,9 @@ func (qs *QuestionService) SearchByTitleLike(ctx context.Context, title string,
if question.AcceptedAnswerID != "0" { if question.AcceptedAnswerID != "0" {
item.AcceptedAnswer = true item.AcceptedAnswer = true
} }
list = append(list, item) resp = append(resp, item)
} }
return resp, nil
return list, nil
} }
// SimilarQuestion // SimilarQuestion

View File

@ -7,8 +7,8 @@ import (
) )
type SearchRepo interface { type SearchRepo interface {
SearchContents(ctx context.Context, words []string, tagIDs []string, userID string, votes, page, size int, order string) (resp []schema.SearchResult, total int64, err error) SearchContents(ctx context.Context, words []string, tagIDs []string, userID string, votes, page, size int, order string) (resp []*schema.SearchResult, total int64, err error)
SearchQuestions(ctx context.Context, words []string, tagIDs []string, notAccepted bool, views, answers int, page, size int, order string) (resp []schema.SearchResult, total int64, err error) SearchQuestions(ctx context.Context, words []string, tagIDs []string, notAccepted bool, views, answers int, page, size int, order string) (resp []*schema.SearchResult, total int64, err error)
SearchAnswers(ctx context.Context, words []string, tagIDs []string, accepted bool, questionID string, page, size int, order string) (resp []schema.SearchResult, total int64, err error) SearchAnswers(ctx context.Context, words []string, tagIDs []string, accepted bool, questionID string, page, size int, order string) (resp []*schema.SearchResult, total int64, err error)
ParseSearchPluginResult(ctx context.Context, sres []plugin.SearchResult) (resp []schema.SearchResult, err error) ParseSearchPluginResult(ctx context.Context, sres []plugin.SearchResult) (resp []*schema.SearchResult, err error)
} }

View File

@ -2,6 +2,7 @@ package search_parser
import ( import (
"context" "context"
"fmt"
"github.com/answerdev/answer/internal/base/constant" "github.com/answerdev/answer/internal/base/constant"
"regexp" "regexp"
"strings" "strings"
@ -105,7 +106,11 @@ func (sp *SearchParser) parseTags(ctx context.Context, query *string) (tags []st
if err != nil || !exists { if err != nil || !exists {
continue continue
} }
tags = append(tags, tag.ID) if tag.MainTagID > 0 {
tags = append(tags, fmt.Sprintf("%d", tag.MainTagID))
} else {
tags = append(tags, tag.ID)
}
} }
// limit maximum 5 tags // limit maximum 5 tags

View File

@ -24,7 +24,7 @@ type TagCommonRepo interface {
AddTagList(ctx context.Context, tagList []*entity.Tag) (err error) AddTagList(ctx context.Context, tagList []*entity.Tag) (err error)
GetTagListByIDs(ctx context.Context, ids []string) (tagList []*entity.Tag, err error) GetTagListByIDs(ctx context.Context, ids []string) (tagList []*entity.Tag, err error)
GetTagBySlugName(ctx context.Context, slugName string) (tagInfo *entity.Tag, exist bool, err error) GetTagBySlugName(ctx context.Context, slugName string) (tagInfo *entity.Tag, exist bool, err error)
GetTagListByName(ctx context.Context, name string, hasReserved bool) (tagList []*entity.Tag, err error) GetTagListByName(ctx context.Context, name string, recommend, reserved bool) (tagList []*entity.Tag, err error)
GetTagListByNames(ctx context.Context, names []string) (tagList []*entity.Tag, err error) GetTagListByNames(ctx context.Context, names []string) (tagList []*entity.Tag, err error)
GetTagByID(ctx context.Context, tagID string, includeDeleted bool) (tag *entity.Tag, exist bool, err error) GetTagByID(ctx context.Context, tagID string, includeDeleted bool) (tag *entity.Tag, exist bool, err error)
GetTagPage(ctx context.Context, page, pageSize int, tag *entity.Tag, queryCond string) (tagList []*entity.Tag, total int64, err error) GetTagPage(ctx context.Context, page, pageSize int, tag *entity.Tag, queryCond string) (tagList []*entity.Tag, total int64, err error)
@ -86,7 +86,7 @@ func NewTagCommonService(
// SearchTagLike get tag list all // SearchTagLike get tag list all
func (ts *TagCommonService) SearchTagLike(ctx context.Context, req *schema.SearchTagLikeReq) (resp []schema.SearchTagLikeResp, err error) { func (ts *TagCommonService) SearchTagLike(ctx context.Context, req *schema.SearchTagLikeReq) (resp []schema.SearchTagLikeResp, err error) {
tags, err := ts.tagCommonRepo.GetTagListByName(ctx, req.Tag, req.IsAdmin) tags, err := ts.tagCommonRepo.GetTagListByName(ctx, req.Tag, len(req.Tag) == 0, false)
if err != nil { if err != nil {
return return
} }
@ -97,35 +97,39 @@ func (ts *TagCommonService) SearchTagLike(ctx context.Context, req *schema.Searc
mainTagId = append(mainTagId, converter.IntToString(tag.MainTagID)) mainTagId = append(mainTagId, converter.IntToString(tag.MainTagID))
} }
} }
mainTagList, err := ts.tagCommonRepo.GetTagListByIDs(ctx, mainTagId)
if err != nil {
return
}
mainTagMap := make(map[string]*entity.Tag) mainTagMap := make(map[string]*entity.Tag)
for _, tag := range mainTagList { if len(mainTagId) > 0 {
mainTagMap[tag.ID] = tag mainTagList, err := ts.tagCommonRepo.GetTagListByIDs(ctx, mainTagId)
} if err != nil {
for _, tag := range tags { return nil, err
if tag.MainTagID != 0 { }
_, ok := mainTagMap[converter.IntToString(tag.MainTagID)] for _, tag := range mainTagList {
if ok { mainTagMap[tag.ID] = tag
tag.SlugName = mainTagMap[converter.IntToString(tag.MainTagID)].SlugName
tag.DisplayName = mainTagMap[converter.IntToString(tag.MainTagID)].DisplayName
tag.Reserved = mainTagMap[converter.IntToString(tag.MainTagID)].Reserved
tag.Recommend = mainTagMap[converter.IntToString(tag.MainTagID)].Recommend
}
} }
} }
RepetitiveTag := make(map[string]bool)
for _, tag := range tags { for _, tag := range tags {
if _, ok := RepetitiveTag[tag.SlugName]; !ok { if tag.MainTagID == 0 {
continue
}
mainTagID := converter.IntToString(tag.MainTagID)
if _, ok := mainTagMap[mainTagID]; ok {
tag.SlugName = mainTagMap[mainTagID].SlugName
tag.DisplayName = mainTagMap[mainTagID].DisplayName
tag.Reserved = mainTagMap[mainTagID].Reserved
tag.Recommend = mainTagMap[mainTagID].Recommend
}
}
resp = make([]schema.SearchTagLikeResp, 0)
repetitiveTag := make(map[string]bool)
for _, tag := range tags {
if _, ok := repetitiveTag[tag.SlugName]; !ok {
item := schema.SearchTagLikeResp{} item := schema.SearchTagLikeResp{}
item.SlugName = tag.SlugName item.SlugName = tag.SlugName
item.DisplayName = tag.DisplayName item.DisplayName = tag.DisplayName
item.Recommend = tag.Recommend item.Recommend = tag.Recommend
item.Reserved = tag.Reserved item.Reserved = tag.Reserved
resp = append(resp, item) resp = append(resp, item)
RepetitiveTag[tag.SlugName] = true repetitiveTag[tag.SlugName] = true
} }
} }
return resp, nil return resp, nil
@ -432,6 +436,9 @@ func (ts *TagCommonService) tagFormatRecommendAndReserved(ctx context.Context, t
// BatchGetObjectTag batch get object tag // BatchGetObjectTag batch get object tag
func (ts *TagCommonService) BatchGetObjectTag(ctx context.Context, objectIds []string) (map[string][]*schema.TagResp, error) { func (ts *TagCommonService) BatchGetObjectTag(ctx context.Context, objectIds []string) (map[string][]*schema.TagResp, error) {
objectIDTagMap := make(map[string][]*schema.TagResp) objectIDTagMap := make(map[string][]*schema.TagResp)
if len(objectIds) == 0 {
return objectIDTagMap, nil
}
objectTagRelList, err := ts.tagRelRepo.BatchGetObjectTagRelList(ctx, objectIds) objectTagRelList, err := ts.tagRelRepo.BatchGetObjectTagRelList(ctx, objectIds)
if err != nil { if err != nil {
return objectIDTagMap, err return objectIDTagMap, err

View File

@ -106,9 +106,12 @@ func (us *UserCommon) UpdateQuestionCount(ctx context.Context, userID string, nu
return us.userRepo.UpdateQuestionCount(ctx, userID, num) return us.userRepo.UpdateQuestionCount(ctx, userID, num)
} }
func (us *UserCommon) BatchUserBasicInfoByID(ctx context.Context, IDs []string) (map[string]*schema.UserBasicInfo, error) { func (us *UserCommon) BatchUserBasicInfoByID(ctx context.Context, userIDs []string) (map[string]*schema.UserBasicInfo, error) {
userMap := make(map[string]*schema.UserBasicInfo) userMap := make(map[string]*schema.UserBasicInfo)
userList, err := us.userRepo.BatchGetByID(ctx, IDs) if len(userIDs) == 0 {
return userMap, nil
}
userList, err := us.userRepo.BatchGetByID(ctx, userIDs)
if err != nil { if err != nil {
return userMap, err return userMap, err
} }

View File

@ -9,6 +9,7 @@ import (
) )
type UserNotificationConfigRepo interface { type UserNotificationConfigRepo interface {
Add(ctx context.Context, userIDs []string, source, channels string) (err error)
Save(ctx context.Context, uc *entity.UserNotificationConfig) (err error) Save(ctx context.Context, uc *entity.UserNotificationConfig) (err error)
GetByUserID(ctx context.Context, userID string) ([]*entity.UserNotificationConfig, error) GetByUserID(ctx context.Context, userID string) ([]*entity.UserNotificationConfig, error)
GetBySource(ctx context.Context, source constant.NotificationSource) ([]*entity.UserNotificationConfig, error) GetBySource(ctx context.Context, source constant.NotificationSource) ([]*entity.UserNotificationConfig, error)
@ -68,6 +69,13 @@ func (us *UserNotificationConfigService) UpdateUserNotificationConfig(
return nil return nil
} }
// SetDefaultUserNotificationConfig set default user notification config for user register
func (us *UserNotificationConfigService) SetDefaultUserNotificationConfig(ctx context.Context, userIDs []string) (
err error) {
return us.userNotificationConfigRepo.Add(ctx, userIDs,
string(constant.InboxSource), `[{"key":"email","enable":true}]`)
}
func (us *UserNotificationConfigService) convertToEntity(ctx context.Context, userID string, func (us *UserNotificationConfigService) convertToEntity(ctx context.Context, userID string,
source constant.NotificationSource, channels schema.NotificationChannels) (c *entity.UserNotificationConfig) { source constant.NotificationSource, channels schema.NotificationChannels) (c *entity.UserNotificationConfig) {
c = &entity.UserNotificationConfig{ c = &entity.UserNotificationConfig{

View File

@ -32,16 +32,17 @@ import (
// UserService user service // UserService user service
type UserService struct { type UserService struct {
userCommonService *usercommon.UserCommon userCommonService *usercommon.UserCommon
userRepo usercommon.UserRepo userRepo usercommon.UserRepo
userActivity activity.UserActiveActivityRepo userActivity activity.UserActiveActivityRepo
activityRepo activity_common.ActivityRepo activityRepo activity_common.ActivityRepo
emailService *export.EmailService emailService *export.EmailService
authService *auth.AuthService authService *auth.AuthService
siteInfoService siteinfo_common.SiteInfoCommonService siteInfoService siteinfo_common.SiteInfoCommonService
userRoleService *role.UserRoleRelService userRoleService *role.UserRoleRelService
userExternalLoginService *user_external_login.UserExternalLoginService userExternalLoginService *user_external_login.UserExternalLoginService
userNotificationConfigRepo user_notification_config.UserNotificationConfigRepo userNotificationConfigRepo user_notification_config.UserNotificationConfigRepo
userNotificationConfigService *user_notification_config.UserNotificationConfigService
} }
func NewUserService(userRepo usercommon.UserRepo, func NewUserService(userRepo usercommon.UserRepo,
@ -54,18 +55,20 @@ func NewUserService(userRepo usercommon.UserRepo,
userCommonService *usercommon.UserCommon, userCommonService *usercommon.UserCommon,
userExternalLoginService *user_external_login.UserExternalLoginService, userExternalLoginService *user_external_login.UserExternalLoginService,
userNotificationConfigRepo user_notification_config.UserNotificationConfigRepo, userNotificationConfigRepo user_notification_config.UserNotificationConfigRepo,
userNotificationConfigService *user_notification_config.UserNotificationConfigService,
) *UserService { ) *UserService {
return &UserService{ return &UserService{
userCommonService: userCommonService, userCommonService: userCommonService,
userRepo: userRepo, userRepo: userRepo,
userActivity: userActivity, userActivity: userActivity,
activityRepo: activityRepo, activityRepo: activityRepo,
emailService: emailService, emailService: emailService,
authService: authService, authService: authService,
siteInfoService: siteInfoService, siteInfoService: siteInfoService,
userRoleService: userRoleService, userRoleService: userRoleService,
userExternalLoginService: userExternalLoginService, userExternalLoginService: userExternalLoginService,
userNotificationConfigRepo: userNotificationConfigRepo, userNotificationConfigRepo: userNotificationConfigRepo,
userNotificationConfigService: userNotificationConfigService,
} }
} }
@ -398,6 +401,9 @@ func (us *UserService) UserRegisterByEmail(ctx context.Context, registerUserInfo
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
if err := us.userNotificationConfigService.SetDefaultUserNotificationConfig(ctx, []string{userInfo.ID}); err != nil {
log.Errorf("set default user notification config failed, err: %v", err)
}
// send email // send email
data := &schema.EmailCodeContent{ data := &schema.EmailCodeContent{

View File

@ -12,6 +12,7 @@ interface Props {
avatarSearchStr?: string; avatarSearchStr?: string;
className?: string; className?: string;
avatarClass?: string; avatarClass?: string;
nameMaxWidth?: string;
} }
const Index: FC<Props> = ({ const Index: FC<Props> = ({
@ -22,11 +23,14 @@ const Index: FC<Props> = ({
className = 'small', className = 'small',
avatarSearchStr = 's=48', avatarSearchStr = 's=48',
showReputation = true, showReputation = true,
nameMaxWidth = '300px',
}) => { }) => {
return ( return (
<div className={`d-flex align-items-center text-secondary ${className}`}> <div className={`d-flex align-items-center text-secondary ${className}`}>
{data?.status !== 'deleted' ? ( {data?.status !== 'deleted' ? (
<Link to={`/users/${data?.username}`}> <Link
to={`/users/${data?.username}`}
className="d-flex align-items-center">
{showAvatar && ( {showAvatar && (
<Avatar <Avatar
avatar={data?.avatar} avatar={data?.avatar}
@ -36,7 +40,9 @@ const Index: FC<Props> = ({
alt={data?.display_name} alt={data?.display_name}
/> />
)} )}
<span className="me-1 text-truncate-1" style={{ maxWidth: '300px' }}> <span
className="me-1 name-ellipsis"
style={{ maxWidth: nameMaxWidth }}>
{data?.display_name} {data?.display_name}
</span> </span>
</Link> </Link>
@ -51,9 +57,7 @@ const Index: FC<Props> = ({
alt={data?.display_name} alt={data?.display_name}
/> />
)} )}
<span className="me-1 text-truncate-1" style={{ maxWidth: '300px' }}> <span className="me-1 name-ellipsis">{data?.display_name}</span>
{data?.display_name}
</span>
</> </>
)} )}

View File

@ -1,5 +1,5 @@
import { FC, useContext, useEffect } from 'react'; import { FC, useContext, useEffect } from 'react';
import { Dropdown, OverlayTrigger, Tooltip, Button } from 'react-bootstrap'; import { Dropdown, Button } from 'react-bootstrap';
import { EditorContext } from './EditorContext'; import { EditorContext } from './EditorContext';
@ -49,28 +49,27 @@ const ToolItem: FC<IProps> = (props) => {
}, []); }, []);
const btnRender = () => ( const btnRender = () => (
<OverlayTrigger placement="bottom" overlay={<Tooltip>{tip}</Tooltip>}> <Button
<Button variant="link"
variant="link" title={tip}
className={`p-0 b-0 btn-no-border toolbar icon-${label} ${ className={`p-0 b-0 btn-no-border toolbar icon-${label} ${
disable ? 'disabled' : '' disable ? 'disabled' : ''
} `} } `}
disabled={disable} disabled={disable}
tabIndex={-1} tabIndex={-1}
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
if (typeof onClick === 'function') { if (typeof onClick === 'function') {
onClick(); onClick();
} }
}} }}
onBlur={(e) => { onBlur={(e) => {
e.preventDefault(); e.preventDefault();
if (typeof onBlur === 'function') { if (typeof onBlur === 'function') {
onBlur(); onBlur();
} }
}} }}
/> />
</OverlayTrigger>
); );
if (!context) { if (!context) {

View File

@ -141,6 +141,13 @@ img[src=""] {
} }
} }
.name-ellipsis {
display: inline-block;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.text-truncate-1, .text-truncate-1,
.text-truncate-2, .text-truncate-2,
.text-truncate-3, .text-truncate-3,

View File

@ -155,7 +155,7 @@ const Answers: FC = () => {
<td>{li.vote_count}</td> <td>{li.vote_count}</td>
<td> <td>
<Stack> <Stack>
<BaseUserCard data={li.user_info} /> <BaseUserCard data={li.user_info} nameMaxWidth="200px" />
<FormatTime <FormatTime
className="small text-secondary" className="small text-secondary"

View File

@ -160,7 +160,7 @@ const Questions: FC = () => {
</td> </td>
<td> <td>
<Stack> <Stack>
<BaseUserCard data={li.user_info} /> <BaseUserCard data={li.user_info} nameMaxWidth="130px" />
<FormatTime <FormatTime
className="small text-secondary" className="small text-secondary"
time={li.create_time} time={li.create_time}

View File

@ -6,6 +6,7 @@ import { getSeoSetting, putSeoSetting } from '@/services';
import { SchemaForm, JSONSchema, initFormData, UISchema } from '@/components'; import { SchemaForm, JSONSchema, initFormData, UISchema } from '@/components';
import { useToast } from '@/hooks'; import { useToast } from '@/hooks';
import { handleFormError } from '@/utils'; import { handleFormError } from '@/utils';
import { seoSettingStore } from '@/stores';
const Index: FC = () => { const Index: FC = () => {
const { t } = useTranslation('translation', { const { t } = useTranslation('translation', {
@ -64,6 +65,7 @@ const Index: FC = () => {
msg: t('update', { keyPrefix: 'toast' }), msg: t('update', { keyPrefix: 'toast' }),
variant: 'success', variant: 'success',
}); });
seoSettingStore.getState().update(reqParams);
}) })
.catch((err) => { .catch((err) => {
if (err.isError) { if (err.isError) {

View File

@ -254,6 +254,7 @@ const Users: FC = () => {
avatarSearchStr="s=48" avatarSearchStr="s=48"
avatarClass="me-2" avatarClass="me-2"
showReputation={false} showReputation={false}
nameMaxWidth="160px"
/> />
</td> </td>
<td>{formatCount(user.rank)}</td> <td>{formatCount(user.rank)}</td>

View File

@ -28,6 +28,15 @@ const Index: FC<Props> = ({ visible, data, changeCallback, nextCallback }) => {
}; };
} }
if (site_name.value && site_name.value.length > 30) {
bol = false;
data.site_url = {
value: site_name.value,
isInvalid: true,
errorMsg: t('site_name.msg_max_length'),
};
}
if (!site_url.value) { if (!site_url.value) {
bol = false; bol = false;
data.site_url = { data.site_url = {
@ -36,6 +45,7 @@ const Index: FC<Props> = ({ visible, data, changeCallback, nextCallback }) => {
errorMsg: t('site_name.msg.empty'), errorMsg: t('site_name.msg.empty'),
}; };
} }
const reg = /^(http|https):\/\//g; const reg = /^(http|https):\/\//g;
if (site_url.value && !site_url.value.match(reg)) { if (site_url.value && !site_url.value.match(reg)) {
bol = false; bol = false;
@ -44,6 +54,13 @@ const Index: FC<Props> = ({ visible, data, changeCallback, nextCallback }) => {
isInvalid: true, isInvalid: true,
errorMsg: t('site_url.msg.incorrect'), errorMsg: t('site_url.msg.incorrect'),
}; };
} else if (site_url.value.length > 512) {
bol = false;
data.site_url = {
value: site_url.value,
isInvalid: true,
errorMsg: t('site_url.msg.max_length'),
};
} }
if (!contact_email.value) { if (!contact_email.value) {
@ -78,6 +95,13 @@ const Index: FC<Props> = ({ visible, data, changeCallback, nextCallback }) => {
isInvalid: true, isInvalid: true,
errorMsg: t('admin_name.character'), errorMsg: t('admin_name.character'),
}; };
} else if (data.name.value.length > 30) {
bol = false;
data.name = {
value: data.name.value,
isInvalid: true,
errorMsg: t('admin_name.msg_max_length'),
};
} }
if (!password.value) { if (!password.value) {
@ -89,6 +113,24 @@ const Index: FC<Props> = ({ visible, data, changeCallback, nextCallback }) => {
}; };
} }
if (password.value && password.value.length < 4) {
bol = false;
data.password = {
value: data.password.value,
isInvalid: true,
errorMsg: t('admin_password.msg_min_length'),
};
}
if (password.value && password.value.length > 32) {
bol = false;
data.password = {
value: data.password.value,
isInvalid: true,
errorMsg: t('admin_password.msg_max_length'),
};
}
if (!email.value) { if (!email.value) {
bol = false; bol = false;
data.email = { data.email = {
@ -132,7 +174,6 @@ const Index: FC<Props> = ({ visible, data, changeCallback, nextCallback }) => {
required required
value={data.site_name.value} value={data.site_name.value}
isInvalid={data.site_name.isInvalid} isInvalid={data.site_name.isInvalid}
maxLength={30}
onChange={(e) => { onChange={(e) => {
changeCallback({ changeCallback({
site_name: { site_name: {
@ -153,7 +194,6 @@ const Index: FC<Props> = ({ visible, data, changeCallback, nextCallback }) => {
required required
value={data.site_url.value} value={data.site_url.value}
isInvalid={data.site_url.isInvalid} isInvalid={data.site_url.isInvalid}
maxLength={512}
onChange={(e) => { onChange={(e) => {
changeCallback({ changeCallback({
site_url: { site_url: {
@ -220,7 +260,6 @@ const Index: FC<Props> = ({ visible, data, changeCallback, nextCallback }) => {
required required
value={data.name.value} value={data.name.value}
isInvalid={data.name.isInvalid} isInvalid={data.name.isInvalid}
maxLength={30}
onChange={(e) => { onChange={(e) => {
changeCallback({ changeCallback({
name: { name: {
@ -241,7 +280,6 @@ const Index: FC<Props> = ({ visible, data, changeCallback, nextCallback }) => {
<Form.Control <Form.Control
required required
type="password" type="password"
maxLength={32}
value={data.password.value} value={data.password.value}
isInvalid={data.password.isInvalid} isInvalid={data.password.isInvalid}
onChange={(e) => { onChange={(e) => {

View File

@ -23,7 +23,7 @@ import {
const Index: FC = () => { const Index: FC = () => {
const { t } = useTranslation('translation', { keyPrefix: 'install' }); const { t } = useTranslation('translation', { keyPrefix: 'install' });
const [step, setStep] = useState(1); const [step, setStep] = useState(4);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [errorData, setErrorData] = useState<{ [propName: string]: any }>({ const [errorData, setErrorData] = useState<{ [propName: string]: any }>({
msg: '', msg: '',

View File

@ -27,7 +27,7 @@ const SearchQuestion = ({ similarQuestions }) => {
<ListGroup.Item <ListGroup.Item
action action
as="a" as="a"
className="link-dark" className="d-flex align-items-center link-dark"
key={item.id} key={item.id}
href={pathFactory.questionLanding(item.id, item.url_title)} href={pathFactory.questionLanding(item.id, item.url_title)}
target="_blank"> target="_blank">
@ -38,20 +38,24 @@ const SearchQuestion = ({ similarQuestions }) => {
: null} : null}
</span> </span>
{item.accepted_answer ? ( {item.accepted_answer ? (
<span className="ms-3 text-success"> <span className="small ms-3 text-success">
<Icon type="bi" name="check-circle-fill" /> <Icon type="bi" name="check-circle-fill" />
<span className="ms-1">{item.answer_count}</span> <span className="ms-1">
{t('x_answers', {
keyPrefix: 'question',
count: item.answer_count,
})}
</span>
</span> </span>
) : ( ) : (
item.answer_count > 0 && ( item.answer_count > 0 && (
<span className="ms-3"> <span className="small ms-3 text-secondary">
<Icon <Icon type="bi" name="chat-square-text-fill" />
type="bi" <span className="ms-1">
name="chat-square-text-fill" {t('x_answers', {
className="text-secondary" keyPrefix: 'question',
/> count: item.answer_count,
<span className="ms-1 text-primary"> })}
{item.answer_count}
</span> </span>
</span> </span>
) )

View File

@ -108,7 +108,7 @@ const Index: FC = () => {
return ( return (
<Row className="pt-4 mb-5"> <Row className="pt-4 mb-5">
<Col className="page-main flex-auto"> <Col className="page-main flex-auto">
{isLoading || listLoading ? ( {isLoading ? (
<div className="tag-box mb-5 placeholder-glow"> <div className="tag-box mb-5 placeholder-glow">
<div className="mb-3 h3 placeholder" style={{ width: '120px' }} /> <div className="mb-3 h3 placeholder" style={{ width: '120px' }} />
<p <p

View File

@ -187,7 +187,6 @@ const Index: React.FC = () => {
tabIndex={1} tabIndex={1}
type="password" type="password"
// value={formData.pass.value} // value={formData.pass.value}
maxLength={32}
isInvalid={formData.pass.isInvalid} isInvalid={formData.pass.isInvalid}
onChange={(e) => onChange={(e) =>
handleChange({ handleChange({

View File

@ -127,7 +127,6 @@ const Index: React.FC = () => {
autoComplete="off" autoComplete="off"
required required
type="password" type="password"
maxLength={32}
isInvalid={formData.pass.isInvalid} isInvalid={formData.pass.isInvalid}
onChange={(e) => { onChange={(e) => {
handleChange({ handleChange({
@ -150,7 +149,6 @@ const Index: React.FC = () => {
autoComplete="off" autoComplete="off"
required required
type="password" type="password"
maxLength={32}
isInvalid={formData.passSecond.isInvalid} isInvalid={formData.passSecond.isInvalid}
onChange={(e) => { onChange={(e) => {
handleChange({ handleChange({

View File

@ -184,7 +184,6 @@ const Index: React.FC<Props> = ({ callback }) => {
autoComplete="off" autoComplete="off"
required required
type="password" type="password"
maxLength={32}
isInvalid={formData.pass.isInvalid} isInvalid={formData.pass.isInvalid}
value={formData.pass.value} value={formData.pass.value}
onChange={(e) => onChange={(e) =>

View File

@ -158,7 +158,6 @@ const Index: FC = () => {
autoComplete="new-password" autoComplete="new-password"
required required
type="password" type="password"
maxLength={32}
isInvalid={formData.pass.isInvalid} isInvalid={formData.pass.isInvalid}
onChange={(e) => onChange={(e) =>
handleChange({ handleChange({

View File

@ -185,7 +185,6 @@ const Index: FC = () => {
autoComplete="off" autoComplete="off"
required required
type="password" type="password"
maxLength={32}
isInvalid={formData.pass.isInvalid} isInvalid={formData.pass.isInvalid}
onChange={(e) => onChange={(e) =>
handleChange({ handleChange({
@ -208,7 +207,6 @@ const Index: FC = () => {
autoComplete="off" autoComplete="off"
required required
type="password" type="password"
maxLength={32}
isInvalid={formData.pass2.isInvalid} isInvalid={formData.pass2.isInvalid}
onChange={(e) => onChange={(e) =>
handleChange({ handleChange({

View File

@ -72,7 +72,9 @@ export const addComment = (params) => {
}; };
export const queryTags = (tag: string) => { export const queryTags = (tag: string) => {
return request.get(`/answer/api/v1/question/tags?tag=${tag}`); return request.get(
`/answer/api/v1/question/tags?tag=${encodeURIComponent(tag)}`,
);
}; };
export const useQueryAnswerInfo = (id: string) => { export const useQueryAnswerInfo = (id: string) => {