mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
feat: add public id field to resource (#1451)
* feat: add public id field to resource * feat: support reset resource link
This commit is contained in:
@@ -122,6 +122,10 @@ func JWTMiddleware(server *Server, next echo.HandlerFunc, secret string) echo.Ha
|
||||
|
||||
token := findAccessToken(c)
|
||||
if token == "" {
|
||||
// Allow the user to access the public endpoints.
|
||||
if common.HasPrefixes(path, "/o") {
|
||||
return next(c)
|
||||
}
|
||||
// When the request is not authenticated, we allow the user to access the memo endpoints for those public memos.
|
||||
if common.HasPrefixes(path, "/api/memo") && method == http.MethodGet {
|
||||
return next(c)
|
||||
|
@@ -194,6 +194,11 @@ func (s *Server) registerResourceRoutes(g *echo.Group) {
|
||||
}
|
||||
}
|
||||
|
||||
if s.Profile.IsDev() {
|
||||
publicID := common.GenUUID()
|
||||
resourceCreate.PublicID = publicID
|
||||
}
|
||||
|
||||
resource, err := s.Store.CreateResource(ctx, resourceCreate)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create resource").SetInternal(err)
|
||||
@@ -227,52 +232,6 @@ func (s *Server) registerResourceRoutes(g *echo.Group) {
|
||||
return c.JSON(http.StatusOK, composeResponse(list))
|
||||
})
|
||||
|
||||
g.GET("/resource/:resourceId", func(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
resourceID, err := strconv.Atoi(c.Param("resourceId"))
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("resourceId"))).SetInternal(err)
|
||||
}
|
||||
|
||||
userID, ok := c.Get(getUserIDContextKey()).(int)
|
||||
if !ok {
|
||||
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
||||
}
|
||||
resourceFind := &api.ResourceFind{
|
||||
ID: &resourceID,
|
||||
CreatorID: &userID,
|
||||
GetBlob: true,
|
||||
}
|
||||
resource, err := s.Store.FindResource(ctx, resourceFind)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to fetch resource").SetInternal(err)
|
||||
}
|
||||
return c.JSON(http.StatusOK, composeResponse(resource))
|
||||
})
|
||||
|
||||
g.GET("/resource/:resourceId/blob", func(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
resourceID, err := strconv.Atoi(c.Param("resourceId"))
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("resourceId"))).SetInternal(err)
|
||||
}
|
||||
|
||||
userID, ok := c.Get(getUserIDContextKey()).(int)
|
||||
if !ok {
|
||||
return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
|
||||
}
|
||||
resourceFind := &api.ResourceFind{
|
||||
ID: &resourceID,
|
||||
CreatorID: &userID,
|
||||
GetBlob: true,
|
||||
}
|
||||
resource, err := s.Store.FindResource(ctx, resourceFind)
|
||||
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))
|
||||
})
|
||||
|
||||
g.PATCH("/resource/:resourceId", func(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
userID, ok := c.Get(getUserIDContextKey()).(int)
|
||||
@@ -304,6 +263,11 @@ func (s *Server) registerResourceRoutes(g *echo.Group) {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted patch resource request").SetInternal(err)
|
||||
}
|
||||
|
||||
if resourcePatch.ResetPublicID != nil && *resourcePatch.ResetPublicID {
|
||||
publicID := common.GenUUID()
|
||||
resourcePatch.PublicID = &publicID
|
||||
}
|
||||
|
||||
resourcePatch.ID = resourceID
|
||||
resource, err = s.Store.PatchResource(ctx, resourcePatch)
|
||||
if err != nil {
|
||||
@@ -349,19 +313,19 @@ func (s *Server) registerResourceRoutes(g *echo.Group) {
|
||||
}
|
||||
|
||||
func (s *Server) registerResourcePublicRoutes(g *echo.Group) {
|
||||
g.GET("/r/:resourceId/:filename", func(c echo.Context) error {
|
||||
g.GET("/r/:resourceId/:publicId", func(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
resourceID, err := strconv.Atoi(c.Param("resourceId"))
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("ID is not a number: %s", c.Param("resourceId"))).SetInternal(err)
|
||||
}
|
||||
filename, err := url.QueryUnescape(c.Param("filename"))
|
||||
publicID, err := url.QueryUnescape(c.Param("publicId"))
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("filename is invalid: %s", c.Param("filename"))).SetInternal(err)
|
||||
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("publicID is invalid: %s", c.Param("publicId"))).SetInternal(err)
|
||||
}
|
||||
resourceFind := &api.ResourceFind{
|
||||
ID: &resourceID,
|
||||
Filename: &filename,
|
||||
PublicID: &publicID,
|
||||
GetBlob: true,
|
||||
}
|
||||
resource, err := s.Store.FindResource(ctx, resourceFind)
|
||||
@@ -369,6 +333,10 @@ func (s *Server) registerResourcePublicRoutes(g *echo.Group) {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Failed to find resource by ID: %v", resourceID)).SetInternal(err)
|
||||
}
|
||||
|
||||
if resource.ExternalLink != "" {
|
||||
return c.Redirect(http.StatusSeeOther, resource.ExternalLink)
|
||||
}
|
||||
|
||||
blob := resource.Blob
|
||||
if resource.InternalPath != "" {
|
||||
src, err := os.Open(resource.InternalPath)
|
||||
|
@@ -79,29 +79,32 @@ func NewServer(ctx context.Context, profile *profile.Profile) (*Server, error) {
|
||||
}
|
||||
s.ID = serverID
|
||||
|
||||
secretSessionName := "usememos"
|
||||
embedFrontend(e)
|
||||
|
||||
secret := "usememos"
|
||||
if profile.Mode == "prod" {
|
||||
secretSessionName, err = s.getSystemSecretSessionName(ctx)
|
||||
secret, err = s.getSystemSecretSessionName(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
embedFrontend(e)
|
||||
|
||||
rootGroup := e.Group("")
|
||||
s.registerRSSRoutes(rootGroup)
|
||||
|
||||
publicGroup := e.Group("/o")
|
||||
s.registerResourcePublicRoutes(publicGroup)
|
||||
publicGroup.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return JWTMiddleware(s, next, secret)
|
||||
})
|
||||
registerGetterPublicRoutes(publicGroup)
|
||||
s.registerResourcePublicRoutes(publicGroup)
|
||||
|
||||
apiGroup := e.Group("/api")
|
||||
apiGroup.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return JWTMiddleware(s, next, secretSessionName)
|
||||
return JWTMiddleware(s, next, secret)
|
||||
})
|
||||
s.registerSystemRoutes(apiGroup)
|
||||
s.registerAuthRoutes(apiGroup, secretSessionName)
|
||||
s.registerAuthRoutes(apiGroup, secret)
|
||||
s.registerUserRoutes(apiGroup)
|
||||
s.registerMemoRoutes(apiGroup)
|
||||
s.registerShortcutRoutes(apiGroup)
|
||||
|
Reference in New Issue
Block a user