This is an automated email from the ASF dual-hosted git repository. kumfo pushed a commit to branch feat/1.8.0/menu in repository https://gitbox.apache.org/repos/asf/answer.git
commit 29ec29bde770542efe2a0f299f00d7466f4fb8c9 Author: kumfo <[email protected]> AuthorDate: Tue Jan 20 14:54:52 2026 +0800 feat(menu): update admin menu settings to include questions, tags, and advanced options --- cmd/wire_gen.go | 74 ++++----- go.mod | 2 +- internal/base/constant/site_type.go | 3 + internal/controller/answer_controller.go | 2 +- internal/controller/siteinfo_controller.go | 10 +- internal/controller_admin/siteinfo_controller.go | 94 +++++++++-- internal/migrations/migrations.go | 1 + internal/migrations/v30.go | 173 +++++++++++++++++++++ internal/router/answer_api_router.go | 10 +- internal/schema/siteinfo_schema.go | 41 ++++- internal/service/mock/siteinfo_repo_mock.go | 81 +++++++--- internal/service/question_common/question.go | 2 +- internal/service/siteinfo/siteinfo_service.go | 51 ++++-- .../service/siteinfo_common/siteinfo_service.go | 30 ++++ internal/service/tag_common/tag_common.go | 8 +- internal/service/uploader/upload.go | 32 ++-- 16 files changed, 490 insertions(+), 124 deletions(-) diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go index 22a70f29..2808619b 100644 --- a/cmd/wire_gen.go +++ b/cmd/wire_gen.go @@ -1,28 +1,8 @@ -//go:build !wireinject -// +build !wireinject - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - // Code generated by Wire. DO NOT EDIT. -//go:generate go run github.com/google/wire/cmd/wire +//go:generate go run -mod=mod github.com/google/wire/cmd/wire +//go:build !wireinject +// +build !wireinject package answercmd @@ -172,29 +152,29 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, tagRepo := tag.NewTagRepo(dataData, uniqueIDRepo) revisionRepo := revision.NewRevisionRepo(dataData, uniqueIDRepo) revisionService := revision_common.NewRevisionService(revisionRepo, userRepo) - v := activityqueue.NewService() - tagCommonService := tag_common2.NewTagCommonService(tagCommonRepo, tagRelRepo, tagRepo, revisionService, siteInfoCommonService, v) + service := activityqueue.NewService() + tagCommonService := tag_common2.NewTagCommonService(tagCommonRepo, tagRelRepo, tagRepo, revisionService, siteInfoCommonService, service) collectionRepo := collection.NewCollectionRepo(dataData, uniqueIDRepo) collectionCommon := collectioncommon.NewCollectionCommon(collectionRepo) answerCommon := answercommon.NewAnswerCommon(answerRepo) metaRepo := meta.NewMetaRepo(dataData) metaCommonService := metacommon.NewMetaCommonService(metaRepo) - questionCommon := questioncommon.NewQuestionCommon(questionRepo, answerRepo, voteRepo, followRepo, tagCommonService, userCommon, collectionCommon, answerCommon, metaCommonService, configService, v, revisionRepo, siteInfoCommonService, dataData) - v2 := eventqueue.NewService() + questionCommon := questioncommon.NewQuestionCommon(questionRepo, answerRepo, voteRepo, followRepo, tagCommonService, userCommon, collectionCommon, answerCommon, metaCommonService, configService, service, revisionRepo, siteInfoCommonService, dataData) + eventqueueService := eventqueue.NewService() fileRecordRepo := file_record.NewFileRecordRepo(dataData) fileRecordService := file_record2.NewFileRecordService(fileRecordRepo, revisionRepo, serviceConf, siteInfoCommonService, userCommon) - userService := content.NewUserService(userRepo, userActiveActivityRepo, activityRepo, emailService, authService, siteInfoCommonService, userRoleRelService, userCommon, userExternalLoginService, userNotificationConfigRepo, userNotificationConfigService, questionCommon, v2, fileRecordService) + userService := content.NewUserService(userRepo, userActiveActivityRepo, activityRepo, emailService, authService, siteInfoCommonService, userRoleRelService, userCommon, userExternalLoginService, userNotificationConfigRepo, userNotificationConfigService, questionCommon, eventqueueService, fileRecordService) captchaRepo := captcha.NewCaptchaRepo(dataData) captchaService := action.NewCaptchaService(captchaRepo) userController := controller.NewUserController(authService, userService, captchaService, emailService, siteInfoCommonService, userNotificationConfigService) commentRepo := comment.NewCommentRepo(dataData, uniqueIDRepo) commentCommonRepo := comment.NewCommentCommonRepo(dataData, uniqueIDRepo) objService := object_info.NewObjService(answerRepo, questionRepo, commentCommonRepo, tagCommonRepo, tagCommonService) - v3 := noticequeue.NewService() - v4 := noticequeue.NewExternalService() + noticequeueService := noticequeue.NewService() + externalService := noticequeue.NewExternalService() reviewRepo := review.NewReviewRepo(dataData) - reviewService := review2.NewReviewService(reviewRepo, objService, userCommon, userRepo, questionRepo, answerRepo, userRoleRelService, v4, tagCommonService, questionCommon, v3, siteInfoCommonService, commentCommonRepo) - commentService := comment2.NewCommentService(commentRepo, commentCommonRepo, userCommon, objService, voteRepo, emailService, userRepo, v3, v4, v, v2, reviewService) + reviewService := review2.NewReviewService(reviewRepo, objService, userCommon, userRepo, questionRepo, answerRepo, userRoleRelService, externalService, tagCommonService, questionCommon, noticequeueService, siteInfoCommonService, commentCommonRepo) + commentService := comment2.NewCommentService(commentRepo, commentCommonRepo, userCommon, objService, voteRepo, emailService, userRepo, noticequeueService, externalService, service, eventqueueService, reviewService) rolePowerRelRepo := role.NewRolePowerRelRepo(dataData) rolePowerRelService := role2.NewRolePowerRelService(rolePowerRelRepo, userRoleRelService) rankService := rank2.NewRankService(userCommon, userRankRepo, objService, userRoleRelService, rolePowerRelService, configService) @@ -202,17 +182,17 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, rateLimitMiddleware := middleware.NewRateLimitMiddleware(limitRepo) commentController := controller.NewCommentController(commentService, rankService, captchaService, rateLimitMiddleware) reportRepo := report.NewReportRepo(dataData, uniqueIDRepo) - tagService := tag2.NewTagService(tagRepo, tagCommonService, revisionService, followRepo, siteInfoCommonService, v) - answerActivityRepo := activity.NewAnswerActivityRepo(dataData, activityRepo, userRankRepo, v3) + tagService := tag2.NewTagService(tagRepo, tagCommonService, revisionService, followRepo, siteInfoCommonService, service) + answerActivityRepo := activity.NewAnswerActivityRepo(dataData, activityRepo, userRankRepo, noticequeueService) answerActivityService := activity2.NewAnswerActivityService(answerActivityRepo, configService) - externalNotificationService := notification.NewExternalNotificationService(dataData, userNotificationConfigRepo, followRepo, emailService, userRepo, v4, userExternalLoginRepo, siteInfoCommonService) - questionService := content.NewQuestionService(activityRepo, questionRepo, answerRepo, tagCommonService, tagService, questionCommon, userCommon, userRepo, userRoleRelService, revisionService, metaCommonService, collectionCommon, answerActivityService, emailService, v3, v4, v, siteInfoCommonService, externalNotificationService, reviewService, configService, v2, reviewRepo) - answerService := content.NewAnswerService(answerRepo, questionRepo, questionCommon, userCommon, collectionCommon, userRepo, revisionService, answerActivityService, answerCommon, voteRepo, emailService, userRoleRelService, v3, v4, v, reviewService, v2) + externalNotificationService := notification.NewExternalNotificationService(dataData, userNotificationConfigRepo, followRepo, emailService, userRepo, externalService, userExternalLoginRepo, siteInfoCommonService) + questionService := content.NewQuestionService(activityRepo, questionRepo, answerRepo, tagCommonService, tagService, questionCommon, userCommon, userRepo, userRoleRelService, revisionService, metaCommonService, collectionCommon, answerActivityService, emailService, noticequeueService, externalService, service, siteInfoCommonService, externalNotificationService, reviewService, configService, eventqueueService, reviewRepo) + answerService := content.NewAnswerService(answerRepo, questionRepo, questionCommon, userCommon, collectionCommon, userRepo, revisionService, answerActivityService, answerCommon, voteRepo, emailService, userRoleRelService, noticequeueService, externalService, service, reviewService, eventqueueService) reportHandle := report_handle.NewReportHandle(questionService, answerService, commentService) - reportService := report2.NewReportService(reportRepo, objService, userCommon, answerRepo, questionRepo, commentCommonRepo, reportHandle, configService, v2) + reportService := report2.NewReportService(reportRepo, objService, userCommon, answerRepo, questionRepo, commentCommonRepo, reportHandle, configService, eventqueueService) reportController := controller.NewReportController(reportService, rankService, captchaService) - contentVoteRepo := activity.NewVoteRepo(dataData, activityRepo, userRankRepo, v3) - voteService := content.NewVoteService(contentVoteRepo, configService, questionRepo, answerRepo, commentCommonRepo, objService, v2) + contentVoteRepo := activity.NewVoteRepo(dataData, activityRepo, userRankRepo, noticequeueService) + voteService := content.NewVoteService(contentVoteRepo, configService, questionRepo, answerRepo, commentCommonRepo, objService, eventqueueService) voteController := controller.NewVoteController(voteService, rankService, captchaService) tagController := controller.NewTagController(tagService, tagCommonService, rankService) followFollowRepo := activity.NewFollowRepo(dataData, uniqueIDRepo, activityRepo) @@ -228,7 +208,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, searchService := content.NewSearchService(searchParser, searchRepo) searchController := controller.NewSearchController(searchService, captchaService) reviewActivityRepo := activity.NewReviewActivityRepo(dataData, activityRepo, userRankRepo, configService) - contentRevisionService := content.NewRevisionService(revisionRepo, userCommon, questionCommon, answerService, objService, questionRepo, answerRepo, tagRepo, tagCommonService, v3, v, reportRepo, reviewService, reviewActivityRepo) + contentRevisionService := content.NewRevisionService(revisionRepo, userCommon, questionCommon, answerService, objService, questionRepo, answerRepo, tagRepo, tagCommonService, noticequeueService, service, reportRepo, reviewService, reviewActivityRepo) revisionController := controller.NewRevisionController(contentRevisionService, rankService) rankController := controller.NewRankController(rankService) userAdminRepo := user.NewUserAdminRepo(dataData, authRepo) @@ -244,7 +224,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, siteInfoService := siteinfo.NewSiteInfoService(siteInfoRepo, siteInfoCommonService, emailService, tagCommonService, configService, questionCommon, fileRecordService) siteInfoController := controller_admin.NewSiteInfoController(siteInfoService) controllerSiteInfoController := controller.NewSiteInfoController(siteInfoCommonService) - notificationCommon := notificationcommon.NewNotificationCommon(dataData, notificationRepo, userCommon, activityRepo, followRepo, objService, v3, userExternalLoginRepo, siteInfoCommonService) + notificationCommon := notificationcommon.NewNotificationCommon(dataData, notificationRepo, userCommon, activityRepo, followRepo, objService, noticequeueService, userExternalLoginRepo, siteInfoCommonService) badgeRepo := badge.NewBadgeRepo(dataData, uniqueIDRepo) notificationService := notification.NewNotificationService(dataData, notificationRepo, notificationCommon, revisionService, userRepo, reportRepo, reviewService, badgeRepo) notificationController := controller.NewNotificationController(notificationService, rankService) @@ -253,7 +233,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, uploaderService := uploader.NewUploaderService(serviceConf, siteInfoCommonService, fileRecordService) uploadController := controller.NewUploadController(uploaderService) activityActivityRepo := activity.NewActivityRepo(dataData, configService) - activityCommon := activity_common2.NewActivityCommon(activityRepo, v) + activityCommon := activity_common2.NewActivityCommon(activityRepo, service) commentCommonService := comment_common.NewCommentCommonService(commentCommonRepo) activityService := activity2.NewActivityService(activityActivityRepo, userCommon, activityCommon, tagCommonService, objService, commentCommonService, revisionService, metaCommonService, configService) activityController := controller.NewActivityController(activityService) @@ -265,12 +245,12 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, permissionController := controller.NewPermissionController(rankService) userPluginController := controller.NewUserPluginController(pluginCommonService) reviewController := controller.NewReviewController(reviewService, rankService, captchaService) - metaService := meta2.NewMetaService(metaCommonService, userCommon, answerRepo, questionRepo, v2) + metaService := meta2.NewMetaService(metaCommonService, userCommon, answerRepo, questionRepo, eventqueueService) metaController := controller.NewMetaController(metaService) badgeGroupRepo := badge_group.NewBadgeGroupRepo(dataData, uniqueIDRepo) eventRuleRepo := badge.NewEventRuleRepo(dataData) - badgeAwardService := badge2.NewBadgeAwardService(badgeAwardRepo, badgeRepo, userCommon, objService, v3) - badgeEventService := badge2.NewBadgeEventService(dataData, v2, badgeRepo, eventRuleRepo, badgeAwardService) + badgeAwardService := badge2.NewBadgeAwardService(badgeAwardRepo, badgeRepo, userCommon, objService, noticequeueService) + badgeEventService := badge2.NewBadgeEventService(dataData, eventqueueService, badgeRepo, eventRuleRepo, badgeAwardService) badgeService := badge2.NewBadgeService(badgeRepo, badgeGroupRepo, badgeAwardRepo, badgeEventService, siteInfoCommonService) badgeController := controller.NewBadgeController(badgeService, badgeAwardService) controller_adminBadgeController := controller_admin.NewBadgeController(badgeService) @@ -281,7 +261,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, avatarMiddleware := middleware.NewAvatarMiddleware(serviceConf, uploaderService) shortIDMiddleware := middleware.NewShortIDMiddleware(siteInfoCommonService) templateRenderController := templaterender.NewTemplateRenderController(questionService, userService, tagService, answerService, commentService, siteInfoCommonService, questionRepo) - templateController := controller.NewTemplateController(templateRenderController, siteInfoCommonService, v2, userService, questionService) + templateController := controller.NewTemplateController(templateRenderController, siteInfoCommonService, eventqueueService, userService, questionService) templateRouter := router.NewTemplateRouter(templateController, templateRenderController, siteInfoController, authUserMiddleware) connectorController := controller.NewConnectorController(siteInfoCommonService, emailService, userExternalLoginService) userCenterLoginService := user_external_login2.NewUserCenterLoginService(userRepo, userCommon, userExternalLoginRepo, userActiveActivityRepo, siteInfoCommonService) diff --git a/go.mod b/go.mod index 52d64c73..d2430295 100644 --- a/go.mod +++ b/go.mod @@ -37,6 +37,7 @@ require ( github.com/grokify/html-strip-tags-go v0.1.0 github.com/jinzhu/copier v0.4.0 github.com/jinzhu/now v1.1.5 + github.com/joho/godotenv v1.5.1 github.com/lib/pq v1.10.9 github.com/microcosm-cc/bluemonday v1.0.27 github.com/mozillazg/go-pinyin v0.20.0 @@ -117,7 +118,6 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/joho/godotenv v1.5.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect diff --git a/internal/base/constant/site_type.go b/internal/base/constant/site_type.go index 65b487c5..6106b190 100644 --- a/internal/base/constant/site_type.go +++ b/internal/base/constant/site_type.go @@ -31,4 +31,7 @@ const ( SiteTypeTheme = "theme" SiteTypePrivileges = "privileges" SiteTypeUsers = "users" + SiteTypeAdvanced = "advanced" + SiteTypeQuestions = "questions" + SiteTypeTags = "tags" ) diff --git a/internal/controller/answer_controller.go b/internal/controller/answer_controller.go index e76b02cc..99c89b77 100644 --- a/internal/controller/answer_controller.go +++ b/internal/controller/answer_controller.go @@ -242,7 +242,7 @@ func (ac *AnswerController) AddAnswer(ctx *gin.Context) { return } - write, err := ac.siteInfoCommonService.GetSiteWrite(ctx) + write, err := ac.siteInfoCommonService.GetSiteQuestion(ctx) if err != nil { handler.HandleResponse(ctx, err, nil) return diff --git a/internal/controller/siteinfo_controller.go b/internal/controller/siteinfo_controller.go index a336fb24..8035275a 100644 --- a/internal/controller/siteinfo_controller.go +++ b/internal/controller/siteinfo_controller.go @@ -87,7 +87,15 @@ func (sc *SiteInfoController) GetSiteInfo(ctx *gin.Context) { if err != nil { log.Error(err) } - resp.Write, err = sc.siteInfoService.GetSiteWrite(ctx) + resp.Questions, err = sc.siteInfoService.GetSiteQuestion(ctx) + if err != nil { + log.Error(err) + } + resp.Tags, err = sc.siteInfoService.GetSiteTag(ctx) + if err != nil { + log.Error(err) + } + resp.Advanced, err = sc.siteInfoService.GetSiteAdvanced(ctx) if err != nil { log.Error(err) } diff --git a/internal/controller_admin/siteinfo_controller.go b/internal/controller_admin/siteinfo_controller.go index 8a92daba..bbab9794 100644 --- a/internal/controller_admin/siteinfo_controller.go +++ b/internal/controller_admin/siteinfo_controller.go @@ -82,16 +82,42 @@ func (sc *SiteInfoController) GetSiteBranding(ctx *gin.Context) { handler.HandleResponse(ctx, err, resp) } -// GetSiteWrite get site interface -// @Summary get site interface -// @Description get site interface +// GetSiteTag get site tags setting +// @Summary get site tags setting +// @Description get site tags setting +// @Security ApiKeyAuth +// @Tags admin +// @Produce json +// @Success 200 {object} handler.RespBody{data=schema.SiteTagsResp} +// @Router /answer/admin/api/siteinfo/tag [get] +func (sc *SiteInfoController) GetSiteTag(ctx *gin.Context) { + resp, err := sc.siteInfoService.GetSiteTag(ctx) + handler.HandleResponse(ctx, err, resp) +} + +// GetSiteQuestion get site questions setting +// @Summary get site questions setting +// @Description get site questions setting +// @Security ApiKeyAuth +// @Tags admin +// @Produce json +// @Success 200 {object} handler.RespBody{data=schema.SiteQuestionsResp} +// @Router /answer/admin/api/siteinfo/question [get] +func (sc *SiteInfoController) GetSiteQuestion(ctx *gin.Context) { + resp, err := sc.siteInfoService.GetSiteQuestion(ctx) + handler.HandleResponse(ctx, err, resp) +} + +// GetSiteAdvanced get site advanced setting +// @Summary get site advanced setting +// @Description get site advanced setting // @Security ApiKeyAuth // @Tags admin // @Produce json -// @Success 200 {object} handler.RespBody{data=schema.SiteWriteResp} -// @Router /answer/admin/api/siteinfo/write [get] -func (sc *SiteInfoController) GetSiteWrite(ctx *gin.Context) { - resp, err := sc.siteInfoService.GetSiteWrite(ctx) +// @Success 200 {object} handler.RespBody{data=schema.SiteAdvancedResp} +// @Router /answer/admin/api/siteinfo/advanced [get] +func (sc *SiteInfoController) GetSiteAdvanced(ctx *gin.Context) { + resp, err := sc.siteInfoService.GetSiteAdvanced(ctx) handler.HandleResponse(ctx, err, resp) } @@ -288,23 +314,61 @@ func (sc *SiteInfoController) UpdateBranding(ctx *gin.Context) { handler.HandleResponse(ctx, saveErr, nil) } -// UpdateSiteWrite update site write info -// @Summary update site write info -// @Description update site write info +// UpdateSiteQuestion update site question settings +// @Summary update site question settings +// @Description update site question settings +// @Security ApiKeyAuth +// @Tags admin +// @Produce json +// @Param data body schema.SiteQuestionsReq true "questions settings" +// @Success 200 {object} handler.RespBody{} +// @Router /answer/admin/api/siteinfo/question [put] +func (sc *SiteInfoController) UpdateSiteQuestion(ctx *gin.Context) { + req := &schema.SiteQuestionsReq{} + if handler.BindAndCheck(ctx, req) { + return + } + + resp, err := sc.siteInfoService.SaveSiteQuestions(ctx, req) + handler.HandleResponse(ctx, err, resp) +} + +// UpdateSiteTag update site tag settings +// @Summary update site tag settings +// @Description update site tag settings // @Security ApiKeyAuth // @Tags admin // @Produce json -// @Param data body schema.SiteWriteReq true "write info" +// @Param data body schema.SiteTagsReq true "tags settings" // @Success 200 {object} handler.RespBody{} -// @Router /answer/admin/api/siteinfo/write [put] -func (sc *SiteInfoController) UpdateSiteWrite(ctx *gin.Context) { - req := &schema.SiteWriteReq{} +// @Router /answer/admin/api/siteinfo/tag [put] +func (sc *SiteInfoController) UpdateSiteTag(ctx *gin.Context) { + req := &schema.SiteTagsReq{} if handler.BindAndCheck(ctx, req) { return } req.UserID = middleware.GetLoginUserIDFromContext(ctx) - resp, err := sc.siteInfoService.SaveSiteWrite(ctx, req) + resp, err := sc.siteInfoService.SaveSiteTags(ctx, req) + handler.HandleResponse(ctx, err, resp) +} + +// UpdateSiteAdvanced update site advanced info +// @Summary update site advanced info +// @Description update site advanced info +// @Security ApiKeyAuth +// @Tags admin +// @Produce json +// @Param data body schema.SiteAdvancedReq true "advanced settings" +// @Success 200 {object} handler.RespBody{} +// @Router /answer/admin/api/siteinfo/advanced [put] +func (sc *SiteInfoController) UpdateSiteAdvanced(ctx *gin.Context) { + req := &schema.SiteAdvancedReq{} + if handler.BindAndCheck(ctx, req) { + return + } + + resp, err := sc.siteInfoService.SaveSiteAdvanced(ctx, req) handler.HandleResponse(ctx, err, resp) } diff --git a/internal/migrations/migrations.go b/internal/migrations/migrations.go index 9fda8c34..783332df 100644 --- a/internal/migrations/migrations.go +++ b/internal/migrations/migrations.go @@ -105,6 +105,7 @@ var migrations = []Migration{ NewMigration("v1.6.0", "move user config to interface", moveUserConfigToInterface, true), NewMigration("v1.7.0", "add optional tags", addOptionalTags, true), NewMigration("v1.7.2", "expand avatar column length", expandAvatarColumnLength, false), + NewMigration("v1.8.0", "change admin menu", updateAdminMenuSettings, true), } func GetMigrations() []Migration { diff --git a/internal/migrations/v30.go b/internal/migrations/v30.go new file mode 100644 index 00000000..5d5d5223 --- /dev/null +++ b/internal/migrations/v30.go @@ -0,0 +1,173 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package migrations + +import ( + "context" + "encoding/json" + + "github.com/apache/answer/internal/base/constant" + "github.com/apache/answer/internal/base/reason" + "github.com/apache/answer/internal/entity" + "github.com/apache/answer/internal/schema" + "github.com/segmentfault/pacman/errors" + "xorm.io/builder" + "xorm.io/xorm" +) + +func updateAdminMenuSettings(ctx context.Context, x *xorm.Engine) (err error) { + err = splitWriteMenu(ctx, x) + if err != nil { + return + } + return +} + +// splitWriteMenu splits the site write settings into advanced, questions, and tags settings +func splitWriteMenu(ctx context.Context, x *xorm.Engine) error { + var ( + siteInfo = &entity.SiteInfo{} + siteInfoAdvanced = &entity.SiteInfo{} + siteInfoQuestions = &entity.SiteInfo{} + siteInfoTags = &entity.SiteInfo{} + ) + exist, err := x.Context(ctx).Where(builder.Eq{"type": constant.SiteTypeWrite}).Get(siteInfo) + if err != nil { + err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() + return err + } + if !exist { + return nil + } + siteWrite := &schema.SiteWriteResp{} + if err := json.Unmarshal([]byte(siteInfo.Content), siteWrite); err != nil { + return err + } + // site advanced settings + siteAdvanced := &schema.SiteAdvancedResp{ + MaxImageSize: siteWrite.MaxImageSize, + MaxAttachmentSize: siteWrite.MaxAttachmentSize, + MaxImageMegapixel: siteWrite.MaxImageMegapixel, + AuthorizedImageExtensions: siteWrite.AuthorizedImageExtensions, + AuthorizedAttachmentExtensions: siteWrite.AuthorizedAttachmentExtensions, + } + // site questions settings + siteQuestions := &schema.SiteQuestionsResp{ + MinimumContent: siteWrite.MinimumContent, + RestrictAnswer: siteWrite.RestrictAnswer, + } + // site tags settings + siteTags := &schema.SiteTagsResp{ + ReservedTags: siteWrite.ReservedTags, + RecommendTags: siteWrite.RecommendTags, + MinimumTags: siteWrite.MinimumTags, + RequiredTag: siteWrite.RequiredTag, + } + + // save site settings + // save advanced settings + existsAdvanced, err := x.Context(ctx).Where(builder.Eq{"type": constant.SiteTypeWrite}).Get(siteInfoAdvanced) + if err != nil { + return err + } + advancedContent, err := json.Marshal(siteAdvanced) + if err != nil { + return err + } + if existsAdvanced { + _, err = x.Context(ctx).ID(siteInfoAdvanced.ID).Update(&entity.SiteInfo{ + Type: constant.SiteTypeAdvanced, + Content: string(advancedContent), + Status: 1, + }) + if err != nil { + return err + } + } else { + _, err = x.Context(ctx).Insert(&entity.SiteInfo{ + Type: constant.SiteTypeAdvanced, + Content: string(advancedContent), + Status: 1, + }) + if err != nil { + return err + } + } + + // save questions settings + existsQuestions, err := x.Context(ctx).Where(builder.Eq{"type": constant.SiteTypeQuestions}).Get(siteInfoQuestions) + if err != nil { + return err + } + questionsContent, err := json.Marshal(siteQuestions) + if err != nil { + return err + } + if existsQuestions { + _, err = x.Context(ctx).ID(siteInfoQuestions.ID).Update(&entity.SiteInfo{ + Type: constant.SiteTypeQuestions, + Content: string(questionsContent), + Status: 1, + }) + if err != nil { + return err + } + } else { + _, err = x.Context(ctx).Insert(&entity.SiteInfo{ + Type: constant.SiteTypeQuestions, + Content: string(questionsContent), + Status: 1, + }) + if err != nil { + return err + } + } + + // save tags settings + existsTags, err := x.Context(ctx).Where(builder.Eq{"type": constant.SiteTypeTags}).Get(siteInfoTags) + if err != nil { + return err + } + tagsContent, err := json.Marshal(siteTags) + if err != nil { + return err + } + if existsTags { + _, err = x.Context(ctx).ID(siteInfoTags.ID).Update(&entity.SiteInfo{ + Type: constant.SiteTypeTags, + Content: string(tagsContent), + Status: 1, + }) + if err != nil { + return err + } + } else { + _, err = x.Context(ctx).Insert(&entity.SiteInfo{ + Type: constant.SiteTypeTags, + Content: string(tagsContent), + Status: 1, + }) + if err != nil { + return err + } + } + + return nil +} diff --git a/internal/router/answer_api_router.go b/internal/router/answer_api_router.go index 1191492b..d717bc9d 100644 --- a/internal/router/answer_api_router.go +++ b/internal/router/answer_api_router.go @@ -347,8 +347,14 @@ func (a *AnswerAPIRouter) RegisterAnswerAdminAPIRouter(r *gin.RouterGroup) { r.PUT("/siteinfo/interface", a.adminSiteInfoController.UpdateInterface) r.GET("/siteinfo/branding", a.adminSiteInfoController.GetSiteBranding) r.PUT("/siteinfo/branding", a.adminSiteInfoController.UpdateBranding) - r.GET("/siteinfo/write", a.adminSiteInfoController.GetSiteWrite) - r.PUT("/siteinfo/write", a.adminSiteInfoController.UpdateSiteWrite) + + r.GET("/siteinfo/question", a.adminSiteInfoController.GetSiteQuestion) + r.PUT("/siteinfo/question", a.adminSiteInfoController.UpdateSiteQuestion) + r.GET("/siteinfo/tag", a.adminSiteInfoController.GetSiteTag) + r.PUT("/siteinfo/tag", a.adminSiteInfoController.UpdateSiteTag) + r.GET("/siteinfo/advanced", a.adminSiteInfoController.GetSiteAdvanced) + r.PUT("/siteinfo/advanced", a.adminSiteInfoController.UpdateSiteAdvanced) + r.GET("/siteinfo/legal", a.adminSiteInfoController.GetSiteLegal) r.PUT("/siteinfo/legal", a.adminSiteInfoController.UpdateSiteLegal) r.GET("/siteinfo/seo", a.adminSiteInfoController.GetSeo) diff --git a/internal/schema/siteinfo_schema.go b/internal/schema/siteinfo_schema.go index 7ab65751..daf49146 100644 --- a/internal/schema/siteinfo_schema.go +++ b/internal/schema/siteinfo_schema.go @@ -89,21 +89,47 @@ type SiteWriteReq struct { UserID string `json:"-"` } -func (s *SiteWriteResp) GetMaxImageSize() int64 { +type SiteWriteResp SiteWriteReq + +// SiteQuestionsReq site questions settings request +type SiteQuestionsReq struct { + MinimumContent int `validate:"omitempty,gte=0,lte=65535" json:"min_content"` + RestrictAnswer bool `validate:"omitempty" json:"restrict_answer"` +} + +// SiteAdvancedReq site advanced settings request +type SiteAdvancedReq struct { + MaxImageSize int `validate:"omitempty,gt=0" json:"max_image_size"` + MaxAttachmentSize int `validate:"omitempty,gt=0" json:"max_attachment_size"` + MaxImageMegapixel int `validate:"omitempty,gt=0" json:"max_image_megapixel"` + AuthorizedImageExtensions []string `validate:"omitempty" json:"authorized_image_extensions"` + AuthorizedAttachmentExtensions []string `validate:"omitempty" json:"authorized_attachment_extensions"` +} + +// SiteTagsReq site tags settings request +type SiteTagsReq struct { + ReservedTags []*SiteWriteTag `validate:"omitempty,dive" json:"reserved_tags"` + RecommendTags []*SiteWriteTag `validate:"omitempty,dive" json:"recommend_tags"` + MinimumTags int `validate:"omitempty,gte=0,lte=5" json:"min_tags"` + RequiredTag bool `validate:"omitempty" json:"required_tag"` + UserID string `json:"-"` +} + +func (s *SiteAdvancedResp) GetMaxImageSize() int64 { if s.MaxImageSize <= 0 { return constant.DefaultMaxImageSize } return int64(s.MaxImageSize) * 1024 * 1024 } -func (s *SiteWriteResp) GetMaxAttachmentSize() int64 { +func (s *SiteAdvancedResp) GetMaxAttachmentSize() int64 { if s.MaxAttachmentSize <= 0 { return constant.DefaultMaxAttachmentSize } return int64(s.MaxAttachmentSize) * 1024 * 1024 } -func (s *SiteWriteResp) GetMaxImageMegapixel() int { +func (s *SiteAdvancedResp) GetMaxImageMegapixel() int { if s.MaxImageMegapixel <= 0 { return constant.DefaultMaxImageMegapixel } @@ -236,8 +262,9 @@ type ThemeOption struct { Value string `json:"value"` } -// SiteWriteResp site write response -type SiteWriteResp SiteWriteReq +type SiteQuestionsResp SiteQuestionsReq +type SiteAdvancedResp SiteAdvancedReq +type SiteTagsResp SiteTagsReq // SiteLegalResp site write response type SiteLegalResp SiteLegalReq @@ -260,7 +287,9 @@ type SiteInfoResp struct { CustomCssHtml *SiteCustomCssHTMLResp `json:"custom_css_html"` SiteSeo *SiteSeoResp `json:"site_seo"` SiteUsers *SiteUsersResp `json:"site_users"` - Write *SiteWriteResp `json:"site_write"` + Advanced *SiteAdvancedResp `json:"site_advanced"` + Questions *SiteQuestionsResp `json:"site_questions"` + Tags *SiteTagsResp `json:"site_tags"` Legal *SiteLegalSimpleResp `json:"site_legal"` Version string `json:"version"` Revision string `json:"revision"` diff --git a/internal/service/mock/siteinfo_repo_mock.go b/internal/service/mock/siteinfo_repo_mock.go index a98ceb68..5d5429ba 100644 --- a/internal/service/mock/siteinfo_repo_mock.go +++ b/internal/service/mock/siteinfo_repo_mock.go @@ -41,7 +41,6 @@ import ( type MockSiteInfoRepo struct { ctrl *gomock.Controller recorder *MockSiteInfoRepoMockRecorder - isgomock struct{} } // MockSiteInfoRepoMockRecorder is the mock recorder for MockSiteInfoRepo. @@ -72,7 +71,7 @@ func (m *MockSiteInfoRepo) GetByType(ctx context.Context, siteType string) (*ent } // GetByType indicates an expected call of GetByType. -func (mr *MockSiteInfoRepoMockRecorder) GetByType(ctx, siteType any) *gomock.Call { +func (mr *MockSiteInfoRepoMockRecorder) GetByType(ctx, siteType interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByType", reflect.TypeOf((*MockSiteInfoRepo)(nil).GetByType), ctx, siteType) } @@ -87,7 +86,7 @@ func (m *MockSiteInfoRepo) IsBrandingFileUsed(ctx context.Context, filePath stri } // IsBrandingFileUsed indicates an expected call of IsBrandingFileUsed. -func (mr *MockSiteInfoRepoMockRecorder) IsBrandingFileUsed(ctx, filePath any) *gomock.Call { +func (mr *MockSiteInfoRepoMockRecorder) IsBrandingFileUsed(ctx, filePath interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsBrandingFileUsed", reflect.TypeOf((*MockSiteInfoRepo)(nil).IsBrandingFileUsed), ctx, filePath) } @@ -101,7 +100,7 @@ func (m *MockSiteInfoRepo) SaveByType(ctx context.Context, siteType string, data } // SaveByType indicates an expected call of SaveByType. -func (mr *MockSiteInfoRepoMockRecorder) SaveByType(ctx, siteType, data any) *gomock.Call { +func (mr *MockSiteInfoRepoMockRecorder) SaveByType(ctx, siteType, data interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SaveByType", reflect.TypeOf((*MockSiteInfoRepo)(nil).SaveByType), ctx, siteType, data) } @@ -110,7 +109,6 @@ func (mr *MockSiteInfoRepoMockRecorder) SaveByType(ctx, siteType, data any) *gom type MockSiteInfoCommonService struct { ctrl *gomock.Controller recorder *MockSiteInfoCommonServiceMockRecorder - isgomock struct{} } // MockSiteInfoCommonServiceMockRecorder is the mock recorder for MockSiteInfoCommonService. @@ -139,7 +137,7 @@ func (m *MockSiteInfoCommonService) FormatAvatar(ctx context.Context, originalAv } // FormatAvatar indicates an expected call of FormatAvatar. -func (mr *MockSiteInfoCommonServiceMockRecorder) FormatAvatar(ctx, originalAvatarData, email, userStatus any) *gomock.Call { +func (mr *MockSiteInfoCommonServiceMockRecorder) FormatAvatar(ctx, originalAvatarData, email, userStatus interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FormatAvatar", reflect.TypeOf((*MockSiteInfoCommonService)(nil).FormatAvatar), ctx, originalAvatarData, email, userStatus) } @@ -153,11 +151,26 @@ func (m *MockSiteInfoCommonService) FormatListAvatar(ctx context.Context, userLi } // FormatListAvatar indicates an expected call of FormatListAvatar. -func (mr *MockSiteInfoCommonServiceMockRecorder) FormatListAvatar(ctx, userList any) *gomock.Call { +func (mr *MockSiteInfoCommonServiceMockRecorder) FormatListAvatar(ctx, userList interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FormatListAvatar", reflect.TypeOf((*MockSiteInfoCommonService)(nil).FormatListAvatar), ctx, userList) } +// GetSiteAdvanced mocks base method. +func (m *MockSiteInfoCommonService) GetSiteAdvanced(ctx context.Context) (*schema.SiteAdvancedResp, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSiteAdvanced", ctx) + ret0, _ := ret[0].(*schema.SiteAdvancedResp) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSiteAdvanced indicates an expected call of GetSiteAdvanced. +func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteAdvanced(ctx interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSiteAdvanced", reflect.TypeOf((*MockSiteInfoCommonService)(nil).GetSiteAdvanced), ctx) +} + // GetSiteBranding mocks base method. func (m *MockSiteInfoCommonService) GetSiteBranding(ctx context.Context) (*schema.SiteBrandingResp, error) { m.ctrl.T.Helper() @@ -168,7 +181,7 @@ func (m *MockSiteInfoCommonService) GetSiteBranding(ctx context.Context) (*schem } // GetSiteBranding indicates an expected call of GetSiteBranding. -func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteBranding(ctx any) *gomock.Call { +func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteBranding(ctx interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSiteBranding", reflect.TypeOf((*MockSiteInfoCommonService)(nil).GetSiteBranding), ctx) } @@ -183,7 +196,7 @@ func (m *MockSiteInfoCommonService) GetSiteCustomCssHTML(ctx context.Context) (* } // GetSiteCustomCssHTML indicates an expected call of GetSiteCustomCssHTML. -func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteCustomCssHTML(ctx any) *gomock.Call { +func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteCustomCssHTML(ctx interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSiteCustomCssHTML", reflect.TypeOf((*MockSiteInfoCommonService)(nil).GetSiteCustomCssHTML), ctx) } @@ -198,7 +211,7 @@ func (m *MockSiteInfoCommonService) GetSiteGeneral(ctx context.Context) (*schema } // GetSiteGeneral indicates an expected call of GetSiteGeneral. -func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteGeneral(ctx any) *gomock.Call { +func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteGeneral(ctx interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSiteGeneral", reflect.TypeOf((*MockSiteInfoCommonService)(nil).GetSiteGeneral), ctx) } @@ -212,7 +225,7 @@ func (m *MockSiteInfoCommonService) GetSiteInfoByType(ctx context.Context, siteT } // GetSiteInfoByType indicates an expected call of GetSiteInfoByType. -func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteInfoByType(ctx, siteType, resp any) *gomock.Call { +func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteInfoByType(ctx, siteType, resp interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSiteInfoByType", reflect.TypeOf((*MockSiteInfoCommonService)(nil).GetSiteInfoByType), ctx, siteType, resp) } @@ -227,7 +240,7 @@ func (m *MockSiteInfoCommonService) GetSiteInterface(ctx context.Context) (*sche } // GetSiteInterface indicates an expected call of GetSiteInterface. -func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteInterface(ctx any) *gomock.Call { +func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteInterface(ctx interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSiteInterface", reflect.TypeOf((*MockSiteInfoCommonService)(nil).GetSiteInterface), ctx) } @@ -242,7 +255,7 @@ func (m *MockSiteInfoCommonService) GetSiteLegal(ctx context.Context) (*schema.S } // GetSiteLegal indicates an expected call of GetSiteLegal. -func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteLegal(ctx any) *gomock.Call { +func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteLegal(ctx interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSiteLegal", reflect.TypeOf((*MockSiteInfoCommonService)(nil).GetSiteLegal), ctx) } @@ -257,11 +270,26 @@ func (m *MockSiteInfoCommonService) GetSiteLogin(ctx context.Context) (*schema.S } // GetSiteLogin indicates an expected call of GetSiteLogin. -func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteLogin(ctx any) *gomock.Call { +func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteLogin(ctx interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSiteLogin", reflect.TypeOf((*MockSiteInfoCommonService)(nil).GetSiteLogin), ctx) } +// GetSiteQuestion mocks base method. +func (m *MockSiteInfoCommonService) GetSiteQuestion(ctx context.Context) (*schema.SiteQuestionsResp, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSiteQuestion", ctx) + ret0, _ := ret[0].(*schema.SiteQuestionsResp) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSiteQuestion indicates an expected call of GetSiteQuestion. +func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteQuestion(ctx interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSiteQuestion", reflect.TypeOf((*MockSiteInfoCommonService)(nil).GetSiteQuestion), ctx) +} + // GetSiteSeo mocks base method. func (m *MockSiteInfoCommonService) GetSiteSeo(ctx context.Context) (*schema.SiteSeoResp, error) { m.ctrl.T.Helper() @@ -272,11 +300,26 @@ func (m *MockSiteInfoCommonService) GetSiteSeo(ctx context.Context) (*schema.Sit } // GetSiteSeo indicates an expected call of GetSiteSeo. -func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteSeo(ctx any) *gomock.Call { +func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteSeo(ctx interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSiteSeo", reflect.TypeOf((*MockSiteInfoCommonService)(nil).GetSiteSeo), ctx) } +// GetSiteTag mocks base method. +func (m *MockSiteInfoCommonService) GetSiteTag(ctx context.Context) (*schema.SiteTagsResp, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSiteTag", ctx) + ret0, _ := ret[0].(*schema.SiteTagsResp) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSiteTag indicates an expected call of GetSiteTag. +func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteTag(ctx interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSiteTag", reflect.TypeOf((*MockSiteInfoCommonService)(nil).GetSiteTag), ctx) +} + // GetSiteTheme mocks base method. func (m *MockSiteInfoCommonService) GetSiteTheme(ctx context.Context) (*schema.SiteThemeResp, error) { m.ctrl.T.Helper() @@ -287,7 +330,7 @@ func (m *MockSiteInfoCommonService) GetSiteTheme(ctx context.Context) (*schema.S } // GetSiteTheme indicates an expected call of GetSiteTheme. -func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteTheme(ctx any) *gomock.Call { +func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteTheme(ctx interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSiteTheme", reflect.TypeOf((*MockSiteInfoCommonService)(nil).GetSiteTheme), ctx) } @@ -302,7 +345,7 @@ func (m *MockSiteInfoCommonService) GetSiteUsers(ctx context.Context) (*schema.S } // GetSiteUsers indicates an expected call of GetSiteUsers. -func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteUsers(ctx any) *gomock.Call { +func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteUsers(ctx interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSiteUsers", reflect.TypeOf((*MockSiteInfoCommonService)(nil).GetSiteUsers), ctx) } @@ -317,7 +360,7 @@ func (m *MockSiteInfoCommonService) GetSiteWrite(ctx context.Context) (*schema.S } // GetSiteWrite indicates an expected call of GetSiteWrite. -func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteWrite(ctx any) *gomock.Call { +func (mr *MockSiteInfoCommonServiceMockRecorder) GetSiteWrite(ctx interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSiteWrite", reflect.TypeOf((*MockSiteInfoCommonService)(nil).GetSiteWrite), ctx) } @@ -331,7 +374,7 @@ func (m *MockSiteInfoCommonService) IsBrandingFileUsed(ctx context.Context, file } // IsBrandingFileUsed indicates an expected call of IsBrandingFileUsed. -func (mr *MockSiteInfoCommonServiceMockRecorder) IsBrandingFileUsed(ctx, filePath any) *gomock.Call { +func (mr *MockSiteInfoCommonServiceMockRecorder) IsBrandingFileUsed(ctx, filePath interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsBrandingFileUsed", reflect.TypeOf((*MockSiteInfoCommonService)(nil).IsBrandingFileUsed), ctx, filePath) } diff --git a/internal/service/question_common/question.go b/internal/service/question_common/question.go index 557a5db1..3a730634 100644 --- a/internal/service/question_common/question.go +++ b/internal/service/question_common/question.go @@ -900,7 +900,7 @@ func (qs *QuestionCommon) tryToGetQuestionIDFromMsg(ctx context.Context, closeMs } func (qs *QuestionCommon) GetMinimumContentLength(ctx context.Context) (int, error) { - siteInfo, err := qs.siteInfoService.GetSiteWrite(ctx) + siteInfo, err := qs.siteInfoService.GetSiteQuestion(ctx) if err != nil { return 6, err } diff --git a/internal/service/siteinfo/siteinfo_service.go b/internal/service/siteinfo/siteinfo_service.go index f355d09f..b633ed42 100644 --- a/internal/service/siteinfo/siteinfo_service.go +++ b/internal/service/siteinfo/siteinfo_service.go @@ -103,17 +103,14 @@ func (s *SiteInfoService) GetSiteUsers(ctx context.Context) (resp *schema.SiteUs return s.siteInfoCommonService.GetSiteUsers(ctx) } -// GetSiteWrite get site info write -func (s *SiteInfoService) GetSiteWrite(ctx context.Context) (resp *schema.SiteWriteResp, err error) { - resp = &schema.SiteWriteResp{} - siteInfo, exist, err := s.siteInfoRepo.GetByType(ctx, constant.SiteTypeWrite) +// GetSiteTag get site info write +func (s *SiteInfoService) GetSiteTag(ctx context.Context) (resp *schema.SiteTagsResp, err error) { + resp = &schema.SiteTagsResp{} + _, err = s.siteInfoCommonService.GetSiteTag(ctx) if err != nil { log.Error(err) return resp, nil } - if exist { - _ = json.Unmarshal([]byte(siteInfo.Content), resp) - } resp.RecommendTags, err = s.tagCommonService.GetSiteWriteRecommendTag(ctx) if err != nil { @@ -126,6 +123,16 @@ func (s *SiteInfoService) GetSiteWrite(ctx context.Context) (resp *schema.SiteWr return resp, nil } +// GetSiteQuestion get site questions settings +func (s *SiteInfoService) GetSiteQuestion(ctx context.Context) (resp *schema.SiteQuestionsResp, err error) { + return s.siteInfoCommonService.GetSiteQuestion(ctx) +} + +// GetSiteAdvanced get site advanced settings +func (s *SiteInfoService) GetSiteAdvanced(ctx context.Context) (resp *schema.SiteAdvancedResp, err error) { + return s.siteInfoCommonService.GetSiteAdvanced(ctx) +} + // GetSiteLegal get site legal info func (s *SiteInfoService) GetSiteLegal(ctx context.Context) (resp *schema.SiteLegalResp, err error) { return s.siteInfoCommonService.GetSiteLegal(ctx) @@ -182,8 +189,30 @@ func (s *SiteInfoService) SaveSiteBranding(ctx context.Context, req *schema.Site return s.siteInfoRepo.SaveByType(ctx, constant.SiteTypeBranding, data) } -// SaveSiteWrite save site configuration about write -func (s *SiteInfoService) SaveSiteWrite(ctx context.Context, req *schema.SiteWriteReq) (resp any, err error) { +// SaveSiteAdvanced save site advanced configuration +func (s *SiteInfoService) SaveSiteAdvanced(ctx context.Context, req *schema.SiteAdvancedReq) (resp any, err error) { + content, _ := json.Marshal(req) + data := &entity.SiteInfo{ + Type: constant.SiteTypeAdvanced, + Content: string(content), + Status: 1, + } + return nil, s.siteInfoRepo.SaveByType(ctx, constant.SiteTypeAdvanced, data) +} + +// SaveSiteQuestions save site questions configuration +func (s *SiteInfoService) SaveSiteQuestions(ctx context.Context, req *schema.SiteQuestionsReq) (resp any, err error) { + content, _ := json.Marshal(req) + data := &entity.SiteInfo{ + Type: constant.SiteTypeQuestions, + Content: string(content), + Status: 1, + } + return nil, s.siteInfoRepo.SaveByType(ctx, constant.SiteTypeQuestions, data) +} + +// SaveSiteTags save site tags configuration +func (s *SiteInfoService) SaveSiteTags(ctx context.Context, req *schema.SiteTagsReq) (resp any, err error) { recommendTags, reservedTags := make([]string, 0), make([]string, 0) recommendTagMapping, reservedTagMapping := make(map[string]bool), make(map[string]bool) for _, tag := range req.ReservedTags { @@ -210,11 +239,11 @@ func (s *SiteInfoService) SaveSiteWrite(ctx context.Context, req *schema.SiteWri content, _ := json.Marshal(req) data := &entity.SiteInfo{ - Type: constant.SiteTypeWrite, + Type: constant.SiteTypeTags, Content: string(content), Status: 1, } - return nil, s.siteInfoRepo.SaveByType(ctx, constant.SiteTypeWrite, data) + return nil, s.siteInfoRepo.SaveByType(ctx, constant.SiteTypeTags, data) } // SaveSiteLegal save site legal configuration diff --git a/internal/service/siteinfo_common/siteinfo_service.go b/internal/service/siteinfo_common/siteinfo_service.go index fda11722..87bc7ee1 100644 --- a/internal/service/siteinfo_common/siteinfo_service.go +++ b/internal/service/siteinfo_common/siteinfo_service.go @@ -51,6 +51,9 @@ type SiteInfoCommonService interface { FormatAvatar(ctx context.Context, originalAvatarData, email string, userStatus int) *schema.AvatarInfo FormatListAvatar(ctx context.Context, userList []*entity.User) (userID2AvatarMapping map[string]*schema.AvatarInfo) GetSiteWrite(ctx context.Context) (resp *schema.SiteWriteResp, err error) + GetSiteAdvanced(ctx context.Context) (resp *schema.SiteAdvancedResp, err error) + GetSiteQuestion(ctx context.Context) (resp *schema.SiteQuestionsResp, err error) + GetSiteTag(ctx context.Context) (resp *schema.SiteTagsResp, err error) GetSiteLegal(ctx context.Context) (resp *schema.SiteLegalResp, err error) GetSiteLogin(ctx context.Context) (resp *schema.SiteLoginResp, err error) GetSiteCustomCssHTML(ctx context.Context) (resp *schema.SiteCustomCssHTMLResp, err error) @@ -167,6 +170,33 @@ func (s *siteInfoCommonService) GetSiteWrite(ctx context.Context) (resp *schema. return resp, nil } +// GetSiteAdvanced get site info advanced +func (s *siteInfoCommonService) GetSiteAdvanced(ctx context.Context) (resp *schema.SiteAdvancedResp, err error) { + resp = &schema.SiteAdvancedResp{} + if err = s.GetSiteInfoByType(ctx, constant.SiteTypeAdvanced, resp); err != nil { + return nil, err + } + return resp, nil +} + +// GetSiteQuestion get site info question +func (s *siteInfoCommonService) GetSiteQuestion(ctx context.Context) (resp *schema.SiteQuestionsResp, err error) { + resp = &schema.SiteQuestionsResp{} + if err = s.GetSiteInfoByType(ctx, constant.SiteTypeQuestions, resp); err != nil { + return nil, err + } + return resp, nil +} + +// GetSiteTag get site info tag +func (s *siteInfoCommonService) GetSiteTag(ctx context.Context) (resp *schema.SiteTagsResp, err error) { + resp = &schema.SiteTagsResp{} + if err = s.GetSiteInfoByType(ctx, constant.SiteTypeTags, resp); err != nil { + return nil, err + } + return resp, nil +} + // GetSiteLegal get site info write func (s *siteInfoCommonService) GetSiteLegal(ctx context.Context) (resp *schema.SiteLegalResp, err error) { resp = &schema.SiteLegalResp{} diff --git a/internal/service/tag_common/tag_common.go b/internal/service/tag_common/tag_common.go index 9ca8e100..0da9f6fd 100644 --- a/internal/service/tag_common/tag_common.go +++ b/internal/service/tag_common/tag_common.go @@ -270,7 +270,7 @@ func (ts *TagCommonService) GetTagListByNames(ctx context.Context, tagNames []st } func (ts *TagCommonService) ExistRecommend(ctx context.Context, tags []*schema.TagItem) (bool, error) { - taginfo, err := ts.siteInfoService.GetSiteWrite(ctx) + taginfo, err := ts.siteInfoService.GetSiteTag(ctx) if err != nil { return false, err } @@ -295,7 +295,7 @@ func (ts *TagCommonService) ExistRecommend(ctx context.Context, tags []*schema.T } func (ts *TagCommonService) GetMinimumTags(ctx context.Context) (int, error) { - siteInfo, err := ts.siteInfoService.GetSiteWrite(ctx) + siteInfo, err := ts.siteInfoService.GetSiteTag(ctx) if err != nil { return 1, err } @@ -469,7 +469,7 @@ func (ts *TagCommonService) TagsFormatRecommendAndReserved(ctx context.Context, if len(tagList) == 0 { return } - tagConfig, err := ts.siteInfoService.GetSiteWrite(ctx) + tagConfig, err := ts.siteInfoService.GetSiteTag(ctx) if err != nil { log.Error(err) return @@ -485,7 +485,7 @@ func (ts *TagCommonService) tagFormatRecommendAndReserved(ctx context.Context, t if tag == nil { return } - tagConfig, err := ts.siteInfoService.GetSiteWrite(ctx) + tagConfig, err := ts.siteInfoService.GetSiteTag(ctx) if err != nil { log.Error(err) return diff --git a/internal/service/uploader/upload.go b/internal/service/uploader/upload.go index 8dea746c..58f80846 100644 --- a/internal/service/uploader/upload.go +++ b/internal/service/uploader/upload.go @@ -109,12 +109,12 @@ func (us *uploaderService) UploadAvatarFile(ctx *gin.Context, userID string) (ur return url, nil } - siteWrite, err := us.siteInfoService.GetSiteWrite(ctx) + siteAdvanced, err := us.siteInfoService.GetSiteAdvanced(ctx) if err != nil { return "", err } - ctx.Request.Body = http.MaxBytesReader(ctx.Writer, ctx.Request.Body, siteWrite.GetMaxImageSize()) + ctx.Request.Body = http.MaxBytesReader(ctx.Writer, ctx.Request.Body, siteAdvanced.GetMaxImageSize()) file, fileHeader, err := ctx.Request.FormFile("file") if err != nil { return "", errors.BadRequest(reason.RequestFormatError).WithError(err) @@ -201,12 +201,12 @@ func (us *uploaderService) UploadPostFile(ctx *gin.Context, userID string) ( return url, nil } - siteWrite, err := us.siteInfoService.GetSiteWrite(ctx) + siteAdvanced, err := us.siteInfoService.GetSiteAdvanced(ctx) if err != nil { return "", err } - ctx.Request.Body = http.MaxBytesReader(ctx.Writer, ctx.Request.Body, siteWrite.GetMaxImageSize()) + ctx.Request.Body = http.MaxBytesReader(ctx.Writer, ctx.Request.Body, siteAdvanced.GetMaxImageSize()) file, fileHeader, err := ctx.Request.FormFile("file") if err != nil { return "", errors.BadRequest(reason.RequestFormatError).WithError(err) @@ -214,7 +214,7 @@ func (us *uploaderService) UploadPostFile(ctx *gin.Context, userID string) ( defer func() { _ = file.Close() }() - if checker.IsUnAuthorizedExtension(fileHeader.Filename, siteWrite.AuthorizedImageExtensions) { + if checker.IsUnAuthorizedExtension(fileHeader.Filename, siteAdvanced.AuthorizedImageExtensions) { return "", errors.BadRequest(reason.RequestFormatError).WithError(err) } @@ -239,7 +239,7 @@ func (us *uploaderService) UploadPostAttachment(ctx *gin.Context, userID string) return url, nil } - resp, err := us.siteInfoService.GetSiteWrite(ctx) + resp, err := us.siteInfoService.GetSiteAdvanced(ctx) if err != nil { return "", err } @@ -277,12 +277,12 @@ func (us *uploaderService) UploadBrandingFile(ctx *gin.Context, userID string) ( return url, nil } - siteWrite, err := us.siteInfoService.GetSiteWrite(ctx) + siteAdvanced, err := us.siteInfoService.GetSiteAdvanced(ctx) if err != nil { return "", err } - ctx.Request.Body = http.MaxBytesReader(ctx.Writer, ctx.Request.Body, siteWrite.GetMaxImageSize()) + ctx.Request.Body = http.MaxBytesReader(ctx.Writer, ctx.Request.Body, siteAdvanced.GetMaxImageSize()) file, fileHeader, err := ctx.Request.FormFile("file") if err != nil { return "", errors.BadRequest(reason.RequestFormatError).WithError(err) @@ -311,7 +311,7 @@ func (us *uploaderService) uploadImageFile(ctx *gin.Context, file *multipart.Fil if err != nil { return "", err } - siteWrite, err := us.siteInfoService.GetSiteWrite(ctx) + siteAdvanced, err := us.siteInfoService.GetSiteAdvanced(ctx) if err != nil { return "", err } @@ -328,7 +328,7 @@ func (us *uploaderService) uploadImageFile(ctx *gin.Context, file *multipart.Fil _ = src.Close() }() - if !checker.DecodeAndCheckImageFile(filePath, siteWrite.GetMaxImageMegapixel()) { + if !checker.DecodeAndCheckImageFile(filePath, siteAdvanced.GetMaxImageMegapixel()) { return "", errors.BadRequest(reason.UploadFileUnsupportedFileFormat) } @@ -364,17 +364,17 @@ func (us *uploaderService) uploadAttachmentFile(ctx *gin.Context, file *multipar func (us *uploaderService) tryToUploadByPlugin(ctx *gin.Context, source plugin.UploadSource) ( url string, err error) { - siteWrite, err := us.siteInfoService.GetSiteWrite(ctx) + siteAdvanced, err := us.siteInfoService.GetSiteAdvanced(ctx) if err != nil { return "", err } cond := plugin.UploadFileCondition{ Source: source, - MaxImageSize: siteWrite.MaxImageSize, - MaxAttachmentSize: siteWrite.MaxAttachmentSize, - MaxImageMegapixel: siteWrite.MaxImageMegapixel, - AuthorizedImageExtensions: siteWrite.AuthorizedImageExtensions, - AuthorizedAttachmentExtensions: siteWrite.AuthorizedAttachmentExtensions, + MaxImageSize: siteAdvanced.MaxImageSize, + MaxAttachmentSize: siteAdvanced.MaxAttachmentSize, + MaxImageMegapixel: siteAdvanced.MaxImageMegapixel, + AuthorizedImageExtensions: siteAdvanced.AuthorizedImageExtensions, + AuthorizedAttachmentExtensions: siteAdvanced.AuthorizedAttachmentExtensions, } _ = plugin.CallStorage(func(fn plugin.Storage) error { resp := fn.UploadFile(ctx, cond)
