mirror of
https://github.com/usememos/memos.git
synced 2025-01-02 19:23:30 +03:00
chore: remove shortcut related api (#2072)
This commit is contained in:
parent
d1b0b0da10
commit
1ce82ba0d6
@ -30,15 +30,6 @@ const (
|
||||
// ActivityMemoDelete is the type for deleting memos.
|
||||
ActivityMemoDelete ActivityType = "memo.delete"
|
||||
|
||||
// Shortcut related.
|
||||
|
||||
// ActivityShortcutCreate is the type for creating shortcuts.
|
||||
ActivityShortcutCreate ActivityType = "shortcut.create"
|
||||
// ActivityShortcutUpdate is the type for updating shortcuts.
|
||||
ActivityShortcutUpdate ActivityType = "shortcut.update"
|
||||
// ActivityShortcutDelete is the type for deleting shortcuts.
|
||||
ActivityShortcutDelete ActivityType = "shortcut.delete"
|
||||
|
||||
// Resource related.
|
||||
|
||||
// ActivityResourceCreate is the type for creating resources.
|
||||
@ -100,11 +91,6 @@ type ActivityMemoCreatePayload struct {
|
||||
Visibility string `json:"visibility"`
|
||||
}
|
||||
|
||||
type ActivityShortcutCreatePayload struct {
|
||||
Title string `json:"title"`
|
||||
Payload string `json:"payload"`
|
||||
}
|
||||
|
||||
type ActivityResourceCreatePayload struct {
|
||||
Filename string `json:"filename"`
|
||||
Type string `json:"type"`
|
||||
|
@ -1,242 +0,0 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/usememos/memos/api/auth"
|
||||
"github.com/usememos/memos/store"
|
||||
)
|
||||
|
||||
type Shortcut struct {
|
||||
ID int `json:"id"`
|
||||
|
||||
// Standard fields
|
||||
RowStatus RowStatus `json:"rowStatus"`
|
||||
CreatorID int `json:"creatorId"`
|
||||
CreatedTs int64 `json:"createdTs"`
|
||||
UpdatedTs int64 `json:"updatedTs"`
|
||||
|
||||
// Domain specific fields
|
||||
Title string `json:"title"`
|
||||
Payload string `json:"payload"`
|
||||
}
|
||||
|
||||
type CreateShortcutRequest struct {
|
||||
Title string `json:"title"`
|
||||
Payload string `json:"payload"`
|
||||
}
|
||||
|
||||
type UpdateShortcutRequest struct {
|
||||
RowStatus *RowStatus `json:"rowStatus"`
|
||||
Title *string `json:"title"`
|
||||
Payload *string `json:"payload"`
|
||||
}
|
||||
|
||||
type ShortcutFind struct {
|
||||
ID *int
|
||||
|
||||
// Standard fields
|
||||
CreatorID *int
|
||||
|
||||
// Domain specific fields
|
||||
Title *string `json:"title"`
|
||||
}
|
||||
|
||||
type ShortcutDelete struct {
|
||||
ID *int
|
||||
|
||||
// Standard fields
|
||||
CreatorID *int
|
||||
}
|
||||
|
||||
func (s *APIV1Service) registerShortcutRoutes(g *echo.Group) {
|
||||
g.POST("/shortcut", func(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
userID, ok := c.Get(auth.UserIDContextKey).(int)
|
||||
if !ok {
|
||||
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
||||
}
|
||||
shortcutCreate := &CreateShortcutRequest{}
|
||||
if err := json.NewDecoder(c.Request().Body).Decode(shortcutCreate); err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post shortcut request").SetInternal(err)
|
||||
}
|
||||
|
||||
shortcut, err := s.Store.CreateShortcut(ctx, &store.Shortcut{
|
||||
CreatorID: userID,
|
||||
Title: shortcutCreate.Title,
|
||||
Payload: shortcutCreate.Payload,
|
||||
})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create shortcut").SetInternal(err)
|
||||
}
|
||||
|
||||
shortcutMessage := convertShortcutFromStore(shortcut)
|
||||
if err := s.createShortcutCreateActivity(c, shortcutMessage); err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err)
|
||||
}
|
||||
return c.JSON(http.StatusOK, shortcutMessage)
|
||||
})
|
||||
|
||||
g.PATCH("/shortcut/:shortcutId", func(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
userID, ok := c.Get(auth.UserIDContextKey).(int)
|
||||
if !ok {
|
||||
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
||||
}
|
||||
shortcutID, err := strconv.Atoi(c.Param("shortcutId"))
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("shortcutId"))).SetInternal(err)
|
||||
}
|
||||
|
||||
shortcut, err := s.Store.GetShortcut(ctx, &store.FindShortcut{
|
||||
ID: &shortcutID,
|
||||
})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find shortcut").SetInternal(err)
|
||||
}
|
||||
if shortcut == nil {
|
||||
return echo.NewHTTPError(http.StatusNotFound, fmt.Sprintf("Shortcut not found: %d", shortcutID))
|
||||
}
|
||||
if shortcut.CreatorID != userID {
|
||||
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
|
||||
}
|
||||
|
||||
request := &UpdateShortcutRequest{}
|
||||
if err := json.NewDecoder(c.Request().Body).Decode(request); err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted patch shortcut request").SetInternal(err)
|
||||
}
|
||||
|
||||
currentTs := time.Now().Unix()
|
||||
shortcutUpdate := &store.UpdateShortcut{
|
||||
ID: shortcutID,
|
||||
UpdatedTs: ¤tTs,
|
||||
}
|
||||
if request.RowStatus != nil {
|
||||
rowStatus := store.RowStatus(*request.RowStatus)
|
||||
shortcutUpdate.RowStatus = &rowStatus
|
||||
}
|
||||
if request.Title != nil {
|
||||
shortcutUpdate.Title = request.Title
|
||||
}
|
||||
if request.Payload != nil {
|
||||
shortcutUpdate.Payload = request.Payload
|
||||
}
|
||||
|
||||
shortcut, err = s.Store.UpdateShortcut(ctx, shortcutUpdate)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to patch shortcut").SetInternal(err)
|
||||
}
|
||||
return c.JSON(http.StatusOK, convertShortcutFromStore(shortcut))
|
||||
})
|
||||
|
||||
g.GET("/shortcut", func(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
userID, ok := c.Get(auth.UserIDContextKey).(int)
|
||||
if !ok {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Missing user id to find shortcut")
|
||||
}
|
||||
|
||||
list, err := s.Store.ListShortcuts(ctx, &store.FindShortcut{
|
||||
CreatorID: &userID,
|
||||
})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to get shortcut list").SetInternal(err)
|
||||
}
|
||||
shortcutMessageList := make([]*Shortcut, 0, len(list))
|
||||
for _, shortcut := range list {
|
||||
shortcutMessageList = append(shortcutMessageList, convertShortcutFromStore(shortcut))
|
||||
}
|
||||
return c.JSON(http.StatusOK, shortcutMessageList)
|
||||
})
|
||||
|
||||
g.GET("/shortcut/:shortcutId", func(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
shortcutID, err := strconv.Atoi(c.Param("shortcutId"))
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("shortcutId"))).SetInternal(err)
|
||||
}
|
||||
|
||||
shortcut, err := s.Store.GetShortcut(ctx, &store.FindShortcut{
|
||||
ID: &shortcutID,
|
||||
})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Failed to fetch shortcut by ID %d", shortcutID)).SetInternal(err)
|
||||
}
|
||||
if shortcut == nil {
|
||||
return echo.NewHTTPError(http.StatusNotFound, fmt.Sprintf("Shortcut not found: %d", shortcutID))
|
||||
}
|
||||
return c.JSON(http.StatusOK, convertShortcutFromStore(shortcut))
|
||||
})
|
||||
|
||||
g.DELETE("/shortcut/:shortcutId", func(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
userID, ok := c.Get(auth.UserIDContextKey).(int)
|
||||
if !ok {
|
||||
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
||||
}
|
||||
shortcutID, err := strconv.Atoi(c.Param("shortcutId"))
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("shortcutId"))).SetInternal(err)
|
||||
}
|
||||
|
||||
shortcut, err := s.Store.GetShortcut(ctx, &store.FindShortcut{
|
||||
ID: &shortcutID,
|
||||
})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find shortcut").SetInternal(err)
|
||||
}
|
||||
if shortcut == nil {
|
||||
return echo.NewHTTPError(http.StatusNotFound, fmt.Sprintf("Shortcut not found: %d", shortcutID))
|
||||
}
|
||||
if shortcut.CreatorID != userID {
|
||||
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
|
||||
}
|
||||
|
||||
if err := s.Store.DeleteShortcut(ctx, &store.DeleteShortcut{
|
||||
ID: &shortcutID,
|
||||
}); err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to delete shortcut").SetInternal(err)
|
||||
}
|
||||
return c.JSON(http.StatusOK, true)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *APIV1Service) createShortcutCreateActivity(c echo.Context, shortcut *Shortcut) error {
|
||||
ctx := c.Request().Context()
|
||||
payload := ActivityShortcutCreatePayload{
|
||||
Title: shortcut.Title,
|
||||
Payload: shortcut.Payload,
|
||||
}
|
||||
payloadBytes, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to marshal activity payload")
|
||||
}
|
||||
activity, err := s.Store.CreateActivity(ctx, &store.Activity{
|
||||
CreatorID: shortcut.CreatorID,
|
||||
Type: ActivityShortcutCreate.String(),
|
||||
Level: ActivityInfo.String(),
|
||||
Payload: string(payloadBytes),
|
||||
})
|
||||
if err != nil || activity == nil {
|
||||
return errors.Wrap(err, "failed to create activity")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func convertShortcutFromStore(shortcut *store.Shortcut) *Shortcut {
|
||||
return &Shortcut{
|
||||
ID: shortcut.ID,
|
||||
RowStatus: RowStatus(shortcut.RowStatus),
|
||||
CreatorID: shortcut.CreatorID,
|
||||
Title: shortcut.Title,
|
||||
Payload: shortcut.Payload,
|
||||
CreatedTs: shortcut.CreatedTs,
|
||||
UpdatedTs: shortcut.UpdatedTs,
|
||||
}
|
||||
}
|
@ -36,7 +36,6 @@ func (s *APIV1Service) Register(rootGroup *echo.Group) {
|
||||
s.registerUserRoutes(apiV1Group)
|
||||
s.registerUserSettingRoutes(apiV1Group)
|
||||
s.registerTagRoutes(apiV1Group)
|
||||
s.registerShortcutRoutes(apiV1Group)
|
||||
s.registerStorageRoutes(apiV1Group)
|
||||
s.registerResourceRoutes(apiV1Group)
|
||||
s.registerMemoRoutes(apiV1Group)
|
||||
|
@ -1,211 +0,0 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Shortcut struct {
|
||||
ID int
|
||||
|
||||
// Standard fields
|
||||
RowStatus RowStatus
|
||||
CreatorID int
|
||||
CreatedTs int64
|
||||
UpdatedTs int64
|
||||
|
||||
// Domain specific fields
|
||||
Title string
|
||||
Payload string
|
||||
}
|
||||
|
||||
type UpdateShortcut struct {
|
||||
ID int
|
||||
|
||||
UpdatedTs *int64
|
||||
RowStatus *RowStatus
|
||||
Title *string
|
||||
Payload *string
|
||||
}
|
||||
|
||||
type FindShortcut struct {
|
||||
ID *int
|
||||
CreatorID *int
|
||||
Title *string
|
||||
}
|
||||
|
||||
type DeleteShortcut struct {
|
||||
ID *int
|
||||
CreatorID *int
|
||||
}
|
||||
|
||||
func (s *Store) CreateShortcut(ctx context.Context, create *Shortcut) (*Shortcut, error) {
|
||||
stmt := `
|
||||
INSERT INTO shortcut (
|
||||
title,
|
||||
payload,
|
||||
creator_id
|
||||
)
|
||||
VALUES (?, ?, ?)
|
||||
RETURNING id, created_ts, updated_ts, row_status
|
||||
`
|
||||
if err := s.db.QueryRowContext(ctx, stmt, create.Title, create.Payload, create.CreatorID).Scan(
|
||||
&create.ID,
|
||||
&create.CreatedTs,
|
||||
&create.UpdatedTs,
|
||||
&create.RowStatus,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
shortcut := create
|
||||
return shortcut, nil
|
||||
}
|
||||
|
||||
func (s *Store) ListShortcuts(ctx context.Context, find *FindShortcut) ([]*Shortcut, error) {
|
||||
where, args := []string{"1 = 1"}, []any{}
|
||||
|
||||
if v := find.ID; v != nil {
|
||||
where, args = append(where, "id = ?"), append(args, *v)
|
||||
}
|
||||
if v := find.CreatorID; v != nil {
|
||||
where, args = append(where, "creator_id = ?"), append(args, *v)
|
||||
}
|
||||
if v := find.Title; v != nil {
|
||||
where, args = append(where, "title = ?"), append(args, *v)
|
||||
}
|
||||
|
||||
rows, err := s.db.QueryContext(ctx, `
|
||||
SELECT
|
||||
id,
|
||||
title,
|
||||
payload,
|
||||
creator_id,
|
||||
created_ts,
|
||||
updated_ts,
|
||||
row_status
|
||||
FROM shortcut
|
||||
WHERE `+strings.Join(where, " AND ")+`
|
||||
ORDER BY created_ts DESC`,
|
||||
args...,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
list := make([]*Shortcut, 0)
|
||||
for rows.Next() {
|
||||
var shortcut Shortcut
|
||||
if err := rows.Scan(
|
||||
&shortcut.ID,
|
||||
&shortcut.Title,
|
||||
&shortcut.Payload,
|
||||
&shortcut.CreatorID,
|
||||
&shortcut.CreatedTs,
|
||||
&shortcut.UpdatedTs,
|
||||
&shortcut.RowStatus,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list = append(list, &shortcut)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetShortcut(ctx context.Context, find *FindShortcut) (*Shortcut, error) {
|
||||
list, err := s.ListShortcuts(ctx, find)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(list) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
shortcut := list[0]
|
||||
return shortcut, nil
|
||||
}
|
||||
|
||||
func (s *Store) UpdateShortcut(ctx context.Context, update *UpdateShortcut) (*Shortcut, error) {
|
||||
set, args := []string{}, []any{}
|
||||
if v := update.UpdatedTs; v != nil {
|
||||
set, args = append(set, "updated_ts = ?"), append(args, *v)
|
||||
}
|
||||
if v := update.Title; v != nil {
|
||||
set, args = append(set, "title = ?"), append(args, *v)
|
||||
}
|
||||
if v := update.Payload; v != nil {
|
||||
set, args = append(set, "payload = ?"), append(args, *v)
|
||||
}
|
||||
if v := update.RowStatus; v != nil {
|
||||
set, args = append(set, "row_status = ?"), append(args, *v)
|
||||
}
|
||||
args = append(args, update.ID)
|
||||
|
||||
stmt := `
|
||||
UPDATE shortcut
|
||||
SET ` + strings.Join(set, ", ") + `
|
||||
WHERE id = ?
|
||||
RETURNING id, title, payload, creator_id, created_ts, updated_ts, row_status
|
||||
`
|
||||
shortcut := &Shortcut{}
|
||||
if err := s.db.QueryRowContext(ctx, stmt, args...).Scan(
|
||||
&shortcut.ID,
|
||||
&shortcut.Title,
|
||||
&shortcut.Payload,
|
||||
&shortcut.CreatorID,
|
||||
&shortcut.CreatedTs,
|
||||
&shortcut.UpdatedTs,
|
||||
&shortcut.RowStatus,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return shortcut, nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteShortcut(ctx context.Context, delete *DeleteShortcut) error {
|
||||
where, args := []string{}, []any{}
|
||||
if v := delete.ID; v != nil {
|
||||
where, args = append(where, "id = ?"), append(args, *v)
|
||||
}
|
||||
if v := delete.CreatorID; v != nil {
|
||||
where, args = append(where, "creator_id = ?"), append(args, *v)
|
||||
}
|
||||
stmt := `DELETE FROM shortcut WHERE ` + strings.Join(where, " AND ")
|
||||
result, err := s.db.ExecContext(ctx, stmt, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := result.RowsAffected(); err != nil {
|
||||
return err
|
||||
}
|
||||
s.shortcutCache.Delete(*delete.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func vacuumShortcut(ctx context.Context, tx *sql.Tx) error {
|
||||
stmt := `
|
||||
DELETE FROM
|
||||
shortcut
|
||||
WHERE
|
||||
creator_id NOT IN (
|
||||
SELECT
|
||||
id
|
||||
FROM
|
||||
user
|
||||
)`
|
||||
_, err := tx.ExecContext(ctx, stmt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -17,7 +17,6 @@ type Store struct {
|
||||
systemSettingCache sync.Map // map[string]*SystemSetting
|
||||
userCache sync.Map // map[int]*User
|
||||
userSettingCache sync.Map // map[string]*UserSetting
|
||||
shortcutCache sync.Map // map[int]*Shortcut
|
||||
idpCache sync.Map // map[int]*IdentityProvider
|
||||
}
|
||||
|
||||
@ -100,9 +99,6 @@ func (*Store) vacuumImpl(ctx context.Context, tx *sql.Tx) error {
|
||||
if err := vacuumResource(ctx, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := vacuumShortcut(ctx, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := vacuumUserSetting(ctx, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user