first commit, i i have no idea what i have done
This commit is contained in:
123
server/internal/handlers/records.go
Normal file
123
server/internal/handlers/records.go
Normal file
@@ -0,0 +1,123 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"path"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/minio/minio-go/v7"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"smoop-api/internal/dto"
|
||||
"smoop-api/internal/models"
|
||||
)
|
||||
|
||||
type RecordsHandler struct {
|
||||
db *gorm.DB
|
||||
minio *minio.Client
|
||||
recordsBucket string
|
||||
presignTTL time.Duration
|
||||
}
|
||||
|
||||
func NewRecordsHandler(db *gorm.DB, mc *minio.Client, bucket string, ttl time.Duration) *RecordsHandler {
|
||||
return &RecordsHandler{db: db, minio: mc, recordsBucket: bucket, presignTTL: ttl}
|
||||
}
|
||||
|
||||
func (h *RecordsHandler) Upload(c *gin.Context) {
|
||||
file, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "file required"})
|
||||
return
|
||||
}
|
||||
guid := c.PostForm("guid")
|
||||
if guid == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "guid required"})
|
||||
return
|
||||
}
|
||||
startedAt, _ := strconv.ParseInt(c.PostForm("startedAt"), 10, 64)
|
||||
stoppedAt, _ := strconv.ParseInt(c.PostForm("stoppedAt"), 10, 64)
|
||||
|
||||
var dev models.Device
|
||||
if err := h.db.Where("guid = ?", guid).First(&dev).Error; err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "device not found"})
|
||||
return
|
||||
}
|
||||
|
||||
objKey := fmt.Sprintf("%s/%d_%s", guid, time.Now().UnixNano(), path.Base(file.Filename))
|
||||
if err := h.putFile(c, file, h.recordsBucket, objKey); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "upload failed"})
|
||||
return
|
||||
}
|
||||
|
||||
rec := models.Record{
|
||||
DeviceGUID: dev.GUID,
|
||||
StartedAt: startedAt,
|
||||
StoppedAt: stoppedAt,
|
||||
ObjectKey: objKey,
|
||||
}
|
||||
if err := h.db.Create(&rec).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "db save failed"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusCreated, dto.RecordDto{ID: rec.ID, StartedAt: rec.StartedAt, StoppedAt: rec.StoppedAt})
|
||||
}
|
||||
|
||||
func (h *RecordsHandler) putFile(c *gin.Context, fh *multipart.FileHeader, bucket, object string) error {
|
||||
src, err := fh.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer src.Close()
|
||||
_, err = h.minio.PutObject(c, bucket, object, src, fh.Size, minio.PutObjectOptions{
|
||||
ContentType: fh.Header.Get("Content-Type"),
|
||||
ContentDisposition: "attachment; filename=" + fh.Filename,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *RecordsHandler) List(c *gin.Context) {
|
||||
guid := c.Query("guid")
|
||||
if guid == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "guid is required"})
|
||||
return
|
||||
}
|
||||
offset, _ := strconv.Atoi(c.DefaultQuery("offset", "0"))
|
||||
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "50"))
|
||||
if limit <= 0 || limit > 200 {
|
||||
limit = 50
|
||||
}
|
||||
|
||||
var total int64
|
||||
h.db.Model(&models.Record{}).Where("device_guid = ?", guid).Count(&total)
|
||||
|
||||
var recs []models.Record
|
||||
if err := h.db.Where("device_guid = ?", guid).Order("id desc").Offset(offset).Limit(limit).Find(&recs).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "query failed"})
|
||||
return
|
||||
}
|
||||
out := make([]dto.RecordDto, 0, len(recs))
|
||||
for _, r := range recs {
|
||||
out = append(out, dto.RecordDto{ID: r.ID, StartedAt: r.StartedAt, StoppedAt: r.StoppedAt})
|
||||
}
|
||||
c.JSON(http.StatusOK, dto.RecordListDto{Records: out, Offset: offset, Limit: limit, Total: total})
|
||||
}
|
||||
|
||||
func (h *RecordsHandler) File(c *gin.Context) {
|
||||
id, _ := strconv.Atoi(c.Param("id"))
|
||||
var rec models.Record
|
||||
if err := h.db.First(&rec, id).Error; err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
|
||||
return
|
||||
}
|
||||
u, err := h.minio.PresignedGetObject(context.Background(), h.recordsBucket, rec.ObjectKey, h.presignTTL, nil)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "presign failed"})
|
||||
return
|
||||
}
|
||||
c.Redirect(http.StatusFound, u.String())
|
||||
}
|
||||
Reference in New Issue
Block a user