aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--modules/structs/repo.go6
-rw-r--r--modules/structs/user.go6
-rw-r--r--routers/api/v1/api.go13
-rw-r--r--routers/api/v1/org/avatar.go74
-rw-r--r--routers/api/v1/repo/avatar.go84
-rw-r--r--routers/api/v1/swagger/options.go6
-rw-r--r--routers/api/v1/user/avatar.go63
-rw-r--r--templates/swagger/v1_json.tmpl195
-rw-r--r--tests/integration/api_org_avatar_test.go72
-rw-r--r--tests/integration/api_repo_avatar_test.go76
-rw-r--r--tests/integration/api_user_avatar_test.go72
-rw-r--r--tests/integration/avatar.pngbin0 -> 7787 bytes
12 files changed, 666 insertions, 1 deletions
diff --git a/modules/structs/repo.go b/modules/structs/repo.go
index 3b43f74c79..94992de72e 100644
--- a/modules/structs/repo.go
+++ b/modules/structs/repo.go
@@ -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"`
+}
diff --git a/modules/structs/user.go b/modules/structs/user.go
index f68b92ac06..0df67894b0 100644
--- a/modules/structs/user.go
+++ b/modules/structs/user.go
@@ -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"`
+}
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 8b7f55976b..0e28bde683 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -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() {
diff --git a/routers/api/v1/org/avatar.go b/routers/api/v1/org/avatar.go
new file mode 100644
index 0000000000..b3cb0b81a6
--- /dev/null
+++ b/routers/api/v1/org/avatar.go
@@ -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)
+}
diff --git a/routers/api/v1/repo/avatar.go b/routers/api/v1/repo/avatar.go
new file mode 100644
index 0000000000..48bd143d0c
--- /dev/null
+++ b/routers/api/v1/repo/avatar.go
@@ -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)
+}
diff --git a/routers/api/v1/swagger/options.go b/routers/api/v1/swagger/options.go
index 353d32e214..073d9a19f7 100644
--- a/routers/api/v1/swagger/options.go
+++ b/routers/api/v1/swagger/options.go
@@ -181,4 +181,10 @@ type swaggerParameterBodies struct {
// in:body
CreatePushMirrorOption api.CreatePushMirrorOption
+
+ // in:body
+ UpdateUserAvatarOptions api.UpdateUserAvatarOption
+
+ // in:body
+ UpdateRepoAvatarOptions api.UpdateRepoAvatarOption
}
diff --git a/routers/api/v1/user/avatar.go b/routers/api/v1/user/avatar.go
new file mode 100644
index 0000000000..84fa129b13
--- /dev/null
+++ b/routers/api/v1/user/avatar.go
@@ -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)
+}
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index 11abeac77c..f98dc12d95 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -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": {
diff --git a/tests/integration/api_org_avatar_test.go b/tests/integration/api_org_avatar_test.go
new file mode 100644
index 0000000000..e0a4150e9f
--- /dev/null
+++ b/tests/integration/api_org_avatar_test.go
@@ -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)
+}
diff --git a/tests/integration/api_repo_avatar_test.go b/tests/integration/api_repo_avatar_test.go
new file mode 100644
index 0000000000..58a4fc536c
--- /dev/null
+++ b/tests/integration/api_repo_avatar_test.go
@@ -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)
+}
diff --git a/tests/integration/api_user_avatar_test.go b/tests/integration/api_user_avatar_test.go
new file mode 100644
index 0000000000..807c119e2c
--- /dev/null
+++ b/tests/integration/api_user_avatar_test.go
@@ -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)
+}
diff --git a/tests/integration/avatar.png b/tests/integration/avatar.png
new file mode 100644
index 0000000000..dfd2125edc
--- /dev/null
+++ b/tests/integration/avatar.png
Binary files differ