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>tags/v1.21.0-rc0
@@ -380,3 +380,9 @@ type NewIssuePinsAllowed struct { | |||
Issues bool `json:"issues"` | |||
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 | |||
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). | |||
Delete(user.DeleteHook) | |||
}, reqWebhooksEnabled()) | |||
m.Group("/avatar", func() { | |||
m.Post("", bind(api.UpdateUserAvatarOption{}), user.UpdateAvatar) | |||
m.Delete("", user.DeleteAvatar) | |||
}, reqToken()) | |||
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), reqToken()) | |||
// Repositories (requires repo scope, org scope) | |||
@@ -1134,6 +1139,10 @@ func Routes() *web.Route { | |||
m.Get("/languages", reqRepoReader(unit.TypeCode), repo.GetLanguages) | |||
m.Get("/activities/feeds", repo.ListRepoActivityFeeds) | |||
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()) | |||
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository)) | |||
@@ -1314,6 +1323,10 @@ func Routes() *web.Route { | |||
Patch(bind(api.EditHookOption{}), org.EditHook). | |||
Delete(org.DeleteHook) | |||
}, 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) | |||
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), orgAssignment(true)) | |||
m.Group("/teams/{teamid}", func() { |
@@ -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) | |||
} |
@@ -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 | |||
CreatePushMirrorOption api.CreatePushMirrorOption | |||
// in:body | |||
UpdateUserAvatarOptions api.UpdateUserAvatarOption | |||
// in:body | |||
UpdateRepoAvatarOptions api.UpdateRepoAvatarOption | |||
} |
@@ -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) | |||
} |
@@ -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": { | |||
"get": { | |||
"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": { | |||
"get": { | |||
"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": { | |||
"get": { | |||
"produces": [ | |||
@@ -21548,6 +21717,30 @@ | |||
}, | |||
"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": { | |||
"description": "User represents a user", | |||
"type": "object", | |||
@@ -22837,7 +23030,7 @@ | |||
"parameterBodies": { | |||
"description": "parameterBodies", | |||
"schema": { | |||
"$ref": "#/definitions/CreatePushMirrorOption" | |||
"$ref": "#/definitions/UpdateRepoAvatarOption" | |||
} | |||
}, | |||
"redirect": { |
@@ -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) | |||
} |
@@ -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) | |||
} |
@@ -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) | |||
} |