mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 19:38:23 +00:00 
			
		
		
		
	Add API for changing Avatars (#25369)
This adds an API for uploading and Deleting Avatars for of Users, Repos and Organisations. I'm not sure, if this should also be added to the Admin API. Resolves #25344 --------- Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: Giteabot <teabot@gitea.io>
This commit is contained in:
		| @@ -380,3 +380,9 @@ type NewIssuePinsAllowed struct { | |||||||
| 	Issues       bool `json:"issues"` | 	Issues       bool `json:"issues"` | ||||||
| 	PullRequests bool `json:"pull_requests"` | 	PullRequests bool `json:"pull_requests"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // UpdateRepoAvatarUserOption options when updating the repo avatar | ||||||
|  | type UpdateRepoAvatarOption struct { | ||||||
|  | 	// image must be base64 encoded | ||||||
|  | 	Image string `json:"image" binding:"Required"` | ||||||
|  | } | ||||||
|   | |||||||
| @@ -102,3 +102,9 @@ type RenameUserOption struct { | |||||||
| 	// unique: true | 	// unique: true | ||||||
| 	NewName string `json:"new_username" binding:"Required"` | 	NewName string `json:"new_username" binding:"Required"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // UpdateUserAvatarUserOption options when updating the user avatar | ||||||
|  | type UpdateUserAvatarOption struct { | ||||||
|  | 	// image must be base64 encoded | ||||||
|  | 	Image string `json:"image" binding:"Required"` | ||||||
|  | } | ||||||
|   | |||||||
| @@ -899,6 +899,11 @@ func Routes() *web.Route { | |||||||
| 					Patch(bind(api.EditHookOption{}), user.EditHook). | 					Patch(bind(api.EditHookOption{}), user.EditHook). | ||||||
| 					Delete(user.DeleteHook) | 					Delete(user.DeleteHook) | ||||||
| 			}, reqWebhooksEnabled()) | 			}, reqWebhooksEnabled()) | ||||||
|  |  | ||||||
|  | 			m.Group("/avatar", func() { | ||||||
|  | 				m.Post("", bind(api.UpdateUserAvatarOption{}), user.UpdateAvatar) | ||||||
|  | 				m.Delete("", user.DeleteAvatar) | ||||||
|  | 			}, reqToken()) | ||||||
| 		}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), reqToken()) | 		}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), reqToken()) | ||||||
|  |  | ||||||
| 		// Repositories (requires repo scope, org scope) | 		// Repositories (requires repo scope, org scope) | ||||||
| @@ -1134,6 +1139,10 @@ func Routes() *web.Route { | |||||||
| 				m.Get("/languages", reqRepoReader(unit.TypeCode), repo.GetLanguages) | 				m.Get("/languages", reqRepoReader(unit.TypeCode), repo.GetLanguages) | ||||||
| 				m.Get("/activities/feeds", repo.ListRepoActivityFeeds) | 				m.Get("/activities/feeds", repo.ListRepoActivityFeeds) | ||||||
| 				m.Get("/new_pin_allowed", repo.AreNewIssuePinsAllowed) | 				m.Get("/new_pin_allowed", repo.AreNewIssuePinsAllowed) | ||||||
|  | 				m.Group("/avatar", func() { | ||||||
|  | 					m.Post("", bind(api.UpdateRepoAvatarOption{}), repo.UpdateAvatar) | ||||||
|  | 					m.Delete("", repo.DeleteAvatar) | ||||||
|  | 				}, reqAdmin(), reqToken()) | ||||||
| 			}, repoAssignment()) | 			}, repoAssignment()) | ||||||
| 		}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository)) | 		}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository)) | ||||||
|  |  | ||||||
| @@ -1314,6 +1323,10 @@ func Routes() *web.Route { | |||||||
| 					Patch(bind(api.EditHookOption{}), org.EditHook). | 					Patch(bind(api.EditHookOption{}), org.EditHook). | ||||||
| 					Delete(org.DeleteHook) | 					Delete(org.DeleteHook) | ||||||
| 			}, reqToken(), reqOrgOwnership(), reqWebhooksEnabled()) | 			}, reqToken(), reqOrgOwnership(), reqWebhooksEnabled()) | ||||||
|  | 			m.Group("/avatar", func() { | ||||||
|  | 				m.Post("", bind(api.UpdateUserAvatarOption{}), org.UpdateAvatar) | ||||||
|  | 				m.Delete("", org.DeleteAvatar) | ||||||
|  | 			}, reqToken(), reqOrgOwnership()) | ||||||
| 			m.Get("/activities/feeds", org.ListOrgActivityFeeds) | 			m.Get("/activities/feeds", org.ListOrgActivityFeeds) | ||||||
| 		}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), orgAssignment(true)) | 		}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), orgAssignment(true)) | ||||||
| 		m.Group("/teams/{teamid}", func() { | 		m.Group("/teams/{teamid}", func() { | ||||||
|   | |||||||
							
								
								
									
										74
									
								
								routers/api/v1/org/avatar.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								routers/api/v1/org/avatar.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | |||||||
|  | // Copyright 2023 The Gitea Authors. All rights reserved. | ||||||
|  | // SPDX-License-Identifier: MIT | ||||||
|  |  | ||||||
|  | package org | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/base64" | ||||||
|  | 	"net/http" | ||||||
|  |  | ||||||
|  | 	"code.gitea.io/gitea/modules/context" | ||||||
|  | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/modules/web" | ||||||
|  | 	user_service "code.gitea.io/gitea/services/user" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // UpdateAvatarupdates the Avatar of an Organisation | ||||||
|  | func UpdateAvatar(ctx *context.APIContext) { | ||||||
|  | 	// swagger:operation POST /orgs/{org}/avatar organization orgUpdateAvatar | ||||||
|  | 	// --- | ||||||
|  | 	// summary: Update Avatar | ||||||
|  | 	// produces: | ||||||
|  | 	// - application/json | ||||||
|  | 	// parameters: | ||||||
|  | 	// - name: org | ||||||
|  | 	//   in: path | ||||||
|  | 	//   description: name of the organization | ||||||
|  | 	//   type: string | ||||||
|  | 	//   required: true | ||||||
|  | 	// - name: body | ||||||
|  | 	//   in: body | ||||||
|  | 	//   schema: | ||||||
|  | 	//     "$ref": "#/definitions/UpdateUserAvatarOption" | ||||||
|  | 	// responses: | ||||||
|  | 	//   "204": | ||||||
|  | 	//     "$ref": "#/responses/empty" | ||||||
|  | 	form := web.GetForm(ctx).(*api.UpdateUserAvatarOption) | ||||||
|  |  | ||||||
|  | 	content, err := base64.StdEncoding.DecodeString(form.Image) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ctx.Error(http.StatusBadRequest, "DecodeImage", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = user_service.UploadAvatar(ctx.Org.Organization.AsUser(), content) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ctx.Error(http.StatusInternalServerError, "UploadAvatar", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ctx.Status(http.StatusNoContent) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // DeleteAvatar deletes the Avatar of an Organisation | ||||||
|  | func DeleteAvatar(ctx *context.APIContext) { | ||||||
|  | 	// swagger:operation DELETE /orgs/{org}/avatar organization orgDeleteAvatar | ||||||
|  | 	// --- | ||||||
|  | 	// summary: Delete Avatar | ||||||
|  | 	// produces: | ||||||
|  | 	// - application/json | ||||||
|  | 	// parameters: | ||||||
|  | 	// - name: org | ||||||
|  | 	//   in: path | ||||||
|  | 	//   description: name of the organization | ||||||
|  | 	//   type: string | ||||||
|  | 	//   required: true | ||||||
|  | 	// responses: | ||||||
|  | 	//   "204": | ||||||
|  | 	//     "$ref": "#/responses/empty" | ||||||
|  | 	err := user_service.DeleteAvatar(ctx.Org.Organization.AsUser()) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ctx.Error(http.StatusInternalServerError, "DeleteAvatar", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ctx.Status(http.StatusNoContent) | ||||||
|  | } | ||||||
							
								
								
									
										84
									
								
								routers/api/v1/repo/avatar.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								routers/api/v1/repo/avatar.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | |||||||
|  | // Copyright 2023 The Gitea Authors. All rights reserved. | ||||||
|  | // SPDX-License-Identifier: MIT | ||||||
|  |  | ||||||
|  | package repo | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/base64" | ||||||
|  | 	"net/http" | ||||||
|  |  | ||||||
|  | 	"code.gitea.io/gitea/modules/context" | ||||||
|  | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/modules/web" | ||||||
|  | 	repo_service "code.gitea.io/gitea/services/repository" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // UpdateVatar updates the Avatar of an Repo | ||||||
|  | func UpdateAvatar(ctx *context.APIContext) { | ||||||
|  | 	// swagger:operation POST /repos/{owner}/{repo}/avatar repository repoUpdateAvatar | ||||||
|  | 	// --- | ||||||
|  | 	// summary: Update avatar | ||||||
|  | 	// produces: | ||||||
|  | 	// - application/json | ||||||
|  | 	// parameters: | ||||||
|  | 	// - name: owner | ||||||
|  | 	//   in: path | ||||||
|  | 	//   description: owner of the repo | ||||||
|  | 	//   type: string | ||||||
|  | 	//   required: true | ||||||
|  | 	// - name: repo | ||||||
|  | 	//   in: path | ||||||
|  | 	//   description: name of the repo | ||||||
|  | 	//   type: string | ||||||
|  | 	//   required: true | ||||||
|  | 	// - name: body | ||||||
|  | 	//   in: body | ||||||
|  | 	//   schema: | ||||||
|  | 	//     "$ref": "#/definitions/UpdateRepoAvatarOption" | ||||||
|  | 	// responses: | ||||||
|  | 	//   "204": | ||||||
|  | 	//     "$ref": "#/responses/empty" | ||||||
|  | 	form := web.GetForm(ctx).(*api.UpdateRepoAvatarOption) | ||||||
|  |  | ||||||
|  | 	content, err := base64.StdEncoding.DecodeString(form.Image) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ctx.Error(http.StatusBadRequest, "DecodeImage", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = repo_service.UploadAvatar(ctx, ctx.Repo.Repository, content) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ctx.Error(http.StatusInternalServerError, "UploadAvatar", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ctx.Status(http.StatusNoContent) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // UpdateAvatar deletes the Avatar of an Repo | ||||||
|  | func DeleteAvatar(ctx *context.APIContext) { | ||||||
|  | 	// swagger:operation DELETE /repos/{owner}/{repo}/avatar repository repoDeleteAvatar | ||||||
|  | 	// --- | ||||||
|  | 	// summary: Delete avatar | ||||||
|  | 	// produces: | ||||||
|  | 	// - application/json | ||||||
|  | 	// parameters: | ||||||
|  | 	// - name: owner | ||||||
|  | 	//   in: path | ||||||
|  | 	//   description: owner of the repo | ||||||
|  | 	//   type: string | ||||||
|  | 	//   required: true | ||||||
|  | 	// - name: repo | ||||||
|  | 	//   in: path | ||||||
|  | 	//   description: name of the repo | ||||||
|  | 	//   type: string | ||||||
|  | 	//   required: true | ||||||
|  | 	// responses: | ||||||
|  | 	//   "204": | ||||||
|  | 	//     "$ref": "#/responses/empty" | ||||||
|  | 	err := repo_service.DeleteAvatar(ctx, ctx.Repo.Repository) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ctx.Error(http.StatusInternalServerError, "DeleteAvatar", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ctx.Status(http.StatusNoContent) | ||||||
|  | } | ||||||
| @@ -181,4 +181,10 @@ type swaggerParameterBodies struct { | |||||||
|  |  | ||||||
| 	// in:body | 	// in:body | ||||||
| 	CreatePushMirrorOption api.CreatePushMirrorOption | 	CreatePushMirrorOption api.CreatePushMirrorOption | ||||||
|  |  | ||||||
|  | 	// in:body | ||||||
|  | 	UpdateUserAvatarOptions api.UpdateUserAvatarOption | ||||||
|  |  | ||||||
|  | 	// in:body | ||||||
|  | 	UpdateRepoAvatarOptions api.UpdateRepoAvatarOption | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										63
									
								
								routers/api/v1/user/avatar.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								routers/api/v1/user/avatar.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | |||||||
|  | // Copyright 2023 The Gitea Authors. All rights reserved. | ||||||
|  | // SPDX-License-Identifier: MIT | ||||||
|  |  | ||||||
|  | package user | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/base64" | ||||||
|  | 	"net/http" | ||||||
|  |  | ||||||
|  | 	"code.gitea.io/gitea/modules/context" | ||||||
|  | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/modules/web" | ||||||
|  | 	user_service "code.gitea.io/gitea/services/user" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // UpdateAvatar updates the Avatar of an User | ||||||
|  | func UpdateAvatar(ctx *context.APIContext) { | ||||||
|  | 	// swagger:operation POST /user/avatar user userUpdateAvatar | ||||||
|  | 	// --- | ||||||
|  | 	// summary: Update Avatar | ||||||
|  | 	// produces: | ||||||
|  | 	// - application/json | ||||||
|  | 	// parameters: | ||||||
|  | 	// - name: body | ||||||
|  | 	//   in: body | ||||||
|  | 	//   schema: | ||||||
|  | 	//     "$ref": "#/definitions/UpdateUserAvatarOption" | ||||||
|  | 	// responses: | ||||||
|  | 	//   "204": | ||||||
|  | 	//     "$ref": "#/responses/empty" | ||||||
|  | 	form := web.GetForm(ctx).(*api.UpdateUserAvatarOption) | ||||||
|  |  | ||||||
|  | 	content, err := base64.StdEncoding.DecodeString(form.Image) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ctx.Error(http.StatusBadRequest, "DecodeImage", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = user_service.UploadAvatar(ctx.Doer, content) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ctx.Error(http.StatusInternalServerError, "UploadAvatar", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ctx.Status(http.StatusNoContent) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // DeleteAvatar deletes the Avatar of an User | ||||||
|  | func DeleteAvatar(ctx *context.APIContext) { | ||||||
|  | 	// swagger:operation DELETE /user/avatar user userDeleteAvatar | ||||||
|  | 	// --- | ||||||
|  | 	// summary: Delete Avatar | ||||||
|  | 	// produces: | ||||||
|  | 	// - application/json | ||||||
|  | 	// responses: | ||||||
|  | 	//   "204": | ||||||
|  | 	//     "$ref": "#/responses/empty" | ||||||
|  | 	err := user_service.DeleteAvatar(ctx.Doer) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ctx.Error(http.StatusInternalServerError, "DeleteAvatar", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ctx.Status(http.StatusNoContent) | ||||||
|  | } | ||||||
							
								
								
									
										195
									
								
								templates/swagger/v1_json.tmpl
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										195
									
								
								templates/swagger/v1_json.tmpl
									
									
									
										generated
									
									
									
								
							| @@ -1595,6 +1595,63 @@ | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "/orgs/{org}/avatar": { | ||||||
|  |       "post": { | ||||||
|  |         "produces": [ | ||||||
|  |           "application/json" | ||||||
|  |         ], | ||||||
|  |         "tags": [ | ||||||
|  |           "organization" | ||||||
|  |         ], | ||||||
|  |         "summary": "Update Avatar", | ||||||
|  |         "operationId": "orgUpdateAvatar", | ||||||
|  |         "parameters": [ | ||||||
|  |           { | ||||||
|  |             "type": "string", | ||||||
|  |             "description": "name of the organization", | ||||||
|  |             "name": "org", | ||||||
|  |             "in": "path", | ||||||
|  |             "required": true | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             "name": "body", | ||||||
|  |             "in": "body", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/UpdateUserAvatarOption" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         ], | ||||||
|  |         "responses": { | ||||||
|  |           "204": { | ||||||
|  |             "$ref": "#/responses/empty" | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "delete": { | ||||||
|  |         "produces": [ | ||||||
|  |           "application/json" | ||||||
|  |         ], | ||||||
|  |         "tags": [ | ||||||
|  |           "organization" | ||||||
|  |         ], | ||||||
|  |         "summary": "Delete Avatar", | ||||||
|  |         "operationId": "orgDeleteAvatar", | ||||||
|  |         "parameters": [ | ||||||
|  |           { | ||||||
|  |             "type": "string", | ||||||
|  |             "description": "name of the organization", | ||||||
|  |             "name": "org", | ||||||
|  |             "in": "path", | ||||||
|  |             "required": true | ||||||
|  |           } | ||||||
|  |         ], | ||||||
|  |         "responses": { | ||||||
|  |           "204": { | ||||||
|  |             "$ref": "#/responses/empty" | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "/orgs/{org}/hooks": { |     "/orgs/{org}/hooks": { | ||||||
|       "get": { |       "get": { | ||||||
|         "produces": [ |         "produces": [ | ||||||
| @@ -3174,6 +3231,77 @@ | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "/repos/{owner}/{repo}/avatar": { | ||||||
|  |       "post": { | ||||||
|  |         "produces": [ | ||||||
|  |           "application/json" | ||||||
|  |         ], | ||||||
|  |         "tags": [ | ||||||
|  |           "repository" | ||||||
|  |         ], | ||||||
|  |         "summary": "Update avatar", | ||||||
|  |         "operationId": "repoUpdateAvatar", | ||||||
|  |         "parameters": [ | ||||||
|  |           { | ||||||
|  |             "type": "string", | ||||||
|  |             "description": "owner of the repo", | ||||||
|  |             "name": "owner", | ||||||
|  |             "in": "path", | ||||||
|  |             "required": true | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             "type": "string", | ||||||
|  |             "description": "name of the repo", | ||||||
|  |             "name": "repo", | ||||||
|  |             "in": "path", | ||||||
|  |             "required": true | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             "name": "body", | ||||||
|  |             "in": "body", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/UpdateRepoAvatarOption" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         ], | ||||||
|  |         "responses": { | ||||||
|  |           "204": { | ||||||
|  |             "$ref": "#/responses/empty" | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "delete": { | ||||||
|  |         "produces": [ | ||||||
|  |           "application/json" | ||||||
|  |         ], | ||||||
|  |         "tags": [ | ||||||
|  |           "repository" | ||||||
|  |         ], | ||||||
|  |         "summary": "Delete avatar", | ||||||
|  |         "operationId": "repoDeleteAvatar", | ||||||
|  |         "parameters": [ | ||||||
|  |           { | ||||||
|  |             "type": "string", | ||||||
|  |             "description": "owner of the repo", | ||||||
|  |             "name": "owner", | ||||||
|  |             "in": "path", | ||||||
|  |             "required": true | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             "type": "string", | ||||||
|  |             "description": "name of the repo", | ||||||
|  |             "name": "repo", | ||||||
|  |             "in": "path", | ||||||
|  |             "required": true | ||||||
|  |           } | ||||||
|  |         ], | ||||||
|  |         "responses": { | ||||||
|  |           "204": { | ||||||
|  |             "$ref": "#/responses/empty" | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "/repos/{owner}/{repo}/branch_protections": { |     "/repos/{owner}/{repo}/branch_protections": { | ||||||
|       "get": { |       "get": { | ||||||
|         "produces": [ |         "produces": [ | ||||||
| @@ -13787,6 +13915,47 @@ | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "/user/avatar": { | ||||||
|  |       "post": { | ||||||
|  |         "produces": [ | ||||||
|  |           "application/json" | ||||||
|  |         ], | ||||||
|  |         "tags": [ | ||||||
|  |           "user" | ||||||
|  |         ], | ||||||
|  |         "summary": "Update Avatar", | ||||||
|  |         "operationId": "userUpdateAvatar", | ||||||
|  |         "parameters": [ | ||||||
|  |           { | ||||||
|  |             "name": "body", | ||||||
|  |             "in": "body", | ||||||
|  |             "schema": { | ||||||
|  |               "$ref": "#/definitions/UpdateUserAvatarOption" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         ], | ||||||
|  |         "responses": { | ||||||
|  |           "204": { | ||||||
|  |             "$ref": "#/responses/empty" | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "delete": { | ||||||
|  |         "produces": [ | ||||||
|  |           "application/json" | ||||||
|  |         ], | ||||||
|  |         "tags": [ | ||||||
|  |           "user" | ||||||
|  |         ], | ||||||
|  |         "summary": "Delete Avatar", | ||||||
|  |         "operationId": "userDeleteAvatar", | ||||||
|  |         "responses": { | ||||||
|  |           "204": { | ||||||
|  |             "$ref": "#/responses/empty" | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "/user/emails": { |     "/user/emails": { | ||||||
|       "get": { |       "get": { | ||||||
|         "produces": [ |         "produces": [ | ||||||
| @@ -21548,6 +21717,30 @@ | |||||||
|       }, |       }, | ||||||
|       "x-go-package": "code.gitea.io/gitea/modules/structs" |       "x-go-package": "code.gitea.io/gitea/modules/structs" | ||||||
|     }, |     }, | ||||||
|  |     "UpdateRepoAvatarOption": { | ||||||
|  |       "description": "UpdateRepoAvatarUserOption options when updating the repo avatar", | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": { | ||||||
|  |         "image": { | ||||||
|  |           "description": "image must be base64 encoded", | ||||||
|  |           "type": "string", | ||||||
|  |           "x-go-name": "Image" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "x-go-package": "code.gitea.io/gitea/modules/structs" | ||||||
|  |     }, | ||||||
|  |     "UpdateUserAvatarOption": { | ||||||
|  |       "description": "UpdateUserAvatarUserOption options when updating the user avatar", | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": { | ||||||
|  |         "image": { | ||||||
|  |           "description": "image must be base64 encoded", | ||||||
|  |           "type": "string", | ||||||
|  |           "x-go-name": "Image" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "x-go-package": "code.gitea.io/gitea/modules/structs" | ||||||
|  |     }, | ||||||
|     "User": { |     "User": { | ||||||
|       "description": "User represents a user", |       "description": "User represents a user", | ||||||
|       "type": "object", |       "type": "object", | ||||||
| @@ -22837,7 +23030,7 @@ | |||||||
|     "parameterBodies": { |     "parameterBodies": { | ||||||
|       "description": "parameterBodies", |       "description": "parameterBodies", | ||||||
|       "schema": { |       "schema": { | ||||||
|         "$ref": "#/definitions/CreatePushMirrorOption" |         "$ref": "#/definitions/UpdateRepoAvatarOption" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "redirect": { |     "redirect": { | ||||||
|   | |||||||
							
								
								
									
										72
									
								
								tests/integration/api_org_avatar_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								tests/integration/api_org_avatar_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | |||||||
|  | // Copyright 2023 The Gitea Authors. All rights reserved. | ||||||
|  | // SPDX-License-Identifier: MIT | ||||||
|  |  | ||||||
|  | package integration | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/base64" | ||||||
|  | 	"net/http" | ||||||
|  | 	"os" | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	auth_model "code.gitea.io/gitea/models/auth" | ||||||
|  | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/tests" | ||||||
|  |  | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestAPIUpdateOrgAvatar(t *testing.T) { | ||||||
|  | 	defer tests.PrepareTestEnv(t)() | ||||||
|  |  | ||||||
|  | 	session := loginUser(t, "user1") | ||||||
|  |  | ||||||
|  | 	token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization) | ||||||
|  |  | ||||||
|  | 	// Test what happens if you use a valid image | ||||||
|  | 	avatar, err := os.ReadFile("tests/integration/avatar.png") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	if err != nil { | ||||||
|  | 		assert.FailNow(t, "Unable to open avatar.png") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	opts := api.UpdateUserAvatarOption{ | ||||||
|  | 		Image: base64.StdEncoding.EncodeToString(avatar), | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	req := NewRequestWithJSON(t, "POST", "/api/v1/orgs/user3/avatar?token="+token, &opts) | ||||||
|  | 	MakeRequest(t, req, http.StatusNoContent) | ||||||
|  |  | ||||||
|  | 	// Test what happens if you don't have a valid Base64 string | ||||||
|  | 	opts = api.UpdateUserAvatarOption{ | ||||||
|  | 		Image: "Invalid", | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	req = NewRequestWithJSON(t, "POST", "/api/v1/orgs/user3/avatar?token="+token, &opts) | ||||||
|  | 	MakeRequest(t, req, http.StatusBadRequest) | ||||||
|  |  | ||||||
|  | 	// Test what happens if you use a file that is not an image | ||||||
|  | 	text, err := os.ReadFile("tests/integration/README.md") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	if err != nil { | ||||||
|  | 		assert.FailNow(t, "Unable to open README.md") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	opts = api.UpdateUserAvatarOption{ | ||||||
|  | 		Image: base64.StdEncoding.EncodeToString(text), | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	req = NewRequestWithJSON(t, "POST", "/api/v1/orgs/user3/avatar?token="+token, &opts) | ||||||
|  | 	MakeRequest(t, req, http.StatusInternalServerError) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestAPIDeleteOrgAvatar(t *testing.T) { | ||||||
|  | 	defer tests.PrepareTestEnv(t)() | ||||||
|  |  | ||||||
|  | 	session := loginUser(t, "user1") | ||||||
|  |  | ||||||
|  | 	token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization) | ||||||
|  |  | ||||||
|  | 	req := NewRequest(t, "DELETE", "/api/v1/orgs/user3/avatar?token="+token) | ||||||
|  | 	MakeRequest(t, req, http.StatusNoContent) | ||||||
|  | } | ||||||
							
								
								
									
										76
									
								
								tests/integration/api_repo_avatar_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								tests/integration/api_repo_avatar_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | |||||||
|  | // Copyright 2018 The Gitea Authors. All rights reserved. | ||||||
|  | // SPDX-License-Identifier: MIT | ||||||
|  |  | ||||||
|  | package integration | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/base64" | ||||||
|  | 	"fmt" | ||||||
|  | 	"net/http" | ||||||
|  | 	"os" | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	auth_model "code.gitea.io/gitea/models/auth" | ||||||
|  | 	repo_model "code.gitea.io/gitea/models/repo" | ||||||
|  | 	"code.gitea.io/gitea/models/unittest" | ||||||
|  | 	user_model "code.gitea.io/gitea/models/user" | ||||||
|  | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/tests" | ||||||
|  |  | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestAPIUpdateRepoAvatar(t *testing.T) { | ||||||
|  | 	defer tests.PrepareTestEnv(t)() | ||||||
|  |  | ||||||
|  | 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) | ||||||
|  | 	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) | ||||||
|  | 	token := getUserToken(t, user2.LowerName, auth_model.AccessTokenScopeWriteRepository) | ||||||
|  |  | ||||||
|  | 	// Test what happens if you use a valid image | ||||||
|  | 	avatar, err := os.ReadFile("tests/integration/avatar.png") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	if err != nil { | ||||||
|  | 		assert.FailNow(t, "Unable to open avatar.png") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	opts := api.UpdateRepoAvatarOption{ | ||||||
|  | 		Image: base64.StdEncoding.EncodeToString(avatar), | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/avatar?token=%s", repo.OwnerName, repo.Name, token), &opts) | ||||||
|  | 	MakeRequest(t, req, http.StatusNoContent) | ||||||
|  |  | ||||||
|  | 	// Test what happens if you don't have a valid Base64 string | ||||||
|  | 	opts = api.UpdateRepoAvatarOption{ | ||||||
|  | 		Image: "Invalid", | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/avatar?token=%s", repo.OwnerName, repo.Name, token), &opts) | ||||||
|  | 	MakeRequest(t, req, http.StatusBadRequest) | ||||||
|  |  | ||||||
|  | 	// Test what happens if you use a file that is not an image | ||||||
|  | 	text, err := os.ReadFile("tests/integration/README.md") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	if err != nil { | ||||||
|  | 		assert.FailNow(t, "Unable to open README.md") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	opts = api.UpdateRepoAvatarOption{ | ||||||
|  | 		Image: base64.StdEncoding.EncodeToString(text), | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/avatar?token=%s", repo.OwnerName, repo.Name, token), &opts) | ||||||
|  | 	MakeRequest(t, req, http.StatusInternalServerError) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestAPIDeleteRepoAvatar(t *testing.T) { | ||||||
|  | 	defer tests.PrepareTestEnv(t)() | ||||||
|  |  | ||||||
|  | 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) | ||||||
|  | 	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) | ||||||
|  | 	token := getUserToken(t, user2.LowerName, auth_model.AccessTokenScopeWriteRepository) | ||||||
|  |  | ||||||
|  | 	req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/repos/%s/%s/avatar?token=%s", repo.OwnerName, repo.Name, token)) | ||||||
|  | 	MakeRequest(t, req, http.StatusNoContent) | ||||||
|  | } | ||||||
							
								
								
									
										72
									
								
								tests/integration/api_user_avatar_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								tests/integration/api_user_avatar_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | |||||||
|  | // Copyright 2023 The Gitea Authors. All rights reserved. | ||||||
|  | // SPDX-License-Identifier: MIT | ||||||
|  |  | ||||||
|  | package integration | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/base64" | ||||||
|  | 	"net/http" | ||||||
|  | 	"os" | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	auth_model "code.gitea.io/gitea/models/auth" | ||||||
|  | 	api "code.gitea.io/gitea/modules/structs" | ||||||
|  | 	"code.gitea.io/gitea/tests" | ||||||
|  |  | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestAPIUpdateUserAvatar(t *testing.T) { | ||||||
|  | 	defer tests.PrepareTestEnv(t)() | ||||||
|  |  | ||||||
|  | 	normalUsername := "user2" | ||||||
|  | 	session := loginUser(t, normalUsername) | ||||||
|  | 	token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser) | ||||||
|  |  | ||||||
|  | 	// Test what happens if you use a valid image | ||||||
|  | 	avatar, err := os.ReadFile("tests/integration/avatar.png") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	if err != nil { | ||||||
|  | 		assert.FailNow(t, "Unable to open avatar.png") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Test what happens if you don't have a valid Base64 string | ||||||
|  | 	opts := api.UpdateUserAvatarOption{ | ||||||
|  | 		Image: base64.StdEncoding.EncodeToString(avatar), | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	req := NewRequestWithJSON(t, "POST", "/api/v1/user/avatar?token="+token, &opts) | ||||||
|  | 	MakeRequest(t, req, http.StatusNoContent) | ||||||
|  |  | ||||||
|  | 	opts = api.UpdateUserAvatarOption{ | ||||||
|  | 		Image: "Invalid", | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	req = NewRequestWithJSON(t, "POST", "/api/v1/user/avatar?token="+token, &opts) | ||||||
|  | 	MakeRequest(t, req, http.StatusBadRequest) | ||||||
|  |  | ||||||
|  | 	// Test what happens if you use a file that is not an image | ||||||
|  | 	text, err := os.ReadFile("tests/integration/README.md") | ||||||
|  | 	assert.NoError(t, err) | ||||||
|  | 	if err != nil { | ||||||
|  | 		assert.FailNow(t, "Unable to open README.md") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	opts = api.UpdateUserAvatarOption{ | ||||||
|  | 		Image: base64.StdEncoding.EncodeToString(text), | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	req = NewRequestWithJSON(t, "POST", "/api/v1/user/avatar?token="+token, &opts) | ||||||
|  | 	MakeRequest(t, req, http.StatusInternalServerError) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestAPIDeleteUserAvatar(t *testing.T) { | ||||||
|  | 	defer tests.PrepareTestEnv(t)() | ||||||
|  |  | ||||||
|  | 	normalUsername := "user2" | ||||||
|  | 	session := loginUser(t, normalUsername) | ||||||
|  | 	token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser) | ||||||
|  |  | ||||||
|  | 	req := NewRequest(t, "DELETE", "/api/v1/user/avatar?token="+token) | ||||||
|  | 	MakeRequest(t, req, http.StatusNoContent) | ||||||
|  | } | ||||||
							
								
								
									
										
											BIN
										
									
								
								tests/integration/avatar.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/integration/avatar.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 7.6 KiB | 
		Reference in New Issue
	
	Block a user