Added comments endpoint
This commit is contained in:
parent
aa5d1e4867
commit
aec63ec28d
@ -5,6 +5,7 @@ import { useAtomValue } from "jotai";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { axiosLocalhost } from "../../api/axios/axios";
|
||||
import { userAtom } from "../../AtomStore/AtomStore";
|
||||
import { MINUTE } from "../../constants/timeInMills";
|
||||
import AddPostToBlogDialog from "../Dialogs/AddPostToBlogDialog/AddPostToBlogDialog";
|
||||
import ChangePostButton from "./ChangePostButton/ChangePostButton";
|
||||
import SkeletonPostLoader from "./SkeletonLoader/SkeletonLoader";
|
||||
@ -19,7 +20,7 @@ export default function ArticleViewer(props: TArticleViewer) {
|
||||
let queryParams = useParams();
|
||||
const user = useAtomValue(userAtom);
|
||||
|
||||
const { data, isPending } = useQuery({
|
||||
const { data: blogData, isPending } = useQuery({
|
||||
queryKey: [`post_${queryParams["postId"]}`],
|
||||
queryFn: async () => {
|
||||
const response = await axiosLocalhost.get(
|
||||
@ -28,7 +29,7 @@ export default function ArticleViewer(props: TArticleViewer) {
|
||||
|
||||
return response.data;
|
||||
},
|
||||
gcTime: 0,
|
||||
gcTime: 2 * MINUTE,
|
||||
refetchOnMount: true,
|
||||
});
|
||||
|
||||
@ -38,7 +39,7 @@ export default function ArticleViewer(props: TArticleViewer) {
|
||||
<ScrollArea className="p-0 mx-auto overflow-hidden ql-editor max-w-pc-width">
|
||||
<Flex direction={"column"} className="overflow-hidden">
|
||||
<Text className="mb-2" as="div" size={"9"}>
|
||||
{data.title}
|
||||
{blogData.title}
|
||||
</Text>
|
||||
<Flex
|
||||
gap={"3"}
|
||||
@ -58,20 +59,20 @@ export default function ArticleViewer(props: TArticleViewer) {
|
||||
/>
|
||||
</Flex>
|
||||
|
||||
<Box hidden={data.user_id != user?.id}>
|
||||
<Box hidden={blogData.user_id != user?.id}>
|
||||
<ChangePostButton
|
||||
postId={queryParams["postId"] || ""}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{user ? <AddPostToBlogDialog /> : null}
|
||||
{blogData.user_id == user?.id ? <AddPostToBlogDialog /> : null}
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
||||
<Separator size={"4"} className="my-2" />
|
||||
|
||||
<Text>
|
||||
<Interweave content={data.content} />
|
||||
<Interweave content={blogData.content} />
|
||||
</Text>
|
||||
</ScrollArea>
|
||||
);
|
||||
|
||||
6
enshi/src/constants/timeInMills.ts
Normal file
6
enshi/src/constants/timeInMills.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export const SECOND = 1000;
|
||||
export const MINUTE = 60 * SECOND;
|
||||
export const HOUR = 60 * MINUTE;
|
||||
export const DAY = 24 * HOUR;
|
||||
export const WEEK = 7 * DAY;
|
||||
export const MONTH = 30 * DAY;
|
||||
28
enshi_back/ABAC/GlobalRules/IsOwnerOfTheCommentRule.go
Normal file
28
enshi_back/ABAC/GlobalRules/IsOwnerOfTheCommentRule.go
Normal file
@ -0,0 +1,28 @@
|
||||
package globalrules
|
||||
|
||||
import (
|
||||
"context"
|
||||
db_repo "enshi/db/go_queries"
|
||||
"enshi/db_connection"
|
||||
"enshi/middleware/getters"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func IsOwnerOfTheCommentRule(c *gin.Context) (bool, []error) {
|
||||
commentId, err := getters.GetInt64Param(c, "comment-id")
|
||||
if err != nil {
|
||||
return false, []error{err}
|
||||
}
|
||||
|
||||
contextUserId, err := getters.GetUserIdFromContext(c)
|
||||
if err != nil {
|
||||
return false, []error{err}
|
||||
}
|
||||
|
||||
comment, err := db_repo.New(db_connection.Dbx).GetCommentById(context.Background(), commentId)
|
||||
if err != nil {
|
||||
return false, []error{err}
|
||||
}
|
||||
return contextUserId == comment.UserID, nil
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: badge_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: blogs_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: bookmarks_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: categories_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: comments_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const createComment = `-- name: CreateComment :one
|
||||
@ -19,10 +17,10 @@ RETURNING comment_id, post_id, user_id, content, created_at
|
||||
`
|
||||
|
||||
type CreateCommentParams struct {
|
||||
CommentID int64 `json:"comment_id"`
|
||||
PostID pgtype.Int8 `json:"post_id"`
|
||||
UserID pgtype.Int8 `json:"user_id"`
|
||||
Content pgtype.Text `json:"content"`
|
||||
CommentID int64 `json:"comment_id"`
|
||||
PostID int64 `json:"post_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateComment(ctx context.Context, arg CreateCommentParams) (Comment, error) {
|
||||
@ -53,6 +51,25 @@ func (q *Queries) DeleteComment(ctx context.Context, commentID int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
const getCommentById = `-- name: GetCommentById :one
|
||||
SELECT comment_id, post_id, user_id, "content", created_at
|
||||
FROM public."comments"
|
||||
WHERE comment_id=$1
|
||||
`
|
||||
|
||||
func (q *Queries) GetCommentById(ctx context.Context, commentID int64) (Comment, error) {
|
||||
row := q.db.QueryRow(ctx, getCommentById, commentID)
|
||||
var i Comment
|
||||
err := row.Scan(
|
||||
&i.CommentID,
|
||||
&i.PostID,
|
||||
&i.UserID,
|
||||
&i.Content,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getCommentByUserId = `-- name: GetCommentByUserId :one
|
||||
SELECT comment_id, post_id, user_id, "content", created_at
|
||||
FROM public."comments"
|
||||
@ -60,8 +77,8 @@ where public."comments".user_id = $1 and public."comments".post_id = $2
|
||||
`
|
||||
|
||||
type GetCommentByUserIdParams struct {
|
||||
UserID pgtype.Int8 `json:"user_id"`
|
||||
PostID pgtype.Int8 `json:"post_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
PostID int64 `json:"post_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetCommentByUserId(ctx context.Context, arg GetCommentByUserIdParams) (Comment, error) {
|
||||
@ -86,12 +103,12 @@ LIMIT 10 offset ($2 * 10)
|
||||
`
|
||||
|
||||
type GetCommentsForPostAscParams struct {
|
||||
PostID pgtype.Int8 `json:"post_id"`
|
||||
Column2 interface{} `json:"column_2"`
|
||||
PostID int64 `json:"post_id"`
|
||||
Offset interface{} `json:"offset"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetCommentsForPostAsc(ctx context.Context, arg GetCommentsForPostAscParams) ([]Comment, error) {
|
||||
rows, err := q.db.Query(ctx, getCommentsForPostAsc, arg.PostID, arg.Column2)
|
||||
rows, err := q.db.Query(ctx, getCommentsForPostAsc, arg.PostID, arg.Offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -125,7 +142,7 @@ LIMIT 10 offset ($2 * 10)
|
||||
`
|
||||
|
||||
type GetCommentsForPostDescParams struct {
|
||||
PostID pgtype.Int8 `json:"post_id"`
|
||||
PostID int64 `json:"post_id"`
|
||||
Column2 interface{} `json:"column_2"`
|
||||
}
|
||||
|
||||
@ -163,8 +180,8 @@ RETURNING comment_id, post_id, user_id, content, created_at
|
||||
`
|
||||
|
||||
type UpdateCommentByCommentIdParams struct {
|
||||
CommentID int64 `json:"comment_id"`
|
||||
Content pgtype.Text `json:"content"`
|
||||
CommentID int64 `json:"comment_id"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateCommentByCommentId(ctx context.Context, arg UpdateCommentByCommentIdParams) (Comment, error) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
|
||||
package db_repo
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: favorites_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: likes_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -38,9 +38,9 @@ type Category struct {
|
||||
|
||||
type Comment struct {
|
||||
CommentID int64 `json:"comment_id"`
|
||||
PostID pgtype.Int8 `json:"post_id"`
|
||||
UserID pgtype.Int8 `json:"user_id"`
|
||||
Content pgtype.Text `json:"content"`
|
||||
PostID int64 `json:"post_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Content string `json:"content"`
|
||||
CreatedAt pgtype.Timestamp `json:"created_at"`
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: multi_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: post_tags_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: post_votes_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: posts_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: profiles_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: tags_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// sqlc v1.29.0
|
||||
// source: users_queries.sql
|
||||
|
||||
package db_repo
|
||||
|
||||
@ -57,9 +57,9 @@ CREATE TABLE IF NOT EXISTS "public"."bookmarks" (
|
||||
-- Create "comments" table
|
||||
CREATE TABLE IF NOT EXISTS "public"."comments" (
|
||||
"comment_id" bigint NOT NULL,
|
||||
"post_id" bigint NULL,
|
||||
"user_id" bigint NULL,
|
||||
"content" text NULL,
|
||||
"post_id" bigint NOT NULL,
|
||||
"user_id" bigint NOT NULL,
|
||||
"content" text NOT NULL,
|
||||
"created_at" timestamp NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY ("comment_id"),
|
||||
CONSTRAINT "comments_post_id_fkey" FOREIGN KEY ("post_id") REFERENCES "public"."posts" ("post_id") ON UPDATE NO ACTION ON DELETE CASCADE,
|
||||
|
||||
@ -20,7 +20,7 @@ SELECT comment_id, post_id, user_id, "content", created_at
|
||||
FROM public."comments"
|
||||
where public."comments".post_id = $1
|
||||
order by created_at ASC
|
||||
LIMIT 10 offset ($2 * 10);
|
||||
LIMIT 10 offset (sqlc.arg('offset') * 10);
|
||||
|
||||
-- name: UpdateCommentByCommentId :one
|
||||
UPDATE public."comments"
|
||||
@ -31,4 +31,9 @@ RETURNING *;
|
||||
-- name: GetCommentByUserId :one
|
||||
SELECT comment_id, post_id, user_id, "content", created_at
|
||||
FROM public."comments"
|
||||
where public."comments".user_id = $1 and public."comments".post_id = $2;
|
||||
where public."comments".user_id = $1 and public."comments".post_id = $2;
|
||||
|
||||
-- name: GetCommentById :one
|
||||
SELECT comment_id, post_id, user_id, "content", created_at
|
||||
FROM public."comments"
|
||||
WHERE comment_id=$1;
|
||||
@ -13,7 +13,6 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -38,7 +37,7 @@ func main() {
|
||||
defer cleanup(context.Background())
|
||||
|
||||
router := gin.Default()
|
||||
router.Use(otelgin.Middleware(serviceName))
|
||||
// router.Use(otelgin.Middleware(serviceName))
|
||||
|
||||
f, err := os.OpenFile("gin.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
|
||||
if err != nil {
|
||||
|
||||
63
enshi_back/routes/commentRoutes/createComment.go
Normal file
63
enshi_back/routes/commentRoutes/createComment.go
Normal file
@ -0,0 +1,63 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
rest_api_stuff "enshi/REST_API_stuff"
|
||||
db_repo "enshi/db/go_queries"
|
||||
"enshi/db_connection"
|
||||
"enshi/middleware/getters"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func CreateComment(c *gin.Context) {
|
||||
var CommentParams db_repo.CreateCommentParams
|
||||
if err := c.BindJSON(&CommentParams); err != nil {
|
||||
rest_api_stuff.BadRequestAnswer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
userId, err := getters.GetUserIdFromContext(c)
|
||||
if err != nil {
|
||||
rest_api_stuff.BadRequestAnswer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if commentId, err := uuid.NewV7(); err != nil {
|
||||
rest_api_stuff.InternalErrorAnswer(c, err)
|
||||
return
|
||||
} else {
|
||||
CommentParams.CommentID = -int64(binary.BigEndian.Uint64(commentId[8:]))
|
||||
}
|
||||
|
||||
CommentParams.UserID = userId
|
||||
|
||||
postId, err := getters.GetInt64Param(c, "post-id")
|
||||
if err != nil {
|
||||
rest_api_stuff.BadRequestAnswer(c, err)
|
||||
return
|
||||
}
|
||||
CommentParams.PostID = postId
|
||||
|
||||
transaction, err := db_connection.Dbx.Begin(context.Background())
|
||||
if err != nil {
|
||||
rest_api_stuff.InternalErrorAnswer(c, err)
|
||||
return
|
||||
}
|
||||
defer transaction.Rollback(context.Background())
|
||||
|
||||
_, err = db_repo.New(transaction).CreateComment(
|
||||
context.Background(),
|
||||
CommentParams,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
rest_api_stuff.InternalErrorAnswer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
transaction.Commit(context.Background())
|
||||
rest_api_stuff.OkAnswer(c, "comment has been created")
|
||||
}
|
||||
42
enshi_back/routes/commentRoutes/getCommentsForPost.go
Normal file
42
enshi_back/routes/commentRoutes/getCommentsForPost.go
Normal file
@ -0,0 +1,42 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"context"
|
||||
rest_api_stuff "enshi/REST_API_stuff"
|
||||
db_repo "enshi/db/go_queries"
|
||||
"enshi/db_connection"
|
||||
"enshi/middleware/getters"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func GetCommentsForPost(c *gin.Context) {
|
||||
var params db_repo.GetCommentsForPostAscParams
|
||||
|
||||
postId, err := getters.GetInt64Param(c, "post-id")
|
||||
if err != nil {
|
||||
rest_api_stuff.BadRequestAnswer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
offset, err := strconv.Atoi(c.DefaultQuery("offset", "10"))
|
||||
if err != nil {
|
||||
params.Offset = int32(0)
|
||||
}
|
||||
|
||||
params.Offset = int32(offset)
|
||||
params.PostID = postId
|
||||
|
||||
comments, err := db_repo.New(db_connection.Dbx).GetCommentsForPostAsc(
|
||||
context.Background(),
|
||||
params,
|
||||
)
|
||||
if err != nil {
|
||||
rest_api_stuff.InternalErrorAnswer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, comments)
|
||||
}
|
||||
@ -15,6 +15,7 @@ const (
|
||||
POST_VOTE_MIDDLEWARE = "POST_VOTE_MIDDLEWARE"
|
||||
POST_VOTES_MIDDLEWARE = "POST_VOTES_MIDDLEWARE"
|
||||
USER_MIDDLEWARE = "USER_MIDDLEWARE"
|
||||
COMMENT_MIDDLEWARE = "COMMENT_MIDDLEWARE"
|
||||
)
|
||||
|
||||
var MiddlewareProvider = middleware.MiddlewareProvider{
|
||||
@ -172,6 +173,26 @@ var policiesToRegister = map[string]middleware.RulesToCheck{
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
},
|
||||
|
||||
COMMENT_MIDDLEWARE: {
|
||||
middleware.GET: {
|
||||
Rules: make([]rules.RuleFunction, 0),
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
middleware.POST: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.AuthorizedRule,
|
||||
},
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
middleware.DELETE: {
|
||||
Rules: []rules.RuleFunction{
|
||||
globalrules.AuthorizedRule,
|
||||
globalrules.IsOwnerOfTheCommentRule,
|
||||
},
|
||||
MustBeCompleted: rules.ALL_RULES_MUST_BE_COMPLETED,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func InitMiddlewareProvider() {
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
"enshi/routes/authRoutes"
|
||||
"enshi/routes/blogRoutes"
|
||||
bookmarksroutes "enshi/routes/bookmarksRoutes"
|
||||
routes "enshi/routes/commentRoutes"
|
||||
"enshi/routes/postsRoutes"
|
||||
"enshi/routes/userProfileRoutes"
|
||||
userroutes "enshi/routes/userRoutes"
|
||||
@ -280,6 +281,19 @@ func SetupRotes(g *gin.Engine) error {
|
||||
authRoutes.Logout,
|
||||
)
|
||||
|
||||
commentGroup := g.Group("/comments/")
|
||||
commentGroup.Use(MiddlewareProvider.GetMiddleware(COMMENT_MIDDLEWARE))
|
||||
|
||||
commentGroup.GET(
|
||||
":post-id",
|
||||
routes.GetCommentsForPost,
|
||||
)
|
||||
|
||||
commentGroup.POST(
|
||||
":post-id",
|
||||
routes.CreateComment,
|
||||
)
|
||||
|
||||
temporal := g.Group("/")
|
||||
temporal.Use(middleware.AuthMiddleware())
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user