From 7e4dbd7e560c87a9260662a9190172235d9f84a3 Mon Sep 17 00:00:00 2001 From: d3m0k1d Date: Sat, 14 Feb 2026 16:26:27 +0300 Subject: [PATCH] feat: add auth to swagerr add middleware for check admin --- backend/cmd/main.go | 4 ++ backend/docs/docs.go | 23 ++++++++ backend/docs/swagger.json | 23 ++++++++ backend/docs/swagger.yaml | 12 +++++ backend/internal/auth/jwt.go | 61 ++++++++++++++++++++-- backend/internal/handlers/post_handlers.go | 3 ++ 6 files changed, 123 insertions(+), 3 deletions(-) diff --git a/backend/cmd/main.go b/backend/cmd/main.go index bcde071..2f91c67 100644 --- a/backend/cmd/main.go +++ b/backend/cmd/main.go @@ -10,6 +10,10 @@ import ( ginSwagger "github.com/swaggo/gin-swagger" ) +// @securityDefinitions.apikey Bearer +// @in header +// @name Authorization +// @description Type "Bearer" followed by a space and the JWT token. func main() { log := logger.New(false) diff --git a/backend/docs/docs.go b/backend/docs/docs.go index 0d0daa9..72722c0 100644 --- a/backend/docs/docs.go +++ b/backend/docs/docs.go @@ -133,6 +133,11 @@ const docTemplate = `{ } }, "post": { + "security": [ + { + "Bearer": [] + } + ], "description": "Create new post", "consumes": [ "application/json" @@ -245,6 +250,11 @@ const docTemplate = `{ } }, "put": { + "security": [ + { + "Bearer": [] + } + ], "description": "Update post", "consumes": [ "application/json" @@ -308,6 +318,11 @@ const docTemplate = `{ } }, "delete": { + "security": [ + { + "Bearer": [] + } + ], "description": "Delete post", "consumes": [ "application/json" @@ -440,6 +455,14 @@ const docTemplate = `{ } } } + }, + "securityDefinitions": { + "Bearer": { + "description": "Type \"Bearer\" followed by a space and the JWT token.", + "type": "apiKey", + "name": "Authorization", + "in": "header" + } } }` diff --git a/backend/docs/swagger.json b/backend/docs/swagger.json index 707d3f0..f5d0888 100644 --- a/backend/docs/swagger.json +++ b/backend/docs/swagger.json @@ -122,6 +122,11 @@ } }, "post": { + "security": [ + { + "Bearer": [] + } + ], "description": "Create new post", "consumes": [ "application/json" @@ -234,6 +239,11 @@ } }, "put": { + "security": [ + { + "Bearer": [] + } + ], "description": "Update post", "consumes": [ "application/json" @@ -297,6 +307,11 @@ } }, "delete": { + "security": [ + { + "Bearer": [] + } + ], "description": "Delete post", "consumes": [ "application/json" @@ -429,5 +444,13 @@ } } } + }, + "securityDefinitions": { + "Bearer": { + "description": "Type \"Bearer\" followed by a space and the JWT token.", + "type": "apiKey", + "name": "Authorization", + "in": "header" + } } } \ No newline at end of file diff --git a/backend/docs/swagger.yaml b/backend/docs/swagger.yaml index 0815700..4bf796a 100644 --- a/backend/docs/swagger.yaml +++ b/backend/docs/swagger.yaml @@ -149,6 +149,8 @@ paths: description: Invalid request schema: $ref: '#/definitions/gitea_d3m0k1d_ru_d3m0k1d_d3m0k1d_ru_backend_internal_models.ErrorResponse' + security: + - Bearer: [] summary: Create post tags: - posts @@ -187,6 +189,8 @@ paths: description: Internal server error schema: $ref: '#/definitions/gitea_d3m0k1d_ru_d3m0k1d_d3m0k1d_ru_backend_internal_models.ErrorResponse' + security: + - Bearer: [] summary: Delete post tags: - posts @@ -263,7 +267,15 @@ paths: description: Internal server error schema: $ref: '#/definitions/gitea_d3m0k1d_ru_d3m0k1d_d3m0k1d_ru_backend_internal_models.ErrorResponse' + security: + - Bearer: [] summary: Update post tags: - posts +securityDefinitions: + Bearer: + description: Type "Bearer" followed by a space and the JWT token. + in: header + name: Authorization + type: apiKey swagger: "2.0" diff --git a/backend/internal/auth/jwt.go b/backend/internal/auth/jwt.go index e836759..6a60f9f 100644 --- a/backend/internal/auth/jwt.go +++ b/backend/internal/auth/jwt.go @@ -16,6 +16,7 @@ func GenerateJWT(user storage.User) (string, error) { token := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{ "id": user.ID, "email": user.Email, + "login": user.GithubLogin, "github_id": user.GithubID, }) tokenString, err := token.SignedString(jwtSecret) @@ -35,7 +36,6 @@ func JWTMiddleware() gin.HandlerFunc { tokenString := strings.TrimPrefix(auth, "Bearer ") token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { - if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } @@ -53,8 +53,63 @@ func JWTMiddleware() gin.HandlerFunc { return } - c.Set("user_id", int(claims["id"].(float64))) - c.Set("login", claims["login"].(string)) + idValue, idExists := claims["id"] + if !idExists { + c.AbortWithStatusJSON(401, gin.H{"error": "missing id in token"}) + return + } + + idFloat, ok := idValue.(float64) + if !ok { + c.AbortWithStatusJSON(401, gin.H{"error": "invalid id type in token"}) + return + } + + githubIDValue, githubExists := claims["github_id"] + if !githubExists { + c.AbortWithStatusJSON(401, gin.H{"error": "missing github_id in token"}) + return + } + + githubIDFloat, ok := githubIDValue.(float64) + if !ok { + c.AbortWithStatusJSON(401, gin.H{"error": "invalid github_id type in token"}) + return + } + + loginValue, loginExists := claims["login"] + if !loginExists { + c.AbortWithStatusJSON(401, gin.H{"error": "missing login in token"}) + return + } + + login, ok := loginValue.(string) + if !ok { + c.AbortWithStatusJSON(401, gin.H{"error": "invalid login type in token"}) + return + } + + c.Set("user_id", int(idFloat)) + c.Set("github_id", int(githubIDFloat)) + c.Set("login", login) + c.Next() + } +} + +func RequireAdmin() gin.HandlerFunc { + return func(c *gin.Context) { + githubID, exists := c.Get("github_id") + if !exists { + c.AbortWithStatusJSON(401, gin.H{"error": "unauthorized"}) + return + } + + id := githubID.(int) + if id != 173489813 { + c.AbortWithStatusJSON(403, gin.H{"error": "access denied"}) + return + } + c.Next() } } diff --git a/backend/internal/handlers/post_handlers.go b/backend/internal/handlers/post_handlers.go index 8a92bb0..475d524 100644 --- a/backend/internal/handlers/post_handlers.go +++ b/backend/internal/handlers/post_handlers.go @@ -95,6 +95,7 @@ func (h *PostHandlers) GetPost(c *gin.Context) { // @Accept json // @Produce json // @Param post body storage.PostCreate true "Post data" +// @Security Bearer // @Success 200 {object} models.SuccessResponse{data=storage.Post} // @Failure 400 {object} models.ErrorResponse "Invalid request" // @Router /posts [post] @@ -127,6 +128,7 @@ func (h *PostHandlers) CreatePost(c *gin.Context) { // @Param id path int true "Post ID" // @Param post body storage.PostCreate true "Post data" // @Produce json +// @Security Bearer // @Success 200 {object} models.SuccessResponse{data=storage.PostCreate} // @Failure 400 {object} models.ErrorResponse "Invalid ID format" // @Failure 500 {object} models.ErrorResponse "Internal server error" @@ -162,6 +164,7 @@ func (h *PostHandlers) UpdatePost(c *gin.Context) { // @Param id path int true "Post ID" // @Accept json // @Produce json +// @Security Bearer // @Failure 404 {object} models.ErrorResponse "Post not found" // @Failure 400 {object} models.ErrorResponse "Invalid ID format" // @Failure 500 {object} models.ErrorResponse "Internal server error"