From 096a71c58b9ce49b0b88248b0a26e0d9cfba3047 Mon Sep 17 00:00:00 2001 From: boojack Date: Fri, 17 Feb 2023 23:55:56 +0800 Subject: [PATCH] feat: add `avatar_url` field to user table (#1106) refactor: add `avatar_url` field to user table --- api/user.go | 3 + server/auth.go | 22 ++----- server/http_getter.go | 8 +-- server/memo.go | 76 ++++------------------- server/resource.go | 41 +++--------- server/server.go | 4 +- server/shortcut.go | 33 ++-------- server/storage.go | 22 +------ server/system.go | 32 ++-------- server/tag.go | 26 ++------ server/user.go | 46 +++----------- store/db/migration/dev/LATEST__SCHEMA.sql | 3 +- store/user.go | 25 ++++++-- 13 files changed, 79 insertions(+), 262 deletions(-) diff --git a/api/user.go b/api/user.go index 4032eb263..b2390a4f7 100644 --- a/api/user.go +++ b/api/user.go @@ -45,6 +45,7 @@ type User struct { Nickname string `json:"nickname"` PasswordHash string `json:"-"` OpenID string `json:"openId"` + AvatarURL string `json:"avatarUrl"` UserSettingList []*UserSetting `json:"userSettingList"` } @@ -55,6 +56,7 @@ type UserCreate struct { Email string `json:"email"` Nickname string `json:"nickname"` Password string `json:"password"` + AvatarURL string `json:"avatarUrl"` PasswordHash string OpenID string } @@ -94,6 +96,7 @@ type UserPatch struct { Nickname *string `json:"nickname"` Password *string `json:"password"` ResetOpenID *bool `json:"resetOpenId"` + AvatarURL *string `json:"avatarUrl"` PasswordHash *string OpenID *string } diff --git a/server/auth.go b/server/auth.go index 5a881f4a5..80c9fa7ed 100644 --- a/server/auth.go +++ b/server/auth.go @@ -47,12 +47,7 @@ func (s *Server) registerAuthRoutes(g *echo.Group) { if err := s.createUserAuthSignInActivity(c, user); err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(user)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode user response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(user)) }) g.POST("/auth/signup", func(c echo.Context) error { @@ -122,12 +117,7 @@ func (s *Server) registerAuthRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to set signup session").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(user)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode created user response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(user)) }) g.POST("/auth/signout", func(c echo.Context) error { @@ -146,7 +136,7 @@ func (s *Server) createUserAuthSignInActivity(c echo.Context, user *api.User) er UserID: user.ID, IP: echo.ExtractIPFromRealIPHeader()(c.Request()), } - payloadStr, err := json.Marshal(payload) + payloadBytes, err := json.Marshal(payload) if err != nil { return errors.Wrap(err, "failed to marshal activity payload") } @@ -154,7 +144,7 @@ func (s *Server) createUserAuthSignInActivity(c echo.Context, user *api.User) er CreatorID: user.ID, Type: api.ActivityUserAuthSignIn, Level: api.ActivityInfo, - Payload: string(payloadStr), + Payload: string(payloadBytes), }) if err != nil || activity == nil { return errors.Wrap(err, "failed to create activity") @@ -171,7 +161,7 @@ func (s *Server) createUserAuthSignUpActivity(c echo.Context, user *api.User) er Username: user.Username, IP: echo.ExtractIPFromRealIPHeader()(c.Request()), } - payloadStr, err := json.Marshal(payload) + payloadBytes, err := json.Marshal(payload) if err != nil { return errors.Wrap(err, "failed to marshal activity payload") } @@ -179,7 +169,7 @@ func (s *Server) createUserAuthSignUpActivity(c echo.Context, user *api.User) er CreatorID: user.ID, Type: api.ActivityUserAuthSignUp, Level: api.ActivityInfo, - Payload: string(payloadStr), + Payload: string(payloadBytes), }) if err != nil || activity == nil { return errors.Wrap(err, "failed to create activity") diff --git a/server/http_getter.go b/server/http_getter.go index de75566ed..311963f9d 100644 --- a/server/http_getter.go +++ b/server/http_getter.go @@ -1,7 +1,6 @@ package server import ( - "encoding/json" "fmt" "net/http" "net/url" @@ -24,12 +23,7 @@ func registerGetterPublicRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusNotAcceptable, fmt.Sprintf("Failed to get website meta with url: %s", urlStr)).SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(htmlMeta)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode website HTML meta").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(htmlMeta)) }) g.GET("/get/image", func(c echo.Context) error { diff --git a/server/memo.go b/server/memo.go index 4daea4da7..78e7cafdc 100644 --- a/server/memo.go +++ b/server/memo.go @@ -93,12 +93,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose memo").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(memo)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode memo response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(memo)) }) g.PATCH("/memo/:memoId", func(c echo.Context) error { @@ -150,12 +145,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose memo").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(memo)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode memo response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(memo)) }) g.GET("/memo", func(c echo.Context) error { @@ -238,12 +228,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) { if memoFind.Limit != 0 { memoList = memoList[memoFind.Offset:common.Min(len(memoList), memoFind.Offset+memoFind.Limit)] } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(memoList)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode memo list response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(memoList)) }) g.GET("/memo/:memoId", func(c echo.Context) error { @@ -275,12 +260,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) { return echo.NewHTTPError(http.StatusForbidden, "this memo is protected, missing user in session") } } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(memo)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode memo response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(memo)) }) g.POST("/memo/:memoId/organizer", func(c echo.Context) error { @@ -316,12 +296,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) { return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Failed to find memo by ID: %v", memoID)).SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(memo)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode memo response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(memo)) }) g.POST("/memo/:memoId/resource", func(c echo.Context) error { @@ -358,12 +333,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) { if _, err := s.Store.UpsertMemoResource(ctx, memoResourceUpsert); err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upsert memo resource").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(resource)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode resource response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(resource)) }) g.GET("/memo/:memoId/resource", func(c echo.Context) error { @@ -380,12 +350,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch resource list").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(resourceList)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode resource list response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(resourceList)) }) g.GET("/memo/amount", func(c echo.Context) error { @@ -402,12 +367,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find memo list").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(len(memoList))); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode memo amount").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(memoList)) }) g.GET("/memo/stats", func(c echo.Context) error { @@ -443,12 +403,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) { for _, memo := range list { displayTsList = append(displayTsList, memo.DisplayTs) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(displayTsList)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode memo stats response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(displayTsList)) }) g.GET("/memo/all", func(c echo.Context) error { @@ -503,12 +458,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) { if memoFind.Limit != 0 { list = list[memoFind.Offset:common.Min(len(list), memoFind.Offset+memoFind.Limit)] } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(list)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode all memo list response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(list)) }) g.DELETE("/memo/:memoId", func(c echo.Context) error { @@ -541,7 +491,6 @@ func (s *Server) registerMemoRoutes(g *echo.Group) { } return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Failed to delete memo ID: %v", memoID)).SetInternal(err) } - return c.JSON(http.StatusOK, true) }) @@ -577,7 +526,6 @@ func (s *Server) registerMemoRoutes(g *echo.Group) { if err := s.Store.DeleteMemoResource(ctx, memoResourceDelete); err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch resource list").SetInternal(err) } - return c.JSON(http.StatusOK, true) }) } @@ -588,7 +536,7 @@ func (s *Server) createMemoCreateActivity(c echo.Context, memo *api.Memo) error Content: memo.Content, Visibility: memo.Visibility.String(), } - payloadStr, err := json.Marshal(payload) + payloadBytes, err := json.Marshal(payload) if err != nil { return errors.Wrap(err, "failed to marshal activity payload") } @@ -596,7 +544,7 @@ func (s *Server) createMemoCreateActivity(c echo.Context, memo *api.Memo) error CreatorID: memo.CreatorID, Type: api.ActivityMemoCreate, Level: api.ActivityInfo, - Payload: string(payloadStr), + Payload: string(payloadBytes), }) if err != nil || activity == nil { return errors.Wrap(err, "failed to create activity") diff --git a/server/resource.go b/server/resource.go index 063e3dd1d..fe44cb26a 100644 --- a/server/resource.go +++ b/server/resource.go @@ -49,12 +49,7 @@ func (s *Server) registerResourceRoutes(g *echo.Group) { if err := s.createResourceCreateActivity(c, resource); err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(resource)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode resource response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(resource)) }) g.POST("/resource/blob", func(c echo.Context) error { @@ -140,12 +135,7 @@ func (s *Server) registerResourceRoutes(g *echo.Group) { if err := s.createResourceCreateActivity(c, resource); err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(resource)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode resource response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(resource)) }) g.GET("/resource", func(c echo.Context) error { @@ -171,12 +161,7 @@ func (s *Server) registerResourceRoutes(g *echo.Group) { } resource.LinkedMemoAmount = len(memoResourceList) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(list)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode resource list response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(list)) }) g.GET("/resource/:resourceId", func(c echo.Context) error { @@ -199,12 +184,7 @@ func (s *Server) registerResourceRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch resource").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(resource)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode resource response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(resource)) }) g.GET("/resource/:resourceId/blob", func(c echo.Context) error { @@ -227,7 +207,6 @@ func (s *Server) registerResourceRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch resource").SetInternal(err) } - return c.Stream(http.StatusOK, resource.Type, bytes.NewReader(resource.Blob)) }) @@ -267,12 +246,7 @@ func (s *Server) registerResourceRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to patch resource").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(resource)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode resource response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(resource)) }) g.DELETE("/resource/:resourceId", func(c echo.Context) error { @@ -307,7 +281,6 @@ func (s *Server) registerResourceRoutes(g *echo.Group) { } return echo.NewHTTPError(http.StatusInternalServerError, "Failed to delete resource").SetInternal(err) } - return c.JSON(http.StatusOK, true) }) } @@ -353,7 +326,7 @@ func (s *Server) createResourceCreateActivity(c echo.Context, resource *api.Reso Type: resource.Type, Size: resource.Size, } - payloadStr, err := json.Marshal(payload) + payloadBytes, err := json.Marshal(payload) if err != nil { return errors.Wrap(err, "failed to marshal activity payload") } @@ -361,7 +334,7 @@ func (s *Server) createResourceCreateActivity(c echo.Context, resource *api.Reso CreatorID: resource.CreatorID, Type: api.ActivityResourceCreate, Level: api.ActivityInfo, - Payload: string(payloadStr), + Payload: string(payloadBytes), }) if err != nil || activity == nil { return errors.Wrap(err, "failed to create activity") diff --git a/server/server.go b/server/server.go index f43361f9a..86e55c259 100644 --- a/server/server.go +++ b/server/server.go @@ -150,7 +150,7 @@ func (s *Server) createServerStartActivity(ctx context.Context) error { ServerID: s.ID, Profile: s.Profile, } - payloadStr, err := json.Marshal(payload) + payloadBytes, err := json.Marshal(payload) if err != nil { return errors.Wrap(err, "failed to marshal activity payload") } @@ -158,7 +158,7 @@ func (s *Server) createServerStartActivity(ctx context.Context) error { CreatorID: api.UnknownID, Type: api.ActivityServerStart, Level: api.ActivityInfo, - Payload: string(payloadStr), + Payload: string(payloadBytes), }) if err != nil || activity == nil { return errors.Wrap(err, "failed to create activity") diff --git a/server/shortcut.go b/server/shortcut.go index 3d5c585d0..2e50c5015 100644 --- a/server/shortcut.go +++ b/server/shortcut.go @@ -34,12 +34,7 @@ func (s *Server) registerShortcutRoutes(g *echo.Group) { if err := s.createShortcutCreateActivity(c, shortcut); err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(shortcut)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode shortcut response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(shortcut)) }) g.PATCH("/shortcut/:shortcutId", func(c echo.Context) error { @@ -77,12 +72,7 @@ func (s *Server) registerShortcutRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to patch shortcut").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(shortcut)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode shortcut response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(shortcut)) }) g.GET("/shortcut", func(c echo.Context) error { @@ -99,12 +89,7 @@ func (s *Server) registerShortcutRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch shortcut list").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(list)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode shortcut list response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(list)) }) g.GET("/shortcut/:shortcutId", func(c echo.Context) error { @@ -121,12 +106,7 @@ func (s *Server) registerShortcutRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Failed to fetch shortcut by ID %d", *shortcutFind.ID)).SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(shortcut)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode shortcut response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(shortcut)) }) g.DELETE("/shortcut/:shortcutId", func(c echo.Context) error { @@ -160,7 +140,6 @@ func (s *Server) registerShortcutRoutes(g *echo.Group) { } return echo.NewHTTPError(http.StatusInternalServerError, "Failed to delete shortcut").SetInternal(err) } - return c.JSON(http.StatusOK, true) }) } @@ -171,7 +150,7 @@ func (s *Server) createShortcutCreateActivity(c echo.Context, shortcut *api.Shor Title: shortcut.Title, Payload: shortcut.Payload, } - payloadStr, err := json.Marshal(payload) + payloadBytes, err := json.Marshal(payload) if err != nil { return errors.Wrap(err, "failed to marshal activity payload") } @@ -179,7 +158,7 @@ func (s *Server) createShortcutCreateActivity(c echo.Context, shortcut *api.Shor CreatorID: shortcut.CreatorID, Type: api.ActivityShortcutCreate, Level: api.ActivityInfo, - Payload: string(payloadStr), + Payload: string(payloadBytes), }) if err != nil || activity == nil { return errors.Wrap(err, "failed to create activity") diff --git a/server/storage.go b/server/storage.go index 5b2dfd339..e3afedbab 100644 --- a/server/storage.go +++ b/server/storage.go @@ -38,12 +38,7 @@ func (s *Server) registerStorageRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create storage").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(storage)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode storage response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(storage)) }) g.PATCH("/storage/:storageId", func(c echo.Context) error { @@ -79,12 +74,7 @@ func (s *Server) registerStorageRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to patch storage").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(storage)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode memo response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(storage)) }) g.GET("/storage", func(c echo.Context) error { @@ -109,12 +99,7 @@ func (s *Server) registerStorageRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find storage list").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(storageList)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode storage list response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(storageList)) }) g.DELETE("/storage/:storageId", func(c echo.Context) error { @@ -160,7 +145,6 @@ func (s *Server) registerStorageRoutes(g *echo.Group) { } return echo.NewHTTPError(http.StatusInternalServerError, "Failed to delete storage").SetInternal(err) } - return c.JSON(http.StatusOK, true) }) } diff --git a/server/system.go b/server/system.go index 3be8fc03a..71bf6249f 100644 --- a/server/system.go +++ b/server/system.go @@ -15,13 +15,7 @@ import ( func (s *Server) registerSystemRoutes(g *echo.Group) { g.GET("/ping", func(c echo.Context) error { - data := s.Profile - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(data)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose system profile").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(s.Profile)) }) g.GET("/status", func(c echo.Context) error { @@ -126,12 +120,7 @@ func (s *Server) registerSystemRoutes(g *echo.Group) { systemStatus.DBSize = fi.Size() } } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(systemStatus)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode system status response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(systemStatus)) }) g.POST("/system/setting", func(c echo.Context) error { @@ -163,12 +152,7 @@ func (s *Server) registerSystemRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upsert system setting").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(systemSetting)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode system setting response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(systemSetting)) }) g.GET("/system/setting", func(c echo.Context) error { @@ -177,12 +161,7 @@ func (s *Server) registerSystemRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find system setting list").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(systemSettingList)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode system setting list response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(systemSettingList)) }) g.POST("/system/vacuum", func(c echo.Context) error { @@ -203,8 +182,7 @@ func (s *Server) registerSystemRoutes(g *echo.Group) { if err := s.Store.Vacuum(ctx); err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to vacuum database").SetInternal(err) } - c.Response().WriteHeader(http.StatusOK) - return nil + return c.JSON(http.StatusOK, true) }) } diff --git a/server/tag.go b/server/tag.go index d63f6ecd8..1e40ff53f 100644 --- a/server/tag.go +++ b/server/tag.go @@ -39,12 +39,7 @@ func (s *Server) registerTagRoutes(g *echo.Group) { if err := s.createTagCreateActivity(c, tag); err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(tag.Name)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode tag response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(tag.Name)) }) g.GET("/tag", func(c echo.Context) error { @@ -66,12 +61,7 @@ func (s *Server) registerTagRoutes(g *echo.Group) { for _, tag := range tagList { tagNameList = append(tagNameList, tag.Name) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(tagNameList)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode tags response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(tagNameList)) }) g.GET("/tag/suggestion", func(c echo.Context) error { @@ -118,12 +108,7 @@ func (s *Server) registerTagRoutes(g *echo.Group) { tagList = append(tagList, tag) } sort.Strings(tagList) - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(tagList)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode tags response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(tagList)) }) g.POST("/tag/delete", func(c echo.Context) error { @@ -148,7 +133,6 @@ func (s *Server) registerTagRoutes(g *echo.Group) { } return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Failed to delete tag name: %v", tagDelete.Name)).SetInternal(err) } - return c.JSON(http.StatusOK, true) }) } @@ -176,7 +160,7 @@ func (s *Server) createTagCreateActivity(c echo.Context, tag *api.Tag) error { payload := api.ActivityTagCreatePayload{ TagName: tag.Name, } - payloadStr, err := json.Marshal(payload) + payloadBytes, err := json.Marshal(payload) if err != nil { return errors.Wrap(err, "failed to marshal activity payload") } @@ -184,7 +168,7 @@ func (s *Server) createTagCreateActivity(c echo.Context, tag *api.Tag) error { CreatorID: tag.CreatorID, Type: api.ActivityTagCreate, Level: api.ActivityInfo, - Payload: string(payloadStr), + Payload: string(payloadBytes), }) if err != nil || activity == nil { return errors.Wrap(err, "failed to create activity") diff --git a/server/user.go b/server/user.go index 410ff7364..dc806987d 100644 --- a/server/user.go +++ b/server/user.go @@ -59,12 +59,7 @@ func (s *Server) registerUserRoutes(g *echo.Group) { if err := s.createUserCreateActivity(c, user); err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(user)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode user response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(user)) }) g.GET("/user", func(c echo.Context) error { @@ -79,12 +74,7 @@ func (s *Server) registerUserRoutes(g *echo.Group) { user.OpenID = "" user.Email = "" } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(userList)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode user list response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(userList)) }) g.POST("/user/setting", func(c echo.Context) error { @@ -107,12 +97,7 @@ func (s *Server) registerUserRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upsert user setting").SetInternal(err) } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(userSetting)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode user setting response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(userSetting)) }) // GET /api/user/me is used to check if the user is logged in. @@ -138,12 +123,7 @@ func (s *Server) registerUserRoutes(g *echo.Group) { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find userSettingList").SetInternal(err) } user.UserSettingList = userSettingList - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(user)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode user response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(user)) }) g.GET("/user/:id", func(c echo.Context) error { @@ -165,12 +145,7 @@ func (s *Server) registerUserRoutes(g *echo.Group) { user.OpenID = "" user.Email = "" } - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(user)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode user response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(user)) }) g.PATCH("/user/:id", func(c echo.Context) error { @@ -234,12 +209,7 @@ func (s *Server) registerUserRoutes(g *echo.Group) { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find userSettingList").SetInternal(err) } user.UserSettingList = userSettingList - - c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8) - if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(user)); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode user response").SetInternal(err) - } - return nil + return c.JSON(http.StatusOK, composeResponse(user)) }) g.DELETE("/user/:id", func(c echo.Context) error { @@ -286,7 +256,7 @@ func (s *Server) createUserCreateActivity(c echo.Context, user *api.User) error Username: user.Username, Role: user.Role, } - payloadStr, err := json.Marshal(payload) + payloadBytes, err := json.Marshal(payload) if err != nil { return errors.Wrap(err, "failed to marshal activity payload") } @@ -294,7 +264,7 @@ func (s *Server) createUserCreateActivity(c echo.Context, user *api.User) error CreatorID: user.ID, Type: api.ActivityUserCreate, Level: api.ActivityInfo, - Payload: string(payloadStr), + Payload: string(payloadBytes), }) if err != nil || activity == nil { return errors.Wrap(err, "failed to create activity") diff --git a/store/db/migration/dev/LATEST__SCHEMA.sql b/store/db/migration/dev/LATEST__SCHEMA.sql index 268018d74..d3dd87171 100644 --- a/store/db/migration/dev/LATEST__SCHEMA.sql +++ b/store/db/migration/dev/LATEST__SCHEMA.sql @@ -23,7 +23,8 @@ CREATE TABLE user ( email TEXT NOT NULL DEFAULT '', nickname TEXT NOT NULL DEFAULT '', password_hash TEXT NOT NULL, - open_id TEXT NOT NULL UNIQUE + open_id TEXT NOT NULL UNIQUE, + avatar_url TEXT NOT NULL DEFAULT '' ); -- user_setting diff --git a/store/user.go b/store/user.go index bee8a0c05..903782954 100644 --- a/store/user.go +++ b/store/user.go @@ -27,6 +27,7 @@ type userRaw struct { Nickname string PasswordHash string OpenID string + AvatarURL string } func (raw *userRaw) toUser() *api.User { @@ -43,6 +44,7 @@ func (raw *userRaw) toUser() *api.User { Nickname: raw.Nickname, PasswordHash: raw.PasswordHash, OpenID: raw.OpenID, + AvatarURL: raw.AvatarURL, } } @@ -180,10 +182,11 @@ func createUser(ctx context.Context, tx *sql.Tx, create *api.UserCreate) (*userR email, nickname, password_hash, - open_id + open_id, + avatar_url ) - VALUES (?, ?, ?, ?, ?, ?) - RETURNING id, username, role, email, nickname, password_hash, open_id, created_ts, updated_ts, row_status + VALUES (?, ?, ?, ?, ?, ?, ?) + RETURNING id, username, role, email, nickname, password_hash, open_id, avatar_url, created_ts, updated_ts, row_status ` var userRaw userRaw if err := tx.QueryRowContext(ctx, query, @@ -193,6 +196,7 @@ func createUser(ctx context.Context, tx *sql.Tx, create *api.UserCreate) (*userR create.Nickname, create.PasswordHash, create.OpenID, + create.AvatarURL, ).Scan( &userRaw.ID, &userRaw.Username, @@ -201,6 +205,7 @@ func createUser(ctx context.Context, tx *sql.Tx, create *api.UserCreate) (*userR &userRaw.Nickname, &userRaw.PasswordHash, &userRaw.OpenID, + &userRaw.AvatarURL, &userRaw.CreatedTs, &userRaw.UpdatedTs, &userRaw.RowStatus, @@ -229,6 +234,9 @@ func patchUser(ctx context.Context, tx *sql.Tx, patch *api.UserPatch) (*userRaw, if v := patch.Nickname; v != nil { set, args = append(set, "nickname = ?"), append(args, *v) } + if v := patch.AvatarURL; v != nil { + set, args = append(set, "avatar_url = ?"), append(args, *v) + } if v := patch.PasswordHash; v != nil { set, args = append(set, "password_hash = ?"), append(args, *v) } @@ -242,7 +250,7 @@ func patchUser(ctx context.Context, tx *sql.Tx, patch *api.UserPatch) (*userRaw, UPDATE user SET ` + strings.Join(set, ", ") + ` WHERE id = ? - RETURNING id, username, role, email, nickname, password_hash, open_id, created_ts, updated_ts, row_status + RETURNING id, username, role, email, nickname, password_hash, open_id, avatar_url, created_ts, updated_ts, row_status ` var userRaw userRaw if err := tx.QueryRowContext(ctx, query, args...).Scan( @@ -253,6 +261,7 @@ func patchUser(ctx context.Context, tx *sql.Tx, patch *api.UserPatch) (*userRaw, &userRaw.Nickname, &userRaw.PasswordHash, &userRaw.OpenID, + &userRaw.AvatarURL, &userRaw.CreatedTs, &userRaw.UpdatedTs, &userRaw.RowStatus, @@ -294,6 +303,7 @@ func findUserList(ctx context.Context, tx *sql.Tx, find *api.UserFind) ([]*userR nickname, password_hash, open_id, + avatar_url, created_ts, updated_ts, row_status @@ -318,13 +328,13 @@ func findUserList(ctx context.Context, tx *sql.Tx, find *api.UserFind) ([]*userR &userRaw.Nickname, &userRaw.PasswordHash, &userRaw.OpenID, + &userRaw.AvatarURL, &userRaw.CreatedTs, &userRaw.UpdatedTs, &userRaw.RowStatus, ); err != nil { return nil, FormatError(err) } - userRawList = append(userRawList, &userRaw) } @@ -343,7 +353,10 @@ func deleteUser(ctx context.Context, tx *sql.Tx, delete *api.UserDelete) error { return FormatError(err) } - rows, _ := result.RowsAffected() + rows, err := result.RowsAffected() + if err != nil { + return err + } if rows == 0 { return &common.Error{Code: common.NotFound, Err: fmt.Errorf("user not found")} }