diff --git a/.gitignore b/.gitignore index d4063a95..5776cd0c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ /.fleet /.vscode/*.log /cmd/answer/*.sh +/cmd/answer/answer /cmd/answer/uploads/* /cmd/logs /configs/config-dev.yaml @@ -22,3 +23,5 @@ tmp vendor/ /answer-data/ /answer + +dist/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cc4dd08e..f96e65ef 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,8 +13,6 @@ stages: "compile the html and other static files": image: node:16 stage: compile-html - tags: - - runner-nanjing before_script: - npm config set registry https://repo.huaweicloud.com/repository/npm/ - make install-ui-packages @@ -27,10 +25,9 @@ stages: "compile the golang project": image: golang:1.18 stage: compile-golang - before_script: - - export GOPROXY=https://goproxy.cn,direct +# before_script: +# - export GOPROXY=https://goproxy.cn,direct script: - - make generate - make build artifacts: paths: @@ -38,8 +35,8 @@ stages: "build docker images and push": stage: push - before_script: - - export GOPROXY=https://goproxy.cn,direct +# before_script: +# - export GOPROXY=https://goproxy.cn,direct extends: .docker-build-push only: - test diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 00000000..fd9380ee --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,90 @@ +env: + - GO11MODULE=on + - GO111MODULE=on + - GOPROXY=https://goproxy.io + - CGO_ENABLED=1 + +before: + hooks: + - go mod tidy +builds: + - id: build-amd64 + main: ./cmd/answer/. + binary: answer + ldflags: -s -w -X main.Version={{.Version}} -X main.Revision={{.ShortCommit}} -X main.Time={{.Date}} -X main.BuildUser=goreleaser + goos: + - linux + goarch: + - amd64 + # linux windows need cgomingw64-gcc + - id: build-windows + main: ./cmd/answer/. + binary: answer + ldflags: -s -w -X main.Version={{.Version}} -X main.Revision={{.ShortCommit}} -X main.Time={{.Date}} -X main.BuildUser=goreleaser + env: + - CC=x86_64-w64-mingw32-gcc + - CXX=x86_64-w64-mingw32-g++ + goos: + - windows + goarch: + - amd64 + # linux arm64 need cgo arm64 + - id: build-arm64 + main: ./cmd/answer/. + binary: answer + ldflags: -s -w -X main.Version={{.Version}} -X main.Revision={{.ShortCommit}} -X main.Time={{.Date}} -X main.BuildUser=goreleaser + env: + - CC=aarch64-linux-gnu-gcc + - CXX=aarch64-linux-gnu-g++ + goos: + - linux + goarch: + - arm64 + - id: build-darwin-arm64 + main: ./cmd/answer/. + binary: answer + env: + - CC=oa64-clang + - CXX=oa64-clang++ + goos: + - darwin + goarch: + - arm64 + ldflags: -s -w -X main.Version={{.Version}} -X main.Revision={{.ShortCommit}} -X main.Time={{.Date}} -X main.BuildUser=goreleaser + flags: -v + - id: build-darwin-amd64 + main: ./cmd/answer/. + binary: answer + env: + - CC=o64-clang + - CXX=o64-clang++ + goos: + - darwin + goarch: + - amd64 + ldflags: -s -w -X main.Version={{.Version}} -X main.Revision={{.ShortCommit}} -X main.Time={{.Date}} -X main.BuildUser=goreleaser + flags: -v + + +archives: + - replacements: + darwin: Darwin + amd64: x86_64 +checksum: + name_template: 'checksums.txt' +snapshot: + name_template: "{{ incpatch .Version }}" +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' + + +# sudo apt-get install build-essential +# sudo apt-get install gcc-multilib g++-multilib +# sudo apt-get install gcc-mingw-w64 +# sudo apt-get -y install gcc-aarch64-linux-gnu gcc-arm-linux-gnueabihf +# sudo apt-get install clang llvm +# goreleaser release --snapshot --rm-dist \ No newline at end of file diff --git a/Makefile b/Makefile index 3c0b6a40..7f4e6ec7 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY: build clean ui -VERSION=0.5.0 +VERSION=1.0.0 BIN=answer DIR_SRC=./cmd/answer DOCKER_CMD=docker @@ -22,6 +22,7 @@ universal: generate: go get github.com/google/wire/cmd/wire@latest + go install github.com/golang/mock/mockgen@v1.6.0 go generate ./... go mod tidy diff --git a/cmd/answer/main.go b/cmd/answer/main.go index cea99db9..626eb2b2 100644 --- a/cmd/answer/main.go +++ b/cmd/answer/main.go @@ -6,6 +6,7 @@ import ( "github.com/answerdev/answer/internal/base/conf" "github.com/answerdev/answer/internal/base/constant" + "github.com/answerdev/answer/internal/base/cron" "github.com/answerdev/answer/internal/cli" "github.com/answerdev/answer/internal/schema" "github.com/gin-gonic/gin" @@ -45,6 +46,7 @@ func runApp() { if err != nil { panic(err) } + conf.GetPathIgnoreList() app, cleanup, err := initApplication( c.Debug, c.Server, c.Data.Database, c.Data.Cache, c.I18n, c.Swaggerui, c.ServiceConfig, log.GetLogger()) if err != nil { @@ -59,7 +61,8 @@ func runApp() { } } -func newApplication(serverConf *conf.Server, server *gin.Engine) *pacman.Application { +func newApplication(serverConf *conf.Server, server *gin.Engine, manager *cron.ScheduledTaskManager) *pacman.Application { + manager.Run() return pacman.NewApp( pacman.WithName(Name), pacman.WithVersion(Version), diff --git a/cmd/answer/wire.go b/cmd/answer/wire.go index 067314f7..11d735aa 100644 --- a/cmd/answer/wire.go +++ b/cmd/answer/wire.go @@ -7,11 +7,13 @@ package main import ( "github.com/answerdev/answer/internal/base/conf" + "github.com/answerdev/answer/internal/base/cron" "github.com/answerdev/answer/internal/base/data" "github.com/answerdev/answer/internal/base/middleware" "github.com/answerdev/answer/internal/base/server" "github.com/answerdev/answer/internal/base/translator" "github.com/answerdev/answer/internal/controller" + "github.com/answerdev/answer/internal/controller/template_render" "github.com/answerdev/answer/internal/controller_backyard" "github.com/answerdev/answer/internal/repo" "github.com/answerdev/answer/internal/router" @@ -37,7 +39,9 @@ func initApplication( router.ProviderSetRouter, controller.ProviderSetController, controller_backyard.ProviderSetController, + templaterender.ProviderSetTemplateRenderController, service.ProviderSetService, + cron.ProviderSetService, repo.ProviderSetRepo, translator.ProviderSet, middleware.ProviderSetMiddleware, diff --git a/cmd/answer/wire_gen.go b/cmd/answer/wire_gen.go index 852fd015..3fa06bf7 100644 --- a/cmd/answer/wire_gen.go +++ b/cmd/answer/wire_gen.go @@ -8,11 +8,13 @@ package main import ( "github.com/answerdev/answer/internal/base/conf" + "github.com/answerdev/answer/internal/base/cron" "github.com/answerdev/answer/internal/base/data" "github.com/answerdev/answer/internal/base/middleware" "github.com/answerdev/answer/internal/base/server" "github.com/answerdev/answer/internal/base/translator" "github.com/answerdev/answer/internal/controller" + "github.com/answerdev/answer/internal/controller/template_render" "github.com/answerdev/answer/internal/controller_backyard" "github.com/answerdev/answer/internal/repo/activity" "github.com/answerdev/answer/internal/repo/activity_common" @@ -31,6 +33,7 @@ import ( "github.com/answerdev/answer/internal/repo/reason" "github.com/answerdev/answer/internal/repo/report" "github.com/answerdev/answer/internal/repo/revision" + "github.com/answerdev/answer/internal/repo/role" "github.com/answerdev/answer/internal/repo/search_common" "github.com/answerdev/answer/internal/repo/site_info" "github.com/answerdev/answer/internal/repo/tag" @@ -61,6 +64,7 @@ import ( "github.com/answerdev/answer/internal/service/report_backyard" "github.com/answerdev/answer/internal/service/report_handle_backyard" "github.com/answerdev/answer/internal/service/revision_common" + role2 "github.com/answerdev/answer/internal/service/role" "github.com/answerdev/answer/internal/service/search_parser" "github.com/answerdev/answer/internal/service/service_config" "github.com/answerdev/answer/internal/service/siteinfo" @@ -109,14 +113,18 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, userActiveActivityRepo := activity.NewUserActiveActivityRepo(dataData, activityRepo, userRankRepo, configRepo) emailRepo := export.NewEmailRepo(dataData) emailService := export2.NewEmailService(configRepo, emailRepo, siteInfoRepo) - userService := service.NewUserService(userRepo, userActiveActivityRepo, emailService, authService, serviceConf, siteInfoCommonService) + userRoleRelRepo := role.NewUserRoleRelRepo(dataData) + roleRepo := role.NewRoleRepo(dataData) + roleService := role2.NewRoleService(roleRepo) + userRoleRelService := role2.NewUserRoleRelService(userRoleRelRepo, roleService) + userCommon := usercommon.NewUserCommon(userRepo) + userService := service.NewUserService(userRepo, userActiveActivityRepo, activityRepo, emailService, authService, serviceConf, siteInfoCommonService, userRoleRelService, userCommon) captchaRepo := captcha.NewCaptchaRepo(dataData) captchaService := action.NewCaptchaService(captchaRepo) uploaderService := uploader.NewUploaderService(serviceConf, siteInfoCommonService) - userController := controller.NewUserController(authService, userService, captchaService, emailService, uploaderService) + userController := controller.NewUserController(authService, userService, captchaService, emailService, uploaderService, siteInfoCommonService) commentRepo := comment.NewCommentRepo(dataData, uniqueIDRepo) commentCommonRepo := comment.NewCommentCommonRepo(dataData, uniqueIDRepo) - userCommon := usercommon.NewUserCommon(userRepo) answerRepo := answer.NewAnswerRepo(dataData, uniqueIDRepo, userRankRepo, activityRepo) questionRepo := question.NewQuestionRepo(dataData, uniqueIDRepo) tagCommonRepo := tag_common.NewTagCommonRepo(dataData, uniqueIDRepo) @@ -128,7 +136,9 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, objService := object_info.NewObjService(answerRepo, questionRepo, commentCommonRepo, tagCommonRepo, tagCommonService) voteRepo := activity_common.NewVoteRepo(dataData, activityRepo) commentService := comment2.NewCommentService(commentRepo, commentCommonRepo, userCommon, objService, voteRepo) - rankService := rank2.NewRankService(userCommon, userRankRepo, objService, configRepo) + rolePowerRelRepo := role.NewRolePowerRelRepo(dataData) + rolePowerRelService := role2.NewRolePowerRelService(rolePowerRelRepo, userRoleRelService) + rankService := rank2.NewRankService(userCommon, userRankRepo, objService, userRoleRelService, rolePowerRelService, configRepo) commentController := controller.NewCommentController(commentService, rankService) reportRepo := report.NewReportRepo(dataData, uniqueIDRepo) reportService := report2.NewReportService(reportRepo, objService) @@ -154,7 +164,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, answerActivityRepo := activity.NewAnswerActivityRepo(dataData, activityRepo, userRankRepo) questionActivityRepo := activity.NewQuestionActivityRepo(dataData, activityRepo, userRankRepo) answerActivityService := activity2.NewAnswerActivityService(answerActivityRepo, questionActivityRepo) - questionService := service.NewQuestionService(questionRepo, tagCommonService, questionCommon, userCommon, revisionService, metaService, collectionCommon, answerActivityService) + questionService := service.NewQuestionService(questionRepo, tagCommonService, questionCommon, userCommon, revisionService, metaService, collectionCommon, answerActivityService, dataData) questionController := controller.NewQuestionController(questionService, rankService) answerService := service.NewAnswerService(answerRepo, questionRepo, questionCommon, userCommon, collectionCommon, userRepo, revisionService, answerActivityService, answerCommon, voteRepo) dashboardService := dashboard.NewDashboardService(questionRepo, answerRepo, commentCommonRepo, voteRepo, userRepo, reportRepo, configRepo, siteInfoCommonService, serviceConf, dataData) @@ -171,13 +181,13 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, reportBackyardService := report_backyard.NewReportBackyardService(reportRepo, userCommon, commonRepo, answerRepo, questionRepo, commentCommonRepo, reportHandle, configRepo) controller_backyardReportController := controller_backyard.NewReportController(reportBackyardService) userBackyardRepo := user.NewUserBackyardRepo(dataData, authRepo) - userBackyardService := user_backyard.NewUserBackyardService(userBackyardRepo) + userBackyardService := user_backyard.NewUserBackyardService(userBackyardRepo, userRoleRelService, authService, userCommon) userBackyardController := controller_backyard.NewUserBackyardController(userBackyardService) reasonRepo := reason.NewReasonRepo(configRepo) reasonService := reason2.NewReasonService(reasonRepo) reasonController := controller.NewReasonController(reasonService) themeController := controller_backyard.NewThemeController() - siteInfoService := siteinfo.NewSiteInfoService(siteInfoRepo, emailService, tagCommonService) + siteInfoService := siteinfo.NewSiteInfoService(siteInfoRepo, siteInfoCommonService, emailService, tagCommonService) siteInfoController := controller_backyard.NewSiteInfoController(siteInfoService) siteinfoController := controller.NewSiteinfoController(siteInfoCommonService) notificationRepo := notification.NewNotificationRepo(dataData) @@ -191,13 +201,18 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, commentCommonService := comment_common.NewCommentCommonService(commentCommonRepo) activityService := activity2.NewActivityService(activityActivityRepo, userCommon, activityCommon, tagCommonService, objService, commentCommonService, revisionService, metaService) activityController := controller.NewActivityController(activityCommon, activityService) - answerAPIRouter := router.NewAnswerAPIRouter(langController, userController, commentController, reportController, voteController, tagController, followController, collectionController, questionController, answerController, searchController, revisionController, rankController, controller_backyardReportController, userBackyardController, reasonController, themeController, siteInfoController, siteinfoController, notificationController, dashboardController, uploadController, activityController) + roleController := controller_backyard.NewRoleController(roleService) + answerAPIRouter := router.NewAnswerAPIRouter(langController, userController, commentController, reportController, voteController, tagController, followController, collectionController, questionController, answerController, searchController, revisionController, rankController, controller_backyardReportController, userBackyardController, reasonController, themeController, siteInfoController, siteinfoController, notificationController, dashboardController, uploadController, activityController, roleController) swaggerRouter := router.NewSwaggerRouter(swaggerConf) - uiRouter := router.NewUIRouter() - authUserMiddleware := middleware.NewAuthUserMiddleware(authService) + uiRouter := router.NewUIRouter(siteinfoController, siteInfoCommonService) + authUserMiddleware := middleware.NewAuthUserMiddleware(authService, siteInfoCommonService) avatarMiddleware := middleware.NewAvatarMiddleware(serviceConf, uploaderService) - ginEngine := server.NewHTTPServer(debug, staticRouter, answerAPIRouter, swaggerRouter, uiRouter, authUserMiddleware, avatarMiddleware) - application := newApplication(serverConf, ginEngine) + templateRenderController := templaterender.NewTemplateRenderController(questionService, userService, tagService, answerService, commentService, dataData, siteInfoCommonService) + templateController := controller.NewTemplateController(templateRenderController, siteInfoCommonService) + templateRouter := router.NewTemplateRouter(templateController, templateRenderController, siteInfoController) + ginEngine := server.NewHTTPServer(debug, staticRouter, answerAPIRouter, swaggerRouter, uiRouter, authUserMiddleware, avatarMiddleware, templateRouter) + scheduledTaskManager := cron.NewScheduledTaskManager(siteInfoCommonService, questionService) + application := newApplication(serverConf, ginEngine, scheduledTaskManager) return application, func() { cleanup2() cleanup() diff --git a/configs/config.go b/configs/config.go index 52c7b843..3a7c32c2 100644 --- a/configs/config.go +++ b/configs/config.go @@ -4,3 +4,6 @@ import _ "embed" //go:embed config.yaml var Config []byte + +//go:embed path_ignore.yaml +var PathIgnore []byte diff --git a/configs/path_ignore.yaml b/configs/path_ignore.yaml new file mode 100644 index 00000000..4ecb1237 --- /dev/null +++ b/configs/path_ignore.yaml @@ -0,0 +1,13 @@ +# url path reserves the keywords list +users: + - settings + - login + - register + - account-recovery + - change-email + - password-reset + - account-activation + - confirm-new-email + - account-suspended +questions: + - ask diff --git a/docs/docs.go b/docs/docs.go index 21f184bc..05b8d73a 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -105,7 +105,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/entity.AdminSetAnswerStatusRequest" + "$ref": "#/definitions/schema.AdminSetAnswerStatusRequest" } } ], @@ -432,6 +432,41 @@ const docTemplate = `{ } } }, + "/answer/admin/api/roles": { + "get": { + "description": "get role list", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "get role list", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/handler.RespBody" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/schema.GetRoleResp" + } + } + } + } + ] + } + } + } + } + }, "/answer/admin/api/setting/smtp": { "get": { "security": [ @@ -574,6 +609,77 @@ const docTemplate = `{ } } }, + "/answer/admin/api/siteinfo/custom-css-html": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "get site info custom html css config", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "get site info custom html css config", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/handler.RespBody" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/schema.SiteCustomCssHTMLResp" + } + } + } + ] + } + } + } + }, + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "update site custom css html config", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "update site custom css html config", + "parameters": [ + { + "description": "login info", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/schema.SiteCustomCssHTMLReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handler.RespBody" + } + } + } + } + }, "/answer/admin/api/siteinfo/general": { "get": { "security": [ @@ -787,6 +893,219 @@ const docTemplate = `{ } } }, + "/answer/admin/api/siteinfo/login": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "get site info login config", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "get site info login config", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/handler.RespBody" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/schema.SiteLoginResp" + } + } + } + ] + } + } + } + }, + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "update site login", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "update site login", + "parameters": [ + { + "description": "login info", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/schema.SiteLoginReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handler.RespBody" + } + } + } + } + }, + "/answer/admin/api/siteinfo/seo": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "get site seo information", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "get site seo information", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/handler.RespBody" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/schema.SiteSeoResp" + } + } + } + ] + } + } + } + }, + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "update site seo information", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "update site seo information", + "parameters": [ + { + "description": "seo", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/schema.SiteSeoReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handler.RespBody" + } + } + } + } + }, + "/answer/admin/api/siteinfo/theme": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "get site info theme config", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "get site info theme config", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/handler.RespBody" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/schema.SiteThemeResp" + } + } + } + ] + } + } + } + }, + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "update site custom css html config", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "update site custom css html config", + "parameters": [ + { + "description": "login info", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/schema.SiteThemeReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handler.RespBody" + } + } + } + } + }, "/answer/admin/api/siteinfo/write": { "get": { "security": [ @@ -883,6 +1202,123 @@ const docTemplate = `{ } } }, + "/answer/admin/api/user": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "add user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "add user", + "parameters": [ + { + "description": "user", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/schema.AddUserReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handler.RespBody" + } + } + } + } + }, + "/answer/admin/api/user/password": { + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "update user password", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "update user password", + "parameters": [ + { + "description": "user", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/schema.UpdateUserPasswordReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handler.RespBody" + } + } + } + } + }, + "/answer/admin/api/user/role": { + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "update user role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "update user role", + "parameters": [ + { + "description": "user", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/schema.UpdateUserRoleReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handler.RespBody" + } + } + } + } + }, "/answer/admin/api/user/status": { "put": { "security": [ @@ -956,6 +1392,12 @@ const docTemplate = `{ "name": "query", "in": "query" }, + { + "type": "boolean", + "description": "staff user", + "name": "staff", + "in": "query" + }, { "enum": [ "suspended", @@ -2666,6 +3108,45 @@ const docTemplate = `{ } } }, + "/answer/api/v1/question/reopen": { + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "reopen question", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "api-question" + ], + "summary": "reopen question", + "parameters": [ + { + "description": "question", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/schema.ReopenQuestionReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handler.RespBody" + } + } + } + } + }, "/answer/api/v1/question/search": { "post": { "description": "SearchQuestionList", @@ -3266,7 +3747,7 @@ const docTemplate = `{ "type": "object", "properties": { "data": { - "$ref": "#/definitions/schema.SiteGeneralResp" + "$ref": "#/definitions/schema.SiteInfoResp" } } } @@ -4196,6 +4677,81 @@ const docTemplate = `{ } } }, + "/answer/api/v1/user/ranking": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "get user ranking", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "User" + ], + "summary": "get user ranking", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/handler.RespBody" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/schema.UserRankingResp" + } + } + } + ] + } + } + } + } + }, + "/answer/api/v1/user/register/captcha": { + "get": { + "description": "UserRegisterCaptcha", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "User" + ], + "summary": "UserRegisterCaptcha", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/handler.RespBody" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/schema.GetUserResp" + } + } + } + ] + } + } + } + } + }, "/answer/api/v1/user/register/email": { "post": { "description": "UserRegisterByEmail", @@ -4344,6 +4900,26 @@ const docTemplate = `{ } } }, + "/custom.css": { + "get": { + "description": "get site robots information", + "produces": [ + "application/json" + ], + "tags": [ + "site" + ], + "summary": "get site robots information", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, "/installation/base-info": { "post": { "description": "init base info", @@ -4592,20 +5168,29 @@ const docTemplate = `{ } } } + }, + "/robots.txt": { + "get": { + "description": "get site robots information", + "produces": [ + "application/json" + ], + "tags": [ + "site" + ], + "summary": "get site robots information", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } } }, "definitions": { - "entity.AdminSetAnswerStatusRequest": { - "type": "object", - "properties": { - "answer_id": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, "handler.RespBody": { "type": "object", "properties": { @@ -4732,6 +5317,9 @@ const docTemplate = `{ "display_name": { "type": "string" }, + "main_tag_slug_name": { + "type": "string" + }, "object_type": { "type": "string" }, @@ -4767,6 +5355,9 @@ const docTemplate = `{ "created_at": { "type": "integer" }, + "id": { + "type": "string" + }, "object_id": { "type": "string" }, @@ -4854,6 +5445,40 @@ const docTemplate = `{ } } }, + "schema.AddUserReq": { + "type": "object", + "required": [ + "display_name", + "email", + "password" + ], + "properties": { + "display_name": { + "type": "string", + "maxLength": 30 + }, + "email": { + "type": "string", + "maxLength": 500 + }, + "password": { + "type": "string", + "maxLength": 32, + "minLength": 8 + } + } + }, + "schema.AdminSetAnswerStatusRequest": { + "type": "object", + "properties": { + "answer_id": { + "type": "string" + }, + "status": { + "type": "string" + } + } + }, "schema.AdminSetQuestionStatusRequest": { "type": "object", "properties": { @@ -4889,7 +5514,6 @@ const docTemplate = `{ "type": "string" }, "question_id": { - "description": "question_id", "type": "string" } } @@ -5386,6 +6010,20 @@ const docTemplate = `{ } } }, + "schema.GetRoleResp": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, "schema.GetSMTPConfigResp": { "type": "object", "properties": { @@ -5495,6 +6133,10 @@ const docTemplate = `{ "description": "created time", "type": "integer" }, + "description": { + "description": "description text", + "type": "string" + }, "display_name": { "description": "display name", "type": "string" @@ -5614,6 +6256,14 @@ const docTemplate = `{ "description": "rank", "type": "integer" }, + "role_id": { + "description": "role id", + "type": "integer" + }, + "role_name": { + "description": "role name", + "type": "string" + }, "status": { "description": "user status(normal,suspended,deleted,inactive)", "type": "string" @@ -6061,6 +6711,14 @@ const docTemplate = `{ } } }, + "schema.ReopenQuestionReq": { + "type": "object", + "properties": { + "question_id": { + "type": "string" + } + } + }, "schema.ReportHandleReq": { "type": "object", "required": [ @@ -6221,6 +6879,48 @@ const docTemplate = `{ } } }, + "schema.SiteCustomCssHTMLReq": { + "type": "object", + "properties": { + "custom_css": { + "type": "string", + "maxLength": 65536 + }, + "custom_footer": { + "type": "string", + "maxLength": 65536 + }, + "custom_head": { + "type": "string", + "maxLength": 65536 + }, + "custom_header": { + "type": "string", + "maxLength": 65536 + } + } + }, + "schema.SiteCustomCssHTMLResp": { + "type": "object", + "properties": { + "custom_css": { + "type": "string", + "maxLength": 65536 + }, + "custom_footer": { + "type": "string", + "maxLength": 65536 + }, + "custom_head": { + "type": "string", + "maxLength": 65536 + }, + "custom_header": { + "type": "string", + "maxLength": 65536 + } + } + }, "schema.SiteGeneralReq": { "type": "object", "required": [ @@ -6281,6 +6981,32 @@ const docTemplate = `{ } } }, + "schema.SiteInfoResp": { + "type": "object", + "properties": { + "branding": { + "$ref": "#/definitions/schema.SiteBrandingResp" + }, + "custom_css_html": { + "$ref": "#/definitions/schema.SiteCustomCssHTMLResp" + }, + "general": { + "$ref": "#/definitions/schema.SiteGeneralResp" + }, + "interface": { + "$ref": "#/definitions/schema.SiteInterfaceResp" + }, + "login": { + "$ref": "#/definitions/schema.SiteLoginResp" + }, + "site__seo": { + "$ref": "#/definitions/schema.SiteSeoReq" + }, + "theme": { + "$ref": "#/definitions/schema.SiteThemeResp" + } + } + }, "schema.SiteInterfaceReq": { "type": "object", "required": [ @@ -6359,6 +7085,96 @@ const docTemplate = `{ } } }, + "schema.SiteLoginReq": { + "type": "object", + "properties": { + "allow_new_registrations": { + "type": "boolean" + }, + "login_required": { + "type": "boolean" + } + } + }, + "schema.SiteLoginResp": { + "type": "object", + "properties": { + "allow_new_registrations": { + "type": "boolean" + }, + "login_required": { + "type": "boolean" + } + } + }, + "schema.SiteSeoReq": { + "type": "object", + "required": [ + "permalink", + "robots" + ], + "properties": { + "permalink": { + "type": "integer", + "maximum": 3, + "minimum": 0 + }, + "robots": { + "type": "string" + } + } + }, + "schema.SiteSeoResp": { + "type": "object", + "required": [ + "permalink", + "robots" + ], + "properties": { + "permalink": { + "type": "integer", + "maximum": 3, + "minimum": 0 + }, + "robots": { + "type": "string" + } + } + }, + "schema.SiteThemeReq": { + "type": "object", + "required": [ + "theme" + ], + "properties": { + "theme": { + "type": "string", + "maxLength": 255 + }, + "theme_config": { + "type": "object", + "additionalProperties": true + } + } + }, + "schema.SiteThemeResp": { + "type": "object", + "properties": { + "theme": { + "type": "string" + }, + "theme_config": { + "type": "object", + "additionalProperties": true + }, + "theme_options": { + "type": "array", + "items": { + "$ref": "#/definitions/schema.ThemeOption" + } + } + } + }, "schema.SiteWriteReq": { "type": "object", "properties": { @@ -6464,6 +7280,17 @@ const docTemplate = `{ } } }, + "schema.ThemeOption": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, "schema.UnreviewedRevisionInfoInfo": { "type": "object", "properties": { @@ -6671,6 +7498,40 @@ const docTemplate = `{ } } }, + "schema.UpdateUserPasswordReq": { + "type": "object", + "required": [ + "password", + "user_id" + ], + "properties": { + "password": { + "type": "string", + "maxLength": 32, + "minLength": 8 + }, + "user_id": { + "type": "string" + } + } + }, + "schema.UpdateUserRoleReq": { + "type": "object", + "required": [ + "role_id", + "user_id" + ], + "properties": { + "role_id": { + "description": "role id", + "type": "integer" + }, + "user_id": { + "description": "user id", + "type": "string" + } + } + }, "schema.UpdateUserStatusReq": { "type": "object", "required": [ @@ -6705,6 +7566,10 @@ const docTemplate = `{ "description": "display_name", "type": "string" }, + "id": { + "description": "user_id", + "type": "string" + }, "ip_info": { "description": "ip info", "type": "string" @@ -6820,6 +7685,54 @@ const docTemplate = `{ } } }, + "schema.UserRankingResp": { + "type": "object", + "properties": { + "staffs": { + "type": "array", + "items": { + "$ref": "#/definitions/schema.UserRankingSimpleInfo" + } + }, + "users_with_the_most_reputation": { + "type": "array", + "items": { + "$ref": "#/definitions/schema.UserRankingSimpleInfo" + } + }, + "users_with_the_most_vote": { + "type": "array", + "items": { + "$ref": "#/definitions/schema.UserRankingSimpleInfo" + } + } + } + }, + "schema.UserRankingSimpleInfo": { + "type": "object", + "properties": { + "avatar": { + "description": "avatar", + "type": "string" + }, + "display_name": { + "description": "display name", + "type": "string" + }, + "rank": { + "description": "rank", + "type": "integer" + }, + "username": { + "description": "username", + "type": "string" + }, + "vote_count": { + "description": "vote", + "type": "integer" + } + } + }, "schema.UserRePassWordRequest": { "type": "object", "required": [ @@ -6847,6 +7760,14 @@ const docTemplate = `{ "pass" ], "properties": { + "captcha_code": { + "description": "captcha_code", + "type": "string" + }, + "captcha_id": { + "description": "captcha_id", + "type": "string" + }, "e_mail": { "description": "email", "type": "string", diff --git a/docs/swagger.json b/docs/swagger.json index 05fdf0af..913c2834 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -93,7 +93,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/entity.AdminSetAnswerStatusRequest" + "$ref": "#/definitions/schema.AdminSetAnswerStatusRequest" } } ], @@ -420,6 +420,41 @@ } } }, + "/answer/admin/api/roles": { + "get": { + "description": "get role list", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "get role list", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/handler.RespBody" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/schema.GetRoleResp" + } + } + } + } + ] + } + } + } + } + }, "/answer/admin/api/setting/smtp": { "get": { "security": [ @@ -562,6 +597,77 @@ } } }, + "/answer/admin/api/siteinfo/custom-css-html": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "get site info custom html css config", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "get site info custom html css config", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/handler.RespBody" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/schema.SiteCustomCssHTMLResp" + } + } + } + ] + } + } + } + }, + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "update site custom css html config", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "update site custom css html config", + "parameters": [ + { + "description": "login info", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/schema.SiteCustomCssHTMLReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handler.RespBody" + } + } + } + } + }, "/answer/admin/api/siteinfo/general": { "get": { "security": [ @@ -775,6 +881,219 @@ } } }, + "/answer/admin/api/siteinfo/login": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "get site info login config", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "get site info login config", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/handler.RespBody" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/schema.SiteLoginResp" + } + } + } + ] + } + } + } + }, + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "update site login", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "update site login", + "parameters": [ + { + "description": "login info", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/schema.SiteLoginReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handler.RespBody" + } + } + } + } + }, + "/answer/admin/api/siteinfo/seo": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "get site seo information", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "get site seo information", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/handler.RespBody" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/schema.SiteSeoResp" + } + } + } + ] + } + } + } + }, + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "update site seo information", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "update site seo information", + "parameters": [ + { + "description": "seo", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/schema.SiteSeoReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handler.RespBody" + } + } + } + } + }, + "/answer/admin/api/siteinfo/theme": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "get site info theme config", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "get site info theme config", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/handler.RespBody" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/schema.SiteThemeResp" + } + } + } + ] + } + } + } + }, + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "update site custom css html config", + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "update site custom css html config", + "parameters": [ + { + "description": "login info", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/schema.SiteThemeReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handler.RespBody" + } + } + } + } + }, "/answer/admin/api/siteinfo/write": { "get": { "security": [ @@ -871,6 +1190,123 @@ } } }, + "/answer/admin/api/user": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "add user", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "add user", + "parameters": [ + { + "description": "user", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/schema.AddUserReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handler.RespBody" + } + } + } + } + }, + "/answer/admin/api/user/password": { + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "update user password", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "update user password", + "parameters": [ + { + "description": "user", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/schema.UpdateUserPasswordReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handler.RespBody" + } + } + } + } + }, + "/answer/admin/api/user/role": { + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "update user role", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "update user role", + "parameters": [ + { + "description": "user", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/schema.UpdateUserRoleReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handler.RespBody" + } + } + } + } + }, "/answer/admin/api/user/status": { "put": { "security": [ @@ -944,6 +1380,12 @@ "name": "query", "in": "query" }, + { + "type": "boolean", + "description": "staff user", + "name": "staff", + "in": "query" + }, { "enum": [ "suspended", @@ -2654,6 +3096,45 @@ } } }, + "/answer/api/v1/question/reopen": { + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "reopen question", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "api-question" + ], + "summary": "reopen question", + "parameters": [ + { + "description": "question", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/schema.ReopenQuestionReq" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handler.RespBody" + } + } + } + } + }, "/answer/api/v1/question/search": { "post": { "description": "SearchQuestionList", @@ -3254,7 +3735,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/definitions/schema.SiteGeneralResp" + "$ref": "#/definitions/schema.SiteInfoResp" } } } @@ -4184,6 +4665,81 @@ } } }, + "/answer/api/v1/user/ranking": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "get user ranking", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "User" + ], + "summary": "get user ranking", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/handler.RespBody" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/schema.UserRankingResp" + } + } + } + ] + } + } + } + } + }, + "/answer/api/v1/user/register/captcha": { + "get": { + "description": "UserRegisterCaptcha", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "User" + ], + "summary": "UserRegisterCaptcha", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/handler.RespBody" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/schema.GetUserResp" + } + } + } + ] + } + } + } + } + }, "/answer/api/v1/user/register/email": { "post": { "description": "UserRegisterByEmail", @@ -4332,6 +4888,26 @@ } } }, + "/custom.css": { + "get": { + "description": "get site robots information", + "produces": [ + "application/json" + ], + "tags": [ + "site" + ], + "summary": "get site robots information", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, "/installation/base-info": { "post": { "description": "init base info", @@ -4580,20 +5156,29 @@ } } } + }, + "/robots.txt": { + "get": { + "description": "get site robots information", + "produces": [ + "application/json" + ], + "tags": [ + "site" + ], + "summary": "get site robots information", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } } }, "definitions": { - "entity.AdminSetAnswerStatusRequest": { - "type": "object", - "properties": { - "answer_id": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, "handler.RespBody": { "type": "object", "properties": { @@ -4720,6 +5305,9 @@ "display_name": { "type": "string" }, + "main_tag_slug_name": { + "type": "string" + }, "object_type": { "type": "string" }, @@ -4755,6 +5343,9 @@ "created_at": { "type": "integer" }, + "id": { + "type": "string" + }, "object_id": { "type": "string" }, @@ -4842,6 +5433,40 @@ } } }, + "schema.AddUserReq": { + "type": "object", + "required": [ + "display_name", + "email", + "password" + ], + "properties": { + "display_name": { + "type": "string", + "maxLength": 30 + }, + "email": { + "type": "string", + "maxLength": 500 + }, + "password": { + "type": "string", + "maxLength": 32, + "minLength": 8 + } + } + }, + "schema.AdminSetAnswerStatusRequest": { + "type": "object", + "properties": { + "answer_id": { + "type": "string" + }, + "status": { + "type": "string" + } + } + }, "schema.AdminSetQuestionStatusRequest": { "type": "object", "properties": { @@ -4877,7 +5502,6 @@ "type": "string" }, "question_id": { - "description": "question_id", "type": "string" } } @@ -5374,6 +5998,20 @@ } } }, + "schema.GetRoleResp": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, "schema.GetSMTPConfigResp": { "type": "object", "properties": { @@ -5483,6 +6121,10 @@ "description": "created time", "type": "integer" }, + "description": { + "description": "description text", + "type": "string" + }, "display_name": { "description": "display name", "type": "string" @@ -5602,6 +6244,14 @@ "description": "rank", "type": "integer" }, + "role_id": { + "description": "role id", + "type": "integer" + }, + "role_name": { + "description": "role name", + "type": "string" + }, "status": { "description": "user status(normal,suspended,deleted,inactive)", "type": "string" @@ -6049,6 +6699,14 @@ } } }, + "schema.ReopenQuestionReq": { + "type": "object", + "properties": { + "question_id": { + "type": "string" + } + } + }, "schema.ReportHandleReq": { "type": "object", "required": [ @@ -6209,6 +6867,48 @@ } } }, + "schema.SiteCustomCssHTMLReq": { + "type": "object", + "properties": { + "custom_css": { + "type": "string", + "maxLength": 65536 + }, + "custom_footer": { + "type": "string", + "maxLength": 65536 + }, + "custom_head": { + "type": "string", + "maxLength": 65536 + }, + "custom_header": { + "type": "string", + "maxLength": 65536 + } + } + }, + "schema.SiteCustomCssHTMLResp": { + "type": "object", + "properties": { + "custom_css": { + "type": "string", + "maxLength": 65536 + }, + "custom_footer": { + "type": "string", + "maxLength": 65536 + }, + "custom_head": { + "type": "string", + "maxLength": 65536 + }, + "custom_header": { + "type": "string", + "maxLength": 65536 + } + } + }, "schema.SiteGeneralReq": { "type": "object", "required": [ @@ -6269,6 +6969,32 @@ } } }, + "schema.SiteInfoResp": { + "type": "object", + "properties": { + "branding": { + "$ref": "#/definitions/schema.SiteBrandingResp" + }, + "custom_css_html": { + "$ref": "#/definitions/schema.SiteCustomCssHTMLResp" + }, + "general": { + "$ref": "#/definitions/schema.SiteGeneralResp" + }, + "interface": { + "$ref": "#/definitions/schema.SiteInterfaceResp" + }, + "login": { + "$ref": "#/definitions/schema.SiteLoginResp" + }, + "site__seo": { + "$ref": "#/definitions/schema.SiteSeoReq" + }, + "theme": { + "$ref": "#/definitions/schema.SiteThemeResp" + } + } + }, "schema.SiteInterfaceReq": { "type": "object", "required": [ @@ -6347,6 +7073,96 @@ } } }, + "schema.SiteLoginReq": { + "type": "object", + "properties": { + "allow_new_registrations": { + "type": "boolean" + }, + "login_required": { + "type": "boolean" + } + } + }, + "schema.SiteLoginResp": { + "type": "object", + "properties": { + "allow_new_registrations": { + "type": "boolean" + }, + "login_required": { + "type": "boolean" + } + } + }, + "schema.SiteSeoReq": { + "type": "object", + "required": [ + "permalink", + "robots" + ], + "properties": { + "permalink": { + "type": "integer", + "maximum": 3, + "minimum": 0 + }, + "robots": { + "type": "string" + } + } + }, + "schema.SiteSeoResp": { + "type": "object", + "required": [ + "permalink", + "robots" + ], + "properties": { + "permalink": { + "type": "integer", + "maximum": 3, + "minimum": 0 + }, + "robots": { + "type": "string" + } + } + }, + "schema.SiteThemeReq": { + "type": "object", + "required": [ + "theme" + ], + "properties": { + "theme": { + "type": "string", + "maxLength": 255 + }, + "theme_config": { + "type": "object", + "additionalProperties": true + } + } + }, + "schema.SiteThemeResp": { + "type": "object", + "properties": { + "theme": { + "type": "string" + }, + "theme_config": { + "type": "object", + "additionalProperties": true + }, + "theme_options": { + "type": "array", + "items": { + "$ref": "#/definitions/schema.ThemeOption" + } + } + } + }, "schema.SiteWriteReq": { "type": "object", "properties": { @@ -6452,6 +7268,17 @@ } } }, + "schema.ThemeOption": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, "schema.UnreviewedRevisionInfoInfo": { "type": "object", "properties": { @@ -6659,6 +7486,40 @@ } } }, + "schema.UpdateUserPasswordReq": { + "type": "object", + "required": [ + "password", + "user_id" + ], + "properties": { + "password": { + "type": "string", + "maxLength": 32, + "minLength": 8 + }, + "user_id": { + "type": "string" + } + } + }, + "schema.UpdateUserRoleReq": { + "type": "object", + "required": [ + "role_id", + "user_id" + ], + "properties": { + "role_id": { + "description": "role id", + "type": "integer" + }, + "user_id": { + "description": "user id", + "type": "string" + } + } + }, "schema.UpdateUserStatusReq": { "type": "object", "required": [ @@ -6693,6 +7554,10 @@ "description": "display_name", "type": "string" }, + "id": { + "description": "user_id", + "type": "string" + }, "ip_info": { "description": "ip info", "type": "string" @@ -6808,6 +7673,54 @@ } } }, + "schema.UserRankingResp": { + "type": "object", + "properties": { + "staffs": { + "type": "array", + "items": { + "$ref": "#/definitions/schema.UserRankingSimpleInfo" + } + }, + "users_with_the_most_reputation": { + "type": "array", + "items": { + "$ref": "#/definitions/schema.UserRankingSimpleInfo" + } + }, + "users_with_the_most_vote": { + "type": "array", + "items": { + "$ref": "#/definitions/schema.UserRankingSimpleInfo" + } + } + } + }, + "schema.UserRankingSimpleInfo": { + "type": "object", + "properties": { + "avatar": { + "description": "avatar", + "type": "string" + }, + "display_name": { + "description": "display name", + "type": "string" + }, + "rank": { + "description": "rank", + "type": "integer" + }, + "username": { + "description": "username", + "type": "string" + }, + "vote_count": { + "description": "vote", + "type": "integer" + } + } + }, "schema.UserRePassWordRequest": { "type": "object", "required": [ @@ -6835,6 +7748,14 @@ "pass" ], "properties": { + "captcha_code": { + "description": "captcha_code", + "type": "string" + }, + "captcha_id": { + "description": "captcha_id", + "type": "string" + }, "e_mail": { "description": "email", "type": "string", diff --git a/docs/swagger.yaml b/docs/swagger.yaml index ae9e1bf8..06837519 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1,11 +1,4 @@ definitions: - entity.AdminSetAnswerStatusRequest: - properties: - answer_id: - type: string - status: - type: string - type: object handler.RespBody: properties: code: @@ -95,6 +88,8 @@ definitions: type: string display_name: type: string + main_tag_slug_name: + type: string object_type: type: string question_id: @@ -118,6 +113,8 @@ definitions: type: string created_at: type: integer + id: + type: string object_id: type: string object_type: @@ -179,6 +176,30 @@ definitions: - object_id - report_type type: object + schema.AddUserReq: + properties: + display_name: + maxLength: 30 + type: string + email: + maxLength: 500 + type: string + password: + maxLength: 32 + minLength: 8 + type: string + required: + - display_name + - email + - password + type: object + schema.AdminSetAnswerStatusRequest: + properties: + answer_id: + type: string + status: + type: string + type: object schema.AdminSetQuestionStatusRequest: properties: question_id: @@ -203,7 +224,6 @@ definitions: answer_id: type: string question_id: - description: question_id type: string type: object schema.AnswerUpdateReq: @@ -562,6 +582,15 @@ definitions: user_info: $ref: '#/definitions/schema.UserBasicInfo' type: object + schema.GetRoleResp: + properties: + description: + type: string + id: + type: integer + name: + type: string + type: object schema.GetSMTPConfigResp: properties: encryption: @@ -638,6 +667,9 @@ definitions: created_at: description: created time type: integer + description: + description: description text + type: string display_name: description: display name type: string @@ -724,6 +756,12 @@ definitions: rank: description: rank type: integer + role_id: + description: role id + type: integer + role_name: + description: role name + type: string status: description: user status(normal,suspended,deleted,inactive) type: string @@ -1052,6 +1090,11 @@ definitions: required: - tag_id type: object + schema.ReopenQuestionReq: + properties: + question_id: + type: string + type: object schema.ReportHandleReq: properties: flagged_content: @@ -1163,6 +1206,36 @@ definitions: - logo - square_icon type: object + schema.SiteCustomCssHTMLReq: + properties: + custom_css: + maxLength: 65536 + type: string + custom_footer: + maxLength: 65536 + type: string + custom_head: + maxLength: 65536 + type: string + custom_header: + maxLength: 65536 + type: string + type: object + schema.SiteCustomCssHTMLResp: + properties: + custom_css: + maxLength: 65536 + type: string + custom_footer: + maxLength: 65536 + type: string + custom_head: + maxLength: 65536 + type: string + custom_header: + maxLength: 65536 + type: string + type: object schema.SiteGeneralReq: properties: contact_email: @@ -1207,6 +1280,23 @@ definitions: - name - site_url type: object + schema.SiteInfoResp: + properties: + branding: + $ref: '#/definitions/schema.SiteBrandingResp' + custom_css_html: + $ref: '#/definitions/schema.SiteCustomCssHTMLResp' + general: + $ref: '#/definitions/schema.SiteGeneralResp' + interface: + $ref: '#/definitions/schema.SiteInterfaceResp' + login: + $ref: '#/definitions/schema.SiteLoginResp' + site__seo: + $ref: '#/definitions/schema.SiteSeoReq' + theme: + $ref: '#/definitions/schema.SiteThemeResp' + type: object schema.SiteInterfaceReq: properties: language: @@ -1261,6 +1351,67 @@ definitions: terms_of_service_parsed_text: type: string type: object + schema.SiteLoginReq: + properties: + allow_new_registrations: + type: boolean + login_required: + type: boolean + type: object + schema.SiteLoginResp: + properties: + allow_new_registrations: + type: boolean + login_required: + type: boolean + type: object + schema.SiteSeoReq: + properties: + permalink: + maximum: 3 + minimum: 0 + type: integer + robots: + type: string + required: + - permalink + - robots + type: object + schema.SiteSeoResp: + properties: + permalink: + maximum: 3 + minimum: 0 + type: integer + robots: + type: string + required: + - permalink + - robots + type: object + schema.SiteThemeReq: + properties: + theme: + maxLength: 255 + type: string + theme_config: + additionalProperties: true + type: object + required: + - theme + type: object + schema.SiteThemeResp: + properties: + theme: + type: string + theme_config: + additionalProperties: true + type: object + theme_options: + items: + $ref: '#/definitions/schema.ThemeOption' + type: array + type: object schema.SiteWriteReq: properties: recommend_tags: @@ -1335,6 +1486,13 @@ definitions: description: tag id type: string type: object + schema.ThemeOption: + properties: + label: + type: string + value: + type: string + type: object schema.UnreviewedRevisionInfoInfo: properties: content: @@ -1483,6 +1641,30 @@ definitions: required: - language type: object + schema.UpdateUserPasswordReq: + properties: + password: + maxLength: 32 + minLength: 8 + type: string + user_id: + type: string + required: + - password + - user_id + type: object + schema.UpdateUserRoleReq: + properties: + role_id: + description: role id + type: integer + user_id: + description: user id + type: string + required: + - role_id + - user_id + type: object schema.UpdateUserStatusReq: properties: status: @@ -1508,6 +1690,9 @@ definitions: display_name: description: display_name type: string + id: + description: user_id + type: string ip_info: description: ip info type: string @@ -1589,6 +1774,39 @@ definitions: notice_switch: type: boolean type: object + schema.UserRankingResp: + properties: + staffs: + items: + $ref: '#/definitions/schema.UserRankingSimpleInfo' + type: array + users_with_the_most_reputation: + items: + $ref: '#/definitions/schema.UserRankingSimpleInfo' + type: array + users_with_the_most_vote: + items: + $ref: '#/definitions/schema.UserRankingSimpleInfo' + type: array + type: object + schema.UserRankingSimpleInfo: + properties: + avatar: + description: avatar + type: string + display_name: + description: display name + type: string + rank: + description: rank + type: integer + username: + description: username + type: string + vote_count: + description: vote + type: integer + type: object schema.UserRePassWordRequest: properties: code: @@ -1605,6 +1823,12 @@ definitions: type: object schema.UserRegisterReq: properties: + captcha_code: + description: captcha_code + type: string + captcha_id: + description: captcha_id + type: string e_mail: description: email maxLength: 500 @@ -1722,7 +1946,7 @@ paths: name: data required: true schema: - $ref: '#/definitions/entity.AdminSetAnswerStatusRequest' + $ref: '#/definitions/schema.AdminSetAnswerStatusRequest' produces: - application/json responses: @@ -1935,6 +2159,26 @@ paths: summary: list report page tags: - admin + /answer/admin/api/roles: + get: + description: get role list + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/handler.RespBody' + - properties: + data: + items: + $ref: '#/definitions/schema.GetRoleResp' + type: array + type: object + summary: get role list + tags: + - admin /answer/admin/api/setting/smtp: get: description: GetSMTPConfig get smtp config @@ -2017,6 +2261,47 @@ paths: summary: update site info branding tags: - admin + /answer/admin/api/siteinfo/custom-css-html: + get: + description: get site info custom html css config + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/handler.RespBody' + - properties: + data: + $ref: '#/definitions/schema.SiteCustomCssHTMLResp' + type: object + security: + - ApiKeyAuth: [] + summary: get site info custom html css config + tags: + - admin + put: + description: update site custom css html config + parameters: + - description: login info + in: body + name: data + required: true + schema: + $ref: '#/definitions/schema.SiteCustomCssHTMLReq' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/handler.RespBody' + security: + - ApiKeyAuth: [] + summary: update site custom css html config + tags: + - admin /answer/admin/api/siteinfo/general: get: description: get site general information @@ -2140,6 +2425,129 @@ paths: summary: update site legal info tags: - admin + /answer/admin/api/siteinfo/login: + get: + description: get site info login config + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/handler.RespBody' + - properties: + data: + $ref: '#/definitions/schema.SiteLoginResp' + type: object + security: + - ApiKeyAuth: [] + summary: get site info login config + tags: + - admin + put: + description: update site login + parameters: + - description: login info + in: body + name: data + required: true + schema: + $ref: '#/definitions/schema.SiteLoginReq' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/handler.RespBody' + security: + - ApiKeyAuth: [] + summary: update site login + tags: + - admin + /answer/admin/api/siteinfo/seo: + get: + description: get site seo information + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/handler.RespBody' + - properties: + data: + $ref: '#/definitions/schema.SiteSeoResp' + type: object + security: + - ApiKeyAuth: [] + summary: get site seo information + tags: + - admin + put: + description: update site seo information + parameters: + - description: seo + in: body + name: data + required: true + schema: + $ref: '#/definitions/schema.SiteSeoReq' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/handler.RespBody' + security: + - ApiKeyAuth: [] + summary: update site seo information + tags: + - admin + /answer/admin/api/siteinfo/theme: + get: + description: get site info theme config + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/handler.RespBody' + - properties: + data: + $ref: '#/definitions/schema.SiteThemeResp' + type: object + security: + - ApiKeyAuth: [] + summary: get site info theme config + tags: + - admin + put: + description: update site custom css html config + parameters: + - description: login info + in: body + name: data + required: true + schema: + $ref: '#/definitions/schema.SiteThemeReq' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/handler.RespBody' + security: + - ApiKeyAuth: [] + summary: update site custom css html config + tags: + - admin /answer/admin/api/siteinfo/write: get: description: get site interface @@ -2196,6 +2604,78 @@ paths: summary: Get theme options tags: - admin + /answer/admin/api/user: + post: + consumes: + - application/json + description: add user + parameters: + - description: user + in: body + name: data + required: true + schema: + $ref: '#/definitions/schema.AddUserReq' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/handler.RespBody' + security: + - ApiKeyAuth: [] + summary: add user + tags: + - admin + /answer/admin/api/user/password: + put: + consumes: + - application/json + description: update user password + parameters: + - description: user + in: body + name: data + required: true + schema: + $ref: '#/definitions/schema.UpdateUserPasswordReq' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/handler.RespBody' + security: + - ApiKeyAuth: [] + summary: update user password + tags: + - admin + /answer/admin/api/user/role: + put: + consumes: + - application/json + description: update user role + parameters: + - description: user + in: body + name: data + required: true + schema: + $ref: '#/definitions/schema.UpdateUserRoleReq' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/handler.RespBody' + security: + - ApiKeyAuth: [] + summary: update user role + tags: + - admin /answer/admin/api/user/status: put: consumes: @@ -2236,6 +2716,10 @@ paths: in: query name: query type: string + - description: staff user + in: query + name: staff + type: boolean - description: user status enum: - suspended @@ -3279,6 +3763,30 @@ paths: summary: SearchQuestionList tags: - api-question + /answer/api/v1/question/reopen: + put: + consumes: + - application/json + description: reopen question + parameters: + - description: question + in: body + name: data + required: true + schema: + $ref: '#/definitions/schema.ReopenQuestionReq' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/handler.RespBody' + security: + - ApiKeyAuth: [] + summary: reopen question + tags: + - api-question /answer/api/v1/question/search: post: consumes: @@ -3646,7 +4154,7 @@ paths: - $ref: '#/definitions/handler.RespBody' - properties: data: - $ref: '#/definitions/schema.SiteGeneralResp' + $ref: '#/definitions/schema.SiteInfoResp' type: object summary: get site info tags: @@ -4213,6 +4721,48 @@ paths: summary: RetrievePassWord tags: - User + /answer/api/v1/user/ranking: + get: + consumes: + - application/json + description: get user ranking + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/handler.RespBody' + - properties: + data: + $ref: '#/definitions/schema.UserRankingResp' + type: object + security: + - ApiKeyAuth: [] + summary: get user ranking + tags: + - User + /answer/api/v1/user/register/captcha: + get: + consumes: + - application/json + description: UserRegisterCaptcha + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/handler.RespBody' + - properties: + data: + $ref: '#/definitions/schema.GetUserResp' + type: object + summary: UserRegisterCaptcha + tags: + - User /answer/api/v1/user/register/email: post: consumes: @@ -4298,6 +4848,19 @@ paths: summary: vote up tags: - Activity + /custom.css: + get: + description: get site robots information + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + summary: get site robots information + tags: + - site /installation/base-info: post: consumes: @@ -4453,6 +5016,19 @@ paths: summary: UserList tags: - api-question + /robots.txt: + get: + description: get site robots information + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + summary: get site robots information + tags: + - site securityDefinitions: ApiKeyAuth: in: header diff --git a/go.mod b/go.mod index 13bd9f47..78fd6031 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/Chain-Zhang/pinyin v0.1.3 github.com/anargu/gin-brotli v0.0.0-20220116052358-12bf532d5267 github.com/bwmarrin/snowflake v0.3.0 + github.com/davecgh/go-spew v1.1.1 github.com/disintegration/imaging v1.6.2 github.com/gin-gonic/gin v1.8.1 github.com/go-playground/locales v0.14.0 @@ -13,8 +14,11 @@ require ( github.com/go-playground/validator/v10 v10.11.1 github.com/go-sql-driver/mysql v1.6.0 github.com/goccy/go-json v0.9.11 + github.com/golang/mock v1.4.4 + github.com/gomarkdown/markdown v0.0.0-20221013030248-663e2500819c github.com/google/uuid v1.3.0 github.com/google/wire v0.5.0 + github.com/gosimple/slug v1.13.1 github.com/grokify/html-strip-tags-go v0.0.1 github.com/jinzhu/copier v0.3.5 github.com/jinzhu/now v1.1.5 @@ -22,10 +26,11 @@ require ( github.com/mattn/go-sqlite3 v1.14.16 github.com/mojocn/base64Captcha v1.3.5 github.com/ory/dockertest/v3 v3.9.1 + github.com/robfig/cron/v3 v3.0.1 github.com/segmentfault/pacman v1.0.1 github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20221018072427-a15dd1434e05 github.com/segmentfault/pacman/contrib/conf/viper v0.0.0-20221018072427-a15dd1434e05 - github.com/segmentfault/pacman/contrib/i18n v0.0.0-20221109042453-26158da67632 + github.com/segmentfault/pacman/contrib/i18n v0.0.0-20221207032920-3662d1e32068 github.com/segmentfault/pacman/contrib/log/zap v0.0.0-20221018072427-a15dd1434e05 github.com/segmentfault/pacman/contrib/server/http v0.0.0-20221018072427-a15dd1434e05 github.com/spf13/cobra v1.6.1 @@ -45,12 +50,12 @@ require ( require ( github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect github.com/KyleBanks/depth v1.2.1 // indirect + github.com/LinkinStars/go-i18n/v2 v2.2.2 // indirect github.com/Microsoft/go-winio v0.5.2 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/andybalholm/brotli v1.0.4 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/containerd/continuity v0.3.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/cli v20.10.14+incompatible // indirect github.com/docker/docker v20.10.7+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect @@ -65,7 +70,7 @@ require ( github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/subcommands v1.0.1 // indirect + github.com/gosimple/unidecode v1.0.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect @@ -81,7 +86,6 @@ require ( github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/nicksnyder/go-i18n/v2 v2.2.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect github.com/opencontainers/runc v1.1.2 // indirect @@ -106,9 +110,8 @@ require ( go.uber.org/multierr v1.8.0 // indirect go.uber.org/zap v1.23.0 // indirect golang.org/x/image v0.1.0 // indirect - golang.org/x/mod v0.6.0 // indirect golang.org/x/sys v0.1.0 // indirect - golang.org/x/text v0.4.0 // indirect + golang.org/x/text v0.5.0 // indirect golang.org/x/tools v0.2.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect diff --git a/go.sum b/go.sum index 8bfba639..dec4922a 100644 --- a/go.sum +++ b/go.sum @@ -50,6 +50,8 @@ github.com/Chain-Zhang/pinyin v0.1.3/go.mod h1:5iHpt9p4znrnaP59/hfPMnAojajkDxQaP github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/LinkinStars/go-i18n/v2 v2.2.2 h1:ZfjpzbW13dv6btv3RALKZkpN9A+7K1JA//2QcNeWaxU= +github.com/LinkinStars/go-i18n/v2 v2.2.2/go.mod h1:hLglSJ4/3M0Y7ZVcoEJI+OwqkglHCA32DdjuJJR2LbM= 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.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= @@ -233,6 +235,7 @@ github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFU github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -253,6 +256,8 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8l github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20221013030248-663e2500819c h1:iyaGYbCmcYK0Ja9a3OUa2Fo+EaN0cbLu0eKpBwPFzc8= +github.com/gomarkdown/markdown v0.0.0-20221013030248-663e2500819c/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -284,7 +289,6 @@ github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLe github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/subcommands v1.0.1 h1:/eqq+otEXm5vhfBrbREPCSVQbvofip6kIz+mX5TUH7k= github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -300,6 +304,10 @@ github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51 github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gosimple/slug v1.13.1 h1:bQ+kpX9Qa6tHRaK+fZR0A0M2Kd7Pa5eHPPsb1JpHD+Q= +github.com/gosimple/slug v1.13.1/go.mod h1:UiRaFH+GEilHstLUmcBgWcI42viBN7mAb818JrYOeFQ= +github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6T/o= +github.com/gosimple/unidecode v1.0.1/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc= github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0= github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -499,8 +507,6 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nicksnyder/go-i18n/v2 v2.2.0 h1:MNXbyPvd141JJqlU6gJKrczThxJy+kdCNivxZpBQFkw= -github.com/nicksnyder/go-i18n/v2 v2.2.0/go.mod h1:4OtLfzqyAxsscyCb//3gfqSvBc81gImX91LrZzczN1o= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= @@ -576,6 +582,8 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -597,8 +605,8 @@ github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20221018072427-a15dd1 github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20221018072427-a15dd1434e05/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/go.mod h1:prPjFam7MyZ5b3S9dcDOt2tMPz6kf7C9c243s9zSwPY= -github.com/segmentfault/pacman/contrib/i18n v0.0.0-20221109042453-26158da67632 h1:so07u8RWXZQ0gz30KXJ9MKtQ5zjgcDlQ/UwFZrwm5b0= -github.com/segmentfault/pacman/contrib/i18n v0.0.0-20221109042453-26158da67632/go.mod h1:5Afm+OQdau/HQqSOp/ALlSUp0vZsMMMbv//kJhxuoi8= +github.com/segmentfault/pacman/contrib/i18n v0.0.0-20221207032920-3662d1e32068 h1:ln/qgrC62e7/XHGPiikWFV4dyYgCaWeZYkmSGqrHZp4= +github.com/segmentfault/pacman/contrib/i18n v0.0.0-20221207032920-3662d1e32068/go.mod h1:7QcRmnV7OYq4hNOOCWXT5HXnN/u756JUsqIW0Bw8n9E= github.com/segmentfault/pacman/contrib/log/zap v0.0.0-20221018072427-a15dd1434e05 h1:jcGZU2juv0L3eFEkuZYV14ESLUlWfGMWnP0mjOfrSZc= github.com/segmentfault/pacman/contrib/log/zap v0.0.0-20221018072427-a15dd1434e05/go.mod h1:L4GqtXLoR73obTYqUQIzfkm8NG8pvZafxFb6KZFSSHk= github.com/segmentfault/pacman/contrib/server/http v0.0.0-20221018072427-a15dd1434e05 h1:91is1nKNbfTOl8CvMYiFgg4c5Vmol+5mVmMV/jDXD+A= @@ -780,7 +788,6 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= -golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -930,8 +937,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 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-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/i18n/en_US.yaml b/i18n/en_US.yaml index 555bb439..e5a67c36 100644 --- a/i18n/en_US.yaml +++ b/i18n/en_US.yaml @@ -13,6 +13,22 @@ backend: database_error: other: "Data server error." + role: + name: + user: + other: "User" + admin: + other: "Admin" + moderator: + other: "Moderator" + description: + user: + other: "Default with no special access." + admin: + other: "Have the full power to access the site." + moderator: + other: "Has access to all posts except admin settings." + email: other: "Email" password: @@ -93,6 +109,8 @@ backend: other: "Should not contain synonym tags." cannot_update: other: "No permission to update." + cannot_set_synonym_as_itself: + other: "You cannot set the synonym of the current tag as itself." theme: not_found: other: "Theme not found." @@ -125,36 +143,40 @@ backend: install: create_config_failed: other: "Can’t create the config.yaml file." + cannot_update_your_role: + other: "You cannot modify your role." + not_allowed_registration: + other: "Currently the site is not open for registration" report: spam: name: other: "spam" - description: + desc: other: "This post is an advertisement, or vandalism. It is not useful or relevant to the current topic." rude: name: other: "rude or abusive" - description: + desc: other: "A reasonable person would find this content inappropriate for respectful discourse." duplicate: name: other: "a duplicate" - description: + desc: other: "This question has been asked before and already has an answer." not_answer: name: other: "not an answer" - description: + desc: other: "This was posted as an answer, but it does not attempt to answer the question. It should possibly be an edit, a comment, another question, or deleted altogether." not_need: name: other: "no longer needed" - description: + desc: other: "This comment is outdated, conversational or not relevant to this post." other: name: other: "something else" - description: + desc: other: "This post requires staff attention for another reason not listed above." question: @@ -162,22 +184,22 @@ backend: duplicate: name: other: "spam" - description: + desc: other: "This question has been asked before and already has an answer." guideline: name: other: "a community-specific reason" - description: + desc: other: "This question doesn't meet a community guideline." multiple: name: other: "needs details or clarity" - description: + desc: other: "This question currently includes multiple questions in one. It should focus on one problem only." other: name: other: "something else" - description: + desc: other: "This post requires another reason not listed above." notification: @@ -206,11 +228,12 @@ backend: other: "Your answer has been deleted" your_comment_was_deleted: other: "Your comment has been deleted" + # The following fields are used for interface presentation(Front-end) ui: how_to_format: title: How to Format - description: >- + desc: >-