mirror of
https://github.com/Unkn0wnCat/matrix-veles.git
synced 2025-05-18 11:26:34 +02:00
Add entry API endpoints
This commit is contained in:
parent
c8d1c33cb4
commit
1e071ffed4
8 changed files with 325 additions and 31 deletions
230
internal/web/api/bot_entries.go
Normal file
230
internal/web/api/bot_entries.go
Normal file
|
@ -0,0 +1,230 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/Unkn0wnCat/matrix-veles/internal/db"
|
||||
"github.com/Unkn0wnCat/matrix-veles/internal/db/model"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type apiEntryPostBody struct {
|
||||
Hash string `json:"hash"`
|
||||
Tags []string `json:"tags"`
|
||||
PartOf []*primitive.ObjectID `json:"part_of"`
|
||||
FileURL string `json:"file_url"`
|
||||
Comment *string `json:"comment"`
|
||||
}
|
||||
|
||||
func apiHandleBotEntriesPost(res http.ResponseWriter, req *http.Request) {
|
||||
var body apiEntryPostBody
|
||||
|
||||
err := json.NewDecoder(req.Body).Decode(&body)
|
||||
if err != nil {
|
||||
writeJSONError(res, http.StatusBadRequest, errors.New("malformed body"))
|
||||
return
|
||||
}
|
||||
|
||||
existingEntry, err := db.GetEntryByHash(body.Hash)
|
||||
if err == nil {
|
||||
writeJSONError(res, http.StatusConflict, fmt.Errorf("hash already in database: %s", existingEntry.ID))
|
||||
return
|
||||
}
|
||||
if !errors.Is(err, mongo.ErrNoDocuments) {
|
||||
// TODO: LOG THIS ERROR
|
||||
writeJSONError(res, http.StatusInternalServerError, errors.New("database error"))
|
||||
return
|
||||
}
|
||||
|
||||
user := getClaims(req)
|
||||
userId, err := primitive.ObjectIDFromHex(user.Subject)
|
||||
if err != nil {
|
||||
// TODO: LOG THIS ERROR
|
||||
log.Println(userId)
|
||||
writeJSONError(res, http.StatusInternalServerError, errors.New("internal corruption 0x01"))
|
||||
return
|
||||
}
|
||||
|
||||
for i, partOf := range body.PartOf {
|
||||
list, err := db.GetListByID(*partOf)
|
||||
if err != nil {
|
||||
if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
writeJSONError(res, http.StatusNotFound, fmt.Errorf("invalid partof value at index %d - not found", i))
|
||||
return
|
||||
}
|
||||
// TODO: LOG THIS ERROR
|
||||
writeJSONError(res, http.StatusInternalServerError, errors.New("database error"))
|
||||
return
|
||||
}
|
||||
|
||||
authorized := false
|
||||
|
||||
for _, maintainer := range list.Maintainers {
|
||||
log.Println(maintainer, userId)
|
||||
if maintainer.Hex() == userId.Hex() {
|
||||
authorized = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !authorized {
|
||||
writeJSONError(res, http.StatusUnauthorized, fmt.Errorf("invalid partof value at index %d - not authorized", i))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
newEntry := model.DBEntry{
|
||||
ID: primitive.NewObjectID(),
|
||||
Tags: body.Tags,
|
||||
PartOf: body.PartOf,
|
||||
HashValue: body.Hash,
|
||||
FileURL: body.FileURL,
|
||||
Timestamp: time.Now(),
|
||||
AddedBy: &userId,
|
||||
Comments: nil,
|
||||
}
|
||||
|
||||
if body.Comment != nil && *body.Comment != "" {
|
||||
newEntry.Comments = append(newEntry.Comments, &model.DBComment{
|
||||
CommentedBy: &userId,
|
||||
Content: *body.Comment,
|
||||
Timestamp: time.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
err = db.SaveEntry(&newEntry)
|
||||
if err != nil {
|
||||
// TODO: LOG THIS ERROR
|
||||
writeJSONError(res, http.StatusInternalServerError, errors.New("database error"))
|
||||
return
|
||||
}
|
||||
|
||||
encoded, err := json.Marshal(newEntry)
|
||||
if err != nil {
|
||||
// TODO: LOG THIS ERROR
|
||||
writeJSONError(res, http.StatusInternalServerError, errors.New("could not marshal data"))
|
||||
return
|
||||
}
|
||||
|
||||
res.Header().Set("Content-Type", "application/json")
|
||||
res.WriteHeader(http.StatusOK)
|
||||
res.Write(encoded)
|
||||
}
|
||||
|
||||
func apiHandleBotEntriesList(res http.ResponseWriter, req *http.Request) {
|
||||
requestUri, err := url.ParseRequestURI(req.RequestURI)
|
||||
if err != nil {
|
||||
writeJSONError(res, http.StatusBadRequest, errors.New("unable to parse uri"))
|
||||
return
|
||||
}
|
||||
|
||||
first := int64(50)
|
||||
var cursor *primitive.ObjectID
|
||||
|
||||
if requestUri.Query().Has("first") {
|
||||
first2, err := strconv.Atoi(requestUri.Query().Get("first"))
|
||||
if err != nil {
|
||||
writeJSONError(res, http.StatusBadRequest, errors.New("malformed query"))
|
||||
return
|
||||
}
|
||||
first = int64(first2)
|
||||
}
|
||||
|
||||
if requestUri.Query().Has("cursor") {
|
||||
cursor2, err := primitive.ObjectIDFromHex(requestUri.Query().Get("cursor"))
|
||||
if err != nil {
|
||||
writeJSONError(res, http.StatusBadRequest, errors.New("malformed query"))
|
||||
return
|
||||
}
|
||||
cursor = &cursor2
|
||||
}
|
||||
|
||||
entries, err := db.GetEntries(first, cursor)
|
||||
if err != nil {
|
||||
if !errors.Is(err, mongo.ErrNoDocuments) {
|
||||
// TODO: LOG THIS ERROR
|
||||
writeJSONError(res, http.StatusInternalServerError, errors.New("database error"))
|
||||
return
|
||||
}
|
||||
res.Header().Set("Content-Type", "application/json")
|
||||
res.WriteHeader(http.StatusOK)
|
||||
res.Write([]byte("[]"))
|
||||
return
|
||||
}
|
||||
|
||||
encoded, err := json.Marshal(entries)
|
||||
if err != nil {
|
||||
// TODO: LOG THIS ERROR
|
||||
writeJSONError(res, http.StatusInternalServerError, errors.New("could not marshal data"))
|
||||
return
|
||||
}
|
||||
|
||||
res.Header().Set("Content-Type", "application/json")
|
||||
res.WriteHeader(http.StatusOK)
|
||||
res.Write(encoded)
|
||||
}
|
||||
|
||||
func apiHandleBotEntry(res http.ResponseWriter, req *http.Request) {
|
||||
requestedId := chi.URLParam(req, "id")
|
||||
objectId, err := primitive.ObjectIDFromHex(requestedId)
|
||||
if err != nil {
|
||||
writeJSONError(res, http.StatusNotFound, errors.New("malformed id"))
|
||||
return
|
||||
}
|
||||
|
||||
entry, err := db.GetEntryByID(objectId)
|
||||
if err != nil {
|
||||
if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
writeJSONError(res, http.StatusNotFound, errors.New("not found"))
|
||||
return
|
||||
}
|
||||
// TODO: LOG THIS ERROR
|
||||
writeJSONError(res, http.StatusInternalServerError, errors.New("database error"))
|
||||
return
|
||||
}
|
||||
|
||||
encoded, err := json.Marshal(entry)
|
||||
if err != nil {
|
||||
// TODO: LOG THIS ERROR
|
||||
writeJSONError(res, http.StatusInternalServerError, errors.New("could not marshal data"))
|
||||
return
|
||||
}
|
||||
|
||||
res.Header().Set("Content-Type", "application/json")
|
||||
res.WriteHeader(http.StatusOK)
|
||||
res.Write(encoded)
|
||||
}
|
||||
|
||||
func apiHandleBotEntryByHash(res http.ResponseWriter, req *http.Request) {
|
||||
requestedHash := chi.URLParam(req, "hash")
|
||||
|
||||
entry, err := db.GetEntryByHash(requestedHash)
|
||||
if err != nil {
|
||||
if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
writeJSONError(res, http.StatusNotFound, errors.New("not found"))
|
||||
return
|
||||
}
|
||||
// TODO: LOG THIS ERROR
|
||||
writeJSONError(res, http.StatusInternalServerError, errors.New("database error"))
|
||||
return
|
||||
}
|
||||
|
||||
encoded, err := json.Marshal(entry)
|
||||
if err != nil {
|
||||
// TODO: LOG THIS ERROR
|
||||
writeJSONError(res, http.StatusInternalServerError, errors.New("could not marshal data"))
|
||||
return
|
||||
}
|
||||
|
||||
res.Header().Set("Content-Type", "application/json")
|
||||
res.WriteHeader(http.StatusOK)
|
||||
res.Write(encoded)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue