modified: go.mod

modified:   go.sum
	modified:   internal/handlers/auth.go
	new file:   internal/handlers/oauth.go
	modified:   internal/handlers/user_handler.go
	renamed:    internal/model/o_auth_provider.go -> internal/models/o_auth_provider.go
	renamed:    internal/model/user.go -> internal/models/user.go
	modified:   internal/repository/user_repository.go
	modified:   internal/service/user_service.go
	modified:   pkg/database/postgres.go
add  oauth_handler
This commit is contained in:
2025-09-29 22:01:04 +05:00
parent ca37a475c9
commit f7b09e260c
10 changed files with 160 additions and 42 deletions
@@ -3,7 +3,7 @@ package handlers
import (
"net/http"
"serv_golang_rest_api/internal/model"
"serv_golang_rest_api/internal/models"
"serv_golang_rest_api/internal/utils"
"gorm.io/gorm"
@@ -32,7 +32,7 @@ func (h *AuthHandler) Register(w http.ResponseWriter, r *http.Request) {
}
// Проверяем, существует ли пользователь
var existingUser model.User
var existingUser models.User
if err := h.DB.Where("email = ?", req.Email).First(&existingUser).Error; err == nil {
utils.WriteError(w, http.StatusConflict, "User already exists")
return
@@ -46,7 +46,7 @@ func (h *AuthHandler) Register(w http.ResponseWriter, r *http.Request) {
}
// Создаем пользователя
user := model.User{
user := models.User{
Email: req.Email,
Password: hashedPassword,
Name: req.Name,
@@ -78,7 +78,7 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) {
}
// Ищем пользователя
var user model.User
var user models.User
if err := h.DB.Where("email = ?", req.Email).First(&user).Error; err != nil {
utils.WriteError(w, http.StatusUnauthorized, "Invalid credentials")
return
@@ -0,0 +1,129 @@
// handlers/oauth.go
package handlers
import (
"encoding/json"
"net/http"
"serv_golang_rest_api/internal/config"
"serv_golang_rest_api/internal/models"
"serv_golang_rest_api/internal/utils"
"gorm.io/gorm"
)
type OAuthHandler struct {
DB *gorm.DB
}
type GoogleUserInfo struct {
ID string `json:"id"`
Email string `json:"email"`
Name string `json:"name"`
}
type VKUserInfo struct {
Response []struct {
ID int `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Email string `json:"email"`
} `json:"response"`
}
func (h *OAuthHandler) GoogleLogin(w http.ResponseWriter, r *http.Request) {
url := config.GoogleOAuthConfig.AuthCodeURL("state")
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
}
func (h *OAuthHandler) GoogleCallback(w http.ResponseWriter, r *http.Request) {
code := r.URL.Query().Get("code")
token, err := config.GoogleOAuthConfig.Exchange(r.Context(), code)
if err != nil {
utils.WriteError(w, http.StatusBadRequest, "Failed to exchange token")
return
}
client := config.GoogleOAuthConfig.Client(r.Context(), token)
resp, err := client.Get("https://www.googleapis.com/oauth2/v2/userinfo")
if err != nil {
utils.WriteError(w, http.StatusBadRequest, "Failed to get user info")
return
}
defer resp.Body.Close()
var userInfo GoogleUserInfo
if err := json.NewDecoder(resp.Body).Decode(&userInfo); err != nil {
utils.WriteError(w, http.StatusBadRequest, "Failed to decode user info")
return
}
// Создаем или находим пользователя
user, err := h.findOrCreateOAuthUser("google", userInfo.ID, userInfo.Email, userInfo.Name)
if err != nil {
utils.WriteError(w, http.StatusInternalServerError, "Error processing user")
return
}
jwtToken, err := utils.GenerateJWT(user.ID, user.Email)
if err != nil {
utils.WriteError(w, http.StatusInternalServerError, "Error generating token")
return
}
// Редирект или возврат токена
utils.WriteJSON(w, http.StatusOK, map[string]interface{}{
"token": jwtToken,
"user": user,
})
}
// Аналогичные методы для Yandex и VK...
func (h *OAuthHandler) findOrCreateOAuthUser(provider, providerID, email, name string) (*models.User, error) {
var oauthProvider models.OAuthProvider
// Ищем существующую привязку OAuth
err := h.DB.Where("provider = ? AND provider_id = ?", provider, providerID).
Preload("User").
First(&oauthProvider).Error
if err == nil {
// Нашли привязку, теперь загружаем пользователя
var user models.User
if err := h.DB.First(&user, oauthProvider.UserID).Error; err != nil {
return nil, err
}
return &user, nil
}
// Если привязки нет, ищем пользователя по email
var user models.User
err = h.DB.Where("email = ?", email).First(&user).Error
if err != nil {
// Создаем нового пользователя
user = models.User{
Email: email,
Name: name,
// Генерируем случайный пароль для OAuth пользователей
Password: utils.GenerateRandomPassword(),
}
if err := h.DB.Create(&user).Error; err != nil {
return nil, err
}
}
// Создаем привязку OAuth
oauthProvider = models.OAuthProvider{
UserID: user.ID,
Provider: provider,
ProviderID: providerID,
}
if err := h.DB.Create(&oauthProvider).Error; err != nil {
return nil, err
}
return &user, nil
}
@@ -6,7 +6,7 @@ import (
"strconv"
"github.com/go-chi/chi/v5"
"serv_golang_rest_api/internal/model"
"serv_golang_rest_api/internal/models"
"serv_golang_rest_api/internal/service"
)
@@ -19,7 +19,7 @@ func NewUserHandler(userService *service.UserService) *UserHandler {
}
func (h *UserHandler) CreateUser(w http.ResponseWriter, r *http.Request) {
var req model.CreateUserRequest
var req models.CreateUserRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "Invalid request body", http.StatusBadRequest)
return
@@ -1,4 +1,4 @@
package model
package models
import (
"time"
@@ -1,4 +1,4 @@
package model
package models
import (
"time"
@@ -1,7 +1,7 @@
package repository
import (
"serv_golang_rest_api/internal/model"
"serv_golang_rest_api/internal/models"
"gorm.io/gorm"
)
@@ -14,32 +14,32 @@ func NewUserRepository(db *gorm.DB) *UserRepository {
return &UserRepository{db: db}
}
func (r *UserRepository) Create(user *model.User) error {
func (r *UserRepository) Create(user *models.User) error {
return r.db.Create(user).Error
}
func (r *UserRepository) FindByID(id uint) (*model.User, error) {
var user model.User
func (r *UserRepository) FindByID(id uint) (*models.User, error) {
var user models.User
err := r.db.First(&user, id).Error
return &user, err
}
func (r *UserRepository) FindByEmail(email string) (*model.User, error) {
var user model.User
func (r *UserRepository) FindByEmail(email string) (*models.User, error) {
var user models.User
err := r.db.Where("email = ?", email).First(&user).Error
return &user, err
}
func (r *UserRepository) FindAll() ([]model.User, error) {
var users []model.User
func (r *UserRepository) FindAll() ([]models.User, error) {
var users []models.User
err := r.db.Find(&users).Error
return users, err
}
func (r *UserRepository) Update(user *model.User) error {
func (r *UserRepository) Update(user *models.User) error {
return r.db.Save(user).Error
}
func (r *UserRepository) Delete(id uint) error {
return r.db.Delete(&model.User{}, id).Error
return r.db.Delete(&models.User{}, id).Error
}
@@ -2,7 +2,7 @@ package service
import (
"errors"
"serv_golang_rest_api/internal/model"
"serv_golang_rest_api/internal/models"
"serv_golang_rest_api/internal/repository"
"golang.org/x/crypto/bcrypt"
@@ -16,7 +16,7 @@ func NewUserService(userRepo *repository.UserRepository) *UserService {
return &UserService{userRepo: userRepo}
}
func (s *UserService) CreateUser(req *model.CreateUserRequest) (*model.UserResponse, error) {
func (s *UserService) CreateUser(req *models.CreateUserRequest) (*models.UserResponse, error) {
// Проверяем существует ли пользователь с таким email
existingUser, err := s.userRepo.FindByEmail(req.Email)
// Проверяем как на nil, так на пустой ID
@@ -30,7 +30,7 @@ func (s *UserService) CreateUser(req *model.CreateUserRequest) (*model.UserRespo
return nil, err
}
user := &model.User{
user := &models.User{
Name: req.Name,
Email: req.Email,
Password: string(hashedPassword),
@@ -43,7 +43,7 @@ func (s *UserService) CreateUser(req *model.CreateUserRequest) (*model.UserRespo
return s.toUserResponse(user), nil
}
func (s *UserService) GetUserByID(id uint) (*model.UserResponse, error) {
func (s *UserService) GetUserByID(id uint) (*models.UserResponse, error) {
user, err := s.userRepo.FindByID(id)
if err != nil {
return nil, errors.New("user not found")
@@ -52,13 +52,13 @@ func (s *UserService) GetUserByID(id uint) (*model.UserResponse, error) {
return s.toUserResponse(user), nil
}
func (s *UserService) GetAllUsers() ([]model.UserResponse, error) {
func (s *UserService) GetAllUsers() ([]models.UserResponse, error) {
users, err := s.userRepo.FindAll()
if err != nil {
return nil, err
}
var responses []model.UserResponse
var responses []models.UserResponse
for _, user := range users {
responses = append(responses, *s.toUserResponse(&user))
}
@@ -66,8 +66,8 @@ func (s *UserService) GetAllUsers() ([]model.UserResponse, error) {
return responses, nil
}
func (s *UserService) toUserResponse(user *model.User) *model.UserResponse {
return &model.UserResponse{
func (s *UserService) toUserResponse(user *models.User) *models.UserResponse {
return &models.UserResponse{
ID: user.ID,
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,