From afa55c2112ade0acb0b12e843b61e6c0220acc64 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Thu, 1 Feb 2024 00:14:25 +0800 Subject: [PATCH] :sparkles: Avatar --- .gitignore | 3 +- pkg/models/accounts.go | 8 +++ pkg/server/avatar_api.go | 35 ++++++++++ pkg/server/startup.go | 3 + pkg/view/src/pages/personalise.tsx | 100 ++++++++++++++++++++--------- settings.toml | 2 + 6 files changed, 121 insertions(+), 30 deletions(-) create mode 100644 pkg/server/avatar_api.go diff --git a/.gitignore b/.gitignore index 3e22129..9e23ac2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -/dist \ No newline at end of file +/dist +/uploads \ No newline at end of file diff --git a/pkg/models/accounts.go b/pkg/models/accounts.go index 5fe7071..0645b54 100644 --- a/pkg/models/accounts.go +++ b/pkg/models/accounts.go @@ -2,6 +2,8 @@ package models import ( "github.com/samber/lo" + "github.com/spf13/viper" + "path/filepath" "time" "gorm.io/datatypes" @@ -19,6 +21,7 @@ type Account struct { Name string `json:"name" gorm:"uniqueIndex"` Nick string `json:"nick"` + Avatar string `json:"avatar"` State AccountState `json:"state"` Profile AccountProfile `json:"profile"` Sessions []AuthSession `json:"sessions"` @@ -39,6 +42,11 @@ func (v Account) GetPrimaryEmail() AccountContact { return val } +func (v Account) GetAvatarPath() string { + basepath := viper.GetString("content") + return filepath.Join(basepath, v.Avatar) +} + type AccountContactType = int8 const ( diff --git a/pkg/server/avatar_api.go b/pkg/server/avatar_api.go new file mode 100644 index 0000000..41b8bbe --- /dev/null +++ b/pkg/server/avatar_api.go @@ -0,0 +1,35 @@ +package server + +import ( + "code.smartsheep.studio/hydrogen/passport/pkg/database" + "code.smartsheep.studio/hydrogen/passport/pkg/models" + "github.com/gofiber/fiber/v2" + "github.com/google/uuid" + "github.com/spf13/viper" + "path/filepath" +) + +func getAvatar(c *fiber.Ctx) error { + id := c.Params("avatarId") + basepath := viper.GetString("content") + + return c.SendFile(filepath.Join(basepath, id)) +} + +func setAvatar(c *fiber.Ctx) error { + user := c.Locals("principal").(models.Account) + file, err := c.FormFile("avatar") + if err != nil { + return err + } + + user.Avatar = uuid.NewString() + + if err := c.SaveFile(file, user.GetAvatarPath()); err != nil { + return err + } else { + database.C.Save(&user) + } + + return c.SendStatus(fiber.StatusOK) +} diff --git a/pkg/server/startup.go b/pkg/server/startup.go index 93479f4..233cfe7 100644 --- a/pkg/server/startup.go +++ b/pkg/server/startup.go @@ -57,6 +57,9 @@ func NewServer() { api := A.Group("/api").Name("API") { + api.Get("/avatar/:avatarId", getAvatar) + api.Put("/avatar", auth, setAvatar) + api.Get("/users/me", auth, getUserinfo) api.Put("/users/me", auth, editUserinfo) api.Get("/users/me/events", auth, getEvents) diff --git a/pkg/view/src/pages/personalise.tsx b/pkg/view/src/pages/personalise.tsx index 00d9485..0cd32ec 100644 --- a/pkg/view/src/pages/personalise.tsx +++ b/pkg/view/src/pages/personalise.tsx @@ -8,7 +8,7 @@ export default function PersonalPage() { const [success, setSuccess] = createSignal(null); const [loading, setLoading] = createSignal(false); - async function update(evt: SubmitEvent) { + async function updateBasis(evt: SubmitEvent) { evt.preventDefault(); const data = Object.fromEntries(new FormData(evt.target as HTMLFormElement)); @@ -33,6 +33,27 @@ export default function PersonalPage() { setLoading(false); } + async function updateAvatar(evt: SubmitEvent) { + evt.preventDefault(); + + setLoading(true); + const data = new FormData(evt.target as HTMLFormElement); + const res = await fetch("/api/avatar", { + method: "PUT", + headers: { "Authorization": `Bearer ${getAtk()}` }, + body: data + }); + if (res.status !== 200) { + setSuccess(null); + setError(await res.text()); + } else { + await readProfiles(); + setSuccess("Your avatar has been update."); + setError(null); + } + setLoading(false); + } + return (
@@ -40,36 +61,34 @@ export default function PersonalPage() {

Joined at {new Date(userinfo?.meta?.created_at).toLocaleString()}

-
-
+
+ + + - -
- -
-
+ + + +
- -
- -
-
+
-
+
+
+
+
+ +
+
+ + +