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

129
api/edit.go Normal file
View File

@@ -0,0 +1,129 @@
package api
import (
"TheAdversary/config"
"TheAdversary/database"
"TheAdversary/schema"
"encoding/base64"
"encoding/json"
"fmt"
"github.com/gomarkdown/markdown"
"go.uber.org/zap"
"net/http"
"path"
"strings"
"time"
)
type editPayload struct {
Id int `json:"id"`
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 Edit(w http.ResponseWriter, r *http.Request) {
authorId, ok := authorizedSession(r)
if !ok {
w.WriteHeader(http.StatusUnauthorized)
return
}
var payload editPayload
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
InvalidJson.Send(w)
return
}
if !database.Exists(database.GetDB().Table("article"), "id = ?", payload.Id) {
w.WriteHeader(http.StatusNotFound)
return
} else if !database.Exists(database.GetDB().Table("article_author"), "article_id = ? AND author_id = ?", payload.Id, authorId) {
w.WriteHeader(http.StatusUnauthorized)
return
}
updates := map[string]interface{}{}
var authorUpdates, tagUpdates []map[string]interface{}
a := article{
ID: payload.Id,
Modified: time.Now().Unix(),
}
if payload.Title != nil {
updates["title"] = *payload.Title
}
if payload.Summary != nil {
updates["summary"] = *payload.Summary
}
if payload.Authors != nil {
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
}
for _, author := range append([]int{authorId}, *payload.Authors...) {
authorUpdates = append(authorUpdates, map[string]interface{}{
"article_id": payload.Id,
"author_id": author,
})
}
}
if payload.Tags != nil {
for _, tag := range *payload.Tags {
tagUpdates = append(tagUpdates, map[string]interface{}{
"article_id": payload.Id,
"tag": tag,
})
}
}
if payload.Image != nil {
updates["image"] = *payload.Image
}
if payload.Link != nil {
updates["link"] = path.Join(config.Prefix, "article", *payload.Link)
}
if payload.Content != nil {
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
}
a.Markdown = string(rawMarkdown)
a.Html = string(markdown.ToHTML(rawMarkdown, nil, nil))
updates["markdown"] = string(rawMarkdown)
updates["html"] = string(markdown.ToHTML(rawMarkdown, nil, nil))
}
if len(updates) > 0 {
updates["modified"] = time.Now().Unix()
database.GetDB().Table("article").Where("id = ?", payload.Id).Updates(&updates)
if authorUpdates != nil {
database.GetDB().Table("article_author").Where("article_id = ?", payload.Id).Delete(nil)
database.GetDB().Table("article_author").Create(&authorUpdates)
}
if tagUpdates != nil {
database.GetDB().Table("article_tag").Where("article_id = ?", payload.Id).Delete(nil)
database.GetDB().Table("article_tag").Create(&tagUpdates)
}
}
var articleSummary schema.ArticleSummary
database.GetDB().Table("article").Find(&articleSummary, payload.Id)
database.GetDB().Table("author").Where("id IN (?)", database.GetDB().Table("article_author").Select("author_id").Where("article_id = ?", payload.Id)).Find(&articleSummary.Authors)
if payload.Tags != nil {
articleSummary.Tags = *payload.Tags
} else {
articleSummary.Tags = []string{}
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(articleSummary)
}