d45c5841dc
modified: main_dc/yalarba/api_yal/go.sum modified: main_dc/yalarba/api_yal/internal/domain/auth/dto.go modified: main_dc/yalarba/api_yal/internal/domain/auth/handler.go modified: main_dc/yalarba/api_yal/internal/domain/auth/router.go modified: main_dc/yalarba/api_yal/internal/domain/auth/servcie.go new file: main_dc/yalarba/api_yal/internal/middleware/auth.go deleted: main_dc/yalarba/api_yal/internal/middleware/authMiddleware.go modified: main_dc/yalarba/api_yal/internal/router/router.go set auth domain, not tested
251 lines
7.1 KiB
Go
251 lines
7.1 KiB
Go
package auth
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"api_yal/internal/logger"
|
|
"api_yal/internal/middleware"
|
|
|
|
"github.com/go-playground/validator/v10"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// AuthHandler обработчик для аутентификации
|
|
type AuthHandler struct {
|
|
authService AuthService
|
|
validator *validator.Validate
|
|
}
|
|
|
|
// NewAuthHandler создает новый экземпляр AuthHandler
|
|
func NewAuthHandler(authService *AuthService) *AuthHandler {
|
|
return &AuthHandler{
|
|
authService: *authService,
|
|
validator: validator.New(),
|
|
}
|
|
}
|
|
|
|
// Register регистрация аккаунта пользователя
|
|
func (h *AuthHandler) Register(w http.ResponseWriter, r *http.Request) {
|
|
l := logger.Get()
|
|
l.Debug("Регистрация нового пользователя AuthHandler")
|
|
|
|
var req RegisterRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "Invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := h.validator.Struct(req); err != nil {
|
|
var invalidValidationError *validator.InvalidValidationError
|
|
if errors.As(err, &invalidValidationError) {
|
|
http.Error(w, "Invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var errs []string
|
|
for _, err := range err.(validator.ValidationErrors) {
|
|
errs = append(errs, fmt.Sprintf("field %s is invalid: %s", err.Field(), err.Tag()))
|
|
}
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"error": "Validation failed",
|
|
"fields": errs,
|
|
})
|
|
return
|
|
}
|
|
|
|
response, err := h.authService.Register(req)
|
|
if err != nil {
|
|
l.Error("Ошибка регистрации: %v", zap.Error(err))
|
|
|
|
status := http.StatusInternalServerError
|
|
message := "Registration failed"
|
|
|
|
if errors.Is(err, ErrUserAlreadyExists) {
|
|
status = http.StatusConflict
|
|
message = "User with this email already exists"
|
|
}
|
|
|
|
http.Error(w, message, status)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusCreated)
|
|
json.NewEncoder(w).Encode(response)
|
|
}
|
|
|
|
// Login вход пользователя
|
|
func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) {
|
|
l := logger.Get()
|
|
l.Debug("Вход пользователя AuthHandler")
|
|
|
|
var req LoginRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "Invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := h.validator.Struct(req); err != nil {
|
|
var invalidValidationError *validator.InvalidValidationError
|
|
if errors.As(err, &invalidValidationError) {
|
|
http.Error(w, "Invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var errs []string
|
|
for _, err := range err.(validator.ValidationErrors) {
|
|
errs = append(errs, fmt.Sprintf("field %s is invalid: %s", err.Field(), err.Tag()))
|
|
}
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"error": "Validation failed",
|
|
"fields": errs,
|
|
})
|
|
return
|
|
}
|
|
|
|
response, err := h.authService.Login(req)
|
|
if err != nil {
|
|
l.Error("Ошибка входа: %v", zap.Error(err))
|
|
|
|
status := http.StatusUnauthorized
|
|
message := "Login failed"
|
|
|
|
if errors.Is(err, ErrUserNotFound) {
|
|
message = "User not found"
|
|
} else if errors.Is(err, ErrInvalidPassword) {
|
|
message = "Invalid password"
|
|
}
|
|
|
|
http.Error(w, message, status)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(response)
|
|
}
|
|
|
|
// RefreshToken обновление токена
|
|
func (h *AuthHandler) RefreshToken(w http.ResponseWriter, r *http.Request) {
|
|
l := logger.Get()
|
|
l.Debug("Обновление токена AuthHandler")
|
|
|
|
// Получаем токен из заголовка Authorization
|
|
authHeader := r.Header.Get("Authorization")
|
|
if authHeader == "" {
|
|
http.Error(w, "Authorization header required", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
// Ожидаем формат "Bearer <token>"
|
|
parts := strings.Split(authHeader, " ")
|
|
if len(parts) != 2 || strings.ToLower(parts[0]) != "bearer" {
|
|
http.Error(w, "Invalid authorization header format", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
response, err := h.authService.RefreshToken(parts[1])
|
|
if err != nil {
|
|
l.Error("Ошибка обновления токена: %v", zap.Error(err))
|
|
http.Error(w, "Token refresh failed", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(response)
|
|
}
|
|
|
|
// Logout выход пользователя
|
|
func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) {
|
|
l := logger.Get()
|
|
l.Debug("Выход пользователя AuthHandler")
|
|
|
|
// Получаем ID пользователя из контекста (устанавливается middleware)
|
|
userID, ok := r.Context().Value(middleware.UserIDKey).(uint)
|
|
if !ok {
|
|
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
if err := h.authService.Logout(userID); err != nil {
|
|
l.Error("Ошибка выхода: %v", zap.Error(err))
|
|
http.Error(w, "Logout failed", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(map[string]string{
|
|
"message": "Successfully logged out",
|
|
})
|
|
}
|
|
|
|
// GetProfile получение профиля пользователя
|
|
func (h *AuthHandler) GetProfile(w http.ResponseWriter, r *http.Request) {
|
|
l := logger.Get()
|
|
l.Debug("Получение профиля пользователя")
|
|
|
|
// Получаем ID пользователя из контекста
|
|
userID, ok := r.Context().Value(middleware.UserIDKey).(uint)
|
|
if !ok {
|
|
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
// TODO: Реализовать получение профиля через сервис
|
|
// response, err := h.authService.GetProfile(userID)
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"user_id": userID,
|
|
"message": "Profile endpoint - to be implemented",
|
|
})
|
|
}
|
|
|
|
// UpdateProfile обновление профиля пользователя
|
|
func (h *AuthHandler) UpdateProfile(w http.ResponseWriter, r *http.Request) {
|
|
l := logger.Get()
|
|
l.Debug("Обновление профиля пользователя")
|
|
|
|
// Получаем ID пользователя из контекста
|
|
userID, ok := r.Context().Value(middleware.UserIDKey).(uint)
|
|
if !ok {
|
|
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
// TODO: Реализовать обновление профиля
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"user_id": userID,
|
|
"message": "Update profile endpoint - to be implemented",
|
|
})
|
|
}
|
|
|
|
// ChangePassword смена пароля
|
|
func (h *AuthHandler) ChangePassword(w http.ResponseWriter, r *http.Request) {
|
|
l := logger.Get()
|
|
l.Debug("Смена пароля пользователя")
|
|
|
|
// Получаем ID пользователя из контекста
|
|
userID, ok := r.Context().Value(middleware.UserIDKey).(uint)
|
|
if !ok {
|
|
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
// TODO: Реализовать смену пароля
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"user_id": userID,
|
|
"message": "Change password endpoint - to be implemented",
|
|
})
|
|
}
|