From 1cc8b94b60fb329786f9ee1b831acef70d913c5a Mon Sep 17 00:00:00 2001 From: m Date: Sat, 11 Jul 2026 22:47:33 +0200 Subject: [PATCH] sign url --- backend/internal/handlers/files.go | 32 ++++++++++++++---- backend/internal/service/presignedurl.go | 41 ++++++++++++++++++++++++ backend/internal/service/upload.go | 10 ------ 3 files changed, 66 insertions(+), 17 deletions(-) create mode 100644 backend/internal/service/presignedurl.go delete mode 100644 backend/internal/service/upload.go diff --git a/backend/internal/handlers/files.go b/backend/internal/handlers/files.go index bde7b9e..37d8310 100644 --- a/backend/internal/handlers/files.go +++ b/backend/internal/handlers/files.go @@ -4,9 +4,12 @@ import ( "fmt" "net/http" "os" + "path" "path/filepath" + "strconv" "github.com/gin-gonic/gin" + "github.com/vaultdrop/backend/internal/service" ) func ListFiles(c *gin.Context) { @@ -15,7 +18,6 @@ func ListFiles(c *gin.Context) { if err != nil { - fmt.Println("What") c.JSON(http.StatusInternalServerError, gin.H{ "data": []interface{}{}, "meta": gin.H{ @@ -28,6 +30,7 @@ func ListFiles(c *gin.Context) { } type Finfo struct { + Url string `json:"url"` Name string `json:"name"` Size int64 `json:"size"` Tags []string `json:"tags"` @@ -48,6 +51,7 @@ func ListFiles(c *gin.Context) { } ps := Finfo{ + Url: service.GenerateFileDownloadUrl(i.Name()), Name: i.Name(), Size: i.Size(), Tags: []string{}, @@ -67,12 +71,26 @@ func ListFiles(c *gin.Context) { } func GetFile(c *gin.Context) { - c.JSON(http.StatusNotFound, gin.H{ - "error": gin.H{ - "code": "FILE_NOT_FOUND", - "message": "File not found", - }, - }) + + exp, _ := strconv.ParseInt(c.Query("expires"), 10, 64) + + r := service.Validate(c.Params.ByName("id"), c.Query("sig"), exp) + + if r != true { + + c.JSON(http.StatusNotFound, gin.H{ + "error": gin.H{ + "code": "FILE_NOT_FOUND", + "message": "File not found", + }, + }) + + return + + } + + c.File(path.Join("./uploads/", c.Params.ByName("id"))) + } func UploadFile(c *gin.Context) { diff --git a/backend/internal/service/presignedurl.go b/backend/internal/service/presignedurl.go new file mode 100644 index 0000000..d20d5e8 --- /dev/null +++ b/backend/internal/service/presignedurl.go @@ -0,0 +1,41 @@ +package service + +import ( + "crypto/hmac" + "crypto/sha256" + "encoding/hex" + "fmt" + "time" +) + +const secret = "thisismyrandomstring" + +func sign(fileID string, expires int64, secret string) string { + data := fmt.Sprintf("%s:%d", fileID, expires) + mac := hmac.New(sha256.New, []byte(secret)) + mac.Write([]byte(data)) + return hex.EncodeToString(mac.Sum(nil)) +} + +func GenerateFileDownloadUrl(fileID string) string { + expires := time.Now().Add(10 * time.Minute).Unix() + sig := sign(fileID, expires, secret) + + url := fmt.Sprintf( + "http://192.168.1.142:8080/api/v1/files/%s?expires=%d&sig=%s", + fileID, + expires, + sig, + ) + + return url +} + +func Validate(fileID, sig string, expires int64) bool { + if time.Now().Unix() > expires { + return false + } + + expected := sign(fileID, expires, secret) + return hmac.Equal([]byte(sig), []byte(expected)) +} diff --git a/backend/internal/service/upload.go b/backend/internal/service/upload.go deleted file mode 100644 index d01a6ae..0000000 --- a/backend/internal/service/upload.go +++ /dev/null @@ -1,10 +0,0 @@ -package service - -import ( - "fmt" - "mime/multipart" -) - -func UploadFile(f *multipart.FileHeader) { - fmt.Println(f.Filename) -}