diff --git a/modules/backend/main.go b/modules/backend/main.go index 0cffdcf..aab1287 100644 --- a/modules/backend/main.go +++ b/modules/backend/main.go @@ -25,18 +25,18 @@ import ( var AppConfig Config func main() { - if len(os.Args) != 2 { - AppConfig.Mode = "env" - } else { - AppConfig.Mode = "argv" - } + // if len(os.Args) != 2 { + // AppConfig.Mode = "env" + // } else { + // AppConfig.Mode = "argv" + // } - err := InitConfig() - if err != nil { - log.Fatalf("Failed to init config: %v\n", err) - } + // err := InitConfig() + // if err != nil { + // log.Fatalf("Failed to init config: %v\n", err) + // } - pool, err := pgxpool.New(context.Background(), AppConfig.DdUrl) + pool, err := pgxpool.New(context.Background(), os.Getenv("DATABASE_URL")) if err != nil { fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err) os.Exit(1) @@ -47,11 +47,16 @@ func main() { r := gin.Default() r.Use(middleware.CSRFMiddleware()) - r.Use(middleware.JWTAuthMiddleware(AppConfig.JwtPrivateKey)) - + // jwt middle will be here queries := sqlc.New(pool) - rmqConn, err := amqp091.Dial(AppConfig.rmqURL) + // === RabbitMQ setup === + rmqURL := os.Getenv("RABBITMQ_URL") + if rmqURL == "" { + rmqURL = "amqp://guest:guest@rabbitmq:5672/" + } + + rmqConn, err := amqp091.Dial(rmqURL) if err != nil { log.Fatalf("Failed to connect to RabbitMQ: %v", err) } @@ -63,7 +68,7 @@ func main() { server := handlers.NewServer(queries, publisher, rpcClient) r.Use(cors.New(cors.Config{ - AllowOrigins: []string{AppConfig.ServiceAddress}, + AllowOrigins: []string{"*"}, // allow all origins, change to specific domains in production AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "PATCH"}, AllowHeaders: []string{"Origin", "Content-Type", "Accept"}, ExposeHeaders: []string{"Content-Length"}, @@ -73,7 +78,7 @@ func main() { oapi.RegisterHandlers(r, oapi.NewStrictHandler( server, - + // сюда можно добавить middlewares, если нужно []oapi.StrictMiddlewareFunc{}, )) diff --git a/modules/backend/middlewares/access.go b/modules/backend/middlewares/access.go deleted file mode 100644 index 73200e8..0000000 --- a/modules/backend/middlewares/access.go +++ /dev/null @@ -1,109 +0,0 @@ -package middleware - -import ( - "context" - "errors" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/golang-jwt/jwt/v5" -) - -// ctxKey — приватный тип для ключа контекста -type ctxKey struct{} - -// ginContextKey — уникальный ключ для хранения *gin.Context -var ginContextKey = &ctxKey{} - -// GinContextToContext сохраняет *gin.Context в context.Context запроса -func GinContextToContext(c *gin.Context) { - ctx := context.WithValue(c.Request.Context(), ginContextKey, c) - c.Request = c.Request.WithContext(ctx) -} - -// GinContextFromContext извлекает *gin.Context из context.Context -func GinContextFromContext(ctx context.Context) (*gin.Context, bool) { - ginCtx, ok := ctx.Value(ginContextKey).(*gin.Context) - return ginCtx, ok -} - -func JWTAuthMiddleware(secret string) gin.HandlerFunc { - return func(c *gin.Context) { - // 1. Получаем access_token из cookie - tokenStr, err := c.Cookie("access_token") - if err != nil { - abortWithJSON(c, http.StatusUnauthorized, "missing access_token cookie") - return - } - - // 2. Парсим токен с MapClaims - token, err := jwt.Parse(tokenStr, func(t *jwt.Token) (interface{}, error) { - if t.Method != jwt.SigningMethodHS256 { - return nil, errors.New("unexpected signing method: " + t.Method.Alg()) - } - return []byte(secret), nil // ← конвертируем string → []byte - }) - if err != nil { - abortWithJSON(c, http.StatusUnauthorized, "invalid token: "+err.Error()) - return - } - - // 3. Проверяем валидность - if !token.Valid { - abortWithJSON(c, http.StatusUnauthorized, "token is invalid") - return - } - - // 4. Извлекаем user_id из claims - claims, ok := token.Claims.(jwt.MapClaims) - if !ok { - abortWithJSON(c, http.StatusUnauthorized, "invalid claims format") - return - } - - userID, ok := claims["user_id"].(string) - if !ok || userID == "" { - abortWithJSON(c, http.StatusUnauthorized, "user_id claim missing or invalid") - return - } - - // 5. Сохраняем в контексте - c.Set("user_id", userID) - - // 6. Для oapi-codegen — кладём gin.Context в request context - GinContextToContext(c) - - c.Next() - } -} - -// Вспомогательные функции (без изменений) -func UserIDFromGin(c *gin.Context) (string, bool) { - id, exists := c.Get("user_id") - if !exists { - return "", false - } - if s, ok := id.(string); ok { - return s, true - } - return "", false -} - -func UserIDFromContext(ctx context.Context) (string, error) { - ginCtx, ok := GinContextFromContext(ctx) - if !ok { - return "", errors.New("gin context not found") - } - userID, ok := UserIDFromGin(ginCtx) - if !ok { - return "", errors.New("user_id not found in context") - } - return userID, nil -} - -func abortWithJSON(c *gin.Context, code int, message string) { - c.AbortWithStatusJSON(code, gin.H{ - "error": "unauthorized", - "message": message, - }) -} diff --git a/modules/backend/types.go b/modules/backend/types.go index c4f70ed..20d3158 100644 --- a/modules/backend/types.go +++ b/modules/backend/types.go @@ -1,10 +1,12 @@ package main type Config struct { - Mode string - ServiceAddress string `toml:"ServiceAddress" env:"SERVICE_ADDRESS"` - DdUrl string `toml:"DbUrl" env:"DATABASE_URL"` - JwtPrivateKey string `toml:"JwtPrivateKey" env:"JWT_PRIVATE_KEY"` - LogLevel string `toml:"LogLevel" env:"LOG_LEVEL"` - rmqURL string `toml:"RabbitMQUrl" env:"RABBITMQ_URL"` + Mode string + LogLevel string `toml:"LogLevel" env:"LOG_LEVEL"` +} + +type Item struct { + ID int `json:"id"` + Title string `json:"title"` + Description string `json:"description"` }