package main import ( "fmt" "io" "os" "path/filepath" "time" "github.com/gin-gonic/gin" "github.com/google/uuid" "golang.org/x/crypto/bcrypt" ) func uploadHandler(c *gin.Context) { err := c.Request.ParseMultipartForm(0) // unlimited if err != nil { c.JSON(400, gin.H{"error": err.Error()}) return } src, header, err := c.Request.FormFile("file") if err != nil { c.JSON(400, gin.H{"error": "No file uploaded"}) return } defer src.Close() id := uuid.New().String() delID := uuid.New().String() cleanName := filepath.Base(header.Filename) folderPath := filepath.Join("uploads", id) os.MkdirAll(folderPath, 0755) storagePath := filepath.Join(folderPath, cleanName) dst, err := os.Create(storagePath) if err != nil { c.JSON(500, gin.H{"error": err.Error()}) return } defer dst.Close() written, err := io.Copy(dst, src) fmt.Println("UPLOAD COMPLETE:", cleanName, written, "bytes") if err != nil { c.JSON(500, gin.H{"error": err.Error()}) return } expiry := time.Now().Add(24 * time.Hour) record := FileRecord{ ID: id, DeletionID: delID, Filename: cleanName, Path: storagePath, ExpiresAt: expiry, DeleteAfterDownload: c.PostForm("once") == "true", } db.Create(&record) c.JSON(200, gin.H{ "id": id, "download_url": fmt.Sprintf("/f/%s", id), "delete_url": fmt.Sprintf("/api/file/delete/%s", delID), }) } func downloadHandler(c *gin.Context) { var record FileRecord if err := db.First(&record, "id = ? AND deleted = ?", c.Param("id"), false).Error; err != nil { c.String(404, "File not found or expired") return } if time.Now().After(record.ExpiresAt) { performDeletion(&record) c.String(410, "File has expired") return } //c.FileAttachment(record.Path, record.Filename) c.Header("Content-Disposition", fmt.Sprintf(`inline; filename="%s"`, record.Filename)) c.File(record.Path) db.Model(&record).Update("download_count", record.DownloadCount+1) if record.DeleteAfterDownload { performDeletion(&record) } } func deleteHandler(c *gin.Context) { var record FileRecord if err := db.First(&record, "deletion_id = ?", c.Param("del_id")).Error; err != nil { c.JSON(404, gin.H{"error": "Invalid deletion ID"}) return } performDeletion(&record) c.JSON(200, gin.H{"message": "Deleted successfully"}) } func loginHandler(c *gin.Context) { username := c.PostForm("username") password := c.PostForm("password") var user User if err := db.Where("username = ?", username).First(&user).Error; err != nil { c.HTML(401, "login.html", gin.H{"Error": true}) return } if bcrypt.CompareHashAndPassword( []byte(user.Password), []byte(password), ) != nil { c.HTML(401, "login.html", gin.H{"Error": true}) return } token, _ := generateToken(username) c.SetCookie( "auth", token, 86400, "/", "", false, true, ) c.Redirect(302, "/admin") }