/
DexScen
/
ProjectPOH
Обзор
Документация
Войти
/
DexScen
/
ProjectPOH
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
backend/internal/comments/handler.go
277 строк
8 KB
Александр
changes
14 май 2026, 15:02
14 май 2026, 15:02
3f3feb2
Код
Авторство
О чём код?
package comments import ( "errors" "net/http" "github.com/DexScen/projectpoh/backend/internal/auth" "github.com/DexScen/projectpoh/backend/internal/domainerr" "github.com/DexScen/projectpoh/backend/internal/httpapi" "github.com/DexScen/projectpoh/backend/internal/middleware" ) type Handler struct { service *Service authService *auth.Service } func NewHandler(service *Service, authService *auth.Service) *Handler { return &Handler{service: service, authService: authService} } func (h *Handler) RegisterRoutes(mux *http.ServeMux) { mux.HandleFunc("GET /api/v1/posts/{postID}/comments", h.listByPostID) mux.Handle("POST /api/v1/posts/{postID}/comments", middleware.RequireAuth(h.authService)(http.HandlerFunc(h.createForPost))) mux.Handle("PATCH /api/v1/comments/{id}", middleware.RequireAuth(h.authService)(http.HandlerFunc(h.update))) mux.Handle("DELETE /api/v1/comments/{id}", middleware.RequireAuth(h.authService)(http.HandlerFunc(h.delete))) mux.Handle("POST /api/v1/comments/{id}/reply", middleware.RequireAuth(h.authService)(http.HandlerFunc(h.reply))) mux.Handle("GET /api/v1/moderation/comments/pending", middleware.RequireAuth(h.authService)(http.HandlerFunc(h.listPending))) mux.Handle("GET /api/v1/moderation/comments/pending/count", middleware.RequireAuth(h.authService)(http.HandlerFunc(h.countPending))) mux.Handle("PATCH /api/v1/moderation/comments/{id}/approve", middleware.RequireAuth(h.authService)(http.HandlerFunc(h.approve))) } func (h *Handler) listByPostID(w http.ResponseWriter, r *http.Request) { postID, err := httpapi.ParsePositiveInt64(r.PathValue("postID"), "postID") if err != nil { httpapi.WriteError(w, http.StatusBadRequest, err) return } limit, offset, err := httpapi.ParsePagination(r, 50, 200) if err != nil { httpapi.WriteError(w, http.StatusBadRequest, err) return } items, err := h.service.ListByPostID(r.Context(), postID, limit, offset) if err != nil { httpapi.WriteError(w, http.StatusInternalServerError, err) return } httpapi.WriteJSON(w, http.StatusOK, map[string]any{ "items": items, "limit": limit, "offset": offset, }) } func (h *Handler) listPending(w http.ResponseWriter, r *http.Request) { principal, ok := auth.PrincipalFromContext(r.Context()) if !ok { httpapi.WriteError(w, http.StatusUnauthorized, auth.ErrInvalidToken) return } if principal.Role != "moderator" && principal.Role != "admin" { httpapi.WriteError(w, http.StatusForbidden, domainerr.ErrForbidden) return } limit, offset, err := httpapi.ParsePagination(r, 50, 200) if err != nil { httpapi.WriteError(w, http.StatusBadRequest, err) return } items, err := h.service.ListPending(r.Context(), limit, offset) if err != nil { httpapi.WriteError(w, http.StatusInternalServerError, err) return } httpapi.WriteJSON(w, http.StatusOK, map[string]any{ "items": items, "limit": limit, "offset": offset, }) } func (h *Handler) countPending(w http.ResponseWriter, r *http.Request) { principal, ok := auth.PrincipalFromContext(r.Context()) if !ok { httpapi.WriteError(w, http.StatusUnauthorized, auth.ErrInvalidToken) return } if principal.Role != "moderator" && principal.Role != "admin" { httpapi.WriteError(w, http.StatusForbidden, domainerr.ErrForbidden) return } count, err := h.service.CountPending(r.Context()) if err != nil { httpapi.WriteError(w, http.StatusInternalServerError, err) return } httpapi.WriteJSON(w, http.StatusOK, map[string]int64{"count": count}) } func (h *Handler) approve(w http.ResponseWriter, r *http.Request) { principal, ok := auth.PrincipalFromContext(r.Context()) if !ok { httpapi.WriteError(w, http.StatusUnauthorized, auth.ErrInvalidToken) return } if principal.Role != "moderator" && principal.Role != "admin" { httpapi.WriteError(w, http.StatusForbidden, domainerr.ErrForbidden) return } id, err := httpapi.ParsePositiveInt64(r.PathValue("id"), "id") if err != nil { httpapi.WriteError(w, http.StatusBadRequest, err) return } comment, err := h.service.Approve(r.Context(), id) if err != nil { if errors.Is(err, ErrCommentNotFound) { httpapi.WriteError(w, http.StatusNotFound, err) return } httpapi.WriteError(w, http.StatusInternalServerError, err) return } httpapi.WriteJSON(w, http.StatusOK, comment) } func (h *Handler) createForPost(w http.ResponseWriter, r *http.Request) { principal, ok := auth.PrincipalFromContext(r.Context()) if !ok { httpapi.WriteError(w, http.StatusUnauthorized, auth.ErrInvalidToken) return } postID, err := httpapi.ParsePositiveInt64(r.PathValue("postID"), "postID") if err != nil { httpapi.WriteError(w, http.StatusBadRequest, err) return } var in CreateInput if err := httpapi.ReadJSON(r, &in); err != nil { httpapi.WriteError(w, http.StatusBadRequest, err) return } comment, err := h.service.Create(r.Context(), principal.UserID, postID, in) if err != nil { httpapi.WriteError(w, http.StatusBadRequest, err) return } httpapi.WriteJSON(w, http.StatusCreated, comment) } func (h *Handler) update(w http.ResponseWriter, r *http.Request) { principal, ok := auth.PrincipalFromContext(r.Context()) if !ok { httpapi.WriteError(w, http.StatusUnauthorized, auth.ErrInvalidToken) return } id, err := httpapi.ParsePositiveInt64(r.PathValue("id"), "id") if err != nil { httpapi.WriteError(w, http.StatusBadRequest, err) return } current, err := h.service.GetByID(r.Context(), id) if err != nil { httpapi.WriteError(w, http.StatusNotFound, err) return } if principal.UserID != current.UserID && principal.Role != "admin" && principal.Role != "moderator" { httpapi.WriteError(w, http.StatusForbidden, domainerr.ErrForbidden) return } var in UpdateInput if err := httpapi.ReadJSON(r, &in); err != nil { httpapi.WriteError(w, http.StatusBadRequest, err) return } updated, err := h.service.Update(r.Context(), id, in) if err != nil { if errors.Is(err, ErrCommentNotFound) { httpapi.WriteError(w, http.StatusNotFound, err) return } httpapi.WriteError(w, http.StatusBadRequest, err) return } httpapi.WriteJSON(w, http.StatusOK, updated) } func (h *Handler) delete(w http.ResponseWriter, r *http.Request) { principal, ok := auth.PrincipalFromContext(r.Context()) if !ok { httpapi.WriteError(w, http.StatusUnauthorized, auth.ErrInvalidToken) return } id, err := httpapi.ParsePositiveInt64(r.PathValue("id"), "id") if err != nil { httpapi.WriteError(w, http.StatusBadRequest, err) return } current, err := h.service.GetByID(r.Context(), id) if err != nil { httpapi.WriteError(w, http.StatusNotFound, err) return } if principal.UserID != current.UserID && principal.Role != "admin" && principal.Role != "moderator" { httpapi.WriteError(w, http.StatusForbidden, domainerr.ErrForbidden) return } if err := h.service.SoftDelete(r.Context(), id); err != nil { if errors.Is(err, ErrCommentNotFound) { httpapi.WriteError(w, http.StatusNotFound, err) return } httpapi.WriteError(w, http.StatusInternalServerError, err) return } httpapi.WriteJSON(w, http.StatusOK, map[string]string{"status": "deleted"}) } func (h *Handler) reply(w http.ResponseWriter, r *http.Request) { principal, ok := auth.PrincipalFromContext(r.Context()) if !ok { httpapi.WriteError(w, http.StatusUnauthorized, auth.ErrInvalidToken) return } parentID, err := httpapi.ParsePositiveInt64(r.PathValue("id"), "id") if err != nil { httpapi.WriteError(w, http.StatusBadRequest, err) return } parent, err := h.service.GetByID(r.Context(), parentID) if err != nil { httpapi.WriteError(w, http.StatusNotFound, err) return } var in UpdateInput if err := httpapi.ReadJSON(r, &in); err != nil { httpapi.WriteError(w, http.StatusBadRequest, err) return } input := CreateInput{Content: in.Content, ParentID: &parentID} comment, err := h.service.Create(r.Context(), principal.UserID, parent.PostID, input) if err != nil { httpapi.WriteError(w, http.StatusBadRequest, err) return } httpapi.WriteJSON(w, http.StatusCreated, comment) }