[add] editing

This commit is contained in:
2023-09-23 14:14:57 -04:00
parent 3150c89303
commit 4b0bbda017
7 changed files with 526 additions and 88 deletions

View File

@@ -25,7 +25,7 @@ type API struct {
func NewApi(db *database.DBManager, c *config.Config) *API {
api := &API{
HTMLPolicy: bluemonday.StripTagsPolicy(),
HTMLPolicy: bluemonday.StrictPolicy(),
Router: gin.Default(),
Config: c,
DB: db,
@@ -97,6 +97,8 @@ func (api *API) registerWebAppRoutes() {
api.Router.GET("/activity", api.authWebAppMiddleware, api.createAppResourcesRoute("activity"))
api.Router.GET("/documents", api.authWebAppMiddleware, api.createAppResourcesRoute("documents"))
api.Router.GET("/documents/:document", api.authWebAppMiddleware, api.createAppResourcesRoute("document"))
api.Router.DELETE("/documents/:document", api.authWebAppMiddleware, api.deleteDocument)
api.Router.POST("/documents/:document/edit", api.authWebAppMiddleware, api.createAppResourcesRoute("document-edit"))
api.Router.GET("/documents/:document/file", api.authWebAppMiddleware, api.downloadDocumentFile)
api.Router.GET("/documents/:document/cover", api.authWebAppMiddleware, api.getDocumentCover)

View File

@@ -2,9 +2,11 @@ package api
import (
"fmt"
"mime/multipart"
"net/http"
"os"
"path/filepath"
"strings"
"time"
"github.com/gin-gonic/gin"
@@ -13,6 +15,13 @@ import (
"reichard.io/bbank/metadata"
)
type requestDocumentEdit struct {
Title *string `form:"title"`
Author *string `form:"author"`
Description *string `form:"description"`
Cover *multipart.FileHeader `form:"cover"`
}
func baseResourceRoute(template string, args ...map[string]any) func(c *gin.Context) {
variables := gin.H{"RouteName": template}
if len(args) > 0 {
@@ -84,6 +93,46 @@ func (api *API) createAppResourcesRoute(routeName string, args ...map[string]any
}
templateVars["Data"] = document
} else if routeName == "document-edit" {
var rDocID requestDocumentID
if err := c.ShouldBindUri(&rDocID); err != nil {
log.Error("[createAppResourcesRoute] Invalid URI Bind")
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid Request"})
return
}
var rDocEdit requestDocumentEdit
if err := c.ShouldBind(&rDocEdit); err != nil {
log.Error("[createAppResourcesRoute] Invalid Form Bind")
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid Request"})
return
}
if rDocEdit.Author == nil && rDocEdit.Title == nil && rDocEdit.Description == nil && rDocEdit.Cover == nil {
log.Error("[createAppResourcesRoute] Missing Form Values")
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid Request"})
return
}
// TODO - Handle Cover
if rDocEdit.Cover != nil {
}
// Update Document
if _, err := api.DB.Queries.UpsertDocument(api.DB.Ctx, database.UpsertDocumentParams{
ID: rDocID.DocumentID,
Title: api.sanitizeInput(rDocEdit.Title),
Author: api.sanitizeInput(rDocEdit.Author),
Description: api.sanitizeInput(rDocEdit.Description),
}); err != nil {
log.Error("[createAppResourcesRoute] UpsertDocument DB Error:", err)
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid Request"})
return
}
c.Redirect(http.StatusFound, "./")
return
} else if routeName == "activity" {
activityFilter := database.GetActivityParams{
UserID: rUser.(string),
@@ -195,25 +244,27 @@ func (api *API) getDocumentCover(c *gin.Context) {
var coverFilePath string
// Identify Documents & Save Covers
bookMetadata := metadata.MetadataInfo{
metadataResults, err := metadata.GetMetadata(metadata.MetadataInfo{
Title: document.Title,
Author: document.Author,
}
err = metadata.GetMetadata(&bookMetadata)
if err == nil && bookMetadata.GBID != nil {
})
if err == nil && len(metadataResults) > 0 && metadataResults[0].GBID != nil {
firstResult := metadataResults[0]
// Derive & Sanitize File Name
fileName := "." + filepath.Clean(fmt.Sprintf("/%s.jpg", *bookMetadata.GBID))
fileName := "." + filepath.Clean(fmt.Sprintf("/%s.jpg", *firstResult.GBID))
// Generate Storage Path
coverFilePath = filepath.Join(api.Config.DataPath, "covers", fileName)
err := metadata.SaveCover(*bookMetadata.GBID, coverFilePath)
err := metadata.SaveCover(*firstResult.GBID, coverFilePath)
if err == nil {
coverID = *bookMetadata.GBID
log.Info("Title:", *bookMetadata.Title)
log.Info("Author:", *bookMetadata.Author)
log.Info("Description:", *bookMetadata.Description)
log.Info("IDs:", bookMetadata.ISBN)
coverID = *firstResult.GBID
log.Info("Title:", *firstResult.Title)
log.Info("Author:", *firstResult.Author)
log.Info("Description:", *firstResult.Description)
log.Info("IDs:", firstResult.ISBN)
}
}
@@ -241,3 +292,60 @@ func (api *API) getDocumentCover(c *gin.Context) {
c.File(coverFilePath)
}
// DELETE /api/documents/:document
func (api *API) deleteDocument(c *gin.Context) {
var rDocID requestDocumentID
if err := c.ShouldBindUri(&rDocID); err != nil {
log.Error("[deleteDocument] Invalid URI Bind")
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid Request"})
return
}
// TODO
}
// POST /api/documents/:document/identify
func (api *API) identifyDocument(c *gin.Context) {
var rDocID requestDocumentID
if err := c.ShouldBindUri(&rDocID); err != nil {
log.Error("[identifyDocument] Invalid URI Bind")
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid Request"})
return
}
isbn := strings.TrimSpace(c.PostForm("ISBN"))
if isbn == "" {
log.Error("[identifyDocument] Invalid Form")
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid Request"})
return
}
metadataResults, err := metadata.GetMetadata(metadata.MetadataInfo{
ISBN: []*string{&isbn},
})
if err != nil || len(metadataResults) == 0 {
log.Error("[identifyDocument] Metadata Error")
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Metadata Error"})
return
}
// TODO
firstResult := metadataResults[0]
if firstResult.Title != nil {
log.Info("Title:", *firstResult.Title)
}
if firstResult.Author != nil {
log.Info("Author:", *firstResult.Author)
}
if firstResult.Description != nil {
log.Info("Description:", *firstResult.Description)
}
for _, val := range firstResult.ISBN {
log.Info("ISBN:", *val)
}
c.Redirect(http.StatusFound, "/")
}

View File

@@ -5,6 +5,7 @@ import (
"database/sql"
"encoding/json"
"fmt"
"html"
"io"
"net/http"
"os"
@@ -609,12 +610,12 @@ func (api *API) sanitizeInput(val any) *string {
switch v := val.(type) {
case *string:
if v != nil {
newString := api.HTMLPolicy.Sanitize(string(*v))
newString := html.UnescapeString(api.HTMLPolicy.Sanitize(string(*v)))
return &newString
}
case string:
if v != "" {
newString := api.HTMLPolicy.Sanitize(string(v))
newString := html.UnescapeString(api.HTMLPolicy.Sanitize(string(v)))
return &newString
}
}