140 lines
2.9 KiB
Go
140 lines
2.9 KiB
Go
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")
|
|
}
|