Change logging to be json comaptible

This commit is contained in:
2026-05-03 22:42:43 +02:00
parent d1f6782c96
commit 1a82f21202
14 changed files with 501 additions and 35 deletions

View File

@@ -1,12 +1,13 @@
package file
import (
"ResendIt/internal/api/middleware"
"ResendIt/internal/config"
"ResendIt/internal/logger"
"ResendIt/internal/notify"
"ResendIt/internal/util"
"fmt"
"io"
"log"
"net/http"
"os"
"path/filepath"
@@ -34,26 +35,38 @@ func NewHandler(s *Service, cfg ConfigService) *Handler {
}
func (h *Handler) Upload(c *gin.Context) {
log := middleware.StructuredLog(c).With().
Str("event", "file_upload").
Logger()
err := c.Request.ParseMultipartForm(0)
if err != nil {
log.Warn().Str("reason", "parse_error").Err(err).Msg("Upload failed")
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
file, err := c.FormFile("file")
if err != nil {
log.Warn().Str("reason", "missing_file").Msg("Upload failed")
c.JSON(http.StatusBadRequest, gin.H{"error": "missing file"})
return
}
maxSize := h.configService.GetInt64Default(config.KeyUploadMaxFileSizeBytes, config.DefaultUploadMaxFileSizeBytes)
if file.Size > maxSize {
log.Warn().
Str("reason", "file_too_large").
Int64("file_size", file.Size).
Int64("max_size", maxSize).
Msg("Upload rejected")
c.JSON(http.StatusRequestEntityTooLarge, gin.H{"error": "file too large"})
return
}
f, err := file.Open()
if err != nil {
log.Error().Err(err).Msg("Failed to open uploaded file")
c.JSON(http.StatusInternalServerError, gin.H{"error": "cannot open file"})
return
}
@@ -80,10 +93,18 @@ func (h *Handler) Upload(c *gin.Context) {
duration,
)
if err != nil {
log.Error().Err(err).Msg("Upload failed")
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
log.Info().
Str("file_id", record.ID).
Str("filename", record.Filename).
Int64("file_size", record.Size).
Bool("once", once).
Msg("File uploaded successfully")
enabled := h.configService.GetIntDefault(config.KeyUseNtfy, config.DefaultUseNtfy)
if enabled == 1 {
ntfyURL := h.configService.GetStringDefault(config.KeyNtfyUrl, "")
@@ -94,7 +115,7 @@ func (h *Handler) Upload(c *gin.Context) {
msg := fmt.Sprintf("%s (%s)\nID: %s", record.Filename, util.HumanSize(record.Size), record.ID)
clickUrl := fmt.Sprintf("f/%s", record.ViewID)
if err := notify.Publish(ntfyURL, topic, title, msg, clickUrl); err != nil {
log.Printf("ntfy publish failed: %v", err)
logger.Log.Warn().Err(err).Str("type", "ntfy").Msg("ntfy publish failed")
}
}()
}
@@ -110,13 +131,21 @@ func (h *Handler) Upload(c *gin.Context) {
}
func (h *Handler) View(c *gin.Context) {
log := middleware.StructuredLog(c).With().
Str("event", "file_view").
Logger()
id := c.Param("id")
record, err := h.service.DownloadFile(id)
if err != nil {
log.Warn().Str("file_id", id).Err(err).Msg("File view failed - not found")
c.HTML(http.StatusOK, "error.html", nil)
return
}
log.Info().Str("file_id", id).Str("filename", record.Filename).Msg("File viewed")
name := util.SafeFilename(record.Filename)
c.Header("Content-Disposition", fmt.Sprintf(`inline; filename="%s"`, name))
c.Header("X-Content-Type-Options", "nosniff")
@@ -134,31 +163,46 @@ func isXSSRisk(filename string) bool {
}
func (h *Handler) Download(c *gin.Context) {
log := middleware.StructuredLog(c).With().
Str("event", "file_download").
Logger()
id := c.Param("id")
record, err := h.service.DownloadFile(id)
if err != nil {
log.Warn().Str("file_id", id).Err(err).Msg("File download failed - not found")
c.HTML(http.StatusOK, "error.html", nil)
return
}
log.Info().Str("file_id", id).Str("filename", record.Filename).Int64("size", record.Size).Msg("File downloaded")
name := util.SafeFilename(record.Filename)
c.Header("Content-Disposition", fmt.Sprintf(`inline; filename="%s"`, name))
c.Header("X-Content-Type-Options", "nosniff")
//c.Header("Content-Security-Policy", "default-src 'none'; img-src 'self'; media-src 'self'; script-src 'none'; style-src 'none';")
//c.Header("Content-Type", "application/octet-stream")
c.File(record.Path)
}
func (h *Handler) Delete(c *gin.Context) {
log := middleware.StructuredLog(c).With().
Str("event", "file_delete").
Logger()
id := c.Param("del_id")
_, err := h.service.DeleteFileByDeletionID(id)
record, err := h.service.DeleteFileByDeletionID(id)
if err != nil {
log.Warn().Str("deletion_id", id).Err(err).Msg("File delete failed")
c.HTML(http.StatusOK, "error.html", nil)
return
}
//c.JSON(http.StatusOK, gin.H{"status": "deleted"})
log.Info().
Str("file_id", record.ID).
Str("filename", record.Filename).
Msg("File deleted")
c.HTML(http.StatusOK, "deleted.html", nil)
}
@@ -185,18 +229,29 @@ func (h *Handler) AdminGet(c *gin.Context) {
}
func (h *Handler) AdminDelete(c *gin.Context) {
log := middleware.StructuredLog(c).With().
Str("event", "admin_file_delete").
Logger()
id := c.Param("id")
_, err := h.service.DeleteFileByID(id)
record, err := h.service.DeleteFileByID(id)
if err != nil {
log.Warn().Str("file_id", id).Err(err).Msg("Admin file delete failed")
c.JSON(http.StatusNotFound, gin.H{"error": "file not found"})
return
}
log.Info().Str("file_id", record.ID).Str("filename", record.Filename).Msg("Admin deleted file")
c.Redirect(301, "/admin")
}
func (h *Handler) AdminForceDelete(c *gin.Context) {
log := middleware.StructuredLog(c).With().
Str("event", "admin_file_force_delete").
Logger()
id := c.Param("id")
_, err := h.service.GetFileByID(id)
@@ -206,14 +261,21 @@ func (h *Handler) AdminForceDelete(c *gin.Context) {
}
if _, err := h.service.ForceDelete(id); err != nil {
log.Error().Err(err).Msg("Admin force delete failed")
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
log.Info().Str("file_id", id).Msg("Admin force deleted file")
c.Redirect(301, "/admin")
}
func (h *Handler) AdminReinstate(c *gin.Context) {
log := middleware.StructuredLog(c).With().
Str("event", "admin_file_reinstate").
Logger()
id := c.Param("id")
_, err := h.service.GetFileByID(id)
@@ -223,10 +285,13 @@ func (h *Handler) AdminReinstate(c *gin.Context) {
}
if _, err := h.service.ReinstateFile(id); err != nil {
log.Error().Err(err).Msg("Admin reinstate failed")
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
log.Info().Str("file_id", id).Msg("Admin reinstated file")
c.Redirect(301, "/admin")
}
@@ -331,6 +396,10 @@ func (h *Handler) UploadChunk(c *gin.Context) {
}
func (h *Handler) UploadComplete(c *gin.Context) {
log := middleware.StructuredLog(c).With().
Str("event", "chunked_upload_complete").
Logger()
var req struct {
FileID string `json:"fileId"`
Filename string `json:"filename"`
@@ -377,6 +446,7 @@ func (h *Handler) UploadComplete(c *gin.Context) {
24*time.Hour,
)
if err != nil {
log.Error().Err(err).Msg("Chunked upload failed")
c.JSON(500, gin.H{"error": err.Error()})
return
}
@@ -384,6 +454,12 @@ func (h *Handler) UploadComplete(c *gin.Context) {
// cleanup temp
_ = os.RemoveAll(tmpDir)
log.Info().
Str("file_id", record.ID).
Str("filename", record.Filename).
Int("chunks", req.TotalChunks).
Msg("Chunked upload completed")
c.JSON(200, gin.H{
"id": record.ID,
"view_key": record.ViewID,
@@ -414,4 +490,4 @@ func (h *Handler) UploadStatus(c *gin.Context) {
c.JSON(200, gin.H{
"uploadedChunks": uploaded,
})
}
}