From 4c465bef2d5f6d674ebe4c6038138e93d060f575 Mon Sep 17 00:00:00 2001 From: steven Date: Fri, 30 Sep 2022 22:58:59 +0800 Subject: [PATCH] feat: add memo resource apis --- api/resource.go | 1 + server/memo.go | 77 +++++++++++++++++++++++++++++++++++++++++++++++ store/memo.go | 2 +- store/resource.go | 3 ++ 4 files changed, 82 insertions(+), 1 deletion(-) diff --git a/api/resource.go b/api/resource.go index 203fb027..f232aa77 100644 --- a/api/resource.go +++ b/api/resource.go @@ -34,6 +34,7 @@ type ResourceFind struct { // Domain specific fields Filename *string `json:"filename"` + MemoID *int } type ResourceDelete struct { diff --git a/server/memo.go b/server/memo.go index 8f7f13de..51a6b97f 100644 --- a/server/memo.go +++ b/server/memo.go @@ -6,6 +6,7 @@ import ( "net/http" "strconv" "strings" + "time" "github.com/usememos/memos/api" "github.com/usememos/memos/common" @@ -294,6 +295,82 @@ func (s *Server) registerMemoRoutes(g *echo.Group) { return nil }) + g.POST("/memo/:memoId/resource", func(c echo.Context) error { + ctx := c.Request().Context() + memoID, err := strconv.Atoi(c.Param("memoId")) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("memoId"))).SetInternal(err) + } + + currentTs := time.Now().Unix() + + memoResourceUpsert := &api.MemoResourceUpsert{ + MemoID: memoID, + UpdatedTs: ¤tTs, + } + if err := json.NewDecoder(c.Request().Body).Decode(memoResourceUpsert); err != nil { + return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post memo resource request").SetInternal(err) + } + + resourceFind := &api.ResourceFind{ + ID: &memoResourceUpsert.ResourceID, + } + resource, err := s.Store.FindResource(ctx, resourceFind) + 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 + }) + + g.GET("/memo/:memoId/resource", func(c echo.Context) error { + ctx := c.Request().Context() + memoID, err := strconv.Atoi(c.Param("memoId")) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("memoId"))).SetInternal(err) + } + + resourceFind := &api.ResourceFind{ + MemoID: &memoID, + } + resourceList, err := s.Store.FindResourceList(ctx, resourceFind) + 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 + }) + + g.DELETE("/memo/:memoId/resource/:resourceId", func(c echo.Context) error { + ctx := c.Request().Context() + memoID, err := strconv.Atoi(c.Param("memoId")) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Memo ID is not a number: %s", c.Param("memoId"))).SetInternal(err) + } + resourceID, err := strconv.Atoi(c.Param("resourceId")) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Resource ID is not a number: %s", c.Param("resourceId"))).SetInternal(err) + } + + memoResourceDelete := &api.MemoResourceDelete{ + MemoID: memoID, + ResourceID: &resourceID, + } + 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) + }) + g.DELETE("/memo/:memoId", func(c echo.Context) error { ctx := c.Request().Context() userID, ok := c.Get(getUserIDContextKey()).(int) diff --git a/store/memo.go b/store/memo.go index 17668113..248a14c8 100644 --- a/store/memo.go +++ b/store/memo.go @@ -286,7 +286,7 @@ func findMemoRawList(ctx context.Context, tx *sql.Tx, find *api.MemoFind) ([]*me where, args = append(where, "row_status = ?"), append(args, *v) } if v := find.Pinned; v != nil { - where = append(where, "id in (SELECT memo_id FROM memo_organizer WHERE pinned = 1 AND user_id = memo.creator_id )") + where = append(where, "id in (SELECT memo_id FROM memo_organizer WHERE pinned = 1 AND user_id = memo.creator_id)") } if v := find.ContentSearch; v != nil { where, args = append(where, "content LIKE ?"), append(args, "%"+*v+"%") diff --git a/store/resource.go b/store/resource.go index 3ea5db3a..e10e2a83 100644 --- a/store/resource.go +++ b/store/resource.go @@ -192,6 +192,9 @@ func findResourceList(ctx context.Context, tx *sql.Tx, find *api.ResourceFind) ( if v := find.Filename; v != nil { where, args = append(where, "filename = ?"), append(args, *v) } + if v := find.MemoID; v != nil { + where, args = append(where, "id in (SELECT resource_id FROM memo_resource WHERE memo_id = ?)"), append(args, *v) + } query := ` SELECT