mirror of
https://github.com/Unkn0wnCat/matrix-veles.git
synced 2025-05-07 06:06:30 +02:00
Add list API endpoints
This commit is contained in:
parent
1e071ffed4
commit
c572bbce85
5 changed files with 275 additions and 2 deletions
|
@ -91,8 +91,6 @@ func GetEntries(first int64, cursor *primitive.ObjectID) ([]*model.DBEntry, erro
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("DBG1")
|
|
||||||
|
|
||||||
return object, nil
|
return object, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,6 +142,57 @@ func GetListByID(id primitive.ObjectID) (*model.DBHashList, error) {
|
||||||
return &object, nil
|
return &object, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetListByName(name string) (*model.DBHashList, error) {
|
||||||
|
db := DbClient.Database(viper.GetString("bot.mongo.database"))
|
||||||
|
|
||||||
|
res := db.Collection(viper.GetString("bot.mongo.collection.lists")).FindOne(context.TODO(), bson.D{{"name", name}})
|
||||||
|
if res.Err() != nil {
|
||||||
|
return nil, res.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
object := model.DBHashList{}
|
||||||
|
|
||||||
|
err := res.Decode(&object)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &object, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLists(first int64, cursor *primitive.ObjectID) ([]*model.DBHashList, error) {
|
||||||
|
db := DbClient.Database(viper.GetString("bot.mongo.database"))
|
||||||
|
|
||||||
|
opts := options.FindOptions{
|
||||||
|
Limit: &first,
|
||||||
|
}
|
||||||
|
|
||||||
|
filter := bson.M{}
|
||||||
|
|
||||||
|
if cursor != nil {
|
||||||
|
filter = bson.M{
|
||||||
|
"_id": bson.M{
|
||||||
|
"$gt": *cursor,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
log.Println(filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := db.Collection(viper.GetString("bot.mongo.collection.lists")).Find(context.TODO(), filter, &opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, res.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
var object []*model.DBHashList
|
||||||
|
|
||||||
|
err = res.All(context.TODO(), &object)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return object, nil
|
||||||
|
}
|
||||||
|
|
||||||
func SaveUser(user *model.DBUser) error {
|
func SaveUser(user *model.DBUser) error {
|
||||||
db := DbClient.Database(viper.GetString("bot.mongo.database"))
|
db := DbClient.Database(viper.GetString("bot.mongo.database"))
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import "go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
|
||||||
type DBHashList struct {
|
type DBHashList struct {
|
||||||
ID primitive.ObjectID `bson:"_id" json:"id"`
|
ID primitive.ObjectID `bson:"_id" json:"id"`
|
||||||
|
Name string `bson:"name" json:"name"`
|
||||||
Tags []string `bson:"tags" json:"tags"` // Tags of this list for discovery, and sorting
|
Tags []string `bson:"tags" json:"tags"` // Tags of this list for discovery, and sorting
|
||||||
Comments []*DBComment `bson:"comments" json:"comments"` // Comments regarding this list
|
Comments []*DBComment `bson:"comments" json:"comments"` // Comments regarding this list
|
||||||
Maintainers []*primitive.ObjectID `bson:"maintainers" json:"maintainers"` // Maintainers contains references to the users who may edit this list
|
Maintainers []*primitive.ObjectID `bson:"maintainers" json:"maintainers"` // Maintainers contains references to the users who may edit this list
|
||||||
|
|
|
@ -12,6 +12,8 @@ type DBUser struct {
|
||||||
Username string `bson:"username" json:"username"` // Username is the username the user has
|
Username string `bson:"username" json:"username"` // Username is the username the user has
|
||||||
HashedPassword string `bson:"password" json:"password"` // HashedPassword contains the bcrypt-ed password
|
HashedPassword string `bson:"password" json:"password"` // HashedPassword contains the bcrypt-ed password
|
||||||
|
|
||||||
|
Admin *bool `bson:"admin,omitempty" json:"admin,omitempty"` // If set to true this user will have all privileges
|
||||||
|
|
||||||
MatrixLinks []*string `bson:"matrix_links" json:"matrix_links"` // MatrixLinks is the matrix-users this user has verified ownership over
|
MatrixLinks []*string `bson:"matrix_links" json:"matrix_links"` // MatrixLinks is the matrix-users this user has verified ownership over
|
||||||
PendingMatrixLinks []*string `bson:"pending_matrix_links" json:"pending_matrix_links"` // PendingMatrixLinks is the matrix-users pending verification
|
PendingMatrixLinks []*string `bson:"pending_matrix_links" json:"pending_matrix_links"` // PendingMatrixLinks is the matrix-users pending verification
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,16 @@ func SetupAPI() chi.Router {
|
||||||
r.Get("/{id}", apiHandleBotEntry)
|
r.Get("/{id}", apiHandleBotEntry)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
router.Route("/lists", func(r chi.Router) {
|
||||||
|
r.Use(checkAuthMiddleware)
|
||||||
|
|
||||||
|
r.Get("/", apiHandleBotListsList)
|
||||||
|
r.Post("/", apiHandleBotListsPost)
|
||||||
|
|
||||||
|
r.Get("/by-name/{name}", apiHandleBotListByName)
|
||||||
|
r.Get("/{id}", apiHandleBotList)
|
||||||
|
})
|
||||||
|
|
||||||
router.Route("/test", func(r chi.Router) {
|
router.Route("/test", func(r chi.Router) {
|
||||||
r.Use(checkAuthMiddleware)
|
r.Use(checkAuthMiddleware)
|
||||||
|
|
||||||
|
|
211
internal/web/api/bot_lists.go
Normal file
211
internal/web/api/bot_lists.go
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
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 apiListPostBody struct {
|
||||||
|
Name string
|
||||||
|
Tags []string
|
||||||
|
Comment *string
|
||||||
|
Maintainers []*primitive.ObjectID
|
||||||
|
}
|
||||||
|
|
||||||
|
func apiHandleBotListsPost(res http.ResponseWriter, req *http.Request) {
|
||||||
|
var body apiListPostBody
|
||||||
|
|
||||||
|
err := json.NewDecoder(req.Body).Decode(&body)
|
||||||
|
if err != nil {
|
||||||
|
writeJSONError(res, http.StatusBadRequest, errors.New("malformed body"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
existingEntry, err := db.GetListByName(body.Name)
|
||||||
|
if err == nil {
|
||||||
|
writeJSONError(res, http.StatusConflict, fmt.Errorf("name taken: %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
|
||||||
|
}
|
||||||
|
|
||||||
|
newList := model.DBHashList{
|
||||||
|
ID: primitive.NewObjectID(),
|
||||||
|
Name: body.Name,
|
||||||
|
Tags: body.Tags,
|
||||||
|
Comments: nil,
|
||||||
|
Maintainers: body.Maintainers,
|
||||||
|
}
|
||||||
|
|
||||||
|
listedSelf := false
|
||||||
|
|
||||||
|
for _, maintainer := range newList.Maintainers {
|
||||||
|
if maintainer.Hex() == userId.Hex() {
|
||||||
|
listedSelf = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !listedSelf {
|
||||||
|
newList.Maintainers = append(newList.Maintainers, &userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if body.Comment != nil && *body.Comment != "" {
|
||||||
|
newList.Comments = append(newList.Comments, &model.DBComment{
|
||||||
|
CommentedBy: &userId,
|
||||||
|
Content: *body.Comment,
|
||||||
|
Timestamp: time.Now(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
err = db.SaveList(&newList)
|
||||||
|
if err != nil {
|
||||||
|
// TODO: LOG THIS ERROR
|
||||||
|
writeJSONError(res, http.StatusInternalServerError, errors.New("database error"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
encoded, err := json.Marshal(newList)
|
||||||
|
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 apiHandleBotListsList(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.GetLists(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 apiHandleBotList(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.GetListByID(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 apiHandleBotListByName(res http.ResponseWriter, req *http.Request) {
|
||||||
|
requestedName := chi.URLParam(req, "name")
|
||||||
|
|
||||||
|
entry, err := db.GetListByName(requestedName)
|
||||||
|
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
Reference in a new issue