modified: begushiybashkir/bbvue/src/stores/auth.js
modified: begushiybashkir/bbvue/src/stores/user.js modified: begushiybashkir/bbvue/src/views/Login.vue modified: begushiybashkir/bbvue/src/views/Register.vue modified: serv_nginx/api_bb/.env modified: serv_nginx/api_bb/cmd/main.go modified: serv_nginx/api_bb/internal/handlers/auth.go modified: serv_nginx/api_bb/internal/handlers/handlers.go modified: serv_nginx/api_bb/internal/models/user.go modified: serv_nginx/api_bb/internal/routes/routes.go modified: serv_nginx/api_bb/internal/service/auth_service.go modified: serv_nginx/api_bb/pkg/logger/logger.go delete hash pass from auth_service it is fix the not loging becouse dowble hash password was password hash is in middlewares modified: begushiybashkir/bbvue/src/stores/auth.js modified: begushiybashkir/bbvue/src/stores/user.js modified: begushiybashkir/bbvue/src/views/Login.vue modified: begushiybashkir/bbvue/src/views/Register.vue modified: serv_nginx/api_bb/.env modified: serv_nginx/api_bb/cmd/main.go modified: serv_nginx/api_bb/internal/handlers/auth.go modified: serv_nginx/api_bb/internal/handlers/handlers.go modified: serv_nginx/api_bb/internal/models/user.go modified: serv_nginx/api_bb/internal/routes/routes.go modified: serv_nginx/api_bb/internal/service/auth_service.go modified: serv_nginx/api_bb/pkg/logger/logger.go delete hash password from auth_server becouse is dowble hash was second hash is beforeCreatehash in User struct
This commit is contained in:
@@ -2,7 +2,7 @@ import { defineStore } from 'pinia'
|
|||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import axios from 'axios'
|
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', () => {
|
export const useAuthStore = defineStore('auth', () => {
|
||||||
const user = ref(null)
|
const user = ref(null)
|
||||||
@@ -48,10 +48,10 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
error.value = ''
|
error.value = ''
|
||||||
|
|
||||||
try {
|
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,
|
email: userData.email,
|
||||||
password: userData.password
|
password: userData.password
|
||||||
})
|
})
|
||||||
@@ -75,8 +75,9 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
error.value = ''
|
error.value = ''
|
||||||
|
|
||||||
try {
|
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
|
const { token: authToken, user: userInfo } = response.data
|
||||||
|
console.log("authToken: " + authToken + "userInfo: " + userInfo)
|
||||||
|
|
||||||
setToken(authToken)
|
setToken(authToken)
|
||||||
setUser(userInfo)
|
setUser(userInfo)
|
||||||
@@ -95,7 +96,7 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await axios.post(`${API_BASE_URL}/logout`, {}, {
|
await axios.post(`${AUTH_API_URL}/logout`, {}, {
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${token.value}`
|
'Authorization': `Bearer ${token.value}`
|
||||||
}
|
}
|
||||||
@@ -115,7 +116,7 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
error.value = ''
|
error.value = ''
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(`${API_BASE_URL}/profile`)
|
const response = await axios.get(`${AUTH_API_URL}/profile`)
|
||||||
setUser(response.data)
|
setUser(response.data)
|
||||||
return { success: true, data: response.data }
|
return { success: true, data: response.data }
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
error.value = ''
|
error.value = ''
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// TODO: Заменить на реальный endpoint когда будет доступен
|
|
||||||
// const response = await axios.get(`${API_BASE_URL}/user/stats`)
|
// const response = await axios.get(`${API_BASE_URL}/user/stats`)
|
||||||
|
|
||||||
// Временные данные для демонстрации
|
// Временные данные для демонстрации
|
||||||
|
|||||||
@@ -5,31 +5,15 @@
|
|||||||
|
|
||||||
<form @submit.prevent="handleLogin" class="login-form">
|
<form @submit.prevent="handleLogin" class="login-form">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input
|
<input type="email" placeholder="Email" class="form-input" v-model="credentials.email" required
|
||||||
type="email"
|
:disabled="loading">
|
||||||
placeholder="Email"
|
|
||||||
class="form-input"
|
|
||||||
v-model="credentials.email"
|
|
||||||
required
|
|
||||||
:disabled="loading"
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input
|
<input type="password" placeholder="Пароль" class="form-input" v-model="credentials.password" required
|
||||||
type="password"
|
:disabled="loading">
|
||||||
placeholder="Пароль"
|
|
||||||
class="form-input"
|
|
||||||
v-model="credentials.password"
|
|
||||||
required
|
|
||||||
:disabled="loading"
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button type="submit" class="btn btn-primary" :disabled="loading">
|
||||||
type="submit"
|
|
||||||
class="btn btn-primary"
|
|
||||||
:disabled="loading"
|
|
||||||
>
|
|
||||||
{{ loading ? 'Вход...' : 'Войти' }}
|
{{ loading ? 'Вход...' : 'Войти' }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -78,7 +62,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
async handleLogin() {
|
async handleLogin() {
|
||||||
const result = await this.authStore.login(this.credentials)
|
const result = await this.authStore.login(this.credentials)
|
||||||
|
alert("register success" + result.success + "| data: " + result.data)
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
this.$router.push('/profile')
|
this.$router.push('/profile')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,8 +185,9 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log('Отправка данных регистрации:', { ...registerData, password: '***' })
|
console.log('Отправка данных регистрации:', { ...registerData, password: '***' })
|
||||||
|
alert("|" + registerData.email + "|" + registerData.password + "|")
|
||||||
const result = await this.authStore.register(registerData)
|
const result = await this.authStore.register(registerData)
|
||||||
|
alert("register seccess=" + result.success + "| data=" + result.data)
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
// Перенаправляем на страницу профиля после успешной регистрации
|
// Перенаправляем на страницу профиля после успешной регистрации
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ DB_USER=postgres
|
|||||||
DB_PASSWORD=postgres
|
DB_PASSWORD=postgres
|
||||||
DB_NAME=bb_db
|
DB_NAME=bb_db
|
||||||
DB_SSLMODE=disable
|
DB_SSLMODE=disable
|
||||||
JWT_SECRET=your-super-secret-jwt-key-change-in-production
|
|
||||||
|
|
||||||
|
|
||||||
# .env
|
# .env
|
||||||
|
|||||||
@@ -40,17 +40,45 @@ func main() {
|
|||||||
// Логируем начало работы
|
// Логируем начало работы
|
||||||
logger.LogApplicationStart(os.Getenv("REST_API_VERSION"), os.Getenv("ENVIRONMENT"), "")
|
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{})
|
db, err := gorm.Open(postgres.Open(cfg.DatabaseURL), &gorm.Config{})
|
||||||
if err != nil {
|
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 {
|
if err := db.AutoMigrate(&models.User{}); err != nil {
|
||||||
zapLogger.Fatal("database migration failed", zap.Error(err))
|
zapLogger.Fatal("database migration failed", zap.Error(err))
|
||||||
}
|
}
|
||||||
|
zapLogger.Info("database migration completed successfully")
|
||||||
|
|
||||||
// Настройка роутера
|
// Настройка роутера
|
||||||
router := routes.SetupRouter(db, cfg)
|
router := routes.SetupRouter(db, cfg)
|
||||||
@@ -78,6 +106,14 @@ func main() {
|
|||||||
<-quit
|
<-quit
|
||||||
zapLogger.Info("shutdown signal received")
|
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
|
// Graceful shutdown
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -89,4 +125,27 @@ func main() {
|
|||||||
|
|
||||||
logger.LogApplicationShutdown("graceful shutdown")
|
logger.LogApplicationShutdown("graceful shutdown")
|
||||||
close(done)
|
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 // Заглушка - нужно реализовать маскирование пароля
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"api_bb/internal/models"
|
"api_bb/internal/models"
|
||||||
@@ -201,6 +202,10 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
req.Email = strings.TrimSpace(req.Email)
|
||||||
|
req.Password = strings.TrimSpace(req.Password)
|
||||||
|
|
||||||
// Валидация
|
// Валидация
|
||||||
if req.Email == "" || req.Password == "" {
|
if req.Email == "" || req.Password == "" {
|
||||||
h.logger.Warn("validation failed",
|
h.logger.Warn("validation failed",
|
||||||
|
|||||||
@@ -2,44 +2,49 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"api_bb/internal/repository"
|
"api_bb/internal/config"
|
||||||
"api_bb/internal/service"
|
"api_bb/internal/repository"
|
||||||
"api_bb/internal/config"
|
"api_bb/internal/service"
|
||||||
"gorm.io/gorm"
|
"api_bb/pkg/logger"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
healthHandler *HealthHandler
|
healthHandler *HealthHandler
|
||||||
authHandler *AuthHandler
|
authHandler *AuthHandler
|
||||||
// Здесь будут добавлены другие обработчики
|
// Здесь будут добавлены другие обработчики
|
||||||
// userHandler *UserHandler
|
// userHandler *UserHandler
|
||||||
// eventHandler *EventHandler
|
// eventHandler *EventHandler
|
||||||
// reviewHandler *ReviewHandler
|
// reviewHandler *ReviewHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandler(db *gorm.DB, cfg *config.Config) *Handler {
|
func NewHandler(db *gorm.DB, cfg *config.Config) *Handler {
|
||||||
// Инициализация репозиториев
|
// Инициализация репозиториев
|
||||||
userRepo := repository.NewUserRepository(db)
|
userRepo := repository.NewUserRepository(db)
|
||||||
|
|
||||||
// Инициализация сервисов
|
// Initialize logger
|
||||||
jwtService := service.NewJWTService(cfg.JWTSecret)
|
baseLogger := logger.NewWrapper(logger.Get()) // Создаем базовый логгер
|
||||||
authService := service.NewAuthService(userRepo, jwtService)
|
|
||||||
|
// Инициализация сервисов
|
||||||
// Инициализация обработчиков
|
jwtService := service.NewJWTService(cfg.JWTSecret)
|
||||||
healthHandler := NewHealthHandler()
|
authService := service.NewAuthService(userRepo, jwtService, baseLogger)
|
||||||
authHandler := NewAuthHandler(authService, jwtService)
|
|
||||||
|
// Инициализация обработчиков
|
||||||
return &Handler{
|
healthHandler := NewHealthHandler()
|
||||||
healthHandler: healthHandler,
|
authHandler := NewAuthHandler(authService, jwtService)
|
||||||
authHandler: authHandler,
|
|
||||||
}
|
return &Handler{
|
||||||
|
healthHandler: healthHandler,
|
||||||
|
authHandler: authHandler,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Геттеры для обработчиков (опционально, для удобства)
|
// Геттеры для обработчиков (опционально, для удобства)
|
||||||
func (h *Handler) HealthHandler() *HealthHandler {
|
func (h *Handler) HealthHandler() *HealthHandler {
|
||||||
return h.healthHandler
|
return h.healthHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) AuthHandler() *AuthHandler {
|
func (h *Handler) AuthHandler() *AuthHandler {
|
||||||
return h.authHandler
|
return h.authHandler
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,11 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
@@ -35,8 +37,8 @@ func (u *User) HashPassword() error {
|
|||||||
|
|
||||||
// CheckPassword проверяет пароль
|
// CheckPassword проверяет пароль
|
||||||
func (u *User) CheckPassword(password string) bool {
|
func (u *User) CheckPassword(password string) bool {
|
||||||
err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
|
err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BeforeCreate hook для GORM
|
// BeforeCreate hook для GORM
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"api_bb/internal/handlers"
|
"api_bb/internal/handlers"
|
||||||
"api_bb/internal/repository"
|
"api_bb/internal/repository"
|
||||||
"api_bb/internal/service"
|
"api_bb/internal/service"
|
||||||
|
"api_bb/pkg/logger" // Добавьте импорт логгера
|
||||||
"api_bb/pkg/middleware"
|
"api_bb/pkg/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -25,9 +26,12 @@ func SetupRouter(db *gorm.DB, config *config.Config) http.Handler {
|
|||||||
// Initialize repositories
|
// Initialize repositories
|
||||||
userRepo := repository.NewUserRepository(db)
|
userRepo := repository.NewUserRepository(db)
|
||||||
|
|
||||||
// Initialize services
|
// Initialize logger
|
||||||
|
baseLogger := logger.NewWrapper(logger.Get()) // Создаем базовый логгер
|
||||||
|
|
||||||
|
// Initialize services with logger
|
||||||
jwtService := service.NewJWTService(config.JWTSecret)
|
jwtService := service.NewJWTService(config.JWTSecret)
|
||||||
authService := service.NewAuthService(userRepo, jwtService)
|
authService := service.NewAuthService(userRepo, jwtService, baseLogger) // Передаем логгер
|
||||||
|
|
||||||
// Initialize handlers
|
// Initialize handlers
|
||||||
healthHandler := handlers.NewHealthHandler()
|
healthHandler := handlers.NewHealthHandler()
|
||||||
@@ -36,7 +40,6 @@ func SetupRouter(db *gorm.DB, config *config.Config) http.Handler {
|
|||||||
|
|
||||||
// Health routes
|
// Health routes
|
||||||
r.Mount("/api", healthHandler.Routes())
|
r.Mount("/api", healthHandler.Routes())
|
||||||
|
|
||||||
|
|
||||||
// API v1 routes
|
// API v1 routes
|
||||||
r.Route("/v1", func(r chi.Router) {
|
r.Route("/v1", func(r chi.Router) {
|
||||||
|
|||||||
@@ -5,98 +5,189 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"api_bb/internal/models"
|
"api_bb/internal/models"
|
||||||
"api_bb/internal/repository"
|
"api_bb/internal/repository"
|
||||||
|
"api_bb/pkg/logger"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AuthService interface {
|
type AuthService interface {
|
||||||
Register(user *models.User) error
|
Register(user *models.User) error
|
||||||
Login(email, password string) (*models.User, string, error)
|
Login(email, password string) (*models.User, string, error)
|
||||||
GetUserProfile(userID uint) (*models.User, error)
|
GetUserProfile(userID uint) (*models.User, error)
|
||||||
UpdateProfile(user *models.User) error
|
UpdateProfile(user *models.User) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type authService struct {
|
type authService struct {
|
||||||
userRepo repository.UserRepository
|
userRepo repository.UserRepository
|
||||||
jwtService JWTService
|
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{
|
return &authService{
|
||||||
userRepo: userRepo,
|
userRepo: userRepo,
|
||||||
jwtService: jwtService,
|
jwtService: jwtService,
|
||||||
|
logger: serviceLogger,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *authService) UpdateProfile(user *models.User) error {
|
func (s *authService) UpdateProfile(user *models.User) error {
|
||||||
// Находим существующего пользователя через репозиторий
|
s.logger.Info("Updating user profile",
|
||||||
existingUser, err := s.userRepo.FindByID(user.ID)
|
zap.Uint("user_id", user.ID),
|
||||||
if err != nil {
|
)
|
||||||
return fmt.Errorf("user not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Создаем карту для обновления только разрешенных полей
|
existingUser, err := s.userRepo.FindByID(user.ID)
|
||||||
updateData := &models.User{
|
if err != nil {
|
||||||
ID: existingUser.ID, // Важно сохранить ID
|
s.logger.Warn("User not found for profile update",
|
||||||
FirstName: user.FirstName,
|
zap.Uint("user_id", user.ID),
|
||||||
LastName: user.LastName,
|
zap.Error(err),
|
||||||
Phone: user.Phone,
|
)
|
||||||
Experience: user.Experience,
|
return fmt.Errorf("user not found")
|
||||||
Goals: user.Goals,
|
}
|
||||||
Newsletter: user.Newsletter,
|
|
||||||
UpdatedAt: time.Now(),
|
|
||||||
// Не обновляем: Email, Password, Role, CreatedAt
|
|
||||||
}
|
|
||||||
|
|
||||||
// Сохраняем обновленные данные через репозиторий
|
updateData := &models.User{
|
||||||
if err := s.userRepo.Update(updateData); err != nil {
|
ID: existingUser.ID,
|
||||||
return err
|
FirstName: user.FirstName,
|
||||||
}
|
LastName: user.LastName,
|
||||||
|
Phone: user.Phone,
|
||||||
|
Experience: user.Experience,
|
||||||
|
Goals: user.Goals,
|
||||||
|
Newsletter: user.Newsletter,
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
// Копируем обновленные данные обратно в переданный объект
|
s.logger.Debug("Profile update data prepared",
|
||||||
user.Email = existingUser.Email
|
zap.Uint("user_id", user.ID),
|
||||||
user.Password = existingUser.Password
|
zap.String("first_name", updateData.FirstName),
|
||||||
user.Role = existingUser.Role
|
zap.String("last_name", updateData.LastName),
|
||||||
user.CreatedAt = existingUser.CreatedAt
|
)
|
||||||
user.UpdatedAt = updateData.UpdatedAt
|
|
||||||
|
|
||||||
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 {
|
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)
|
existingUser, err := s.userRepo.FindByEmail(user.Email)
|
||||||
if err == nil && existingUser != nil {
|
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")
|
return errors.New("user with this email already exists")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Хешируем пароль
|
err = s.userRepo.Create(user)
|
||||||
if err := user.HashPassword(); err != nil {
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to create user in database",
|
||||||
|
zap.String("email", user.Email),
|
||||||
|
zap.Error(err),
|
||||||
|
)
|
||||||
return 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) {
|
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)
|
user, err := s.userRepo.FindByEmail(email)
|
||||||
if err != nil {
|
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) {
|
s.logger.Debug("User found for login",
|
||||||
return nil, "", errors.New("invalid email or password")
|
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)
|
token, err := s.jwtService.GenerateToken(user.ID, user.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
s.logger.Error("Failed to generate JWT token",
|
||||||
|
zap.Uint("user_id", user.ID),
|
||||||
|
zap.Error(err),
|
||||||
|
)
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return user, token, nil
|
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) {
|
func (s *authService) GetUserProfile(userID uint) (*models.User, error) {
|
||||||
return s.userRepo.FindByID(userID)
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package logger
|
|||||||
import (
|
import (
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"go.uber.org/zap/zapcore"
|
"go.uber.org/zap/zapcore"
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var globalLogger *zap.Logger
|
var globalLogger *zap.Logger
|
||||||
|
|||||||
Reference in New Issue
Block a user