Added api endpoints and tests

This commit is contained in:
2022-01-24 12:59:43 +01:00
parent 10b768743b
commit cfbdcc7f82
36 changed files with 1781 additions and 315 deletions

View File

@@ -1,60 +1,94 @@
package api
import (
"TheAdversary/config"
"TheAdversary/database"
"TheAdversary/parse"
"TheAdversary/schema"
"encoding/base64"
"encoding/json"
"fmt"
"github.com/gomarkdown/markdown"
"go.uber.org/zap"
"net/http"
"path"
"strings"
"time"
)
type uploadRequest struct {
Name string
Author string
Title string
Summary string
Image string
Tags []string
Content string
type uploadPayload struct {
Title string `json:"title"`
Summary string `json:"summary"`
Authors []int `json:"authors"`
Image string `json:"image"`
Tags []string `json:"tags"`
Link string `json:"link"`
Content string `json:"content"`
}
func Upload(w http.ResponseWriter, r *http.Request) {
var request uploadRequest
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
authorId, ok := authorizedSession(r)
if !ok {
w.WriteHeader(http.StatusUnauthorized)
return
}
var payload uploadPayload
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
InvalidJson.Send(w)
return
}
rawMarkdown, err := base64.StdEncoding.DecodeString(request.Content)
rawMarkdown, err := base64.StdEncoding.DecodeString(payload.Content)
if err != nil {
zap.S().Warnf("Cannot decode base64")
ApiError{Message: "invalid base64 content", Code: http.StatusUnprocessableEntity}.Send(w)
return
}
db := database.GetDB()
tags, err := db.AddOrGetTags(request.Tags)
if err != nil {
zap.S().Error("Failed to add or get tag to / from database: %v", err)
DatabaseError.Send(w)
return
}
if err = db.AddArticle(database.Article{
Name: request.Name,
Title: request.Title,
Summary: request.Summary,
Image: request.Image,
Added: time.Now().Unix(),
Markdown: request.Content,
Html: string(parse.ParseToHtml(rawMarkdown)),
}, tags); err != nil {
zap.S().Errorf("Failed to add article to database: %v", err)
DatabaseError.Send(w)
var notFound []string
database.GetDB().Select("* FROM ? EXCEPT ?", payload.Authors, database.GetDB().Table("author").Select("id")).Find(&notFound)
if len(notFound) > 0 {
ApiError{fmt.Sprintf("no authors with the id(s) %s were found", strings.Join(notFound, ", ")), http.StatusUnprocessableEntity}.Send(w)
return
}
w.WriteHeader(http.StatusOK)
a := article{
Title: payload.Title,
Summary: payload.Summary,
Image: payload.Image,
Created: time.Now().Unix(),
Modified: time.Unix(0, 0).Unix(),
Link: "/" + path.Join(config.Prefix, "article", payload.Link),
Markdown: string(rawMarkdown),
Html: string(markdown.ToHTML(rawMarkdown, nil, nil)),
}
database.GetDB().Table("article").Create(&a)
var authors []map[string]interface{}
for _, author := range append([]int{authorId}, payload.Authors...) {
authors = append(authors, map[string]interface{}{
"article_id": a.ID,
"author_id": author,
})
}
database.GetDB().Table("article_author").Create(&authors)
var tags []map[string]interface{}
for _, tag := range payload.Tags {
authors = append(authors, map[string]interface{}{
"article_id": a.ID,
"tag": tag,
})
}
database.GetDB().Table("article_tag").Create(&tags)
var articleSummary schema.ArticleSummary
database.GetDB().Table("article").Find(&articleSummary, &a.ID)
database.GetDB().Table("author").Where("id IN (?)", database.GetDB().Table("article_author").Select("author_id").Where("article_id = ?", a.ID)).Find(&articleSummary.Authors)
if payload.Tags != nil {
articleSummary.Tags = payload.Tags
} else {
articleSummary.Tags = []string{}
}
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(articleSummary)
}