diff --git a/begushiybashkir/bbvue/src/stores/auth.js b/begushiybashkir/bbvue/src/stores/auth.js index 20abafd..de05a2b 100644 --- a/begushiybashkir/bbvue/src/stores/auth.js +++ b/begushiybashkir/bbvue/src/stores/auth.js @@ -2,7 +2,7 @@ import { defineStore } from 'pinia' import { ref, computed } from 'vue' import axios from 'axios' -const API_BASE_URL = 'https://begushiybashkir.ru/api/v1/auth' +const AUTH_API_URL = 'https://begushiybashkir.ru/api/v1/auth' export const useAuthStore = defineStore('auth', () => { const user = ref(null) @@ -48,10 +48,10 @@ export const useAuthStore = defineStore('auth', () => { error.value = '' try { - const response = await axios.post(`${API_BASE_URL}/register`, userData) + const response = await axios.post(`${AUTH_API_URL}/register`, userData) // После успешной регистрации автоматически логинимся - const loginResponse = await axios.post(`${API_BASE_URL}/login`, { + const loginResponse = await axios.post(`${AUTH_API_URL}/login`, { email: userData.email, password: userData.password }) @@ -75,8 +75,9 @@ export const useAuthStore = defineStore('auth', () => { error.value = '' try { - const response = await axios.post(`${API_BASE_URL}/login`, credentials) + const response = await axios.post(`${AUTH_API_URL}/login`, credentials) const { token: authToken, user: userInfo } = response.data + console.log("authToken: " + authToken + "userInfo: " + userInfo) setToken(authToken) setUser(userInfo) @@ -95,7 +96,7 @@ export const useAuthStore = defineStore('auth', () => { loading.value = true try { - await axios.post(`${API_BASE_URL}/logout`, {}, { + await axios.post(`${AUTH_API_URL}/logout`, {}, { headers: { 'Authorization': `Bearer ${token.value}` } @@ -115,7 +116,7 @@ export const useAuthStore = defineStore('auth', () => { error.value = '' try { - const response = await axios.get(`${API_BASE_URL}/profile`) + const response = await axios.get(`${AUTH_API_URL}/profile`) setUser(response.data) return { success: true, data: response.data } } catch (err) { diff --git a/begushiybashkir/bbvue/src/stores/user.js b/begushiybashkir/bbvue/src/stores/user.js index b8bb4d3..7124a5a 100644 --- a/begushiybashkir/bbvue/src/stores/user.js +++ b/begushiybashkir/bbvue/src/stores/user.js @@ -17,7 +17,6 @@ export const useUserStore = defineStore('user', () => { error.value = '' try { - // TODO: Заменить на реальный endpoint когда будет доступен // const response = await axios.get(`${API_BASE_URL}/user/stats`) // Временные данные для демонстрации diff --git a/begushiybashkir/bbvue/src/views/Login.vue b/begushiybashkir/bbvue/src/views/Login.vue index 75f9541..2de6431 100644 --- a/begushiybashkir/bbvue/src/views/Login.vue +++ b/begushiybashkir/bbvue/src/views/Login.vue @@ -5,31 +5,15 @@
- +
- +
- - @@ -78,7 +62,7 @@ export default { methods: { async handleLogin() { const result = await this.authStore.login(this.credentials) - + alert("register success" + result.success + "| data: " + result.data) if (result.success) { this.$router.push('/profile') } diff --git a/begushiybashkir/bbvue/src/views/Register.vue b/begushiybashkir/bbvue/src/views/Register.vue index d079af2..de2612c 100644 --- a/begushiybashkir/bbvue/src/views/Register.vue +++ b/begushiybashkir/bbvue/src/views/Register.vue @@ -185,8 +185,9 @@ export default { } console.log('Отправка данных регистрации:', { ...registerData, password: '***' }) - + alert("|" + registerData.email + "|" + registerData.password + "|") const result = await this.authStore.register(registerData) + alert("register seccess=" + result.success + "| data=" + result.data) if (result.success) { // Перенаправляем на страницу профиля после успешной регистрации diff --git a/serv_nginx/api_bb/.env b/serv_nginx/api_bb/.env index c5d5e5f..2829a80 100644 --- a/serv_nginx/api_bb/.env +++ b/serv_nginx/api_bb/.env @@ -5,7 +5,6 @@ DB_USER=postgres DB_PASSWORD=postgres DB_NAME=bb_db DB_SSLMODE=disable -JWT_SECRET=your-super-secret-jwt-key-change-in-production # .env diff --git a/serv_nginx/api_bb/cmd/main.go b/serv_nginx/api_bb/cmd/main.go index 991364d..3c2aa3e 100644 --- a/serv_nginx/api_bb/cmd/main.go +++ b/serv_nginx/api_bb/cmd/main.go @@ -40,17 +40,45 @@ func main() { // Логируем начало работы logger.LogApplicationStart(os.Getenv("REST_API_VERSION"), os.Getenv("ENVIRONMENT"), "") + // Логирование попытки подключения к БД + zapLogger.Info("attempting to connect to database", + zap.String("host", extractHostFromDSN(cfg.DatabaseURL)), // функция для извлечения хоста из DSN + zap.String("database", extractDBNameFromDSN(cfg.DatabaseURL)), // функция для извлечения имени БД + ) // Подключение к базе данных db, err := gorm.Open(postgres.Open(cfg.DatabaseURL), &gorm.Config{}) if err != nil { - zapLogger.Fatal("failed to connect to database", zap.Error(err)) + zapLogger.Fatal("failed to connect to database", + zap.Error(err), + zap.String("database_url", maskPassword(cfg.DatabaseURL)), // маскируем пароль в логах + ) } + // Логирование успешного подключения к БД + zapLogger.Info("successfully connected to database", + zap.String("host", extractHostFromDSN(cfg.DatabaseURL)), + zap.String("database", extractDBNameFromDSN(cfg.DatabaseURL)), + ) + + // Проверка соединения с БД + sqlDB, err := db.DB() + if err != nil { + zapLogger.Fatal("failed to get database instance", zap.Error(err)) + } + + if err := sqlDB.Ping(); err != nil { + zapLogger.Fatal("database ping failed", zap.Error(err)) + } + + zapLogger.Info("database ping successful") + // Автомиграция + zapLogger.Info("starting database migration") if err := db.AutoMigrate(&models.User{}); err != nil { zapLogger.Fatal("database migration failed", zap.Error(err)) } + zapLogger.Info("database migration completed successfully") // Настройка роутера router := routes.SetupRouter(db, cfg) @@ -78,6 +106,14 @@ func main() { <-quit zapLogger.Info("shutdown signal received") + // Логирование закрытия соединения с БД + zapLogger.Info("closing database connection") + if err := sqlDB.Close(); err != nil { + zapLogger.Error("failed to close database connection", zap.Error(err)) + } else { + zapLogger.Info("database connection closed successfully") + } + // Graceful shutdown ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() @@ -89,4 +125,27 @@ func main() { logger.LogApplicationShutdown("graceful shutdown") close(done) +} + +// Вспомогательные функции для работы с DSN + +// extractHostFromDSN извлекает хост из DSN строки +func extractHostFromDSN(dsn string) string { + // Простая реализация - в продакшене лучше использовать парсер DSN + // Для postgres DSN формата: "host=localhost user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai" + // Можно использовать более сложный парсер или регулярные выражения + return dsn // Заглушка - нужно реализовать парсинг DSN +} + +// extractDBNameFromDSN извлекает имя базы данных из DSN строки +func extractDBNameFromDSN(dsn string) string { + // Аналогично extractHostFromDSN - нужно реализовать парсинг + return dsn // Заглушка - нужно реализовать парсинг DSN +} + +// maskPassword маскирует пароль в DSN строке для безопасного логирования +func maskPassword(dsn string) string { + // Простая реализация - заменяет пароль на *** + // В продакшене нужно использовать более надежный метод + return dsn // Заглушка - нужно реализовать маскирование пароля } \ No newline at end of file diff --git a/serv_nginx/api_bb/internal/handlers/auth.go b/serv_nginx/api_bb/internal/handlers/auth.go index abb7664..eaa0a75 100644 --- a/serv_nginx/api_bb/internal/handlers/auth.go +++ b/serv_nginx/api_bb/internal/handlers/auth.go @@ -6,6 +6,7 @@ import ( "encoding/json" "io" "net/http" + "strings" "time" "api_bb/internal/models" @@ -201,6 +202,10 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) { return } + + req.Email = strings.TrimSpace(req.Email) + req.Password = strings.TrimSpace(req.Password) + // Валидация if req.Email == "" || req.Password == "" { h.logger.Warn("validation failed", diff --git a/serv_nginx/api_bb/internal/handlers/handlers.go b/serv_nginx/api_bb/internal/handlers/handlers.go index 492c1a6..67e7b28 100644 --- a/serv_nginx/api_bb/internal/handlers/handlers.go +++ b/serv_nginx/api_bb/internal/handlers/handlers.go @@ -2,44 +2,49 @@ package handlers import ( - "api_bb/internal/repository" - "api_bb/internal/service" - "api_bb/internal/config" - "gorm.io/gorm" + "api_bb/internal/config" + "api_bb/internal/repository" + "api_bb/internal/service" + "api_bb/pkg/logger" + + "gorm.io/gorm" ) type Handler struct { - healthHandler *HealthHandler - authHandler *AuthHandler - // Здесь будут добавлены другие обработчики - // userHandler *UserHandler - // eventHandler *EventHandler - // reviewHandler *ReviewHandler + healthHandler *HealthHandler + authHandler *AuthHandler + // Здесь будут добавлены другие обработчики + // userHandler *UserHandler + // eventHandler *EventHandler + // reviewHandler *ReviewHandler } func NewHandler(db *gorm.DB, cfg *config.Config) *Handler { - // Инициализация репозиториев - userRepo := repository.NewUserRepository(db) - - // Инициализация сервисов - jwtService := service.NewJWTService(cfg.JWTSecret) - authService := service.NewAuthService(userRepo, jwtService) - - // Инициализация обработчиков - healthHandler := NewHealthHandler() - authHandler := NewAuthHandler(authService, jwtService) - - return &Handler{ - healthHandler: healthHandler, - authHandler: authHandler, - } + // Инициализация репозиториев + userRepo := repository.NewUserRepository(db) + + // Initialize logger + baseLogger := logger.NewWrapper(logger.Get()) // Создаем базовый логгер + + // Инициализация сервисов + jwtService := service.NewJWTService(cfg.JWTSecret) + authService := service.NewAuthService(userRepo, jwtService, baseLogger) + + // Инициализация обработчиков + healthHandler := NewHealthHandler() + authHandler := NewAuthHandler(authService, jwtService) + + return &Handler{ + healthHandler: healthHandler, + authHandler: authHandler, + } } // Геттеры для обработчиков (опционально, для удобства) func (h *Handler) HealthHandler() *HealthHandler { - return h.healthHandler + return h.healthHandler } func (h *Handler) AuthHandler() *AuthHandler { - return h.authHandler -} \ No newline at end of file + return h.authHandler +} diff --git a/serv_nginx/api_bb/internal/models/user.go b/serv_nginx/api_bb/internal/models/user.go index 6395931..57cdfe8 100644 --- a/serv_nginx/api_bb/internal/models/user.go +++ b/serv_nginx/api_bb/internal/models/user.go @@ -2,9 +2,11 @@ package models import ( + "time" + "golang.org/x/crypto/bcrypt" "gorm.io/gorm" - "time" + ) type User struct { @@ -35,8 +37,8 @@ func (u *User) HashPassword() error { // CheckPassword проверяет пароль func (u *User) CheckPassword(password string) bool { - err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password)) - return err == nil + err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password)) + return err == nil } // BeforeCreate hook для GORM diff --git a/serv_nginx/api_bb/internal/routes/routes.go b/serv_nginx/api_bb/internal/routes/routes.go index 1f4d193..3a356fb 100644 --- a/serv_nginx/api_bb/internal/routes/routes.go +++ b/serv_nginx/api_bb/internal/routes/routes.go @@ -11,6 +11,7 @@ import ( "api_bb/internal/handlers" "api_bb/internal/repository" "api_bb/internal/service" + "api_bb/pkg/logger" // Добавьте импорт логгера "api_bb/pkg/middleware" ) @@ -25,9 +26,12 @@ func SetupRouter(db *gorm.DB, config *config.Config) http.Handler { // Initialize repositories userRepo := repository.NewUserRepository(db) - // Initialize services + // Initialize logger + baseLogger := logger.NewWrapper(logger.Get()) // Создаем базовый логгер + + // Initialize services with logger jwtService := service.NewJWTService(config.JWTSecret) - authService := service.NewAuthService(userRepo, jwtService) + authService := service.NewAuthService(userRepo, jwtService, baseLogger) // Передаем логгер // Initialize handlers healthHandler := handlers.NewHealthHandler() @@ -36,7 +40,6 @@ func SetupRouter(db *gorm.DB, config *config.Config) http.Handler { // Health routes r.Mount("/api", healthHandler.Routes()) - // API v1 routes r.Route("/v1", func(r chi.Router) { diff --git a/serv_nginx/api_bb/internal/service/auth_service.go b/serv_nginx/api_bb/internal/service/auth_service.go index 60b1d52..bd6ca2a 100644 --- a/serv_nginx/api_bb/internal/service/auth_service.go +++ b/serv_nginx/api_bb/internal/service/auth_service.go @@ -5,98 +5,189 @@ import ( "errors" "fmt" "time" - + "api_bb/internal/models" "api_bb/internal/repository" + "api_bb/pkg/logger" + + "go.uber.org/zap" + "golang.org/x/crypto/bcrypt" ) type AuthService interface { Register(user *models.User) error Login(email, password string) (*models.User, string, error) GetUserProfile(userID uint) (*models.User, error) - UpdateProfile(user *models.User) error + UpdateProfile(user *models.User) error } type authService struct { - userRepo repository.UserRepository + userRepo repository.UserRepository jwtService JWTService + logger logger.Interface } -func NewAuthService(userRepo repository.UserRepository, jwtService JWTService) AuthService { +func NewAuthService(userRepo repository.UserRepository, jwtService JWTService, log logger.Interface) AuthService { + // Создаем логгер с контекстом для сервиса + serviceLogger := log.With(zap.String("service", "auth")) + return &authService{ - userRepo: userRepo, + userRepo: userRepo, jwtService: jwtService, + logger: serviceLogger, } } func (s *authService) UpdateProfile(user *models.User) error { - // Находим существующего пользователя через репозиторий - existingUser, err := s.userRepo.FindByID(user.ID) - if err != nil { - return fmt.Errorf("user not found") - } + s.logger.Info("Updating user profile", + zap.Uint("user_id", user.ID), + ) - // Создаем карту для обновления только разрешенных полей - updateData := &models.User{ - ID: existingUser.ID, // Важно сохранить ID - FirstName: user.FirstName, - LastName: user.LastName, - Phone: user.Phone, - Experience: user.Experience, - Goals: user.Goals, - Newsletter: user.Newsletter, - UpdatedAt: time.Now(), - // Не обновляем: Email, Password, Role, CreatedAt - } + existingUser, err := s.userRepo.FindByID(user.ID) + if err != nil { + s.logger.Warn("User not found for profile update", + zap.Uint("user_id", user.ID), + zap.Error(err), + ) + return fmt.Errorf("user not found") + } - // Сохраняем обновленные данные через репозиторий - if err := s.userRepo.Update(updateData); err != nil { - return err - } + updateData := &models.User{ + ID: existingUser.ID, + FirstName: user.FirstName, + LastName: user.LastName, + Phone: user.Phone, + Experience: user.Experience, + Goals: user.Goals, + Newsletter: user.Newsletter, + UpdatedAt: time.Now(), + } - // Копируем обновленные данные обратно в переданный объект - user.Email = existingUser.Email - user.Password = existingUser.Password - user.Role = existingUser.Role - user.CreatedAt = existingUser.CreatedAt - user.UpdatedAt = updateData.UpdatedAt + s.logger.Debug("Profile update data prepared", + zap.Uint("user_id", user.ID), + zap.String("first_name", updateData.FirstName), + zap.String("last_name", updateData.LastName), + ) - return nil + if err := s.userRepo.Update(updateData); err != nil { + s.logger.Error("Failed to update user profile", + zap.Uint("user_id", user.ID), + zap.Error(err), + ) + return err + } + + user.Email = existingUser.Email + user.Password = existingUser.Password + user.Role = existingUser.Role + user.CreatedAt = existingUser.CreatedAt + user.UpdatedAt = updateData.UpdatedAt + + s.logger.Info("User profile updated successfully", + zap.Uint("user_id", user.ID), + ) + + return nil } func (s *authService) Register(user *models.User) error { - // Проверяем, существует ли пользователь + s.logger.Info("Registering new user", + zap.String("email", user.Email), + ) + existingUser, err := s.userRepo.FindByEmail(user.Email) if err == nil && existingUser != nil { + s.logger.Warn("Registration failed - email already exists", + zap.String("email", user.Email), + ) return errors.New("user with this email already exists") } - - // Хешируем пароль - if err := user.HashPassword(); err != nil { + + err = s.userRepo.Create(user) + if err != nil { + s.logger.Error("Failed to create user in database", + zap.String("email", user.Email), + zap.Error(err), + ) return err } - - return s.userRepo.Create(user) + + s.logger.Info("User registered successfully", + zap.Uint("user_id", user.ID), + zap.String("email", user.Email), + ) + + return nil } func (s *authService) Login(email, password string) (*models.User, string, error) { + s.logger.Info("Login attempt", + zap.String("email", email), + zap.Int("password_length", len(password)), + ) + user, err := s.userRepo.FindByEmail(email) if err != nil { - return nil, "", errors.New("invalid email or password") + s.logger.Warn("Login failed - user not found", + zap.String("email", email), + zap.Error(err), + ) + return nil, "", errors.New("invalid email") } - - if !user.CheckPassword(password) { - return nil, "", errors.New("invalid email or password") + + s.logger.Debug("User found for login", + zap.Uint("user_id", user.ID), + zap.String("stored_hash_prefix", user.Password[:min(10, len(user.Password))]), + ) + + // Проверяем пароль + err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)) + if err != nil { + s.logger.Warn("Login failed - invalid password", + zap.Uint("user_id", user.ID), + zap.String("email", email), + zap.Error(err), + ) + return nil, "", errors.New("invalid password") } - + + s.logger.Info("Login successful", + zap.Uint("user_id", user.ID), + zap.String("email", email), + ) + token, err := s.jwtService.GenerateToken(user.ID, user.Email) if err != nil { + s.logger.Error("Failed to generate JWT token", + zap.Uint("user_id", user.ID), + zap.Error(err), + ) return nil, "", err } - + return user, token, nil } +func min(a, b int) int { + if a < b { + return a + } + return b +} + func (s *authService) GetUserProfile(userID uint) (*models.User, error) { - return s.userRepo.FindByID(userID) -} \ No newline at end of file + s.logger.Debug("Getting user profile", + zap.Uint("user_id", userID), + ) + + user, err := s.userRepo.FindByID(userID) + if err != nil { + s.logger.Warn("Failed to get user profile", + zap.Uint("user_id", userID), + zap.Error(err), + ) + return nil, err + } + + return user, nil +} diff --git a/serv_nginx/api_bb/pkg/logger/logger.go b/serv_nginx/api_bb/pkg/logger/logger.go index a263e86..4602535 100644 --- a/serv_nginx/api_bb/pkg/logger/logger.go +++ b/serv_nginx/api_bb/pkg/logger/logger.go @@ -4,6 +4,7 @@ package logger import ( "go.uber.org/zap" "go.uber.org/zap/zapcore" + ) var globalLogger *zap.Logger