From 7e391bd53d9d0a593d81e7c717ae95ec38e57309 Mon Sep 17 00:00:00 2001 From: boojack Date: Sat, 8 Jul 2023 11:29:50 +0800 Subject: [PATCH] chore: remove resource public id (#1912) * chore: remove resource public id * chore: update --- api/v1/auth.go | 2 +- {server => api/v1}/auth/auth.go | 0 api/v1/jwt.go | 2 +- api/v1/resource.go | 46 ++++++------------- api/v1/rss.go | 2 +- server/telegram.go | 2 - store/db/migration/dev/LATEST__SCHEMA.sql | 4 +- .../prod/0.14/00_drop_resource_public_id.sql | 25 ++++++++++ store/db/migration/prod/LATEST__SCHEMA.sql | 4 +- store/resource.go | 26 ++--------- test/store/resource_test.go | 1 - web/src/components/LearnMore.tsx | 26 +++++++++++ web/src/components/ResourceItemDropdown.tsx | 21 --------- .../components/UpdateLocalStorageDialog.tsx | 8 ++-- web/src/pages/ResourcesDashboard.tsx | 2 +- web/src/types/modules/resource.d.ts | 2 - web/src/utils/resource.ts | 2 +- 17 files changed, 82 insertions(+), 93 deletions(-) rename {server => api/v1}/auth/auth.go (100%) create mode 100644 store/db/migration/prod/0.14/00_drop_resource_public_id.sql create mode 100644 web/src/components/LearnMore.tsx diff --git a/api/v1/auth.go b/api/v1/auth.go index 58e64fcc4..62828eb33 100644 --- a/api/v1/auth.go +++ b/api/v1/auth.go @@ -8,10 +8,10 @@ import ( "github.com/labstack/echo/v4" "github.com/pkg/errors" + "github.com/usememos/memos/api/v1/auth" "github.com/usememos/memos/common/util" "github.com/usememos/memos/plugin/idp" "github.com/usememos/memos/plugin/idp/oauth2" - "github.com/usememos/memos/server/auth" "github.com/usememos/memos/store" "golang.org/x/crypto/bcrypt" ) diff --git a/server/auth/auth.go b/api/v1/auth/auth.go similarity index 100% rename from server/auth/auth.go rename to api/v1/auth/auth.go diff --git a/api/v1/jwt.go b/api/v1/jwt.go index f8dd38799..a3e7e4d6a 100644 --- a/api/v1/jwt.go +++ b/api/v1/jwt.go @@ -10,8 +10,8 @@ import ( "github.com/golang-jwt/jwt/v4" "github.com/labstack/echo/v4" "github.com/pkg/errors" + "github.com/usememos/memos/api/v1/auth" "github.com/usememos/memos/common/util" - "github.com/usememos/memos/server/auth" "github.com/usememos/memos/store" ) diff --git a/api/v1/resource.go b/api/v1/resource.go index 05853d195..d9109d982 100644 --- a/api/v1/resource.go +++ b/api/v1/resource.go @@ -43,7 +43,6 @@ type Resource struct { ExternalLink string `json:"externalLink"` Type string `json:"type"` Size int64 `json:"size"` - PublicID string `json:"publicId"` // Related fields LinkedMemoAmount int `json:"linkedMemoAmount"` @@ -54,7 +53,6 @@ type CreateResourceRequest struct { InternalPath string `json:"internalPath"` ExternalLink string `json:"externalLink"` Type string `json:"type"` - PublicID string `json:"publicId"` DownloadToLocal bool `json:"downloadToLocal"` } @@ -62,12 +60,10 @@ type FindResourceRequest struct { ID *int `json:"id"` CreatorID *int `json:"creatorId"` Filename *string `json:"filename"` - PublicID *string `json:"publicId"` } type UpdateResourceRequest struct { - Filename *string `json:"filename"` - ResetPublicID *bool `json:"resetPublicId"` + Filename *string `json:"filename"` } const ( @@ -101,7 +97,6 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) { Filename: request.Filename, ExternalLink: request.ExternalLink, Type: request.Type, - PublicID: util.GenUUID(), } if request.ExternalLink != "" { // Only allow those external links scheme with http/https @@ -195,7 +190,6 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) { } defer sourceFile.Close() - create := &store.Resource{} systemSettingStorageServiceID, err := s.Store.GetSystemSetting(ctx, &store.FindSystemSetting{Name: SystemSettingStorageServiceIDName.String()}) if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find storage").SetInternal(err) @@ -208,7 +202,7 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) { } } - publicID := util.GenUUID() + var create *store.Resource if storageServiceID == DatabaseStorage { fileBytes, err := io.ReadAll(sourceFile) if err != nil { @@ -229,7 +223,7 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find local storage path setting").SetInternal(err) } - localStoragePath := "assets/{publicid}" + localStoragePath := "assets/{filename}" if systemSettingLocalStoragePath != nil && systemSettingLocalStoragePath.Value != "" { err = json.Unmarshal([]byte(systemSettingLocalStoragePath.Value), &localStoragePath) if err != nil { @@ -237,10 +231,10 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) { } } filePath := filepath.FromSlash(localStoragePath) - if !strings.Contains(filePath, "{publicid}") { - filePath = filepath.Join(filePath, "{publicid}") + if !strings.Contains(filePath, "{filename}") { + filePath = filepath.Join(filePath, "{filename}") } - filePath = filepath.Join(s.Profile.Data, replacePathTemplate(filePath, file.Filename, publicID+filepath.Ext(file.Filename))) + filePath = filepath.Join(s.Profile.Data, replacePathTemplate(filePath, file.Filename)) dir := filepath.Dir(filePath) if err = os.MkdirAll(dir, os.ModePerm); err != nil { @@ -292,10 +286,10 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) { } filePath := s3Config.Path - if !strings.Contains(filePath, "{publicid}") { - filePath = path.Join(filePath, "{publicid}") + if !strings.Contains(filePath, "{filename}") { + filePath = path.Join(filePath, "{filename}") } - filePath = replacePathTemplate(filePath, file.Filename, publicID+filepath.Ext(file.Filename)) + filePath = replacePathTemplate(filePath, file.Filename) _, filename := filepath.Split(filePath) link, err := s3Client.UploadFile(ctx, filePath, filetype, sourceFile) if err != nil { @@ -313,7 +307,6 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) { } } - create.PublicID = publicID resource, err := s.Store.CreateResource(ctx, create) if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create resource").SetInternal(err) @@ -389,10 +382,6 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) { if request.Filename != nil && *request.Filename != "" { update.Filename = request.Filename } - if request.ResetPublicID != nil && *request.ResetPublicID { - publicID := util.GenUUID() - update.PublicID = &publicID - } resource, err = s.Store.UpdateResource(ctx, update) if err != nil { @@ -431,7 +420,7 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) { } ext := filepath.Ext(resource.Filename) - thumbnailPath := path.Join(s.Profile.Data, thumbnailImagePath, fmt.Sprintf("%d-%s%s", resource.ID, resource.PublicID, ext)) + thumbnailPath := path.Join(s.Profile.Data, thumbnailImagePath, fmt.Sprintf("%d%s", resource.ID, ext)) if err := os.Remove(thumbnailPath); err != nil { log.Warn(fmt.Sprintf("failed to delete local thumbnail with path %s", thumbnailPath), zap.Error(err)) } @@ -496,7 +485,7 @@ func (s *APIV1Service) registerResourcePublicRoutes(g *echo.Group) { if c.QueryParam("thumbnail") == "1" && util.HasPrefixes(resource.Type, "image/png", "image/jpeg") { ext := filepath.Ext(resource.Filename) - thumbnailPath := path.Join(s.Profile.Data, thumbnailImagePath, fmt.Sprintf("%d-%s%s", resource.ID, resource.PublicID, ext)) + thumbnailPath := path.Join(s.Profile.Data, thumbnailImagePath, fmt.Sprintf("%d%s", resource.ID, ext)) thumbnailBlob, err := getOrGenerateThumbnailImage(blob, thumbnailPath) if err != nil { log.Warn(fmt.Sprintf("failed to get or generate local thumbnail with path %s", thumbnailPath), zap.Error(err)) @@ -516,8 +505,8 @@ func (s *APIV1Service) registerResourcePublicRoutes(g *echo.Group) { } return c.Stream(http.StatusOK, resourceType, bytes.NewReader(blob)) } + g.GET("/r/:resourceId", f) - g.GET("/r/:resourceId/", f) g.GET("/r/:resourceId/*", f) } @@ -543,12 +532,10 @@ func (s *APIV1Service) createResourceCreateActivity(ctx context.Context, resourc return err } -func replacePathTemplate(path, filename, publicID string) string { +func replacePathTemplate(path, filename string) string { t := time.Now() path = fileKeyPattern.ReplaceAllStringFunc(path, func(s string) string { switch s { - case "{publicid}": - return publicID case "{filename}": return filename case "{timestamp}": @@ -624,7 +611,7 @@ func checkResourceVisibility(ctx context.Context, s *store.Store, resourceID int return store.Private, err } - // If resource is belongs to no memo, it'll always PRIVATE + // If resource is belongs to no memo, it'll always PRIVATE. if len(memoResources) == 0 { return store.Private, nil } @@ -640,7 +627,7 @@ func checkResourceVisibility(ctx context.Context, s *store.Store, resourceID int var isProtected bool for _, visibility := range visibilityList { - // If any memo is PUBLIC, resource do + // If any memo is PUBLIC, resource should be PUBLIC too. if visibility == store.Public { return store.Public, nil } @@ -650,12 +637,10 @@ func checkResourceVisibility(ctx context.Context, s *store.Store, resourceID int } } - // If no memo is PUBLIC, but any memo is PROTECTED, resource do if isProtected { return store.Protected, nil } - // If all memo is PRIVATE, the resource do return store.Private, nil } @@ -671,7 +656,6 @@ func convertResourceFromStore(resource *store.Resource) *Resource { ExternalLink: resource.ExternalLink, Type: resource.Type, Size: resource.Size, - PublicID: resource.PublicID, LinkedMemoAmount: resource.LinkedMemoAmount, } } diff --git a/api/v1/rss.go b/api/v1/rss.go index 2f9b4fa76..7d130cf24 100644 --- a/api/v1/rss.go +++ b/api/v1/rss.go @@ -114,7 +114,7 @@ func (s *APIV1Service) generateRSSFromMemoList(ctx context.Context, memoList []* if resource.ExternalLink != "" { enclosure.Url = resource.ExternalLink } else { - enclosure.Url = baseURL + "/o/r/" + strconv.Itoa(resource.ID) + "/" + resource.PublicID + "/" + resource.Filename + enclosure.Url = baseURL + "/o/r/" + strconv.Itoa(resource.ID) } enclosure.Length = strconv.Itoa(int(resource.Size)) enclosure.Type = resource.Type diff --git a/server/telegram.go b/server/telegram.go index a93ad32bd..181c4de4a 100644 --- a/server/telegram.go +++ b/server/telegram.go @@ -9,7 +9,6 @@ import ( "github.com/pkg/errors" apiv1 "github.com/usememos/memos/api/v1" - "github.com/usememos/memos/common/util" "github.com/usememos/memos/plugin/telegram" "github.com/usememos/memos/store" ) @@ -94,7 +93,6 @@ func (t *telegramHandler) MessageHandle(ctx context.Context, bot *telegram.Bot, Type: mime, Size: int64(len(blob)), Blob: blob, - PublicID: util.GenUUID(), }) if err != nil { _, err := bot.EditMessage(ctx, message.Chat.ID, reply.MessageID, fmt.Sprintf("failed to CreateResource: %s", err), nil) diff --git a/store/db/migration/dev/LATEST__SCHEMA.sql b/store/db/migration/dev/LATEST__SCHEMA.sql index fd58a200d..c675118fb 100644 --- a/store/db/migration/dev/LATEST__SCHEMA.sql +++ b/store/db/migration/dev/LATEST__SCHEMA.sql @@ -76,9 +76,7 @@ CREATE TABLE resource ( external_link TEXT NOT NULL DEFAULT '', type TEXT NOT NULL DEFAULT '', size INTEGER NOT NULL DEFAULT 0, - internal_path TEXT NOT NULL DEFAULT '', - public_id TEXT NOT NULL DEFAULT '', - UNIQUE(id, public_id) + internal_path TEXT NOT NULL DEFAULT '' ); -- memo_resource diff --git a/store/db/migration/prod/0.14/00_drop_resource_public_id.sql b/store/db/migration/prod/0.14/00_drop_resource_public_id.sql new file mode 100644 index 000000000..c6e636d04 --- /dev/null +++ b/store/db/migration/prod/0.14/00_drop_resource_public_id.sql @@ -0,0 +1,25 @@ +DROP TABLE IF EXISTS resource_temp; + +CREATE TABLE resource_temp ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + creator_id INTEGER NOT NULL, + created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')), + updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')), + filename TEXT NOT NULL DEFAULT '', + blob BLOB DEFAULT NULL, + external_link TEXT NOT NULL DEFAULT '', + type TEXT NOT NULL DEFAULT '', + size INTEGER NOT NULL DEFAULT 0, + internal_path TEXT NOT NULL DEFAULT '' +); + +INSERT INTO + resource_temp (id, creator_id, created_ts, updated_ts, filename, blob, external_link, type, size, internal_path) +SELECT + id, creator_id, created_ts, updated_ts, filename, blob, external_link, type, size, internal_path +FROM + resource; + +DROP TABLE resource; + +ALTER TABLE resource_temp RENAME TO resource; diff --git a/store/db/migration/prod/LATEST__SCHEMA.sql b/store/db/migration/prod/LATEST__SCHEMA.sql index fd58a200d..c675118fb 100644 --- a/store/db/migration/prod/LATEST__SCHEMA.sql +++ b/store/db/migration/prod/LATEST__SCHEMA.sql @@ -76,9 +76,7 @@ CREATE TABLE resource ( external_link TEXT NOT NULL DEFAULT '', type TEXT NOT NULL DEFAULT '', size INTEGER NOT NULL DEFAULT 0, - internal_path TEXT NOT NULL DEFAULT '', - public_id TEXT NOT NULL DEFAULT '', - UNIQUE(id, public_id) + internal_path TEXT NOT NULL DEFAULT '' ); -- memo_resource diff --git a/store/resource.go b/store/resource.go index e4f75685a..6fbfebd51 100644 --- a/store/resource.go +++ b/store/resource.go @@ -22,7 +22,6 @@ type Resource struct { ExternalLink string Type string Size int64 - PublicID string LinkedMemoAmount int } @@ -32,7 +31,6 @@ type FindResource struct { CreatorID *int Filename *string MemoID *int - PublicID *string Limit *int Offset *int } @@ -41,7 +39,6 @@ type UpdateResource struct { ID int UpdatedTs *int64 Filename *string - PublicID *string } type DeleteResource struct { @@ -63,13 +60,12 @@ func (s *Store) CreateResource(ctx context.Context, create *Resource) (*Resource type, size, creator_id, - internal_path, - public_id + internal_path ) - VALUES (?, ?, ?, ?, ?, ?, ?, ?) + VALUES (?, ?, ?, ?, ?, ?, ?) RETURNING id, created_ts, updated_ts `, - create.Filename, create.Blob, create.ExternalLink, create.Type, create.Size, create.CreatorID, create.InternalPath, create.PublicID, + create.Filename, create.Blob, create.ExternalLink, create.Type, create.Size, create.CreatorID, create.InternalPath, ).Scan(&create.ID, &create.CreatedTs, &create.UpdatedTs); err != nil { return nil, err } @@ -98,10 +94,6 @@ func (s *Store) ListResources(ctx context.Context, find *FindResource) ([]*Resou return nil, err } - if err := tx.Commit(); err != nil { - return nil, err - } - return resources, nil } @@ -143,12 +135,9 @@ func (s *Store) UpdateResource(ctx context.Context, update *UpdateResource) (*Re if v := update.Filename; v != nil { set, args = append(set, "filename = ?"), append(args, *v) } - if v := update.PublicID; v != nil { - set, args = append(set, "public_id = ?"), append(args, *v) - } args = append(args, update.ID) - fields := []string{"id", "filename", "external_link", "type", "size", "creator_id", "created_ts", "updated_ts", "internal_path", "public_id"} + fields := []string{"id", "filename", "external_link", "type", "size", "creator_id", "created_ts", "updated_ts", "internal_path"} query := ` UPDATE resource SET ` + strings.Join(set, ", ") + ` @@ -165,7 +154,6 @@ func (s *Store) UpdateResource(ctx context.Context, update *UpdateResource) (*Re &resource.CreatedTs, &resource.UpdatedTs, &resource.InternalPath, - &resource.PublicID, } if err := tx.QueryRowContext(ctx, query, args...).Scan(dests...); err != nil { return nil, err @@ -215,11 +203,8 @@ func listResources(ctx context.Context, tx *sql.Tx, find *FindResource) ([]*Reso if v := find.MemoID; v != nil { where, args = append(where, "resource.id in (SELECT resource_id FROM memo_resource WHERE memo_id = ?)"), append(args, *v) } - if v := find.PublicID; v != nil { - where, args = append(where, "resource.public_id = ?"), append(args, *v) - } - fields := []string{"resource.id", "resource.filename", "resource.external_link", "resource.type", "resource.size", "resource.creator_id", "resource.created_ts", "resource.updated_ts", "internal_path", "public_id"} + fields := []string{"resource.id", "resource.filename", "resource.external_link", "resource.type", "resource.size", "resource.creator_id", "resource.created_ts", "resource.updated_ts", "internal_path"} if find.GetBlob { fields = append(fields, "resource.blob") } @@ -261,7 +246,6 @@ func listResources(ctx context.Context, tx *sql.Tx, find *FindResource) ([]*Reso &resource.CreatedTs, &resource.UpdatedTs, &resource.InternalPath, - &resource.PublicID, } if find.GetBlob { dests = append(dests, &resource.Blob) diff --git a/test/store/resource_test.go b/test/store/resource_test.go index d525b9cf5..a861bd396 100644 --- a/test/store/resource_test.go +++ b/test/store/resource_test.go @@ -19,7 +19,6 @@ func TestResourceStore(t *testing.T) { ExternalLink: "", Type: "application/epub+zip", Size: 637607, - PublicID: "a02748e2-9b56-46b2-8b1f-72d686d52f77", }) require.NoError(t, err) diff --git a/web/src/components/LearnMore.tsx b/web/src/components/LearnMore.tsx new file mode 100644 index 000000000..d5b919f08 --- /dev/null +++ b/web/src/components/LearnMore.tsx @@ -0,0 +1,26 @@ +import { Tooltip } from "@mui/joy"; +import Icon from "./Icon"; +import { useTranslation } from "react-i18next"; + +interface Props { + className?: string; + url: string; + title?: string; +} + +const LearnMore: React.FC = (props: Props) => { + const { className, url, title } = props; + const { t } = useTranslation(); + + return ( + <> + + + + + + + ); +}; + +export default LearnMore; diff --git a/web/src/components/ResourceItemDropdown.tsx b/web/src/components/ResourceItemDropdown.tsx index f011d9586..52ac80d0b 100644 --- a/web/src/components/ResourceItemDropdown.tsx +++ b/web/src/components/ResourceItemDropdown.tsx @@ -37,21 +37,6 @@ const ResourceItemDropdown = ({ resource }: Props) => { toast.success(t("message.succeed-copy-resource-link")); }; - const handleResetResourceLinkBtnClick = (resource: Resource) => { - showCommonDialog({ - title: t("resource.reset-resource-link"), - content: t("resource.reset-link-prompt"), - style: "warning", - dialogName: "reset-resource-link-dialog", - onConfirm: async () => { - await resourceStore.patchResource({ - id: resource.id, - resetPublicId: true, - }); - }, - }); - }; - const handleRenameBtnClick = (resource: Resource) => { showChangeResourceFilenameDialog(resource.id, resource.filename); }; @@ -91,12 +76,6 @@ const ResourceItemDropdown = ({ resource }: Props) => { > {t("resource.copy-link")} -