diff --git a/api/_build/openapi.yaml b/api/_build/openapi.yaml index 58dd890..e85ddf9 100644 --- a/api/_build/openapi.yaml +++ b/api/_build/openapi.yaml @@ -120,8 +120,6 @@ paths: description: Title not found '500': description: Unknown server error - security: - - JwtAuthCookies: [] '/users/{user_id}': get: operationId: getUsersId @@ -158,8 +156,6 @@ paths: Password updates must be done via the dedicated auth-service (`/auth/`). Fields not provided in the request body remain unchanged. parameters: - - $ref: '#/components/parameters/accessToken' - - $ref: '#/components/parameters/csrfToken' - name: user_id in: path description: User ID (primary key) @@ -227,8 +223,6 @@ paths: description: 'Unprocessable Entity — semantic errors not caught by schema (e.g., invalid `avatar_id`)' '500': description: Unknown server error - security: - - JwtAuthCookies: [] '/users/{user_id}/titles': get: operationId: getUserTitles @@ -480,39 +474,6 @@ paths: description: Internal server error components: parameters: - accessToken: - name: access_token - in: cookie - required: true - schema: - type: string - format: jwt - example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.x.y - description: | - JWT access token. - csrfToken: - name: XSRF-TOKEN - in: cookie - required: true - schema: - type: string - pattern: '^[a-zA-Z0-9_-]{32,64}$' - example: abc123def456ghi789jkl012mno345pqr - description: | - Anti-CSRF token (Double Submit Cookie pattern). - Stored in non-HttpOnly cookie, readable by JavaScript. - Must be echoed in `X-XSRF-TOKEN` header for state-changing requests (POST/PUT/PATCH/DELETE). - csrfTokenHeader: - name: X-XSRF-TOKEN - in: header - required: true - schema: - type: string - pattern: '^[a-zA-Z0-9_-]{32,64}$' - description: | - Anti-CSRF token. Must match the `XSRF-TOKEN` cookie. - Required for all state-changing requests (POST/PUT/PATCH/DELETE). - example: abc123def456ghi789jkl012mno345pqr cursor: in: query name: cursor diff --git a/api/api.gen.go b/api/api.gen.go index 62450e0..c8fd9aa 100644 --- a/api/api.gen.go +++ b/api/api.gen.go @@ -16,10 +16,6 @@ import ( openapi_types "github.com/oapi-codegen/runtime/types" ) -const ( - JwtAuthCookiesScopes = "JwtAuthCookies.Scopes" -) - // Defines values for ReleaseSeason. const ( Fall ReleaseSeason = "fall" @@ -174,12 +170,6 @@ type UserTitleMini struct { // UserTitleStatus User's title status type UserTitleStatus string -// AccessToken defines model for accessToken. -type AccessToken = string - -// CsrfToken defines model for csrfToken. -type CsrfToken = string - // Cursor defines model for cursor. type Cursor = string @@ -229,17 +219,6 @@ type UpdateUserJSONBody struct { UserDesc *string `json:"user_desc,omitempty"` } -// UpdateUserParams defines parameters for UpdateUser. -type UpdateUserParams struct { - // AccessToken JWT access token. - AccessToken AccessToken `form:"access_token" json:"access_token"` - - // XSRFTOKEN Anti-CSRF token (Double Submit Cookie pattern). - // Stored in non-HttpOnly cookie, readable by JavaScript. - // Must be echoed in `X-XSRF-TOKEN` header for state-changing requests (POST/PUT/PATCH/DELETE). - XSRFTOKEN CsrfToken `form:"XSRF-TOKEN" json:"XSRF-TOKEN"` -} - // GetUserTitlesParams defines parameters for GetUserTitles. type GetUserTitlesParams struct { Cursor *Cursor `form:"cursor,omitempty" json:"cursor,omitempty"` @@ -297,7 +276,7 @@ type ServerInterface interface { GetUsersId(c *gin.Context, userId string, params GetUsersIdParams) // Partially update a user account // (PATCH /users/{user_id}) - UpdateUser(c *gin.Context, userId int64, params UpdateUserParams) + UpdateUser(c *gin.Context, userId int64) // Get user titles // (GET /users/{user_id}/titles) GetUserTitles(c *gin.Context, userId string, params GetUserTitlesParams) @@ -452,8 +431,6 @@ func (siw *ServerInterfaceWrapper) GetTitle(c *gin.Context) { return } - c.Set(JwtAuthCookiesScopes, []string{}) - // Parameter object where we will unmarshal all parameters from the context var params GetTitleParams @@ -524,47 +501,6 @@ func (siw *ServerInterfaceWrapper) UpdateUser(c *gin.Context) { return } - c.Set(JwtAuthCookiesScopes, []string{}) - - // Parameter object where we will unmarshal all parameters from the context - var params UpdateUserParams - - { - var cookie string - - if cookie, err = c.Cookie("access_token"); err == nil { - var value AccessToken - err = runtime.BindStyledParameterWithOptions("simple", "access_token", cookie, &value, runtime.BindStyledParameterOptions{Explode: true, Required: true}) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter access_token: %w", err), http.StatusBadRequest) - return - } - params.AccessToken = value - - } else { - siw.ErrorHandler(c, fmt.Errorf("Query argument access_token is required, but not found"), http.StatusBadRequest) - return - } - } - - { - var cookie string - - if cookie, err = c.Cookie("XSRF-TOKEN"); err == nil { - var value CsrfToken - err = runtime.BindStyledParameterWithOptions("simple", "XSRF-TOKEN", cookie, &value, runtime.BindStyledParameterOptions{Explode: true, Required: true}) - if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter XSRF-TOKEN: %w", err), http.StatusBadRequest) - return - } - params.XSRFTOKEN = value - - } else { - siw.ErrorHandler(c, fmt.Errorf("Query argument XSRF-TOKEN is required, but not found"), http.StatusBadRequest) - return - } - } - for _, middleware := range siw.HandlerMiddlewares { middleware(c) if c.IsAborted() { @@ -572,7 +508,7 @@ func (siw *ServerInterfaceWrapper) UpdateUser(c *gin.Context) { } } - siw.Handler.UpdateUser(c, userId, params) + siw.Handler.UpdateUser(c, userId) } // GetUserTitles operation middleware @@ -999,7 +935,6 @@ func (response GetUsersId500Response) VisitGetUsersIdResponse(w http.ResponseWri type UpdateUserRequestObject struct { UserId int64 `json:"user_id"` - Params UpdateUserParams Body *UpdateUserJSONRequestBody } @@ -1476,11 +1411,10 @@ func (sh *strictHandler) GetUsersId(ctx *gin.Context, userId string, params GetU } // UpdateUser operation middleware -func (sh *strictHandler) UpdateUser(ctx *gin.Context, userId int64, params UpdateUserParams) { +func (sh *strictHandler) UpdateUser(ctx *gin.Context, userId int64) { var request UpdateUserRequestObject request.UserId = userId - request.Params = params var body UpdateUserJSONRequestBody if err := ctx.ShouldBindJSON(&body); err != nil { diff --git a/api/parameters/_index.yaml b/api/parameters/_index.yaml index d2e12a8..6249e7d 100644 --- a/api/parameters/_index.yaml +++ b/api/parameters/_index.yaml @@ -1,10 +1,4 @@ cursor: $ref: "./cursor.yaml" title_sort: - $ref: "./title_sort.yaml" -accessToken: - $ref: "./access_token.yaml" -csrfToken: - $ref: "./xsrf_token_cookie.yaml" -csrfTokenHeader: - $ref: "./xsrf_token_header.yaml" \ No newline at end of file + $ref: "./title_sort.yaml" \ No newline at end of file diff --git a/api/parameters/access_token.yaml b/api/parameters/access_token.yaml deleted file mode 100644 index a7e727e..0000000 --- a/api/parameters/access_token.yaml +++ /dev/null @@ -1,9 +0,0 @@ -name: access_token -in: cookie -required: true -schema: - type: string - format: jwt -example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.x.y" -description: | - JWT access token. diff --git a/api/parameters/xsrf_token_cookie.yaml b/api/parameters/xsrf_token_cookie.yaml deleted file mode 100644 index cf85999..0000000 --- a/api/parameters/xsrf_token_cookie.yaml +++ /dev/null @@ -1,11 +0,0 @@ -name: XSRF-TOKEN -in: cookie -required: true -schema: - type: string - pattern: "^[a-zA-Z0-9_-]{32,64}$" -example: "abc123def456ghi789jkl012mno345pqr" -description: | - Anti-CSRF token (Double Submit Cookie pattern). - Stored in non-HttpOnly cookie, readable by JavaScript. - Must be echoed in `X-XSRF-TOKEN` header for state-changing requests (POST/PUT/PATCH/DELETE). \ No newline at end of file diff --git a/api/parameters/xsrf_token_header.yaml b/api/parameters/xsrf_token_header.yaml deleted file mode 100644 index ac14dc1..0000000 --- a/api/parameters/xsrf_token_header.yaml +++ /dev/null @@ -1,10 +0,0 @@ -name: X-XSRF-TOKEN -in: header -required: true -schema: - type: string - pattern: "^[a-zA-Z0-9_-]{32,64}$" -description: | - Anti-CSRF token. Must match the `XSRF-TOKEN` cookie. - Required for all state-changing requests (POST/PUT/PATCH/DELETE). -example: "abc123def456ghi789jkl012mno345pqr" \ No newline at end of file diff --git a/api/paths/titles-id.yaml b/api/paths/titles-id.yaml index f1b9c55..235743f 100644 --- a/api/paths/titles-id.yaml +++ b/api/paths/titles-id.yaml @@ -1,7 +1,5 @@ get: summary: Get title description - security: - - JwtAuthCookies: [] operationId: getTitle parameters: - in: path diff --git a/api/paths/users-id.yaml b/api/paths/users-id.yaml index 0f2f367..fe62e46 100644 --- a/api/paths/users-id.yaml +++ b/api/paths/users-id.yaml @@ -28,16 +28,12 @@ get: patch: summary: Partially update a user account - security: - - JwtAuthCookies: [] description: | Update selected user profile fields (excluding password). Password updates must be done via the dedicated auth-service (`/auth/`). Fields not provided in the request body remain unchanged. operationId: updateUser parameters: - - $ref: '../parameters/access_token.yaml' # ← для поля в UI и GoDoc - - $ref: '../parameters/xsrf_token_cookie.yaml' # ← для CSRF - name: user_id in: path required: true diff --git a/api/schemas/JWTAuth.yaml b/api/schemas/JWTAuth.yaml deleted file mode 100644 index 63c3baa..0000000 --- a/api/schemas/JWTAuth.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# type: apiKey -# in: cookie -# name: access_token -# scheme: bearer -# bearerFormat: JWT -# description: | -# JWT access token sent in `Cookie: access_token=...`. \ No newline at end of file diff --git a/api/schemas/_index.yaml b/api/schemas/_index.yaml index 0cc0f9d..d893ced 100644 --- a/api/schemas/_index.yaml +++ b/api/schemas/_index.yaml @@ -24,5 +24,3 @@ User: $ref: "./User.yaml" UserTitle: $ref: "./UserTitle.yaml" -# JwtAuth: -# $ref: "./JWTAuth.yaml" diff --git a/modules/backend/main.go b/modules/backend/main.go index aab1287..9f992a5 100644 --- a/modules/backend/main.go +++ b/modules/backend/main.go @@ -11,7 +11,6 @@ import ( oapi "nyanimedb/api" handlers "nyanimedb/modules/backend/handlers" - middleware "nyanimedb/modules/backend/middlewares" "nyanimedb/modules/backend/rmq" "github.com/gin-contrib/cors" @@ -46,8 +45,6 @@ func main() { r := gin.Default() - r.Use(middleware.CSRFMiddleware()) - // jwt middle will be here queries := sqlc.New(pool) // === RabbitMQ setup === @@ -66,6 +63,7 @@ func main() { rpcClient := rmq.NewRPCClient(rmqConn, 30*time.Second) server := handlers.NewServer(queries, publisher, rpcClient) + // r.LoadHTMLGlob("templates/*") r.Use(cors.New(cors.Config{ AllowOrigins: []string{"*"}, // allow all origins, change to specific domains in production diff --git a/modules/backend/middlewares/csrf.go b/modules/backend/middlewares/csrf.go deleted file mode 100644 index 41fad7b..0000000 --- a/modules/backend/middlewares/csrf.go +++ /dev/null @@ -1,70 +0,0 @@ -package middleware - -import ( - "crypto/subtle" - "net/http" - - "github.com/gin-gonic/gin" -) - -// CSRFMiddleware для Gin -func CSRFMiddleware() gin.HandlerFunc { - return func(c *gin.Context) { - // Пропускаем безопасные методы - if !isStateChangingMethod(c.Request.Method) { - c.Next() - return - } - - // 1. Получаем токен из заголовка - headerToken := c.GetHeader("X-XSRF-TOKEN") - if headerToken == "" { - c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ - "error": "missing X-XSRF-TOKEN header", - }) - return - } - - // 2. Получаем токен из cookie - cookie, err := c.Cookie("xsrf_token") - if err != nil { - c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ - "error": "missing xsrf_token cookie", - }) - return - } - - // 3. Безопасное сравнение - if subtle.ConstantTimeCompare([]byte(headerToken), []byte(cookie)) != 1 { - c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ - "error": "CSRF token mismatch", - }) - return - } - - // 4. Опционально: сохраняем токен в контексте - c.Set("csrf_token", headerToken) - c.Next() - } -} - -func isStateChangingMethod(method string) bool { - switch method { - case http.MethodPost, http.MethodPut, http.MethodPatch, http.MethodDelete: - return true - default: - return false - } -} - -// CSRFTokenFromGin извлекает токен из Gin context -func CSRFTokenFromGin(c *gin.Context) (string, bool) { - token, exists := c.Get("xsrf_token") - if !exists { - return "", false - } - if s, ok := token.(string); ok { - return s, true - } - return "", false -}