This is an automated email from the ASF dual-hosted git repository.
linkinstar pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/answer.git
The following commit(s) were added to refs/heads/dev by this push:
new def0559a Fix file record and delete files (branding and avatar) (#1335)
def0559a is described below
commit def0559a5513d711d31bbf066fe4442c7ed30c7d
Author: DanielAuerX <[email protected]>
AuthorDate: Fri May 23 09:07:14 2025 +0200
Fix file record and delete files (branding and avatar) (#1335)
- [x] create file_record table
- [x] avatar and branding files are added to file_record
- [x] branding files are being deleted
- [x] avatar files are being deleted
- [x] reload latest avatar (frontend) after backend state is being
updated
problems addressed in the pr:
- clean up job fails, because it cannot access file_record table
- avatar and branding files are not added to the file_record table
- avatar and branding files are never deleted
- after an avatar is being updated/deleted, the old file is still being
requested due to browser caching. This is causing error logs ("no such
file or directory") in the backend.
cf. conversation in [pr
1326](https://github.com/apache/answer/pull/1326)
---------
Co-authored-by: broccoli <[email protected]>
Co-authored-by: LinkinStars <[email protected]>
---
cmd/wire_gen.go | 8 ++--
internal/base/middleware/avatar.go | 4 +-
internal/controller_admin/siteinfo_controller.go | 14 ++++++-
internal/migrations/init_data.go | 1 +
internal/repo/file_record/file_record_repo.go | 15 +++++++
internal/repo/site_info/siteinfo_repo.go | 15 +++++++
internal/repo/user/user_repo.go | 15 +++++++
internal/service/content/user_service.go | 45 +++++++++++++++++++-
.../service/file_record/file_record_service.go | 38 ++++++++++++++++-
internal/service/siteinfo/siteinfo_service.go | 49 ++++++++++++++++++++++
.../service/siteinfo_common/siteinfo_service.go | 12 ++++++
internal/service/uploader/upload.go | 18 ++++++--
internal/service/user_common/user.go | 11 +++++
13 files changed, 232 insertions(+), 13 deletions(-)
diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go
index 702f60df..f98deb42 100644
--- a/cmd/wire_gen.go
+++ b/cmd/wire_gen.go
@@ -181,7 +181,9 @@ func initApplication(debug bool, serverConf *conf.Server,
dbConf *data.Database,
metaCommonService := metacommon.NewMetaCommonService(metaRepo)
questionCommon := questioncommon.NewQuestionCommon(questionRepo,
answerRepo, voteRepo, followRepo, tagCommonService, userCommon,
collectionCommon, answerCommon, metaCommonService, configService,
activityQueueService, revisionRepo, siteInfoCommonService, dataData)
eventQueueService := event_queue.NewEventQueueService()
- userService := content.NewUserService(userRepo, userActiveActivityRepo,
activityRepo, emailService, authService, siteInfoCommonService,
userRoleRelService, userCommon, userExternalLoginService,
userNotificationConfigRepo, userNotificationConfigService, questionCommon,
eventQueueService)
+ 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,
eventQueueService, fileRecordService)
captchaRepo := captcha.NewCaptchaRepo(dataData)
captchaService := action.NewCaptchaService(captchaRepo)
userController := controller.NewUserController(authService,
userService, captchaService, emailService, siteInfoCommonService,
userNotificationConfigService)
@@ -239,7 +241,7 @@ func initApplication(debug bool, serverConf *conf.Server,
dbConf *data.Database,
reasonService := reason2.NewReasonService(reasonRepo)
reasonController := controller.NewReasonController(reasonService)
themeController := controller_admin.NewThemeController()
- siteInfoService := siteinfo.NewSiteInfoService(siteInfoRepo,
siteInfoCommonService, emailService, tagCommonService, configService,
questionCommon)
+ 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, notificationQueueService,
userExternalLoginRepo, siteInfoCommonService)
@@ -248,8 +250,6 @@ func initApplication(debug bool, serverConf *conf.Server,
dbConf *data.Database,
notificationController :=
controller.NewNotificationController(notificationService, rankService)
dashboardService := dashboard.NewDashboardService(questionRepo,
answerRepo, commentCommonRepo, voteRepo, userRepo, reportRepo, configService,
siteInfoCommonService, serviceConf, reviewService, revisionRepo, dataData)
dashboardController :=
controller.NewDashboardController(dashboardService)
- fileRecordRepo := file_record.NewFileRecordRepo(dataData)
- fileRecordService := file_record2.NewFileRecordService(fileRecordRepo,
revisionRepo, serviceConf, siteInfoCommonService)
uploaderService := uploader.NewUploaderService(serviceConf,
siteInfoCommonService, fileRecordService)
uploadController := controller.NewUploadController(uploaderService)
activityActivityRepo := activity.NewActivityRepo(dataData,
configService)
diff --git a/internal/base/middleware/avatar.go
b/internal/base/middleware/avatar.go
index 1d246417..98430638 100644
--- a/internal/base/middleware/avatar.go
+++ b/internal/base/middleware/avatar.go
@@ -21,6 +21,7 @@ package middleware
import (
"fmt"
+ "net/http"
"net/url"
"os"
"path"
@@ -62,7 +63,8 @@ func (am *AvatarMiddleware) AvatarThumb() gin.HandlerFunc {
filePath, err =
am.uploaderService.AvatarThumbFile(ctx, filename, size)
if err != nil {
log.Error(err)
- ctx.Abort()
+ ctx.AbortWithStatus(http.StatusNotFound)
+ return
}
}
avatarFile, err := os.ReadFile(filePath)
diff --git a/internal/controller_admin/siteinfo_controller.go
b/internal/controller_admin/siteinfo_controller.go
index cd1b2ab6..8a92daba 100644
--- a/internal/controller_admin/siteinfo_controller.go
+++ b/internal/controller_admin/siteinfo_controller.go
@@ -28,6 +28,7 @@ import (
"github.com/apache/answer/internal/schema"
"github.com/apache/answer/internal/service/siteinfo"
"github.com/gin-gonic/gin"
+ "github.com/segmentfault/pacman/log"
)
// SiteInfoController site info controller
@@ -274,8 +275,17 @@ func (sc *SiteInfoController) UpdateBranding(ctx
*gin.Context) {
if handler.BindAndCheck(ctx, req) {
return
}
- err := sc.siteInfoService.SaveSiteBranding(ctx, req)
- handler.HandleResponse(ctx, err, nil)
+ currentBranding, getBrandingErr :=
sc.siteInfoService.GetSiteBranding(ctx)
+ if getBrandingErr == nil {
+ cleanUpErr :=
sc.siteInfoService.CleanUpRemovedBrandingFiles(ctx, req, currentBranding)
+ if cleanUpErr != nil {
+ log.Errorf("failed to clean up removed branding
file(s): %v", cleanUpErr)
+ }
+ } else {
+ log.Errorf("failed to get current site branding: %v",
getBrandingErr)
+ }
+ saveErr := sc.siteInfoService.SaveSiteBranding(ctx, req)
+ handler.HandleResponse(ctx, saveErr, nil)
}
// UpdateSiteWrite update site write info
diff --git a/internal/migrations/init_data.go b/internal/migrations/init_data.go
index 8b853c4d..96151625 100644
--- a/internal/migrations/init_data.go
+++ b/internal/migrations/init_data.go
@@ -74,6 +74,7 @@ var (
&entity.Badge{},
&entity.BadgeGroup{},
&entity.BadgeAward{},
+ &entity.FileRecord{},
&entity.PluginKVStorage{},
}
diff --git a/internal/repo/file_record/file_record_repo.go
b/internal/repo/file_record/file_record_repo.go
index ed081be4..ce486c7a 100644
--- a/internal/repo/file_record/file_record_repo.go
+++ b/internal/repo/file_record/file_record_repo.go
@@ -82,3 +82,18 @@ func (fr *fileRecordRepo) UpdateFileRecord(ctx
context.Context, fileRecord *enti
}
return
}
+
+// GetFileRecordByURL gets a file record by its url
+func (fr *fileRecordRepo) GetFileRecordByURL(ctx context.Context, fileURL
string) (record *entity.FileRecord, err error) {
+ record = &entity.FileRecord{}
+ session := fr.data.DB.Context(ctx)
+ exists, err := session.Where("file_url = ? AND status = ?", fileURL,
entity.FileRecordStatusAvailable).Get(record)
+ if err != nil {
+ err =
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
+ return
+ }
+ if !exists {
+ return
+ }
+ return record, nil
+}
diff --git a/internal/repo/site_info/siteinfo_repo.go
b/internal/repo/site_info/siteinfo_repo.go
index 420e483f..5f95b748 100644
--- a/internal/repo/site_info/siteinfo_repo.go
+++ b/internal/repo/site_info/siteinfo_repo.go
@@ -101,3 +101,18 @@ func (sr *siteInfoRepo) setCache(ctx context.Context,
siteType string, siteInfo
log.Error(err)
}
}
+
+func (sr *siteInfoRepo) IsBrandingFileUsed(ctx context.Context, filePath
string) (bool, error) {
+ siteInfo := &entity.SiteInfo{}
+ count, err := sr.data.DB.Context(ctx).
+ Table("site_info").
+ Where(builder.Eq{"type": "branding"}).
+ And(builder.Like{"content", "%" + filePath + "%"}).
+ Count(&siteInfo)
+
+ if err != nil {
+ return false,
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
+ }
+
+ return count > 0, nil
+}
diff --git a/internal/repo/user/user_repo.go b/internal/repo/user/user_repo.go
index f56e00b8..a85cd79a 100644
--- a/internal/repo/user/user_repo.go
+++ b/internal/repo/user/user_repo.go
@@ -33,6 +33,7 @@ import (
"github.com/apache/answer/plugin"
"github.com/segmentfault/pacman/errors"
"github.com/segmentfault/pacman/log"
+ "xorm.io/builder"
"xorm.io/xorm"
)
@@ -380,3 +381,17 @@ func decorateByUserCenterUser(original *entity.User,
ucUser *plugin.UserCenterBa
original.Status = int(ucUser.Status)
}
}
+
+func (ur *userRepo) IsAvatarFileUsed(ctx context.Context, filePath string)
(bool, error) {
+ user := &entity.User{}
+ count, err := ur.data.DB.Context(ctx).
+ Table("user").
+ Where(builder.Like{"avatar", "%" + filePath + "%"}).
+ Count(&user)
+
+ if err != nil {
+ return false,
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
+ }
+
+ return count > 0, nil
+}
diff --git a/internal/service/content/user_service.go
b/internal/service/content/user_service.go
index b59790c1..ece3a86d 100644
--- a/internal/service/content/user_service.go
+++ b/internal/service/content/user_service.go
@@ -23,9 +23,10 @@ import (
"context"
"encoding/json"
"fmt"
+ "time"
+
"github.com/apache/answer/internal/service/event_queue"
"github.com/apache/answer/pkg/token"
- "time"
"github.com/apache/answer/internal/base/constant"
questioncommon
"github.com/apache/answer/internal/service/question_common"
@@ -41,6 +42,7 @@ import (
"github.com/apache/answer/internal/service/activity_common"
"github.com/apache/answer/internal/service/auth"
"github.com/apache/answer/internal/service/export"
+ "github.com/apache/answer/internal/service/file_record"
"github.com/apache/answer/internal/service/role"
"github.com/apache/answer/internal/service/siteinfo_common"
usercommon "github.com/apache/answer/internal/service/user_common"
@@ -67,6 +69,7 @@ type UserService struct {
userNotificationConfigService
*user_notification_config.UserNotificationConfigService
questionService *questioncommon.QuestionCommon
eventQueueService event_queue.EventQueueService
+ fileRecordService *file_record.FileRecordService
}
func NewUserService(userRepo usercommon.UserRepo,
@@ -82,6 +85,7 @@ func NewUserService(userRepo usercommon.UserRepo,
userNotificationConfigService
*user_notification_config.UserNotificationConfigService,
questionService *questioncommon.QuestionCommon,
eventQueueService event_queue.EventQueueService,
+ fileRecordService *file_record.FileRecordService,
) *UserService {
return &UserService{
userCommonService: userCommonService,
@@ -97,6 +101,7 @@ func NewUserService(userRepo usercommon.UserRepo,
userNotificationConfigService: userNotificationConfigService,
questionService: questionService,
eventQueueService: eventQueueService,
+ fileRecordService: fileRecordService,
}
}
@@ -355,6 +360,9 @@ func (us *UserService) UpdateInfo(ctx context.Context, req
*schema.UpdateInfoReq
}
cond := us.formatUserInfoForUpdateInfo(oldUserInfo, req, siteUsers)
+
+ us.cleanUpRemovedAvatar(ctx, oldUserInfo.Avatar, cond.Avatar)
+
err = us.userRepo.UpdateInfo(ctx, cond)
if err != nil {
return nil, err
@@ -363,6 +371,41 @@ func (us *UserService) UpdateInfo(ctx context.Context, req
*schema.UpdateInfoReq
return nil, err
}
+func (us *UserService) cleanUpRemovedAvatar(
+ ctx context.Context,
+ oldAvatarJSON string,
+ newAvatarJSON string,
+) {
+ if oldAvatarJSON == newAvatarJSON {
+ return
+ }
+
+ var oldAvatar, newAvatar schema.AvatarInfo
+
+ _ = json.Unmarshal([]byte(oldAvatarJSON), &oldAvatar)
+ _ = json.Unmarshal([]byte(newAvatarJSON), &newAvatar)
+
+ if len(oldAvatar.Custom) == 0 {
+ return
+ }
+
+ // clean up if old is custom and it's either removed or replaced
+ if oldAvatar.Custom != newAvatar.Custom {
+ fileRecord, err := us.fileRecordService.GetFileRecordByURL(ctx,
oldAvatar.Custom)
+ if err != nil {
+ log.Error(err)
+ return
+ }
+ if fileRecord == nil {
+ log.Warn("no file record found for old avatar url:",
oldAvatar.Custom)
+ return
+ }
+ if err := us.fileRecordService.DeleteAndMoveFileRecord(ctx,
fileRecord); err != nil {
+ log.Error(err)
+ }
+ }
+}
+
func (us *UserService) formatUserInfoForUpdateInfo(
oldUserInfo *entity.User, req *schema.UpdateInfoRequest, siteUsersConf
*schema.SiteUsersResp) *entity.User {
avatar, _ := json.Marshal(req.Avatar)
diff --git a/internal/service/file_record/file_record_service.go
b/internal/service/file_record/file_record_service.go
index abb98376..29097ba8 100644
--- a/internal/service/file_record/file_record_service.go
+++ b/internal/service/file_record/file_record_service.go
@@ -24,6 +24,7 @@ import (
"fmt"
"os"
"path/filepath"
+ "strings"
"time"
"github.com/apache/answer/internal/base/constant"
@@ -31,6 +32,7 @@ import (
"github.com/apache/answer/internal/service/revision"
"github.com/apache/answer/internal/service/service_config"
"github.com/apache/answer/internal/service/siteinfo_common"
+ usercommon "github.com/apache/answer/internal/service/user_common"
"github.com/apache/answer/pkg/checker"
"github.com/apache/answer/pkg/dir"
"github.com/apache/answer/pkg/writer"
@@ -44,6 +46,7 @@ type FileRecordRepo interface {
GetFileRecordPage(ctx context.Context, page, pageSize int, cond
*entity.FileRecord) (
fileRecordList []*entity.FileRecord, total int64, err error)
DeleteFileRecord(ctx context.Context, id int) (err error)
+ GetFileRecordByURL(ctx context.Context, fileURL string) (record
*entity.FileRecord, err error)
}
// FileRecordService file record service
@@ -52,6 +55,7 @@ type FileRecordService struct {
revisionRepo revision.RevisionRepo
serviceConfig *service_config.ServiceConfig
siteInfoService siteinfo_common.SiteInfoCommonService
+ userService *usercommon.UserCommon
}
// NewFileRecordService new file record service
@@ -60,12 +64,14 @@ func NewFileRecordService(
revisionRepo revision.RevisionRepo,
serviceConfig *service_config.ServiceConfig,
siteInfoService siteinfo_common.SiteInfoCommonService,
+ userService *usercommon.UserCommon,
) *FileRecordService {
return &FileRecordService{
fileRecordRepo: fileRecordRepo,
revisionRepo: revisionRepo,
serviceConfig: serviceConfig,
siteInfoService: siteInfoService,
+ userService: userService,
}
}
@@ -104,6 +110,21 @@ func (fs *FileRecordService) CleanOrphanUploadFiles(ctx
context.Context) {
if fileRecord.CreatedAt.AddDate(0, 0,
2).After(time.Now()) {
continue
}
+ if isBrandingOrAvatarFile(fileRecord.FilePath) {
+ if strings.Contains(fileRecord.FilePath,
constant.BrandingSubPath+"/") {
+ if
fs.siteInfoService.IsBrandingFileUsed(ctx, fileRecord.FilePath) {
+ continue
+ }
+ } else if strings.Contains(fileRecord.FilePath,
constant.AvatarSubPath+"/") {
+ if fs.userService.IsAvatarFileUsed(ctx,
fileRecord.FilePath) {
+ continue
+ }
+ }
+ if err := fs.DeleteAndMoveFileRecord(ctx,
fileRecord); err != nil {
+ log.Error(err)
+ }
+ continue
+ }
if checker.IsNotZeroString(fileRecord.ObjectID) {
_, exist, err :=
fs.revisionRepo.GetLastRevisionByObjectID(ctx, fileRecord.ObjectID)
if err != nil {
@@ -129,7 +150,7 @@ func (fs *FileRecordService) CleanOrphanUploadFiles(ctx
context.Context) {
}
}
// Delete and move the file record
- if err := fs.deleteAndMoveFileRecord(ctx, fileRecord);
err != nil {
+ if err := fs.DeleteAndMoveFileRecord(ctx, fileRecord);
err != nil {
log.Error(err)
}
}
@@ -137,6 +158,10 @@ func (fs *FileRecordService) CleanOrphanUploadFiles(ctx
context.Context) {
}
}
+func isBrandingOrAvatarFile(filePath string) bool {
+ return strings.Contains(filePath, constant.BrandingSubPath+"/") ||
strings.Contains(filePath, constant.AvatarSubPath+"/")
+}
+
func (fs *FileRecordService) PurgeDeletedFiles(ctx context.Context) {
deletedPath := filepath.Join(fs.serviceConfig.UploadPath,
constant.DeletedSubPath)
log.Infof("purge deleted files: %s", deletedPath)
@@ -152,7 +177,7 @@ func (fs *FileRecordService) PurgeDeletedFiles(ctx
context.Context) {
return
}
-func (fs *FileRecordService) deleteAndMoveFileRecord(ctx context.Context,
fileRecord *entity.FileRecord) error {
+func (fs *FileRecordService) DeleteAndMoveFileRecord(ctx context.Context,
fileRecord *entity.FileRecord) error {
// Delete the file record
if err := fs.fileRecordRepo.DeleteFileRecord(ctx, fileRecord.ID); err
!= nil {
return fmt.Errorf("delete file record error: %v", err)
@@ -170,3 +195,12 @@ func (fs *FileRecordService) deleteAndMoveFileRecord(ctx
context.Context, fileRe
log.Debugf("delete and move file: %s", fileRecord.FileURL)
return nil
}
+
+func (fs *FileRecordService) GetFileRecordByURL(ctx context.Context, fileURL
string) (record *entity.FileRecord, err error) {
+ record, err = fs.fileRecordRepo.GetFileRecordByURL(ctx, fileURL)
+ if err != nil {
+ log.Errorf("error retrieving file record by URL: %v", err)
+ return
+ }
+ return
+}
diff --git a/internal/service/siteinfo/siteinfo_service.go
b/internal/service/siteinfo/siteinfo_service.go
index 5141faee..a0f4891c 100644
--- a/internal/service/siteinfo/siteinfo_service.go
+++ b/internal/service/siteinfo/siteinfo_service.go
@@ -22,6 +22,7 @@ package siteinfo
import (
"context"
"encoding/json"
+ errpkg "errors"
"fmt"
"strings"
@@ -33,6 +34,7 @@ import (
"github.com/apache/answer/internal/schema"
"github.com/apache/answer/internal/service/config"
"github.com/apache/answer/internal/service/export"
+ "github.com/apache/answer/internal/service/file_record"
questioncommon
"github.com/apache/answer/internal/service/question_common"
"github.com/apache/answer/internal/service/siteinfo_common"
tagcommon "github.com/apache/answer/internal/service/tag_common"
@@ -49,6 +51,7 @@ type SiteInfoService struct {
tagCommonService *tagcommon.TagCommonService
configService *config.ConfigService
questioncommon *questioncommon.QuestionCommon
+ fileRecordService *file_record.FileRecordService
}
func NewSiteInfoService(
@@ -58,6 +61,7 @@ func NewSiteInfoService(
tagCommonService *tagcommon.TagCommonService,
configService *config.ConfigService,
questioncommon *questioncommon.QuestionCommon,
+ fileRecordService *file_record.FileRecordService,
) *SiteInfoService {
plugin.RegisterGetSiteURLFunc(func() string {
@@ -76,6 +80,7 @@ func NewSiteInfoService(
tagCommonService: tagCommonService,
configService: configService,
questioncommon: questioncommon,
+ fileRecordService: fileRecordService,
}
}
@@ -438,3 +443,47 @@ func (s *SiteInfoService) UpdatePrivilegesConfig(ctx
context.Context, req *schem
}
return
}
+
+func (s *SiteInfoService) CleanUpRemovedBrandingFiles(
+ ctx context.Context,
+ newBranding *schema.SiteBrandingReq,
+ currentBranding *schema.SiteBrandingResp,
+) error {
+ var allErrors []error
+ currentFiles := map[string]string{
+ "logo": currentBranding.Logo,
+ "mobile_logo": currentBranding.MobileLogo,
+ "square_icon": currentBranding.SquareIcon,
+ "favicon": currentBranding.Favicon,
+ }
+
+ newFiles := map[string]string{
+ "logo": newBranding.Logo,
+ "mobile_logo": newBranding.MobileLogo,
+ "square_icon": newBranding.SquareIcon,
+ "favicon": newBranding.Favicon,
+ }
+
+ for key, currentFile := range currentFiles {
+ newFile := newFiles[key]
+ if currentFile != "" && currentFile != newFile {
+ fileRecord, err :=
s.fileRecordService.GetFileRecordByURL(ctx, currentFile)
+ if err != nil {
+ allErrors = append(allErrors, err)
+ continue
+ }
+ if fileRecord == nil {
+ err := errpkg.New("file record is nil for key "
+ key)
+ allErrors = append(allErrors, err)
+ continue
+ }
+ if err :=
s.fileRecordService.DeleteAndMoveFileRecord(ctx, fileRecord); err != nil {
+ allErrors = append(allErrors, err)
+ }
+ }
+ }
+ if len(allErrors) > 0 {
+ return errpkg.Join(allErrors...)
+ }
+ return nil
+}
diff --git a/internal/service/siteinfo_common/siteinfo_service.go
b/internal/service/siteinfo_common/siteinfo_service.go
index f715bc9b..0c896c2b 100644
--- a/internal/service/siteinfo_common/siteinfo_service.go
+++ b/internal/service/siteinfo_common/siteinfo_service.go
@@ -35,6 +35,7 @@ import (
type SiteInfoRepo interface {
SaveByType(ctx context.Context, siteType string, data *entity.SiteInfo)
(err error)
GetByType(ctx context.Context, siteType string) (siteInfo
*entity.SiteInfo, exist bool, err error)
+ IsBrandingFileUsed(ctx context.Context, filePath string) (bool, error)
}
// siteInfoCommonService site info common service
@@ -56,6 +57,7 @@ type SiteInfoCommonService interface {
GetSiteTheme(ctx context.Context) (resp *schema.SiteThemeResp, err
error)
GetSiteSeo(ctx context.Context) (resp *schema.SiteSeoResp, err error)
GetSiteInfoByType(ctx context.Context, siteType string, resp
interface{}) (err error)
+ IsBrandingFileUsed(ctx context.Context, filePath string) bool
}
// NewSiteInfoCommonService new site info common service
@@ -233,3 +235,13 @@ func (s *siteInfoCommonService) GetSiteInfoByType(ctx
context.Context, siteType
_ = json.Unmarshal([]byte(siteInfo.Content), resp)
return nil
}
+
+func (s *siteInfoCommonService) IsBrandingFileUsed(ctx context.Context,
filePath string) bool {
+ used, err := s.siteInfoRepo.IsBrandingFileUsed(ctx, filePath)
+ if err != nil {
+ log.Errorf("error checking if branding file is used: %v", err)
+ // will try again with the next clean up
+ return true
+ }
+ return used
+}
diff --git a/internal/service/uploader/upload.go
b/internal/service/uploader/upload.go
index d5cc2dfb..2ae5369d 100644
--- a/internal/service/uploader/upload.go
+++ b/internal/service/uploader/upload.go
@@ -127,7 +127,13 @@ func (us *uploaderService) UploadAvatarFile(ctx
*gin.Context, userID string) (ur
newFilename := fmt.Sprintf("%s%s", uid.IDStr12(), fileExt)
avatarFilePath := path.Join(constant.AvatarSubPath, newFilename)
- return us.uploadImageFile(ctx, fileHeader, avatarFilePath)
+ url, err = us.uploadImageFile(ctx, fileHeader, avatarFilePath)
+ if err != nil {
+ return "", err
+ }
+ us.fileRecordService.AddFileRecord(ctx, userID, avatarFilePath, url,
string(plugin.UserAvatar))
+ return url, nil
+
}
func (us *uploaderService) AvatarThumbFile(ctx *gin.Context, fileName string,
size int) (url string, err error) {
@@ -149,7 +155,7 @@ func (us *uploaderService) AvatarThumbFile(ctx
*gin.Context, fileName string, si
filePath := fmt.Sprintf("%s/%s/%s", us.serviceConfig.UploadPath,
constant.AvatarSubPath, fileName)
avatarFile, err = os.ReadFile(filePath)
if err != nil {
- return "",
errors.InternalServer(reason.UnknownError).WithError(err).WithStack()
+ return "", errors.NotFound(reason.UnknownError).WithError(err)
}
reader := bytes.NewReader(avatarFile)
img, err := imaging.Decode(reader)
@@ -282,7 +288,13 @@ func (us *uploaderService) UploadBrandingFile(ctx
*gin.Context, userID string) (
newFilename := fmt.Sprintf("%s%s", uid.IDStr12(), fileExt)
avatarFilePath := path.Join(constant.BrandingSubPath, newFilename)
- return us.uploadImageFile(ctx, fileHeader, avatarFilePath)
+ url, err = us.uploadImageFile(ctx, fileHeader, avatarFilePath)
+ if err != nil {
+ return "", err
+ }
+ us.fileRecordService.AddFileRecord(ctx, userID, avatarFilePath, url,
string(plugin.AdminBranding))
+ return url, nil
+
}
func (us *uploaderService) uploadImageFile(ctx *gin.Context, file
*multipart.FileHeader, fileSubPath string) (
diff --git a/internal/service/user_common/user.go
b/internal/service/user_common/user.go
index 7f50eafe..3df99261 100644
--- a/internal/service/user_common/user.go
+++ b/internal/service/user_common/user.go
@@ -60,6 +60,7 @@ type UserRepo interface {
GetByEmail(ctx context.Context, email string) (userInfo *entity.User,
exist bool, err error)
GetUserCount(ctx context.Context) (count int64, err error)
SearchUserListByName(ctx context.Context, name string, limit int,
onlyStaff bool) (userList []*entity.User, err error)
+ IsAvatarFileUsed(ctx context.Context, filePath string) (bool, error)
}
// UserCommon user service
@@ -245,3 +246,13 @@ func (us *UserCommon) CacheLoginUserInfo(ctx
context.Context, userID string, use
}
return accessToken, userCacheInfo, nil
}
+
+func (us *UserCommon) IsAvatarFileUsed(ctx context.Context, filePath string)
bool {
+ used, err := us.userRepo.IsAvatarFileUsed(ctx, filePath)
+ if err != nil {
+ log.Errorf("error checking if branding file is used: %v", err)
+ // will try again with the next clean up
+ return true
+ }
+ return used
+}