feat(tenant-api): add desktop content asset endpoint scoped by tenant
Lets desktop clients fetch tenant images/articles assets via Bearer-auth without requiring the public asset signature, so stale-signed assets served from existing articles still load on the desktop side. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"image/jpeg"
|
||||
"image/png"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -42,6 +43,21 @@ func (h *AssetHandler) Serve(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
h.serveObject(c, objectKey)
|
||||
}
|
||||
|
||||
func (h *AssetHandler) ServeDesktop(c *gin.Context) {
|
||||
client := MustDesktopClient(c.Request.Context())
|
||||
objectKey, ok := objectKeyFromAssetToken(c.Param("token"))
|
||||
if !ok || !isDesktopClientAssetKey(objectKey, client.TenantID) {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
h.serveObject(c, objectKey)
|
||||
}
|
||||
|
||||
func (h *AssetHandler) serveObject(c *gin.Context, objectKey string) {
|
||||
content, err := h.app.ObjectStorage.GetBytes(c.Request.Context(), objectKey)
|
||||
if err != nil || len(content) == 0 {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
@@ -121,3 +137,29 @@ func (h *AssetHandler) parseToken(token string) (string, bool) {
|
||||
|
||||
return objectKey, true
|
||||
}
|
||||
|
||||
func objectKeyFromAssetToken(token string) (string, bool) {
|
||||
parts := strings.Split(token, ".")
|
||||
if len(parts) != 2 {
|
||||
return "", false
|
||||
}
|
||||
|
||||
objectKeyBytes, err := base64.RawURLEncoding.DecodeString(parts[0])
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
objectKey := strings.TrimSpace(string(objectKeyBytes))
|
||||
if objectKey == "" {
|
||||
return "", false
|
||||
}
|
||||
return objectKey, true
|
||||
}
|
||||
|
||||
func isDesktopClientAssetKey(objectKey string, tenantID int64) bool {
|
||||
if tenantID <= 0 {
|
||||
return false
|
||||
}
|
||||
tenantPrefix := "tenants/" + strconv.FormatInt(tenantID, 10) + "/"
|
||||
return strings.HasPrefix(objectKey, tenantPrefix+"images/") ||
|
||||
strings.HasPrefix(objectKey, tenantPrefix+"articles/")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user