From b1543c9e22290f246e6e0b6c475ff77ac0a2e28d Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 17 Nov 2024 12:58:13 +0300 Subject: [PATCH] New routes --- enshi_back/ABAC/AdminPolicies/AdminPolicy.go | 17 ++++++ enshi_back/ABAC/PostsPolicies/postPolicy.go | 12 ++-- .../postRules/updatePostBlogRule.go | 25 ++++++++ .../PostsPolicies/postRules/updateRule.go | 1 + enshi_back/ABAC/rules/ShouldAbortRequest.go | 28 +++++++++ enshi_back/db/go_queries/posts_queries.sql.go | 29 +++++++--- enshi_back/db/queries/posts_queries.sql | 12 +++- enshi_back/middleware/ProfileMiddleware.go | 18 +----- enshi_back/middleware/adminMiddleware.go | 17 ++---- enshi_back/middleware/blogsMiddleware.go | 18 +----- .../getters}/GetContextPayload.go | 2 +- enshi_back/middleware/getters/getIntParam.go | 4 +- enshi_back/middleware/postsMiddleware.go | 29 ++++------ enshi_back/routes/blogRoutes/createBlog.go | 2 +- enshi_back/routes/blogRoutes/deleteBlog.go | 36 ++++++++++++ enshi_back/routes/blogRoutes/getBlog.go | 29 ++++++++++ enshi_back/routes/blogRoutes/updateBlog.go | 46 +++++++++++++++ .../routes/postsRoutes/updatePostBlog.go | 58 +++++++++++++++++++ enshi_back/routes/routesSetup.go | 25 ++++++-- .../userProfileRoutes/updateUserProfile.go | 3 +- 20 files changed, 324 insertions(+), 87 deletions(-) create mode 100644 enshi_back/ABAC/AdminPolicies/AdminPolicy.go create mode 100644 enshi_back/ABAC/PostsPolicies/postRules/updatePostBlogRule.go create mode 100644 enshi_back/ABAC/rules/ShouldAbortRequest.go rename enshi_back/{utils => middleware/getters}/GetContextPayload.go (96%) create mode 100644 enshi_back/routes/blogRoutes/deleteBlog.go create mode 100644 enshi_back/routes/blogRoutes/getBlog.go create mode 100644 enshi_back/routes/blogRoutes/updateBlog.go create mode 100644 enshi_back/routes/postsRoutes/updatePostBlog.go diff --git a/enshi_back/ABAC/AdminPolicies/AdminPolicy.go b/enshi_back/ABAC/AdminPolicies/AdminPolicy.go new file mode 100644 index 0000000..00a91e7 --- /dev/null +++ b/enshi_back/ABAC/AdminPolicies/AdminPolicy.go @@ -0,0 +1,17 @@ +package adminpolicies + +import ( + globalrules "enshi/ABAC/GlobalRules" + "enshi/ABAC/rules" + + "github.com/gin-gonic/gin" +) + +func AdminPolicies(c *gin.Context) (bool, []error) { + rulesToCheck := []rules.RuleFunction{ + globalrules.AuthorizedRule, + globalrules.IsAdminRule, + } + + return rules.CheckRules(c, rulesToCheck, rules.ALL_RULES_MUST_BE_COMPLETED) +} diff --git a/enshi_back/ABAC/PostsPolicies/postPolicy.go b/enshi_back/ABAC/PostsPolicies/postPolicy.go index 0d5415f..5bce3dc 100644 --- a/enshi_back/ABAC/PostsPolicies/postPolicy.go +++ b/enshi_back/ABAC/PostsPolicies/postPolicy.go @@ -8,10 +8,11 @@ import ( ) const ( - DELETE_POST = "delete_post" - UPDATE_POST = "update_post" - CREATE_POST = "create_post" - GET_POST = "get_post" + DELETE_POST = "delete_post" + UPDATE_POST = "update_post" + UPDATE_POST_BLOG = "update_post_blog" + CREATE_POST = "create_post" + GET_POST = "get_post" ) func PostsPolicies(c *gin.Context) (bool, []error) { @@ -28,6 +29,9 @@ func PostsPolicies(c *gin.Context) (bool, []error) { case UPDATE_POST: return rules.CheckRule(c, postRules.PostUpdateRule) + case UPDATE_POST_BLOG: + return rules.CheckRule(c, postRules.UpdatePostBlogRule) + case GET_POST: return rules.CheckRule(c, postRules.PostReadRule) diff --git a/enshi_back/ABAC/PostsPolicies/postRules/updatePostBlogRule.go b/enshi_back/ABAC/PostsPolicies/postRules/updatePostBlogRule.go new file mode 100644 index 0000000..887c784 --- /dev/null +++ b/enshi_back/ABAC/PostsPolicies/postRules/updatePostBlogRule.go @@ -0,0 +1,25 @@ +package postRules + +import ( + globalrules "enshi/ABAC/GlobalRules" + "enshi/ABAC/rules" + + "github.com/gin-gonic/gin" +) + +// Only user that own target post and blog can do that +func UpdatePostBlogRule(c *gin.Context) (bool, []error) { + rulesToCheck := []rules.RuleFunction{ + globalrules.AuthorizedRule, + globalrules.IsOwnerOfThePostRule, + globalrules.IsOwnerOfTheBlogRule, + } + + isAllowed, errors := rules.CheckRules( + c, + rulesToCheck, + rules.ALL_RULES_MUST_BE_COMPLETED, + ) + + return isAllowed, errors +} diff --git a/enshi_back/ABAC/PostsPolicies/postRules/updateRule.go b/enshi_back/ABAC/PostsPolicies/postRules/updateRule.go index 44cd7b6..9e04db0 100644 --- a/enshi_back/ABAC/PostsPolicies/postRules/updateRule.go +++ b/enshi_back/ABAC/PostsPolicies/postRules/updateRule.go @@ -11,6 +11,7 @@ import ( func PostUpdateRule(c *gin.Context) (bool, []error) { rulesToCheck := []rules.RuleFunction{ globalrules.AuthorizedRule, + globalrules.IsOwnerOfThePostRule, } isAllowed, errors := rules.CheckRules( diff --git a/enshi_back/ABAC/rules/ShouldAbortRequest.go b/enshi_back/ABAC/rules/ShouldAbortRequest.go new file mode 100644 index 0000000..ee5b804 --- /dev/null +++ b/enshi_back/ABAC/rules/ShouldAbortRequest.go @@ -0,0 +1,28 @@ +package rules + +import ( + rest_api_stuff "enshi/REST_API_stuff" + "fmt" + "net/http" + + "github.com/gin-gonic/gin" +) + +func ShouldAbortRequest(c *gin.Context, isAllowed bool, errors []error) bool { + var errorsMap = map[int]string{} + for i, error := range errors { + errorsMap[i] = error.Error() + } + + if errors != nil { + c.IndentedJSON(http.StatusUnauthorized, errorsMap) + return true + } + + if !isAllowed { + rest_api_stuff.UnauthorizedAnswer(c, fmt.Errorf("you have no permission")) + return true + } + + return false +} diff --git a/enshi_back/db/go_queries/posts_queries.sql.go b/enshi_back/db/go_queries/posts_queries.sql.go index 2090708..5dc478f 100644 --- a/enshi_back/db/go_queries/posts_queries.sql.go +++ b/enshi_back/db/go_queries/posts_queries.sql.go @@ -146,27 +146,38 @@ func (q *Queries) GetPostsByUserId(ctx context.Context, userID int64) ([]Post, e return items, nil } +const updatePostBlogId = `-- name: UpdatePostBlogId :exec +UPDATE public.posts +SET blog_id=$2, updated_at=CURRENT_TIMESTAMP +WHERE post_id = $1 +RETURNING post_id, blog_id, user_id, title, content, created_at, updated_at +` + +type UpdatePostBlogIdParams struct { + PostID int64 `json:"post_id"` + BlogID pgtype.Int8 `json:"blog_id"` +} + +func (q *Queries) UpdatePostBlogId(ctx context.Context, arg UpdatePostBlogIdParams) error { + _, err := q.db.Exec(ctx, updatePostBlogId, arg.PostID, arg.BlogID) + return err +} + const updatePostByPostId = `-- name: UpdatePostByPostId :one UPDATE public.posts -SET blog_id=$1, title=$2, "content"=$3, updated_at=CURRENT_TIMESTAMP -WHERE post_id = $4 +SET title=$1, "content"=$2, updated_at=CURRENT_TIMESTAMP +WHERE post_id = $3 RETURNING post_id, blog_id, user_id, title, content, created_at, updated_at ` type UpdatePostByPostIdParams struct { - BlogID pgtype.Int8 `json:"blog_id"` Title pgtype.Text `json:"title"` Content pgtype.Text `json:"content"` PostID int64 `json:"post_id"` } func (q *Queries) UpdatePostByPostId(ctx context.Context, arg UpdatePostByPostIdParams) (Post, error) { - row := q.db.QueryRow(ctx, updatePostByPostId, - arg.BlogID, - arg.Title, - arg.Content, - arg.PostID, - ) + row := q.db.QueryRow(ctx, updatePostByPostId, arg.Title, arg.Content, arg.PostID) var i Post err := row.Scan( &i.PostID, diff --git a/enshi_back/db/queries/posts_queries.sql b/enshi_back/db/queries/posts_queries.sql index 718e005..39f61f3 100644 --- a/enshi_back/db/queries/posts_queries.sql +++ b/enshi_back/db/queries/posts_queries.sql @@ -21,10 +21,16 @@ RETURNING *; -- name: UpdatePostByPostId :one UPDATE public.posts -SET blog_id=$1, title=$2, "content"=$3, updated_at=CURRENT_TIMESTAMP -WHERE post_id = $4 +SET title=$1, "content"=$2, updated_at=CURRENT_TIMESTAMP +WHERE post_id = $3 RETURNING *; -- name: DeletePostByPostId :exec DELETE FROM public.posts -WHERE post_id=$1; \ No newline at end of file +WHERE post_id=$1; + +-- name: UpdatePostBlogId :exec +UPDATE public.posts +SET blog_id=$2, updated_at=CURRENT_TIMESTAMP +WHERE post_id = $1 +RETURNING *; diff --git a/enshi_back/middleware/ProfileMiddleware.go b/enshi_back/middleware/ProfileMiddleware.go index 494b09c..36877d5 100644 --- a/enshi_back/middleware/ProfileMiddleware.go +++ b/enshi_back/middleware/ProfileMiddleware.go @@ -2,9 +2,7 @@ package middleware import ( profilepolicies "enshi/ABAC/ProfilePolicies" - rest_api_stuff "enshi/REST_API_stuff" - "fmt" - "net/http" + "enshi/ABAC/rules" "github.com/gin-gonic/gin" ) @@ -18,19 +16,7 @@ func ProfileMiddleware() gin.HandlerFunc { isAllowed, errors := profilepolicies.ProfilePolicies(c) - var errorsMap = map[int]string{} - for i, error := range errors { - errorsMap[i] = error.Error() - } - - if errors != nil { - c.IndentedJSON(http.StatusUnauthorized, errorsMap) - c.Abort() - return - } - - if !isAllowed { - rest_api_stuff.UnauthorizedAnswer(c, fmt.Errorf("you have no permission")) + if rules.ShouldAbortRequest(c, isAllowed, errors) { c.Abort() return } diff --git a/enshi_back/middleware/adminMiddleware.go b/enshi_back/middleware/adminMiddleware.go index 0ddf300..51841d6 100644 --- a/enshi_back/middleware/adminMiddleware.go +++ b/enshi_back/middleware/adminMiddleware.go @@ -1,26 +1,19 @@ package middleware import ( - rest_api_stuff "enshi/REST_API_stuff" - "enshi/middleware/checkRole" - "fmt" + adminpolicies "enshi/ABAC/AdminPolicies" + "enshi/ABAC/rules" "github.com/gin-gonic/gin" ) func AdminMiddleware() gin.HandlerFunc { return func(c *gin.Context) { + isAllowed, errors := adminpolicies.AdminPolicies(c) - isAdmin, err := checkRole.IsAdmin(c) - - if err != nil { - rest_api_stuff.BadRequestAnswer(c, err) - c.Abort() - } - - if !isAdmin { - rest_api_stuff.UnauthorizedAnswer(c, fmt.Errorf("not allowed")) + if rules.ShouldAbortRequest(c, isAllowed, errors) { c.Abort() + return } c.Next() diff --git a/enshi_back/middleware/blogsMiddleware.go b/enshi_back/middleware/blogsMiddleware.go index bed7ea1..eeb58dc 100644 --- a/enshi_back/middleware/blogsMiddleware.go +++ b/enshi_back/middleware/blogsMiddleware.go @@ -2,9 +2,7 @@ package middleware import ( blogspolicies "enshi/ABAC/blogsPolicies" - rest_api_stuff "enshi/REST_API_stuff" - "fmt" - "net/http" + "enshi/ABAC/rules" "github.com/gin-gonic/gin" ) @@ -25,19 +23,7 @@ func BlogsMiddleware() gin.HandlerFunc { isAllowed, errors := blogspolicies.BlogPolicies(c) - var errorsMap = map[int]string{} - for i, error := range errors { - errorsMap[i] = error.Error() - } - - if errors != nil { - c.IndentedJSON(http.StatusUnauthorized, errorsMap) - c.Abort() - return - } - - if !isAllowed { - rest_api_stuff.UnauthorizedAnswer(c, fmt.Errorf("you have no permission")) + if rules.ShouldAbortRequest(c, isAllowed, errors) { c.Abort() return } diff --git a/enshi_back/utils/GetContextPayload.go b/enshi_back/middleware/getters/GetContextPayload.go similarity index 96% rename from enshi_back/utils/GetContextPayload.go rename to enshi_back/middleware/getters/GetContextPayload.go index 934207c..84c4dd9 100644 --- a/enshi_back/utils/GetContextPayload.go +++ b/enshi_back/middleware/getters/GetContextPayload.go @@ -1,4 +1,4 @@ -package utils +package getters import ( "github.com/gin-gonic/gin" diff --git a/enshi_back/middleware/getters/getIntParam.go b/enshi_back/middleware/getters/getIntParam.go index f5ddd57..1501981 100644 --- a/enshi_back/middleware/getters/getIntParam.go +++ b/enshi_back/middleware/getters/getIntParam.go @@ -2,12 +2,14 @@ package getters import ( "strconv" + "strings" "github.com/gin-gonic/gin" ) +// Returns -1, error if there is no such param or value invalid func GetInt64Param(c *gin.Context, paramName string) (int64, error) { - int64ParamValue, err := strconv.ParseInt(c.Param(paramName), 10, 64) + int64ParamValue, err := strconv.ParseInt(strings.Trim(c.Param(paramName), "/"), 10, 64) if err != nil { return -1, err diff --git a/enshi_back/middleware/postsMiddleware.go b/enshi_back/middleware/postsMiddleware.go index 2dc90fa..7ee3338 100644 --- a/enshi_back/middleware/postsMiddleware.go +++ b/enshi_back/middleware/postsMiddleware.go @@ -2,9 +2,8 @@ package middleware import ( postspolicies "enshi/ABAC/PostsPolicies" - rest_api_stuff "enshi/REST_API_stuff" - "fmt" - "net/http" + "enshi/ABAC/rules" + "enshi/middleware/getters" "github.com/gin-gonic/gin" ) @@ -16,7 +15,15 @@ func PostsMiddleware() gin.HandlerFunc { case "DELETE": c.Set("target", postspolicies.DELETE_POST) case "PUT": - c.Set("target", postspolicies.UPDATE_POST) + blogId, _ := getters.GetInt64Param(c, "blog-id") + postId, _ := getters.GetInt64Param(c, "post-id") + + if postId > 0 && blogId > 0 { + c.Set("target", postspolicies.UPDATE_POST_BLOG) + } else if postId > 0 { + c.Set("target", postspolicies.UPDATE_POST) + } + case "POST": c.Set("target", postspolicies.CREATE_POST) case "GET": @@ -25,19 +32,7 @@ func PostsMiddleware() gin.HandlerFunc { isAllowed, errors := postspolicies.PostsPolicies(c) - var errorsMap = map[int]string{} - for i, error := range errors { - errorsMap[i] = error.Error() - } - - if errors != nil { - c.IndentedJSON(http.StatusUnauthorized, errorsMap) - c.Abort() - return - } - - if !isAllowed { - rest_api_stuff.UnauthorizedAnswer(c, fmt.Errorf("you have no permission")) + if rules.ShouldAbortRequest(c, isAllowed, errors) { c.Abort() return } diff --git a/enshi_back/routes/blogRoutes/createBlog.go b/enshi_back/routes/blogRoutes/createBlog.go index ecb1e2f..a1f3ede 100644 --- a/enshi_back/routes/blogRoutes/createBlog.go +++ b/enshi_back/routes/blogRoutes/createBlog.go @@ -12,7 +12,7 @@ import ( ) func CreateBlog(c *gin.Context) { - blogParams, err := utils.GetContextPayload[db_repo.CreateBlogByUserIdParams](c) + blogParams, err := getters.GetContextPayload[db_repo.CreateBlogByUserIdParams](c) if err != nil { rest_api_stuff.BadRequestAnswer(c, err) return diff --git a/enshi_back/routes/blogRoutes/deleteBlog.go b/enshi_back/routes/blogRoutes/deleteBlog.go new file mode 100644 index 0000000..25bc5af --- /dev/null +++ b/enshi_back/routes/blogRoutes/deleteBlog.go @@ -0,0 +1,36 @@ +package blogRoutes + +import ( + "context" + rest_api_stuff "enshi/REST_API_stuff" + db_repo "enshi/db/go_queries" + "enshi/db_connection" + "enshi/middleware/getters" + + "github.com/gin-gonic/gin" +) + +func DeleteBlog(c *gin.Context) { + blogId, err := getters.GetInt64Param(c, "blog-id") + if err != nil { + rest_api_stuff.BadRequestAnswer(c, err) + return + } + + 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). + DeleteBlogByBlogId(context.Background(), blogId) + if err != nil { + rest_api_stuff.InternalErrorAnswer(c, err) + return + } + + transaction.Commit(context.Background()) + rest_api_stuff.OkAnswer(c, "blog has been deleted") +} diff --git a/enshi_back/routes/blogRoutes/getBlog.go b/enshi_back/routes/blogRoutes/getBlog.go new file mode 100644 index 0000000..81c20b6 --- /dev/null +++ b/enshi_back/routes/blogRoutes/getBlog.go @@ -0,0 +1,29 @@ +package blogRoutes + +import ( + "context" + rest_api_stuff "enshi/REST_API_stuff" + db_repo "enshi/db/go_queries" + "enshi/db_connection" + "enshi/middleware/getters" + "net/http" + + "github.com/gin-gonic/gin" +) + +func GetBlog(c *gin.Context) { + blogId, err := getters.GetInt64Param(c, "blog-id") + if err != nil { + rest_api_stuff.BadRequestAnswer(c, err) + return + } + + blogData, err := db_repo.New(db_connection.Dbx). + GetBlogByBlogId(context.Background(), blogId) + if err != nil { + rest_api_stuff.InternalErrorAnswer(c, err) + return + } + + c.IndentedJSON(http.StatusOK, blogData) +} diff --git a/enshi_back/routes/blogRoutes/updateBlog.go b/enshi_back/routes/blogRoutes/updateBlog.go new file mode 100644 index 0000000..7924db3 --- /dev/null +++ b/enshi_back/routes/blogRoutes/updateBlog.go @@ -0,0 +1,46 @@ +package blogRoutes + +import ( + "context" + rest_api_stuff "enshi/REST_API_stuff" + db_repo "enshi/db/go_queries" + "enshi/db_connection" + "enshi/middleware/getters" + + "github.com/gin-gonic/gin" +) + +func UpdateBlog(c *gin.Context) { + newBlogParams, err := + getters.GetContextPayload[db_repo.UpdateBlogInfoByBlogIdParams](c) + if err != nil { + rest_api_stuff.BadRequestAnswer(c, err) + return + } + + blogId, err := getters.GetInt64Param(c, "blog-id") + if err != nil { + rest_api_stuff.BadRequestAnswer(c, err) + return + } + + newBlogParams.BlogID = blogId + + 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). + UpdateBlogInfoByBlogId(context.Background(), newBlogParams) + if err != nil { + rest_api_stuff.InternalErrorAnswer(c, err) + return + } + transaction.Commit(context.Background()) + + rest_api_stuff.OkAnswer(c, "blog has been updated") + +} diff --git a/enshi_back/routes/postsRoutes/updatePostBlog.go b/enshi_back/routes/postsRoutes/updatePostBlog.go new file mode 100644 index 0000000..0fcb3c8 --- /dev/null +++ b/enshi_back/routes/postsRoutes/updatePostBlog.go @@ -0,0 +1,58 @@ +package postsRoutes + +import ( + "context" + 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/jackc/pgx/v5/pgtype" +) + +func UpdatePostBlog(c *gin.Context) { + var UpdatedPostParams db_repo.UpdatePostBlogIdParams + + postId, err := getters.GetInt64Param(c, "post-id") + + if err != nil { + rest_api_stuff.InternalErrorAnswer(c, err) + return + } + + blogId, err := getters.GetInt64Param(c, "blog-id") + + if err != nil { + rest_api_stuff.InternalErrorAnswer(c, err) + return + } + + UpdatedPostParams.PostID = postId + UpdatedPostParams.BlogID = pgtype.Int8{ + Valid: true, + Int64: blogId, + } + + 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, + ).UpdatePostBlogId( + context.Background(), + UpdatedPostParams, + ) + + if err != nil { + rest_api_stuff.InternalErrorAnswer(c, err) + return + } + + transaction.Commit(context.Background()) + rest_api_stuff.OkAnswer(c, "post has been updated") +} diff --git a/enshi_back/routes/routesSetup.go b/enshi_back/routes/routesSetup.go index 6662770..5215b95 100644 --- a/enshi_back/routes/routesSetup.go +++ b/enshi_back/routes/routesSetup.go @@ -49,6 +49,10 @@ func SetupRotes(g *gin.Engine) error { "posts/:post-id", postsRoutes.UpdatePost, ) + postsGroup.PUT( + "posts/:post-id/blogs/:blog-id", + postsRoutes.UpdatePostBlog, + ) postsGroup.POST( "posts", postsRoutes.CreatePost, @@ -66,6 +70,21 @@ func SetupRotes(g *gin.Engine) error { blogRoutes.CreateBlog, ) + blogGroup.PUT( + "blogs/:blog-id", + blogRoutes.UpdateBlog, + ) + + blogGroup.DELETE( + "blogs/:blog-id", + blogRoutes.DeleteBlog, + ) + + blogGroup.GET( + "blogs/:blog-id", + blogRoutes.GetBlog, + ) + profilesGroup := g.Group("/") profilesGroup.Use(middleware.ProfileMiddleware()) @@ -74,12 +93,8 @@ func SetupRotes(g *gin.Engine) error { userProfileRoutes.UpdateUserProfile, ) - // Auth group routes - authGroup := g.Group("/") - authGroup.Use(middleware.AuthMiddleware()) - // Admin group routes - adminGroup := authGroup.Group("/admin/") + adminGroup := g.Group("/admin/") adminGroup.Use(middleware.AdminMiddleware()) adminGroup.GET("testAdmin", testAdmin) diff --git a/enshi_back/routes/userProfileRoutes/updateUserProfile.go b/enshi_back/routes/userProfileRoutes/updateUserProfile.go index 22f04e7..2abbd9b 100644 --- a/enshi_back/routes/userProfileRoutes/updateUserProfile.go +++ b/enshi_back/routes/userProfileRoutes/updateUserProfile.go @@ -6,14 +6,13 @@ import ( db_repo "enshi/db/go_queries" "enshi/db_connection" "enshi/middleware/getters" - "enshi/utils" "github.com/gin-gonic/gin" ) func UpdateUserProfile(c *gin.Context) { newProfile, err := - utils.GetContextPayload[db_repo.UpdateProfileByUserIdParams](c) + getters.GetContextPayload[db_repo.UpdateProfileByUserIdParams](c) if err != nil { rest_api_stuff.BadRequestAnswer(c, err)