feat: initial commit
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/FernandoVideira/LK_API_Temp/internal/store"
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
type postKey string
|
||||
|
||||
const postCtx postKey = "post"
|
||||
|
||||
type CreatePostPayload struct {
|
||||
Title string `json:"title" validate:"required,max=100"`
|
||||
Content string `json:"content" validate:"required,max=1000"`
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
// CreatePost godoc
|
||||
//
|
||||
// @Summary Creates a new Post
|
||||
// @Description Creates a new Post
|
||||
// @Tags posts
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param in body CreatePostPayload true "Post Payload"
|
||||
// @Success 200 {object} store.Post
|
||||
// @Failure 400 {object} error
|
||||
// @Failure 404 {object} error
|
||||
// @Failure 500 {object} error
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /posts [post]
|
||||
func (api *api) createPostHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var payload CreatePostPayload
|
||||
if err := readJSON(w, r, &payload); err != nil {
|
||||
api.badRequestError(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := Validate.Struct(payload); err != nil {
|
||||
api.badRequestError(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
user := getUserFromContext(r)
|
||||
|
||||
post := &store.Post{
|
||||
UserID: user.ID,
|
||||
Title: payload.Title,
|
||||
Content: payload.Content,
|
||||
Tags: payload.Tags,
|
||||
}
|
||||
|
||||
ctx := r.Context()
|
||||
|
||||
if err := api.store.Posts.Create(ctx, post); err != nil {
|
||||
api.internalServerError(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := api.jsonResponse(w, http.StatusCreated, post); err != nil {
|
||||
api.internalServerError(w, r, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// GetPost godoc
|
||||
//
|
||||
// @Summary Fetches a Post
|
||||
// @Description Fetches a Post by ID
|
||||
// @Tags posts
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "Post ID"
|
||||
// @Success 200 {object} store.Post
|
||||
// @Failure 400 {object} error
|
||||
// @Failure 404 {object} error
|
||||
// @Failure 500 {object} error
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /posts/{id} [get]
|
||||
func (api *api) getPostHandler(w http.ResponseWriter, r *http.Request) {
|
||||
post := getPostFromContext(r)
|
||||
|
||||
comments, err := api.store.Comments.GetByPostID(r.Context(), post.ID)
|
||||
if err != nil {
|
||||
api.internalServerError(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
post.Comments = comments
|
||||
|
||||
if err := api.jsonResponse(w, http.StatusOK, post); err != nil {
|
||||
api.internalServerError(w, r, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
type UpdatePostPayload struct {
|
||||
Title *string `json:"title" validate:"omitempty,max=100"`
|
||||
Content *string `json:"content" validate:"omitempty,max=1000"`
|
||||
}
|
||||
|
||||
// UpdatePost godoc
|
||||
//
|
||||
// @Summary Update a Post
|
||||
// @Description Update a Post by ID
|
||||
// @Tags posts
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "Post ID"
|
||||
// @Param in body UpdatePostPayload true "Post Payload"
|
||||
// @Success 200 {object} store.Post
|
||||
// @Failure 400 {object} error
|
||||
// @Failure 404 {object} error
|
||||
// @Failure 500 {object} error
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /posts/{id} [patch]
|
||||
func (api *api) updatePostHandler(w http.ResponseWriter, r *http.Request) {
|
||||
post := getPostFromContext(r)
|
||||
|
||||
var payload UpdatePostPayload
|
||||
if err := readJSON(w, r, &payload); err != nil {
|
||||
api.badRequestError(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := Validate.Struct(payload); err != nil {
|
||||
api.badRequestError(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
if payload.Content != nil {
|
||||
post.Content = *payload.Content
|
||||
}
|
||||
|
||||
if payload.Title != nil {
|
||||
post.Title = *payload.Title
|
||||
}
|
||||
|
||||
if err := api.store.Posts.Update(r.Context(), post); err != nil {
|
||||
switch {
|
||||
case errors.Is(err, store.ErrNotFound):
|
||||
api.conflictError(w, r, err)
|
||||
default:
|
||||
api.internalServerError(w, r, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := api.jsonResponse(w, http.StatusOK, post); err != nil {
|
||||
api.internalServerError(w, r, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// DeletePost godoc
|
||||
//
|
||||
// @Summary Deletes a Post
|
||||
// @Description Deletse a Post by ID
|
||||
// @Tags posts
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "Post ID"
|
||||
// @Success 204 {object} string
|
||||
// @Failure 404 {object} error
|
||||
// @Failure 500 {object} error
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /posts/{id} [delete]
|
||||
func (api *api) deletePostHandler(w http.ResponseWriter, r *http.Request) {
|
||||
idParam := chi.URLParam(r, "id")
|
||||
id, err := strconv.ParseInt(idParam, 10, 64)
|
||||
if err != nil {
|
||||
api.badRequestError(w, r, err)
|
||||
return
|
||||
}
|
||||
ctx := r.Context()
|
||||
|
||||
if err := api.store.Posts.Delete(ctx, id); err != nil {
|
||||
switch {
|
||||
case errors.Is(err, store.ErrNotFound):
|
||||
api.notFoundError(w, r, err)
|
||||
default:
|
||||
api.internalServerError(w, r, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func getPostFromContext(r *http.Request) *store.Post {
|
||||
post, _ := r.Context().Value(postCtx).(*store.Post)
|
||||
return post
|
||||
}
|
||||
Reference in New Issue
Block a user