mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Add admin API route for managing user's badges (#23106)
Fix #22785 --------- Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
		| @@ -558,6 +558,8 @@ var migrations = []Migration{ | ||||
| 	NewMigration("Add PreviousDuration to ActionRun", v1_22.AddPreviousDurationToActionRun), | ||||
| 	// v286 -> v287 | ||||
| 	NewMigration("Add support for SHA256 git repositories", v1_22.AdjustDBForSha256), | ||||
| 	// v287 -> v288 | ||||
| 	NewMigration("Use Slug instead of ID for Badges", v1_22.UseSlugInsteadOfIDForBadges), | ||||
| } | ||||
|  | ||||
| // GetCurrentDBVersion returns the current db version | ||||
|   | ||||
							
								
								
									
										46
									
								
								models/migrations/v1_22/v287.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								models/migrations/v1_22/v287.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| // Copyright 2023 The Gitea Authors. All rights reserved. | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| package v1_22 //nolint | ||||
|  | ||||
| import ( | ||||
| 	"xorm.io/xorm" | ||||
| ) | ||||
|  | ||||
| type BadgeUnique struct { | ||||
| 	ID   int64  `xorm:"pk autoincr"` | ||||
| 	Slug string `xorm:"UNIQUE"` | ||||
| } | ||||
|  | ||||
| func (BadgeUnique) TableName() string { | ||||
| 	return "badge" | ||||
| } | ||||
|  | ||||
| func UseSlugInsteadOfIDForBadges(x *xorm.Engine) error { | ||||
| 	type Badge struct { | ||||
| 		Slug string | ||||
| 	} | ||||
|  | ||||
| 	err := x.Sync(new(Badge)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	sess := x.NewSession() | ||||
| 	defer sess.Close() | ||||
| 	if err := sess.Begin(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	_, err = sess.Exec("UPDATE `badge` SET `slug` = `id` Where `slug` IS NULL") | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	err = sess.Sync(new(BadgeUnique)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return sess.Commit() | ||||
| } | ||||
							
								
								
									
										57
									
								
								models/migrations/v1_22/v287_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								models/migrations/v1_22/v287_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| // Copyright 2024 The Gitea Authors. All rights reserved. | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| package v1_22 //nolint | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"testing" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models/migrations/base" | ||||
|  | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func Test_UpdateBadgeColName(t *testing.T) { | ||||
| 	type Badge struct { | ||||
| 		ID          int64 `xorm:"pk autoincr"` | ||||
| 		Description string | ||||
| 		ImageURL    string | ||||
| 	} | ||||
|  | ||||
| 	// Prepare and load the testing database | ||||
| 	x, deferable := base.PrepareTestEnv(t, 0, new(BadgeUnique), new(Badge)) | ||||
| 	defer deferable() | ||||
| 	if x == nil || t.Failed() { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	oldBadges := []Badge{ | ||||
| 		{ID: 1, Description: "Test Badge 1", ImageURL: "https://example.com/badge1.png"}, | ||||
| 		{ID: 2, Description: "Test Badge 2", ImageURL: "https://example.com/badge2.png"}, | ||||
| 		{ID: 3, Description: "Test Badge 3", ImageURL: "https://example.com/badge3.png"}, | ||||
| 	} | ||||
|  | ||||
| 	for _, badge := range oldBadges { | ||||
| 		_, err := x.Insert(&badge) | ||||
| 		assert.NoError(t, err) | ||||
| 	} | ||||
|  | ||||
| 	if err := UseSlugInsteadOfIDForBadges(x); err != nil { | ||||
| 		assert.NoError(t, err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	got := []BadgeUnique{} | ||||
| 	if err := x.Table("badge").Asc("id").Find(&got); !assert.NoError(t, err) { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	for i, e := range oldBadges { | ||||
| 		got := got[i] | ||||
| 		assert.Equal(t, e.ID, got.ID) | ||||
| 		assert.Equal(t, fmt.Sprintf("%d", e.ID), got.Slug) | ||||
| 	} | ||||
|  | ||||
| 	// TODO: check if badges have been updated | ||||
| } | ||||
| @@ -5,13 +5,15 @@ package user | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| ) | ||||
|  | ||||
| // Badge represents a user badge | ||||
| type Badge struct { | ||||
| 	ID          int64 `xorm:"pk autoincr"` | ||||
| 	ID          int64  `xorm:"pk autoincr"` | ||||
| 	Slug        string `xorm:"UNIQUE"` | ||||
| 	Description string | ||||
| 	ImageURL    string | ||||
| } | ||||
| @@ -39,3 +41,84 @@ func GetUserBadges(ctx context.Context, u *User) ([]*Badge, int64, error) { | ||||
| 	count, err := sess.FindAndCount(&badges) | ||||
| 	return badges, count, err | ||||
| } | ||||
|  | ||||
| // CreateBadge creates a new badge. | ||||
| func CreateBadge(ctx context.Context, badge *Badge) error { | ||||
| 	_, err := db.GetEngine(ctx).Insert(badge) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // GetBadge returns a badge | ||||
| func GetBadge(ctx context.Context, slug string) (*Badge, error) { | ||||
| 	badge := new(Badge) | ||||
| 	has, err := db.GetEngine(ctx).Where("slug=?", slug).Get(badge) | ||||
| 	if !has { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return badge, err | ||||
| } | ||||
|  | ||||
| // UpdateBadge updates a badge based on its slug. | ||||
| func UpdateBadge(ctx context.Context, badge *Badge) error { | ||||
| 	_, err := db.GetEngine(ctx).Where("slug=?", badge.Slug).Update(badge) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // DeleteBadge deletes a badge. | ||||
| func DeleteBadge(ctx context.Context, badge *Badge) error { | ||||
| 	_, err := db.GetEngine(ctx).Where("slug=?", badge.Slug).Delete(badge) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // AddUserBadge adds a badge to a user. | ||||
| func AddUserBadge(ctx context.Context, u *User, badge *Badge) error { | ||||
| 	return AddUserBadges(ctx, u, []*Badge{badge}) | ||||
| } | ||||
|  | ||||
| // AddUserBadges adds badges to a user. | ||||
| func AddUserBadges(ctx context.Context, u *User, badges []*Badge) error { | ||||
| 	return db.WithTx(ctx, func(ctx context.Context) error { | ||||
| 		for _, badge := range badges { | ||||
| 			// hydrate badge and check if it exists | ||||
| 			has, err := db.GetEngine(ctx).Where("slug=?", badge.Slug).Get(badge) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} else if !has { | ||||
| 				return fmt.Errorf("badge with slug %s doesn't exist", badge.Slug) | ||||
| 			} | ||||
| 			if err := db.Insert(ctx, &UserBadge{ | ||||
| 				BadgeID: badge.ID, | ||||
| 				UserID:  u.ID, | ||||
| 			}); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 		return nil | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // RemoveUserBadge removes a badge from a user. | ||||
| func RemoveUserBadge(ctx context.Context, u *User, badge *Badge) error { | ||||
| 	return RemoveUserBadges(ctx, u, []*Badge{badge}) | ||||
| } | ||||
|  | ||||
| // RemoveUserBadges removes badges from a user. | ||||
| func RemoveUserBadges(ctx context.Context, u *User, badges []*Badge) error { | ||||
| 	return db.WithTx(ctx, func(ctx context.Context) error { | ||||
| 		for _, badge := range badges { | ||||
| 			if _, err := db.GetEngine(ctx). | ||||
| 				Join("INNER", "badge", "badge.id = `user_badge`.badge_id"). | ||||
| 				Where("`user_badge`.user_id=? AND `badge`.slug=?", u.ID, badge.Slug). | ||||
| 				Delete(&UserBadge{}); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 		return nil | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // RemoveAllUserBadges removes all badges from a user. | ||||
| func RemoveAllUserBadges(ctx context.Context, u *User) error { | ||||
| 	_, err := db.GetEngine(ctx).Where("user_id=?", u.ID).Delete(&UserBadge{}) | ||||
| 	return err | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| // Copyright 2014 The Gogs Authors. All rights reserved. | ||||
| // Copyright 2023 The Gitea Authors. All rights reserved. | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| package structs | ||||
| @@ -108,3 +109,33 @@ type UpdateUserAvatarOption struct { | ||||
| 	// image must be base64 encoded | ||||
| 	Image string `json:"image" binding:"Required"` | ||||
| } | ||||
|  | ||||
| // Badge represents a user badge | ||||
| // swagger:model | ||||
| type Badge struct { | ||||
| 	ID          int64  `json:"id"` | ||||
| 	Slug        string `json:"slug"` | ||||
| 	Description string `json:"description"` | ||||
| 	ImageURL    string `json:"image_url"` | ||||
| } | ||||
|  | ||||
| // UserBadge represents a user badge | ||||
| // swagger:model | ||||
| type UserBadge struct { | ||||
| 	ID      int64 `json:"id"` | ||||
| 	BadgeID int64 `json:"badge_id"` | ||||
| 	UserID  int64 `json:"user_id"` | ||||
| } | ||||
|  | ||||
| // UserBadgeOption options for link between users and badges | ||||
| type UserBadgeOption struct { | ||||
| 	// example: ["badge1","badge2"] | ||||
| 	BadgeSlugs []string `json:"badge_slugs" binding:"Required"` | ||||
| } | ||||
|  | ||||
| // BadgeList | ||||
| // swagger:response BadgeList | ||||
| type BadgeList struct { | ||||
| 	// in:body | ||||
| 	Body []Badge `json:"body"` | ||||
| } | ||||
|   | ||||
							
								
								
									
										124
									
								
								routers/api/v1/admin/user_badge.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								routers/api/v1/admin/user_badge.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,124 @@ | ||||
| // Copyright 2023 The Gitea Authors. All rights reserved. | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| package admin | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
|  | ||||
| 	user_model "code.gitea.io/gitea/models/user" | ||||
| 	api "code.gitea.io/gitea/modules/structs" | ||||
| 	"code.gitea.io/gitea/modules/web" | ||||
| 	"code.gitea.io/gitea/services/context" | ||||
| ) | ||||
|  | ||||
| // ListUserBadges lists all badges belonging to a user | ||||
| func ListUserBadges(ctx *context.APIContext) { | ||||
| 	// swagger:operation GET /admin/users/{username}/badges admin adminListUserBadges | ||||
| 	// --- | ||||
| 	// summary: List a user's badges | ||||
| 	// produces: | ||||
| 	// - application/json | ||||
| 	// parameters: | ||||
| 	// - name: username | ||||
| 	//   in: path | ||||
| 	//   description: username of user | ||||
| 	//   type: string | ||||
| 	//   required: true | ||||
| 	// responses: | ||||
| 	//   "200": | ||||
| 	//     "$ref": "#/responses/BadgeList" | ||||
| 	//   "404": | ||||
| 	//     "$ref": "#/responses/notFound" | ||||
|  | ||||
| 	badges, maxResults, err := user_model.GetUserBadges(ctx, ctx.ContextUser) | ||||
| 	if err != nil { | ||||
| 		ctx.Error(http.StatusInternalServerError, "GetUserBadges", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	ctx.SetTotalCountHeader(maxResults) | ||||
| 	ctx.JSON(http.StatusOK, &badges) | ||||
| } | ||||
|  | ||||
| // AddUserBadges add badges to a user | ||||
| func AddUserBadges(ctx *context.APIContext) { | ||||
| 	// swagger:operation POST /admin/users/{username}/badges admin adminAddUserBadges | ||||
| 	// --- | ||||
| 	// summary: Add a badge to a user | ||||
| 	// consumes: | ||||
| 	// - application/json | ||||
| 	// produces: | ||||
| 	// - application/json | ||||
| 	// parameters: | ||||
| 	// - name: username | ||||
| 	//   in: path | ||||
| 	//   description: username of user | ||||
| 	//   type: string | ||||
| 	//   required: true | ||||
| 	// - name: body | ||||
| 	//   in: body | ||||
| 	//   schema: | ||||
| 	//     "$ref": "#/definitions/UserBadgeOption" | ||||
| 	// responses: | ||||
| 	//   "204": | ||||
| 	//     "$ref": "#/responses/empty" | ||||
| 	//   "403": | ||||
| 	//     "$ref": "#/responses/forbidden" | ||||
|  | ||||
| 	form := web.GetForm(ctx).(*api.UserBadgeOption) | ||||
| 	badges := prepareBadgesForReplaceOrAdd(ctx, *form) | ||||
|  | ||||
| 	if err := user_model.AddUserBadges(ctx, ctx.ContextUser, badges); err != nil { | ||||
| 		ctx.Error(http.StatusInternalServerError, "ReplaceUserBadges", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	ctx.Status(http.StatusNoContent) | ||||
| } | ||||
|  | ||||
| // DeleteUserBadges delete a badge from a user | ||||
| func DeleteUserBadges(ctx *context.APIContext) { | ||||
| 	// swagger:operation DELETE /admin/users/{username}/badges admin adminDeleteUserBadges | ||||
| 	// --- | ||||
| 	// summary: Remove a badge from a user | ||||
| 	// produces: | ||||
| 	// - application/json | ||||
| 	// parameters: | ||||
| 	// - name: username | ||||
| 	//   in: path | ||||
| 	//   description: username of user | ||||
| 	//   type: string | ||||
| 	//   required: true | ||||
| 	// - name: body | ||||
| 	//   in: body | ||||
| 	//   schema: | ||||
| 	//     "$ref": "#/definitions/UserBadgeOption" | ||||
| 	// responses: | ||||
| 	//   "204": | ||||
| 	//     "$ref": "#/responses/empty" | ||||
| 	//   "403": | ||||
| 	//     "$ref": "#/responses/forbidden" | ||||
| 	//   "422": | ||||
| 	//     "$ref": "#/responses/validationError" | ||||
|  | ||||
| 	form := web.GetForm(ctx).(*api.UserBadgeOption) | ||||
| 	badges := prepareBadgesForReplaceOrAdd(ctx, *form) | ||||
|  | ||||
| 	if err := user_model.RemoveUserBadges(ctx, ctx.ContextUser, badges); err != nil { | ||||
| 		ctx.Error(http.StatusInternalServerError, "ReplaceUserBadges", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	ctx.Status(http.StatusNoContent) | ||||
| } | ||||
|  | ||||
| func prepareBadgesForReplaceOrAdd(ctx *context.APIContext, form api.UserBadgeOption) []*user_model.Badge { | ||||
| 	badges := make([]*user_model.Badge, len(form.BadgeSlugs)) | ||||
| 	for i, badge := range form.BadgeSlugs { | ||||
| 		badges[i] = &user_model.Badge{ | ||||
| 			Slug: badge, | ||||
| 		} | ||||
| 	} | ||||
| 	return badges | ||||
| } | ||||
| @@ -1519,6 +1519,9 @@ func Routes() *web.Route { | ||||
| 					m.Post("/orgs", bind(api.CreateOrgOption{}), admin.CreateOrg) | ||||
| 					m.Post("/repos", bind(api.CreateRepoOption{}), admin.CreateRepo) | ||||
| 					m.Post("/rename", bind(api.RenameUserOption{}), admin.RenameUser) | ||||
| 					m.Get("/badges", admin.ListUserBadges) | ||||
| 					m.Post("/badges", bind(api.UserBadgeOption{}), admin.AddUserBadges) | ||||
| 					m.Delete("/badges", bind(api.UserBadgeOption{}), admin.DeleteUserBadges) | ||||
| 				}, context.UserAssignmentAPI()) | ||||
| 			}) | ||||
| 			m.Group("/emails", func() { | ||||
|   | ||||
| @@ -190,4 +190,10 @@ type swaggerParameterBodies struct { | ||||
|  | ||||
| 	// in:body | ||||
| 	CreateOrUpdateSecretOption api.CreateOrUpdateSecretOption | ||||
|  | ||||
| 	// in:body | ||||
| 	UserBadgeOption api.UserBadgeOption | ||||
|  | ||||
| 	// in:body | ||||
| 	UserBadgeList api.BadgeList | ||||
| } | ||||
|   | ||||
							
								
								
									
										171
									
								
								templates/swagger/v1_json.tmpl
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										171
									
								
								templates/swagger/v1_json.tmpl
									
									
									
										generated
									
									
									
								
							| @@ -689,6 +689,109 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "/admin/users/{username}/badges": { | ||||
|       "get": { | ||||
|         "produces": [ | ||||
|           "application/json" | ||||
|         ], | ||||
|         "tags": [ | ||||
|           "admin" | ||||
|         ], | ||||
|         "summary": "List a user's badges", | ||||
|         "operationId": "adminListUserBadges", | ||||
|         "parameters": [ | ||||
|           { | ||||
|             "type": "string", | ||||
|             "description": "username of user", | ||||
|             "name": "username", | ||||
|             "in": "path", | ||||
|             "required": true | ||||
|           } | ||||
|         ], | ||||
|         "responses": { | ||||
|           "200": { | ||||
|             "$ref": "#/responses/BadgeList" | ||||
|           }, | ||||
|           "404": { | ||||
|             "$ref": "#/responses/notFound" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "post": { | ||||
|         "consumes": [ | ||||
|           "application/json" | ||||
|         ], | ||||
|         "produces": [ | ||||
|           "application/json" | ||||
|         ], | ||||
|         "tags": [ | ||||
|           "admin" | ||||
|         ], | ||||
|         "summary": "Add a badge to a user", | ||||
|         "operationId": "adminAddUserBadges", | ||||
|         "parameters": [ | ||||
|           { | ||||
|             "type": "string", | ||||
|             "description": "username of user", | ||||
|             "name": "username", | ||||
|             "in": "path", | ||||
|             "required": true | ||||
|           }, | ||||
|           { | ||||
|             "name": "body", | ||||
|             "in": "body", | ||||
|             "schema": { | ||||
|               "$ref": "#/definitions/UserBadgeOption" | ||||
|             } | ||||
|           } | ||||
|         ], | ||||
|         "responses": { | ||||
|           "204": { | ||||
|             "$ref": "#/responses/empty" | ||||
|           }, | ||||
|           "403": { | ||||
|             "$ref": "#/responses/forbidden" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       "delete": { | ||||
|         "produces": [ | ||||
|           "application/json" | ||||
|         ], | ||||
|         "tags": [ | ||||
|           "admin" | ||||
|         ], | ||||
|         "summary": "Remove a badge from a user", | ||||
|         "operationId": "adminDeleteUserBadges", | ||||
|         "parameters": [ | ||||
|           { | ||||
|             "type": "string", | ||||
|             "description": "username of user", | ||||
|             "name": "username", | ||||
|             "in": "path", | ||||
|             "required": true | ||||
|           }, | ||||
|           { | ||||
|             "name": "body", | ||||
|             "in": "body", | ||||
|             "schema": { | ||||
|               "$ref": "#/definitions/UserBadgeOption" | ||||
|             } | ||||
|           } | ||||
|         ], | ||||
|         "responses": { | ||||
|           "204": { | ||||
|             "$ref": "#/responses/empty" | ||||
|           }, | ||||
|           "403": { | ||||
|             "$ref": "#/responses/forbidden" | ||||
|           }, | ||||
|           "422": { | ||||
|             "$ref": "#/responses/validationError" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "/admin/users/{username}/keys": { | ||||
|       "post": { | ||||
|         "consumes": [ | ||||
| @@ -17003,6 +17106,45 @@ | ||||
|       }, | ||||
|       "x-go-package": "code.gitea.io/gitea/modules/structs" | ||||
|     }, | ||||
|     "Badge": { | ||||
|       "description": "Badge represents a user badge", | ||||
|       "type": "object", | ||||
|       "properties": { | ||||
|         "description": { | ||||
|           "type": "string", | ||||
|           "x-go-name": "Description" | ||||
|         }, | ||||
|         "id": { | ||||
|           "type": "integer", | ||||
|           "format": "int64", | ||||
|           "x-go-name": "ID" | ||||
|         }, | ||||
|         "image_url": { | ||||
|           "type": "string", | ||||
|           "x-go-name": "ImageURL" | ||||
|         }, | ||||
|         "slug": { | ||||
|           "type": "string", | ||||
|           "x-go-name": "Slug" | ||||
|         } | ||||
|       }, | ||||
|       "x-go-package": "code.gitea.io/gitea/modules/structs" | ||||
|     }, | ||||
|     "BadgeList": { | ||||
|       "description": "BadgeList", | ||||
|       "type": "object", | ||||
|       "properties": { | ||||
|         "body": { | ||||
|           "description": "in:body", | ||||
|           "type": "array", | ||||
|           "items": { | ||||
|             "$ref": "#/definitions/Badge" | ||||
|           }, | ||||
|           "x-go-name": "Body" | ||||
|         } | ||||
|       }, | ||||
|       "x-go-package": "code.gitea.io/gitea/modules/structs" | ||||
|     }, | ||||
|     "Branch": { | ||||
|       "description": "Branch represents a repository branch", | ||||
|       "type": "object", | ||||
| @@ -23047,6 +23189,24 @@ | ||||
|       }, | ||||
|       "x-go-package": "code.gitea.io/gitea/modules/structs" | ||||
|     }, | ||||
|     "UserBadgeOption": { | ||||
|       "description": "UserBadgeOption options for link between users and badges", | ||||
|       "type": "object", | ||||
|       "properties": { | ||||
|         "badge_slugs": { | ||||
|           "type": "array", | ||||
|           "items": { | ||||
|             "type": "string" | ||||
|           }, | ||||
|           "x-go-name": "BadgeSlugs", | ||||
|           "example": [ | ||||
|             "badge1", | ||||
|             "badge2" | ||||
|           ] | ||||
|         } | ||||
|       }, | ||||
|       "x-go-package": "code.gitea.io/gitea/modules/structs" | ||||
|     }, | ||||
|     "UserHeatmapData": { | ||||
|       "description": "UserHeatmapData represents the data needed to create a heatmap", | ||||
|       "type": "object", | ||||
| @@ -23336,6 +23496,15 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "BadgeList": { | ||||
|       "description": "BadgeList", | ||||
|       "schema": { | ||||
|         "type": "array", | ||||
|         "items": { | ||||
|           "$ref": "#/definitions/Badge" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "Branch": { | ||||
|       "description": "Branch", | ||||
|       "schema": { | ||||
| @@ -24249,7 +24418,7 @@ | ||||
|     "parameterBodies": { | ||||
|       "description": "parameterBodies", | ||||
|       "schema": { | ||||
|         "$ref": "#/definitions/CreateOrUpdateSecretOption" | ||||
|         "$ref": "#/definitions/BadgeList" | ||||
|       } | ||||
|     }, | ||||
|     "redirect": { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user