From 9300604644d4b8f90ac9433959d1d3c3c961e985 Mon Sep 17 00:00:00 2001 From: chenyifan01 Date: Mon, 10 Oct 2022 17:00:21 +0800 Subject: [PATCH] #2908 1.add icon upload api 2.fix bug --- models/badge.go | 58 ++++++++++++++++++++---- models/badge_category.go | 17 ++++++- models/badge_user.go | 32 +++++++++---- modules/setting/setting.go | 15 +++++++ routers/badge/badge.go | 48 +++++++++++++++++--- routers/badge/category.go | 6 ++- routers/routes/routes.go | 16 +++++-- routers/user/profile.go | 6 +++ services/badge/badge.go | 24 ++++++---- services/badge/category.go | 10 ++--- services/badge/icon.go | 109 +++++++++++++++++++++++++++++++++++++++++++++ services/badge/user.go | 21 +++++---- 12 files changed, 312 insertions(+), 50 deletions(-) create mode 100644 services/badge/icon.go diff --git a/models/badge.go b/models/badge.go index 20e3ea66a..7e20ab2d4 100644 --- a/models/badge.go +++ b/models/badge.go @@ -1,7 +1,10 @@ package models import ( + "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" + "path/filepath" + "strings" "xorm.io/builder" ) @@ -20,14 +23,15 @@ type Badge struct { func (m *Badge) ToUserShow() *Badge4UserShow { return &Badge4UserShow{ Name: m.Name, - LightedIcon: m.LightedIcon, - GreyedIcon: m.GreyedIcon, + LightedIcon: GetIconOuterLink(m.LightedIcon), + GreyedIcon: GetIconOuterLink(m.GreyedIcon), Url: m.Url, } } type GetBadgeOpts struct { BadgeType BadgeType + LO ListOptions } type BadgeAndCategory struct { @@ -43,8 +47,8 @@ func (m *BadgeAndCategory) ToShow() *Badge4AdminShow { return &Badge4AdminShow{ ID: m.Badge.ID, Name: m.Badge.Name, - LightedIcon: m.Badge.LightedIcon, - GreyedIcon: m.Badge.GreyedIcon, + LightedIcon: GetIconOuterLink(m.Badge.LightedIcon), + GreyedIcon: GetIconOuterLink(m.Badge.GreyedIcon), Url: m.Badge.Url, CategoryName: m.Category.Name, CategoryId: m.Category.ID, @@ -75,6 +79,25 @@ func (m Badge4AdminShow) ToDTO() Badge { } } +type BadgeOperateReq struct { + ID int64 + Name string + LightedIcon string + GreyedIcon string + Url string + CategoryId int64 +} + +func (m BadgeOperateReq) ToDTO() Badge { + return Badge{ + Name: m.Name, + LightedIcon: m.LightedIcon, + GreyedIcon: m.GreyedIcon, + Url: m.Url, + CategoryId: m.CategoryId, + } +} + type Badge4UserShow struct { Name string LightedIcon string @@ -94,17 +117,23 @@ type UserAllBadgeInCategory struct { Badges []*BadgeShowWithStatus } -func GetBadgeList(opts GetBadgeOpts) ([]*BadgeAndCategory, error) { +func GetBadgeList(opts GetBadgeOpts) (int64, []*BadgeAndCategory, error) { + if opts.LO.Page <= 0 { + opts.LO.Page = 1 + } var cond = builder.NewCond() if opts.BadgeType > 0 { cond = cond.And(builder.Eq{"badge_category.type": opts.BadgeType}) } - + n, err := x.Join("INNER", "badge_category", "badge_category.ID = badge.category_id").Where(cond).Count(&BadgeAndCategory{}) + if err != nil { + return 0, nil, err + } r := make([]*BadgeAndCategory, 0) - if err := x.Join("INNER", "badge_category", "badge_category.ID = badge.category_id").Where(cond).OrderBy("badge.created_unix desc").Find(&r); err != nil { - return nil, err + if err = x.Join("INNER", "badge_category", "badge_category.ID = badge.category_id").Where(cond).OrderBy("badge.created_unix desc").Limit(opts.LO.PageSize, (opts.LO.Page-1)*opts.LO.PageSize).Find(&r); err != nil { + return 0, nil, err } - return r, nil + return n, r, nil } func AddBadge(m Badge) (int64, error) { @@ -135,3 +164,14 @@ func GetBadgeByCategoryId(categoryId int64) ([]*Badge, error) { err := x.Where("category_id = ?", categoryId).Find(&r) return r, err } + +func GetCustomIconByHash(hash string) string { + if len(hash) == 0 { + return "" + } + return filepath.Join(setting.IconUploadPath, hash) +} + +func GetIconOuterLink(hash string) string { + return strings.TrimRight(setting.AppSubURL, "/") + "/show/icon/" + hash +} diff --git a/models/badge_category.go b/models/badge_category.go index e8f90f6c1..069fb6b10 100644 --- a/models/badge_category.go +++ b/models/badge_category.go @@ -47,6 +47,21 @@ func (m BadgeCategory4Show) ToDTO() BadgeCategory { } } +func GetBadgeCategoryListPaging(opts ListOptions) (int64, []*BadgeCategory, error) { + n, err := x.Count(&BadgeCategory{}) + if err != nil { + return 0, nil, err + } + if opts.Page <= 0 { + opts.Page = 1 + } + r := make([]*BadgeCategory, 0) + if err := x.OrderBy("position asc,created_unix desc").Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).Find(&r); err != nil { + return 0, nil, err + } + return n, r, nil +} + func GetBadgeCategoryList() ([]*BadgeCategory, error) { r := make([]*BadgeCategory, 0) if err := x.OrderBy("position asc,created_unix desc").Find(&r); err != nil { @@ -73,7 +88,7 @@ func GetBadgeCategoryById(id int64) (*BadgeCategory, error) { if err != nil { return nil, err } else if !has { - return nil, &ErrRecordNotExist{} + return nil, ErrRecordNotExist{} } return m, nil } diff --git a/models/badge_user.go b/models/badge_user.go index b2428ab1a..32861248e 100644 --- a/models/badge_user.go +++ b/models/badge_user.go @@ -12,8 +12,8 @@ const ( type BadgeUser struct { ID int64 `xorm:"pk autoincr"` - UserId int64 `xorm:"unique(user_id,badge_id)"` - BadgeId int64 `xorm:"index"` + UserId int64 `xorm:"unique(user_badge)"` + BadgeId int64 `xorm:"unique(user_badge) index"` CreatedUnix timeutil.TimeStamp `xorm:"created index"` } @@ -115,19 +115,23 @@ func DelBadgeUser(id int64) (int64, error) { return n, sess.Commit() } -func GetBadgeUsers(badgeId int64, opts ListOptions) ([]BadgeUserDetail, error) { +func GetBadgeUsers(badgeId int64, opts ListOptions) (int64, []BadgeUserDetail, error) { + n, err := x.Join("LEFT", "public.user", "public.user.ID = badge_user.user_id").Where("badge_user.badge_id = ?", badgeId).Count(&BadgeUserDetail{}) + if err != nil { + return 0, nil, err + } if opts.Page <= 0 { opts.Page = 1 } m := make([]BadgeUserDetail, 0) - err := x.Join("LEFT", "public.user", "public.user.ID = badge_user.user_id").Where("badge_user.badge_id = ?", badgeId).OrderBy("badge_user.created_unix desc").Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).Find(&m) + err = x.Join("LEFT", "public.user", "public.user.ID = badge_user.user_id").Where("badge_user.badge_id = ?", badgeId).OrderBy("badge_user.id desc").Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).Find(&m) if err != nil { - return nil, err + return 0, nil, err } - return m, nil + return n, m, nil } -func GetUserBadges(userId int64, opts GetUserBadgesOpts) ([]*Badge, error) { +func GetUserBadgesPaging(userId int64, opts GetUserBadgesOpts) ([]*Badge, error) { cond := builder.NewCond() cond = cond.And(builder.Eq{"badge_user.user_id": userId}) if opts.CategoryId > 0 { @@ -135,6 +139,18 @@ func GetUserBadges(userId int64, opts GetUserBadgesOpts) ([]*Badge, error) { } r := make([]*Badge, 0) - err := x.Join("INNER", "badge_user", "badge_user.badge_id = badge.id").Where(cond).OrderBy("badge_user.created_unix desc").Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).Find(&r) + err := x.Join("INNER", "badge_user", "badge_user.badge_id = badge.id").Where(cond).OrderBy("badge_user.id desc").Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).Find(&r) + return r, err +} + +func GetUserBadges(userId, categoryId int64) ([]*Badge, error) { + cond := builder.NewCond() + cond = cond.And(builder.Eq{"badge_user.user_id": userId}) + if categoryId > 0 { + cond = cond.And(builder.Eq{"badge.category_id": categoryId}) + } + + r := make([]*Badge, 0) + err := x.Join("INNER", "badge_user", "badge_user.badge_id = badge.id").Where(cond).OrderBy("badge_user.created_unix desc").Find(&r) return r, err } diff --git a/modules/setting/setting.go b/modules/setting/setting.go index d6e4824ef..00b0245f6 100755 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -622,6 +622,13 @@ var ( DeductTaskRange time.Duration DeductTaskRangeForFirst time.Duration + //badge config + BadgeIconMaxFileSize int64 + BadgeIconMaxWidth int + BadgeIconMaxHeight int + BadgeIconDefaultSize uint + IconUploadPath string + //wechat auto reply config UserNameOfWechatReply string RepoNameOfWechatReply string @@ -1515,6 +1522,14 @@ func NewContext() { CloudBrainPayInterval = sec.Key("CLOUDBRAIN_PAY_INTERVAL").MustDuration(60 * time.Minute) DeductTaskRange = sec.Key("DEDUCT_TASK_RANGE").MustDuration(30 * time.Minute) DeductTaskRangeForFirst = sec.Key("DEDUCT_TASK_RANGE_FOR_FIRST").MustDuration(3 * time.Hour) + + sec = Cfg.Section("icons") + BadgeIconMaxFileSize = sec.Key("BADGE_ICON_MAX_FILE_SIZE").MustInt64(1048576) + BadgeIconMaxWidth = sec.Key("BADGE_ICON_MAX_WIDTH").MustInt(4096) + BadgeIconMaxHeight = sec.Key("BADGE_ICON_MAX_HEIGHT").MustInt(3072) + BadgeIconDefaultSize = sec.Key("BADGE_ICON_DEFAULT_SIZE").MustUint(200) + IconUploadPath = sec.Key("ICON_UPLOAD_PATH").MustString(path.Join(AppDataPath, "icons")) + SetRadarMapConfig() sec = Cfg.Section("warn_mail") diff --git a/routers/badge/badge.go b/routers/badge/badge.go index c62c1ee74..5344b4e39 100644 --- a/routers/badge/badge.go +++ b/routers/badge/badge.go @@ -4,15 +4,19 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/routers/response" "code.gitea.io/gitea/services/badge" "errors" + "github.com/unknwon/com" "net/http" "strings" ) func GetCustomizeBadgeList(ctx *context.Context) { - r, err := badge.GetBadgeList(models.GetBadgeOpts{BadgeType: models.CustomizeBadge}) + page := ctx.QueryInt("page") + pageSize := 50 + n, r, err := badge.GetBadgeList(models.GetBadgeOpts{BadgeType: models.CustomizeBadge, LO: models.ListOptions{PageSize: pageSize, Page: page}}) if err != nil { log.Error("GetCustomizeBadgeList error.%v", err) ctx.JSON(http.StatusOK, response.ServerError(err.Error())) @@ -20,20 +24,22 @@ func GetCustomizeBadgeList(ctx *context.Context) { } m := make(map[string]interface{}) m["List"] = r + m["Total"] = n + m["PageSize"] = pageSize ctx.JSON(http.StatusOK, response.SuccessWithData(m)) } -func OperateBadge(ctx *context.Context, category models.Badge4AdminShow) { +func OperateBadge(ctx *context.Context, req models.BadgeOperateReq) { action := ctx.Params(":action") var err error switch action { case "edit": - err = badge.EditBadge(category, ctx.User) + err = badge.EditBadge(req, ctx.User) case "new": - err = badge.AddBadge(category, ctx.User) + err = badge.AddBadge(req, ctx.User) case "del": - err = badge.DelBadge(category.ID, ctx.User) + err = badge.DelBadge(req.ID, ctx.User) default: err = errors.New("action type error") } @@ -49,7 +55,8 @@ func OperateBadge(ctx *context.Context, category models.Badge4AdminShow) { func GetBadgeUsers(ctx *context.Context) { page := ctx.QueryInt("page") badgeId := ctx.QueryInt64("badge") - r, err := badge.GetBadgeUsers(badgeId, models.ListOptions{PageSize: 20, Page: page}) + pageSize := 50 + n, r, err := badge.GetBadgeUsers(badgeId, models.ListOptions{PageSize: pageSize, Page: page}) if err != nil { log.Error("GetBadgeUsers error.%v", err) ctx.JSON(http.StatusOK, response.ServerError(err.Error())) @@ -57,6 +64,8 @@ func GetBadgeUsers(ctx *context.Context) { } m := make(map[string]interface{}) m["List"] = r + m["Total"] = n + m["PageSize"] = pageSize ctx.JSON(http.StatusOK, response.SuccessWithData(m)) } @@ -96,3 +105,30 @@ func DelBadgeUsers(ctx *context.Context, req models.DelBadgeUserReq) { } ctx.JSON(http.StatusOK, response.Success()) } + +func UploadIcon(ctx *context.Context, form badge.IconUploadForm) { + + uploader := badge.NewIconUploader(badge.IconUploadConfig{ + FileMaxSize: setting.BadgeIconMaxFileSize, + FileMaxWidth: setting.BadgeIconMaxWidth, + FileMaxHeight: setting.BadgeIconMaxHeight, + }) + iconName, err := uploader.Upload(form, ctx.User) + if err != nil { + log.Error("UploadIcon error.%v", err) + ctx.JSON(http.StatusOK, response.ServerError(err.Error())) + return + } + m := make(map[string]string, 0) + m["IconName"] = iconName + ctx.JSON(http.StatusOK, response.SuccessWithData(m)) +} + +func GetIcon(ctx *context.Context) { + hash := ctx.Params(":hash") + if !com.IsFile(models.GetCustomIconByHash(hash)) { + ctx.NotFound(ctx.Req.URL.RequestURI(), nil) + return + } + ctx.Redirect(setting.AppSubURL + "/icons/" + hash) +} diff --git a/routers/badge/category.go b/routers/badge/category.go index a386f8fc5..4ac85df4a 100644 --- a/routers/badge/category.go +++ b/routers/badge/category.go @@ -11,7 +11,9 @@ import ( ) func GetBadgeCategoryList(ctx *context.Context) { - r, err := badge.GetBadgeCategoryList() + page := ctx.QueryInt("page") + pageSize := 50 + n, r, err := badge.GetBadgeCategoryList(models.ListOptions{Page: page, PageSize: pageSize}) if err != nil { log.Error("GetCategoryList error.%v", err) ctx.JSON(http.StatusOK, response.ServerError(err.Error())) @@ -19,6 +21,8 @@ func GetBadgeCategoryList(ctx *context.Context) { } m := make(map[string]interface{}) m["List"] = r + m["Total"] = n + m["PageSize"] = pageSize ctx.JSON(http.StatusOK, response.SuccessWithData(m)) } diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 14f2d0f74..91b5690ad 100755 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -9,6 +9,7 @@ import ( "code.gitea.io/gitea/routers/badge" "code.gitea.io/gitea/routers/reward/point" "code.gitea.io/gitea/routers/task" + badge_service "code.gitea.io/gitea/services/badge" "code.gitea.io/gitea/services/reward" "encoding/gob" "net/http" @@ -195,6 +196,14 @@ func NewMacaron() *macaron.Macaron { }, )) m.Use(public.StaticHandler( + setting.IconUploadPath, + &public.Options{ + Prefix: "icons", + SkipLogging: setting.DisableRouterLog, + ExpiresAfter: setting.StaticCacheTime, + }, + )) + m.Use(public.StaticHandler( setting.RepositoryAvatarUploadPath, &public.Options{ Prefix: "repo-avatars", @@ -518,6 +527,8 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("/avatar/:hash", user.AvatarByEmailHash) + m.Get("/show/icon/:hash", badge.GetIcon) + adminReq := context.Toggle(&context.ToggleOptions{SignInRequired: true, AdminRequired: true}) // ***** START: Admin ***** @@ -670,16 +681,15 @@ func RegisterRoutes(m *macaron.Macaron) { }) m.Group("/customize", func() { m.Get("/list", badge.GetCustomizeBadgeList) - }) m.Group("/users", func() { m.Get("", badge.GetBadgeUsers) m.Post("/add", bindIgnErr(models.AddBadgeUsersReq{}), badge.AddOperateBadgeUsers) m.Post("/del", bindIgnErr(models.DelBadgeUserReq{}), badge.DelBadgeUsers) }) - m.Post("/^:action(new|edit|del)$", bindIgnErr(models.Badge4AdminShow{}), badge.OperateBadge) + m.Post("/^:action(new|edit|del)$", bindIgnErr(models.BadgeOperateReq{}), badge.OperateBadge) }) - + m.Post("/icon/upload", bindIgnErr(badge_service.IconUploadForm{}), badge.UploadIcon) }, operationReq) // ***** END: Operation ***** diff --git a/routers/user/profile.go b/routers/user/profile.go index 1d275c191..8685cd734 100755 --- a/routers/user/profile.go +++ b/routers/user/profile.go @@ -6,7 +6,9 @@ package user import ( + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/services/badge" + "encoding/json" "errors" "fmt" "path" @@ -103,6 +105,8 @@ func Profile(ctx *context.Context) { ctx.Data["Owner"] = ctxUser ctx.Data["OpenIDs"] = openIDs ctx.Data["RecentBadges"] = badges + b, _ := json.Marshal(badges) + log.Info(string(b)) ctx.Data["EnableHeatmap"] = setting.Service.EnableUserHeatmap ctx.Data["HeatmapUser"] = ctxUser.Name showPrivate := ctx.IsSigned && (ctx.User.IsAdmin || ctx.User.ID == ctxUser.ID) @@ -312,6 +316,8 @@ func Profile(ctx *context.Context) { ctx.ServerError("GetUserAllBadges", err) return } + ab, _ := json.Marshal(allBadges) + log.Info(string(ab)) ctx.Data["AllBadges"] = allBadges default: ctx.ServerError("tab error", errors.New("tab error")) diff --git a/services/badge/badge.go b/services/badge/badge.go index 83c3581b5..0aefeca6e 100644 --- a/services/badge/badge.go +++ b/services/badge/badge.go @@ -7,24 +7,32 @@ import ( "errors" ) -func GetBadgeList(opts models.GetBadgeOpts) ([]*models.Badge4AdminShow, error) { - list, err := models.GetBadgeList(opts) +func GetBadgeList(opts models.GetBadgeOpts) (int64, []*models.Badge4AdminShow, error) { + total, list, err := models.GetBadgeList(opts) if err != nil { - return nil, err + return 0, nil, err } if len(list) == 0 { - return nil, nil + return 0, nil, nil } r := make([]*models.Badge4AdminShow, len(list)) for i := 0; i < len(list); i++ { r[i] = list[i].ToShow() } - return r, nil + return total, r, nil } -func AddBadge(m models.Badge4AdminShow, doer *models.User) error { - _, err := models.AddBadge(m.ToDTO()) +func AddBadge(m models.BadgeOperateReq, doer *models.User) error { + _, err := models.GetBadgeCategoryById(m.CategoryId) + + if err != nil { + if models.IsErrRecordNotExist(err) { + return errors.New("badge category is not available") + } + return err + } + _, err = models.AddBadge(m.ToDTO()) if err != nil { return err } @@ -32,7 +40,7 @@ func AddBadge(m models.Badge4AdminShow, doer *models.User) error { return nil } -func EditBadge(m models.Badge4AdminShow, doer *models.User) error { +func EditBadge(m models.BadgeOperateReq, doer *models.User) error { if m.ID == 0 { log.Error(" EditBadge param error") return errors.New("param error") diff --git a/services/badge/category.go b/services/badge/category.go index 316e654a7..14d06620a 100644 --- a/services/badge/category.go +++ b/services/badge/category.go @@ -7,20 +7,20 @@ import ( "errors" ) -func GetBadgeCategoryList() ([]*models.BadgeCategory4Show, error) { - list, err := models.GetBadgeCategoryList() +func GetBadgeCategoryList(opts models.ListOptions) (int64, []*models.BadgeCategory4Show, error) { + total, list, err := models.GetBadgeCategoryListPaging(opts) if err != nil { - return nil, err + return 0, nil, err } if len(list) == 0 { - return nil, nil + return 0, nil, nil } r := make([]*models.BadgeCategory4Show, len(list)) for i := 0; i < len(list); i++ { r[i] = list[i].ToShow() } - return r, nil + return total, r, nil } func AddBadgeCategory(m models.BadgeCategory4Show, doer *models.User) error { diff --git a/services/badge/icon.go b/services/badge/icon.go new file mode 100644 index 000000000..ae7c25241 --- /dev/null +++ b/services/badge/icon.go @@ -0,0 +1,109 @@ +package badge + +import ( + "bytes" + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/setting" + "crypto/md5" + "errors" + "fmt" + "image" + "image/png" + "io/ioutil" + "mime/multipart" + "os" +) + +type IconUploader struct { + Config IconUploadConfig +} + +type IconUploadForm struct { + Icon *multipart.FileHeader +} + +type IconUploadConfig struct { + FileMaxSize int64 + FileMaxWidth int + FileMaxHeight int +} + +func NewIconUploader(config IconUploadConfig) IconUploader { + return IconUploader{Config: config} +} + +func (u IconUploader) Upload(form IconUploadForm, user *models.User) (string, error) { + if form.Icon == nil || form.Icon.Filename == "" { + return "", errors.New("File or fileName is empty") + } + + fr, err := form.Icon.Open() + if err != nil { + return "", fmt.Errorf("Icon.Open: %v", err) + } + defer fr.Close() + + if form.Icon.Size > u.Config.FileMaxSize { + return "", errors.New("File is too large") + } + + data, err := ioutil.ReadAll(fr) + if err != nil { + return "", fmt.Errorf("ioutil.ReadAll: %v", err) + } + if !base.IsImageFile(data) { + return "", errors.New("File is not a image") + } + iconName, err := u.uploadIcon(data, user.ID) + if err != nil { + return "", fmt.Errorf("uploadIcon: %v", err) + } + return iconName, nil + +} + +func (u IconUploader) uploadIcon(data []byte, userId int64) (string, error) { + m, err := u.prepare(data) + if err != nil { + return "", err + } + + iconName := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%x", userId, md5.Sum(data))))) + + if err := os.MkdirAll(setting.IconUploadPath, os.ModePerm); err != nil { + return "", fmt.Errorf("uploadIcon. Failed to create dir %s: %v", setting.AvatarUploadPath, err) + } + + fw, err := os.Create(models.GetCustomIconByHash(iconName)) + if err != nil { + return "", fmt.Errorf("Create: %v", err) + } + defer fw.Close() + + if err = png.Encode(fw, *m); err != nil { + return "", fmt.Errorf("Encode: %v", err) + } + + return iconName, nil +} + +func (u IconUploader) prepare(data []byte) (*image.Image, error) { + imgCfg, _, err := image.DecodeConfig(bytes.NewReader(data)) + if err != nil { + return nil, fmt.Errorf("DecodeConfig: %v", err) + } + if imgCfg.Width > u.Config.FileMaxWidth { + return nil, fmt.Errorf("Image width is too large: %d > %d", imgCfg.Width, setting.AvatarMaxWidth) + } + if imgCfg.Height > u.Config.FileMaxHeight { + return nil, fmt.Errorf("Image height is too large: %d > %d", imgCfg.Height, setting.AvatarMaxHeight) + } + + img, _, err := image.Decode(bytes.NewReader(data)) + if err != nil { + return nil, fmt.Errorf("Decode: %v", err) + } + + return &img, nil +} diff --git a/services/badge/user.go b/services/badge/user.go index ccc112f01..70fc7bba7 100644 --- a/services/badge/user.go +++ b/services/badge/user.go @@ -5,20 +5,20 @@ import ( "code.gitea.io/gitea/modules/log" ) -func GetBadgeUsers(badgeId int64, opts models.ListOptions) ([]*models.BadgeUser4SHow, error) { - list, err := models.GetBadgeUsers(badgeId, opts) +func GetBadgeUsers(badgeId int64, opts models.ListOptions) (int64, []*models.BadgeUser4SHow, error) { + total, list, err := models.GetBadgeUsers(badgeId, opts) if err != nil { - return nil, err + return 0, nil, err } if len(list) == 0 { - return nil, nil + return 0, nil, nil } r := make([]*models.BadgeUser4SHow, len(list)) for i := 0; i < len(list); i++ { r[i] = list[i].ToShow() } - return r, nil + return total, r, nil } func AddBadgeUsers(badgeId int64, userNames []string) (int, error) { @@ -49,7 +49,7 @@ func DelBadgeUser(id int64) error { //GetUserBadges Only Returns badges the user has earned func GetUserBadges(userId int64, opts models.ListOptions) ([]*models.Badge4UserShow, error) { - badges, err := models.GetUserBadges(userId, models.GetUserBadgesOpts{ListOptions: opts}) + badges, err := models.GetUserBadgesPaging(userId, models.GetUserBadgesOpts{ListOptions: opts}) if err != nil { return nil, err } @@ -68,7 +68,10 @@ func GetUserAllBadges(userId int64) ([]models.UserAllBadgeInCategory, error) { r := make([]models.UserAllBadgeInCategory, len(categoryList)) for i, v := range categoryList { badges, err := models.GetBadgeByCategoryId(v.ID) - userBadgeMap, err := getUserBadgesMap(userId, v.ID, 100, 1) + if badges == nil || len(badges) == 0 { + continue + } + userBadgeMap, err := getUserBadgesMap(userId, v.ID) if err != nil { return nil, err } @@ -91,8 +94,8 @@ func GetUserAllBadges(userId int64) ([]models.UserAllBadgeInCategory, error) { return r, nil } -func getUserBadgesMap(userId, categoryId int64, pageSize, page int) (map[int64]*models.Badge, error) { - userBadges, err := models.GetUserBadges(userId, models.GetUserBadgesOpts{ListOptions: models.ListOptions{PageSize: pageSize, Page: page}, CategoryId: categoryId}) +func getUserBadgesMap(userId, categoryId int64) (map[int64]*models.Badge, error) { + userBadges, err := models.GetUserBadges(userId, categoryId) if err != nil { return nil, err }