feat: update methods to use validated DTOs and update MountRoutes
This commit is contained in:
@@ -115,32 +115,9 @@ func (h *PostHandler) GetPost(w http.ResponseWriter, r *http.Request) {
|
|||||||
// @Failure 500 {object} PostResponse "Internal server error"
|
// @Failure 500 {object} PostResponse "Internal server error"
|
||||||
// @Router /api/posts [post]
|
// @Router /api/posts [post]
|
||||||
func (h *PostHandler) CreatePost(w http.ResponseWriter, r *http.Request) {
|
func (h *PostHandler) CreatePost(w http.ResponseWriter, r *http.Request) {
|
||||||
var req struct {
|
req, ok := GetValidatedDTO[dto.CreatePostRequest](r)
|
||||||
Title string `json:"title"`
|
if !ok {
|
||||||
URL string `json:"url"`
|
SendErrorResponse(w, "Invalid request", http.StatusBadRequest)
|
||||||
Content string `json:"content"`
|
|
||||||
}
|
|
||||||
|
|
||||||
if !DecodeJSONRequest(w, r, &req) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Title = security.SanitizeInput(req.Title)
|
|
||||||
req.URL = security.SanitizeURL(req.URL)
|
|
||||||
req.Content = security.SanitizePostContent(req.Content)
|
|
||||||
|
|
||||||
if req.URL == "" {
|
|
||||||
SendErrorResponse(w, "URL is required", http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(req.Title) > 200 {
|
|
||||||
SendErrorResponse(w, "Title must be no more than 200 characters", http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(req.Content) > 10000 {
|
|
||||||
SendErrorResponse(w, "Content must be no more than 10,000 characters", http.StatusBadRequest)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,13 +126,15 @@ func (h *PostHandler) CreatePost(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
title := req.Title
|
title := security.SanitizeInput(req.Title)
|
||||||
|
url := security.SanitizeURL(req.URL)
|
||||||
|
content := security.SanitizePostContent(req.Content)
|
||||||
|
|
||||||
if title == "" && h.titleFetcher != nil {
|
if title == "" && h.titleFetcher != nil {
|
||||||
titleCtx, cancel := context.WithTimeout(r.Context(), 7*time.Second)
|
titleCtx, cancel := context.WithTimeout(r.Context(), 7*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
fetchedTitle, err := h.titleFetcher.FetchTitle(titleCtx, req.URL)
|
fetchedTitle, err := h.titleFetcher.FetchTitle(titleCtx, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch {
|
switch {
|
||||||
case errors.Is(err, services.ErrUnsupportedScheme):
|
case errors.Is(err, services.ErrUnsupportedScheme):
|
||||||
@@ -183,8 +162,8 @@ func (h *PostHandler) CreatePost(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
post := &database.Post{
|
post := &database.Post{
|
||||||
Title: title,
|
Title: title,
|
||||||
URL: req.URL,
|
URL: url,
|
||||||
Content: req.Content,
|
Content: content,
|
||||||
AuthorID: &userID,
|
AuthorID: &userID,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,40 +260,27 @@ func (h *PostHandler) UpdatePost(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var req struct {
|
req, ok := GetValidatedDTO[dto.UpdatePostRequest](r)
|
||||||
Title string `json:"title"`
|
if !ok {
|
||||||
Content string `json:"content"`
|
SendErrorResponse(w, "Invalid request", http.StatusBadRequest)
|
||||||
}
|
|
||||||
|
|
||||||
if !DecodeJSONRequest(w, r, &req) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Title = security.SanitizeInput(req.Title)
|
title := security.SanitizeInput(req.Title)
|
||||||
req.Content = security.SanitizePostContent(req.Content)
|
content := security.SanitizePostContent(req.Content)
|
||||||
|
|
||||||
if len(req.Title) > 200 {
|
if err := validation.ValidateTitle(title); err != nil {
|
||||||
SendErrorResponse(w, "Title must be no more than 200 characters", http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(req.Content) > 10000 {
|
|
||||||
SendErrorResponse(w, "Content must be no more than 10,000 characters", http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := validation.ValidateTitle(req.Title); err != nil {
|
|
||||||
SendErrorResponse(w, err.Error(), http.StatusBadRequest)
|
SendErrorResponse(w, err.Error(), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := validation.ValidateContent(req.Content); err != nil {
|
if err := validation.ValidateContent(content); err != nil {
|
||||||
SendErrorResponse(w, err.Error(), http.StatusBadRequest)
|
SendErrorResponse(w, err.Error(), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
post.Title = req.Title
|
post.Title = title
|
||||||
post.Content = req.Content
|
post.Content = content
|
||||||
|
|
||||||
if err := h.postRepo.Update(post); err != nil {
|
if err := h.postRepo.Update(post); err != nil {
|
||||||
SendErrorResponse(w, "Failed to update post", http.StatusInternalServerError)
|
SendErrorResponse(w, "Failed to update post", http.StatusInternalServerError)
|
||||||
@@ -453,7 +419,7 @@ func (h *PostHandler) MountRoutes(r chi.Router, config RouteModuleConfig) {
|
|||||||
if config.GeneralRateLimit != nil {
|
if config.GeneralRateLimit != nil {
|
||||||
protected = config.GeneralRateLimit(protected)
|
protected = config.GeneralRateLimit(protected)
|
||||||
}
|
}
|
||||||
protected.Post("/posts", h.CreatePost)
|
protected.Post("/posts", WithValidation[dto.CreatePostRequest](config.ValidationMiddleware, h.CreatePost))
|
||||||
protected.Put("/posts/{id}", h.UpdatePost)
|
protected.Put("/posts/{id}", WithValidation[dto.UpdatePostRequest](config.ValidationMiddleware, h.UpdatePost))
|
||||||
protected.Delete("/posts/{id}", h.DeletePost)
|
protected.Delete("/posts/{id}", h.DeletePost)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user