From e97796e4f2914eae2c1b025d88dcdf2197f10714 Mon Sep 17 00:00:00 2001 From: LinkinStars Date: Tue, 26 Nov 2024 15:23:33 +0800 Subject: [PATCH 1/2] feat(storage): add upload file condition to plugin upload --- internal/controller/upload_controller.go | 5 +++++ internal/service/uploader/upload.go | 22 +++++++++++++++++++--- plugin/storage.go | 17 ++++++++++++++++- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/internal/controller/upload_controller.go b/internal/controller/upload_controller.go index a43ccf641..753be375f 100644 --- a/internal/controller/upload_controller.go +++ b/internal/controller/upload_controller.go @@ -21,6 +21,7 @@ package controller import ( "github.com/apache/incubator-answer/internal/base/handler" + "github.com/apache/incubator-answer/internal/base/middleware" "github.com/apache/incubator-answer/internal/base/reason" "github.com/apache/incubator-answer/internal/schema" "github.com/apache/incubator-answer/internal/service/uploader" @@ -75,6 +76,10 @@ func (uc *UploadController) UploadFile(ctx *gin.Context) { case fileFromPost: url, err = uc.uploaderService.UploadPostFile(ctx) case fileFromBranding: + if !middleware.GetIsAdminFromContext(ctx) { + handler.HandleResponse(ctx, errors.Forbidden(reason.ForbiddenError), nil) + return + } url, err = uc.uploaderService.UploadBrandingFile(ctx) case fileFromPostAttachment: url, err = uc.uploaderService.UploadPostAttachment(ctx) diff --git a/internal/service/uploader/upload.go b/internal/service/uploader/upload.go index 9b810e534..a8d9c0ccf 100644 --- a/internal/service/uploader/upload.go +++ b/internal/service/uploader/upload.go @@ -105,8 +105,12 @@ func (us *uploaderService) UploadAvatarFile(ctx *gin.Context) (url string, err e return url, nil } - // max size - ctx.Request.Body = http.MaxBytesReader(ctx.Writer, ctx.Request.Body, 5*1024*1024) + siteWrite, err := us.siteInfoService.GetSiteWrite(ctx) + if err != nil { + return "", err + } + + ctx.Request.Body = http.MaxBytesReader(ctx.Writer, ctx.Request.Body, siteWrite.GetMaxImageSize()) file, fileHeader, err := ctx.Request.FormFile("file") if err != nil { return "", errors.BadRequest(reason.RequestFormatError).WithError(err) @@ -317,8 +321,20 @@ 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) + 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, + } _ = plugin.CallStorage(func(fn plugin.Storage) error { - resp := fn.UploadFile(ctx, source) + resp := fn.UploadFile(ctx, cond) if resp.OriginalError != nil { log.Errorf("upload file by plugin failed, err: %v", resp.OriginalError) err = errors.BadRequest("").WithMsg(resp.DisplayErrorMsg.Translate(ctx)).WithError(err) diff --git a/plugin/storage.go b/plugin/storage.go index 39c294886..599a41c4c 100644 --- a/plugin/storage.go +++ b/plugin/storage.go @@ -52,6 +52,21 @@ var ( } ) +type UploadFileCondition struct { + // Source is the source of the file + Source UploadSource + // MaxImageSize is the maximum size of the image in MB + MaxImageSize int + // MaxAttachmentSize is the maximum size of the attachment in MB + MaxAttachmentSize int + // MaxImageMegapixel is the maximum megapixel of the image + MaxImageMegapixel int + // AuthorizedImageExtensions is the list of authorized image extensions + AuthorizedImageExtensions []string + // AuthorizedAttachmentExtensions is the list of authorized attachment extensions + AuthorizedAttachmentExtensions []string +} + type UploadFileResponse struct { // FullURL is the URL that can be used to access the file FullURL string @@ -66,7 +81,7 @@ type Storage interface { // UploadFile uploads a file to storage. // The file is in the Form of the ctx and the key is "file" - UploadFile(ctx *GinContext, source UploadSource) UploadFileResponse + UploadFile(ctx *GinContext, condition UploadFileCondition) UploadFileResponse } var ( From ce0ec4b806b602518bd8cd2a37ff1aa0834a302c Mon Sep 17 00:00:00 2001 From: LinkinStars Date: Fri, 29 Nov 2024 15:15:23 +0800 Subject: [PATCH 2/2] feat(user): add top questions and answers to user homepage --- internal/controller/template_controller.go | 12 ++++++-- ui/template/homepage.html | 33 +++++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/internal/controller/template_controller.go b/internal/controller/template_controller.go index df10931e0..0b22360fe 100644 --- a/internal/controller/template_controller.go +++ b/internal/controller/template_controller.go @@ -546,12 +546,20 @@ func (tc *TemplateController) UserInfo(ctx *gin.Context) { return } + questionList, answerList, err := tc.questionService.SearchUserTopList(ctx, req.Username, "") + if err != nil { + tc.Page404(ctx) + return + } + siteInfo := tc.SiteInfo(ctx) siteInfo.Canonical = fmt.Sprintf("%s/users/%s", siteInfo.General.SiteUrl, username) siteInfo.Title = fmt.Sprintf("%s - %s", username, siteInfo.General.Name) tc.html(ctx, http.StatusOK, "homepage.html", siteInfo, gin.H{ - "userinfo": userinfo, - "bio": template.HTML(userinfo.BioHTML), + "userinfo": userinfo, + "bio": template.HTML(userinfo.BioHTML), + "topQuestions": questionList, + "topAnswers": answerList, }) } diff --git a/ui/template/homepage.html b/ui/template/homepage.html index 2f68200d5..84887a099 100644 --- a/ui/template/homepage.html +++ b/ui/template/homepage.html @@ -63,10 +63,41 @@
{{translator $.language "ui.personal.about_me"}}
{{if .bio }} -
{{.bio}}
+
{{.bio}}
{{else}}
{{translator $.language "ui.personal.about_me_empty"}}
{{end}} +
+
+
Top Answers
+
    + {{ range .topAnswers }} +
  1. + {{.QuestionInfo.Title}} +
    + {{.VoteCount}} votes +
    +
  2. + {{ end }} +
+
+
+
Top Questions
+
    + {{ range .topQuestions }} +
  1. + {{.Title}} +
    + {{.VoteCount}} votes +
    + {{.AnswerCount}} answers +
    +
    +
  2. + {{ end }} +
+
+