Add R2 image uploads to admin
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
This commit is contained in:
parent
9186801c7f
commit
49a0d078da
16 changed files with 809 additions and 14 deletions
|
|
@ -22,6 +22,7 @@ type Server struct {
|
|||
builder *Builder
|
||||
deepSeek DeepSeekConfig
|
||||
localLLM LocalLLMConfig
|
||||
uploader *ImageUploader
|
||||
slugProvider string
|
||||
adminDir string
|
||||
staticDir string
|
||||
|
|
@ -46,12 +47,23 @@ func NewServerWithContext(ctx context.Context, db *pgxpool.Pool, cfg Config) *Se
|
|||
builder.Start(ctx)
|
||||
}
|
||||
}
|
||||
var uploader *ImageUploader
|
||||
if cfg.R2.Endpoint != "" || cfg.R2.Bucket != "" || cfg.R2.AccessKeyID != "" || cfg.R2.SecretAccessKey != "" {
|
||||
createdUploader, err := NewImageUploader(ctx, cfg.R2)
|
||||
if err != nil {
|
||||
log.Printf("R2 image uploader disabled: %v", err)
|
||||
} else {
|
||||
uploader = createdUploader
|
||||
}
|
||||
}
|
||||
|
||||
return &Server{
|
||||
db: db,
|
||||
store: store,
|
||||
builder: builder,
|
||||
deepSeek: cfg.DeepSeek,
|
||||
localLLM: cfg.LocalLLM,
|
||||
uploader: uploader,
|
||||
slugProvider: cfg.SlugProvider,
|
||||
adminDir: cfg.AdminDir,
|
||||
staticDir: cfg.StaticDir,
|
||||
|
|
@ -81,6 +93,7 @@ func (s *Server) Router() http.Handler {
|
|||
protected.GET("/me", s.me)
|
||||
protected.POST("/logout", s.logout)
|
||||
protected.POST("/slug", s.generateSlug)
|
||||
protected.POST("/images", s.uploadImage)
|
||||
protected.GET("/audit-logs", s.listAuditLogs)
|
||||
protected.GET("/posts", s.listPosts)
|
||||
protected.POST("/posts", s.createPost)
|
||||
|
|
@ -347,6 +360,39 @@ func (s *Server) generateSlug(c *gin.Context) {
|
|||
c.JSON(http.StatusOK, gin.H{"slug": slug})
|
||||
}
|
||||
|
||||
func (s *Server) uploadImage(c *gin.Context) {
|
||||
if s.uploader == nil {
|
||||
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "R2 image uploader is not configured"})
|
||||
return
|
||||
}
|
||||
|
||||
file, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "file is required"})
|
||||
return
|
||||
}
|
||||
opened, err := file.Open()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
defer opened.Close()
|
||||
|
||||
uploaded, err := s.uploader.Upload(c.Request.Context(), file.Filename, opened, file.Size)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
s.auditCurrentUser(c, "image_upload", "image", uploaded.Key, gin.H{
|
||||
"filename": uploaded.Filename,
|
||||
"url": uploaded.URL,
|
||||
"size": uploaded.Size,
|
||||
"contentType": uploaded.ContentType,
|
||||
})
|
||||
c.JSON(http.StatusCreated, gin.H{"image": uploaded})
|
||||
}
|
||||
|
||||
func (s *Server) listAuditLogs(c *gin.Context) {
|
||||
if !s.requireStore(c) {
|
||||
return
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue