Splat handler in their own files, added pagination

This commit is contained in:
Florian Sylvain
2023-01-18 23:33:34 +01:00
parent c681b5389c
commit 3376d88f56
7 changed files with 185 additions and 99 deletions
+7 -1
View File
@@ -6,6 +6,8 @@ The features are not complete, not tested and subject to many changes.
## Setup ## Setup
Don't forget to setup the [Environment variables](#environment-variables)!
### Use with Docker ### Use with Docker
To **run** the app, run the command To **run** the app, run the command
@@ -18,7 +20,7 @@ docker-compose up
TODO TODO
## Environment variables ### Environment variables
- ./env - ./env
- APP_API_ADDRESS: `http://example.com` - APP_API_ADDRESS: `http://example.com`
@@ -29,6 +31,10 @@ TODO
- APP_FRONT_PORT: `1234` - APP_FRONT_PORT: `1234`
- APP_JWT_SECRET: `secret` - APP_JWT_SECRET: `secret`
## API Usage
TODO
## Demo ## Demo
TODO TODO
+5 -5
View File
@@ -63,11 +63,11 @@ func initArticlesRoutes(r *gin.RouterGroup) {
articlesRouter := r.Group("/articles") articlesRouter := r.Group("/articles")
articlesRouter.Use(corsMiddleware, api.AuthMiddleware.MiddlewareFunc()) articlesRouter.Use(corsMiddleware, api.AuthMiddleware.MiddlewareFunc())
articlesRouter.GET("/", articles.GetArticleHandler) articlesRouter.GET("/", articles.Get)
articlesRouter.GET("/:id", articles.GetArticleHandler) articlesRouter.GET("/:id", articles.Get)
articlesRouter.POST("/:id", articles.AddArticleHandler) articlesRouter.POST("/:id", articles.Add)
articlesRouter.PUT("/:id", articles.EditArticleHandler) articlesRouter.PUT("/:id", articles.Edit)
articlesRouter.DELETE("/:id", articles.DeleteArticleHandler) articlesRouter.DELETE("/:id", articles.Delete)
} }
func initGin() { func initGin() {
+39
View File
@@ -0,0 +1,39 @@
package articles
import (
"fmt"
"github.com/Floriansylvain/GohCMS/internal/api"
"github.com/Floriansylvain/GohCMS/internal/database"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson"
)
func Add(c *gin.Context) {
var article Article
article.TitleID = c.Params.ByName("id")
if c.BindJSON(&article) != nil {
api.SendBadRequest(c, "Could not correctly parse the article.")
return
}
document, err := bson.Marshal(article)
if err != nil {
api.SendBadRequest(c, "Could not correctly marshal the article.")
return
}
documents, _ := database.GetDocuments(articlesLocation, map[string]any{})
if IsArticleIdAlreadyUsed(article.TitleID, documents) {
api.SendBadRequest(c, fmt.Sprintf("Article ID '%v' already used.", article.TitleID))
return
}
err = database.PushDocument(articlesLocation, document)
if err != nil {
api.SendBadRequest(c, fmt.Sprintf(`Could not insert document(s) into DB: %v`, err.Error()))
return
}
api.SendOk(c, "Article successfully added!")
}
+25
View File
@@ -0,0 +1,25 @@
package articles
import (
"fmt"
"github.com/Floriansylvain/GohCMS/internal/api"
"github.com/Floriansylvain/GohCMS/internal/database"
"github.com/gin-gonic/gin"
)
func Delete(c *gin.Context) {
id := c.Params.ByName("id")
deleteCount, err := database.DeleteDocument(articlesLocation, map[string]any{"titleID": id})
if err != nil {
api.SendBadRequest(c, fmt.Sprintf(`Could not delete document(s) from DB: %v`, err.Error()))
return
}
if deleteCount != 0 {
api.SendOk(c, fmt.Sprintf("%d article(s) was/were successfully deleted!", deleteCount))
} else {
api.SendOk(c, "No articles were deleted.")
}
}
+29
View File
@@ -0,0 +1,29 @@
package articles
import (
"fmt"
"github.com/Floriansylvain/GohCMS/internal/api"
"github.com/Floriansylvain/GohCMS/internal/database"
"github.com/gin-gonic/gin"
)
func Edit(c *gin.Context) {
id := c.Params.ByName("id")
var articleUpdate database.DocumentUpdate
articleUpdate.Filter = map[string]any{"titleID": id}
c.BindJSON(&articleUpdate.Update)
editCount, err := database.EditDocument(articlesLocation, articleUpdate)
if err != nil {
api.SendBadRequest(c, fmt.Sprintf(`Could not edit document(s) from DB: %v`, err.Error()))
return
}
if editCount != 0 {
api.SendOk(c, fmt.Sprintf("%d article(s) was/were successfully edited!", editCount))
} else {
api.SendOk(c, "No articles were edited.")
}
}
+80
View File
@@ -0,0 +1,80 @@
package articles
import (
"fmt"
"net/http"
"os"
"strconv"
"github.com/Floriansylvain/GohCMS/internal/api"
"github.com/Floriansylvain/GohCMS/internal/database"
"github.com/gin-gonic/gin"
)
func getApiFullUrl() string {
return fmt.Sprintf("%v%v", os.Getenv("APP_API_ADDRESS"), os.Getenv("APP_BASE_API_PATH"))
}
func getArticleSkipTakeFullUrl(skip uint64, take uint64) string {
return fmt.Sprintf("%v/articles?skip=%v&take=%v", getApiFullUrl(), skip+take, take)
}
func getBuiltGetResponse(articles []Article, skip uint64, take uint64) map[string]any {
slicedArticles := articles[skip : skip+take]
return map[string]any{
"content": slicedArticles,
"total": len(slicedArticles),
"pagination": map[string]any{
"skip": skip,
"take": take,
"links": map[string]any{
"next": getArticleSkipTakeFullUrl(skip+take, take),
"previous": getArticleSkipTakeFullUrl(skip-take, take),
},
},
}
}
func parseUintQueryParam(c *gin.Context, param string) (uint64, error) {
value, err := strconv.ParseUint(c.Query(param), 10, 0)
if err != nil {
c.JSON(http.StatusBadRequest, fmt.Sprintf("%s query parameter must be a positive number.", param))
}
return value, err
}
func getArticleIdFilter(titleID string) map[string]any {
filter := map[string]any{}
if titleID != "" {
filter["titleID"] = titleID
}
return filter
}
func Get(c *gin.Context) {
titleID := c.Params.ByName("id")
skip, skipErr := parseUintQueryParam(c, "skip")
take, takeErr := parseUintQueryParam(c, "take")
if skipErr != nil || takeErr != nil {
return
}
articles, err := database.GetDocuments(articlesLocation, getArticleIdFilter(titleID))
if err != nil {
api.SendBadRequest(c, fmt.Sprintf("The ID '%v' doesn't match any article.", titleID))
return
}
articlesArray := ParseArticlesFromBytesToArray(articles)
articlesArrayLength := uint64(len(articlesArray))
if skip >= articlesArrayLength || take == 0 {
c.JSON(http.StatusOK, map[string]any{
"content": []string{},
"total": "0",
})
return
}
c.JSON(http.StatusOK, getBuiltGetResponse(articlesArray, skip, take))
}
-93
View File
@@ -1,93 +0,0 @@
package articles
import (
"fmt"
"net/http"
"github.com/Floriansylvain/GohCMS/internal/api"
"github.com/Floriansylvain/GohCMS/internal/database"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson"
)
func GetArticleHandler(c *gin.Context) {
articleID := c.Params.ByName("id")
filter := gin.H{}
if articleID != "" {
filter["titleID"] = articleID
}
articles, err := database.GetDocuments(articlesLocation, filter)
if err != nil {
api.SendBadRequest(c, fmt.Sprintf("The ID '%v' doesn't match any article.", articleID))
return
}
c.JSON(http.StatusOK, ParseArticlesFromBytesToArray(articles))
}
func AddArticleHandler(c *gin.Context) {
var article Article
article.TitleID = c.Params.ByName("id")
if c.BindJSON(&article) != nil {
api.SendBadRequest(c, "Could not correctly parse the article.")
return
}
document, err := bson.Marshal(article)
if err != nil {
api.SendBadRequest(c, "Could not correctly marshal the article.")
return
}
documents, _ := database.GetDocuments(articlesLocation, gin.H{})
if IsArticleIdAlreadyUsed(article.TitleID, documents) {
api.SendBadRequest(c, fmt.Sprintf("Article ID '%v' already used.", article.TitleID))
return
}
err = database.PushDocument(articlesLocation, document)
if err != nil {
api.SendBadRequest(c, fmt.Sprintf(`Could not insert document(s) into DB: %v`, err.Error()))
return
}
api.SendOk(c, "Article successfully added!")
}
func DeleteArticleHandler(c *gin.Context) {
id := c.Params.ByName("id")
deleteCount, err := database.DeleteDocument(articlesLocation, gin.H{"titleID": id})
if err != nil {
api.SendBadRequest(c, fmt.Sprintf(`Could not delete document(s) from DB: %v`, err.Error()))
return
}
if deleteCount != 0 {
api.SendOk(c, fmt.Sprintf("%d article(s) was/were successfully deleted!", deleteCount))
} else {
api.SendOk(c, "No articles were deleted.")
}
}
func EditArticleHandler(c *gin.Context) {
id := c.Params.ByName("id")
var articleUpdate database.DocumentUpdate
articleUpdate.Filter = gin.H{"titleID": id}
c.BindJSON(&articleUpdate.Update)
editCount, err := database.EditDocument(articlesLocation, articleUpdate)
if err != nil {
api.SendBadRequest(c, fmt.Sprintf(`Could not edit document(s) from DB: %v`, err.Error()))
return
}
if editCount != 0 {
api.SendOk(c, fmt.Sprintf("%d article(s) was/were successfully edited!", editCount))
} else {
api.SendOk(c, "No articles were edited.")
}
}