generated from VLADIMIR/template
189 lines
5.0 KiB
Go
189 lines
5.0 KiB
Go
package users_service
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"evening_detective_server/internal/modules/email_sender"
|
|
"evening_detective_server/internal/modules/password_generator"
|
|
"evening_detective_server/internal/modules/processor_jwt"
|
|
"evening_detective_server/internal/repos/refresh_tokens_repo"
|
|
"evening_detective_server/internal/repos/users_repo"
|
|
"fmt"
|
|
"time"
|
|
|
|
"golang.org/x/crypto/bcrypt"
|
|
)
|
|
|
|
type UsersService struct {
|
|
usersRepo *users_repo.UsersRepo
|
|
passwordGenerator password_generator.IPasswordGenerator
|
|
emailSender email_sender.IEmailSender
|
|
processorJWT processor_jwt.IProcessorJWT
|
|
refreshTokensRepo *refresh_tokens_repo.RefreshTokensRepo
|
|
}
|
|
|
|
func NewUsersService(
|
|
usersRepo *users_repo.UsersRepo,
|
|
passwordGenerator password_generator.IPasswordGenerator,
|
|
emailSender email_sender.IEmailSender,
|
|
processorJWT processor_jwt.IProcessorJWT,
|
|
refreshTokensRepo *refresh_tokens_repo.RefreshTokensRepo,
|
|
) *UsersService {
|
|
return &UsersService{
|
|
usersRepo: usersRepo,
|
|
passwordGenerator: passwordGenerator,
|
|
emailSender: emailSender,
|
|
processorJWT: processorJWT,
|
|
refreshTokensRepo: refreshTokensRepo,
|
|
}
|
|
}
|
|
|
|
func (s *UsersService) AddUser(
|
|
ctx context.Context,
|
|
username string,
|
|
email string,
|
|
) error {
|
|
password, err := s.passwordGenerator.Generate()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = s.usersRepo.AddUser(
|
|
ctx,
|
|
username,
|
|
email,
|
|
string(hashedPassword),
|
|
[]string{"user"},
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = s.emailSender.Send(ctx, email_sender.Message{
|
|
To: email,
|
|
Subject: "Приветствую тебя, детектив!",
|
|
Body: fmt.Sprintf("Вот твой пароль для входа в систему: %s", password),
|
|
})
|
|
|
|
return err
|
|
}
|
|
|
|
func (s *UsersService) RefreshPassword(
|
|
ctx context.Context,
|
|
email string,
|
|
) error {
|
|
password, err := s.passwordGenerator.Generate()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = s.usersRepo.UpdateUserPassword(
|
|
ctx,
|
|
email,
|
|
string(hashedPassword),
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = s.emailSender.Send(ctx, email_sender.Message{
|
|
To: email,
|
|
Subject: "Приветствую тебя, детектив!",
|
|
Body: fmt.Sprintf("Вот твой новый пароль для входа в систему, не теряй: %s", password),
|
|
})
|
|
|
|
return err
|
|
}
|
|
|
|
func (s *UsersService) Login(
|
|
ctx context.Context,
|
|
email string,
|
|
password string,
|
|
) (string, string, error) {
|
|
user, err := s.usersRepo.GetUserByEmail(
|
|
ctx,
|
|
email,
|
|
)
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
if err = bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(password)); err != nil {
|
|
return "", "", errors.New("Не верен email или пароль")
|
|
}
|
|
|
|
accessToken, err := s.processorJWT.GenerateAccessToken(user.ID, user.Email, user.Roles)
|
|
if err != nil {
|
|
return "", "", errors.New("Не получилось получить доступ")
|
|
}
|
|
|
|
refreshToken, err := s.processorJWT.GenerateRefreshToken(user.ID)
|
|
if err != nil {
|
|
return "", "", errors.New("Не получилось получить доступ")
|
|
}
|
|
refreshTokenClaims, err := s.processorJWT.GetClaims(refreshToken)
|
|
if err != nil {
|
|
return "", "", errors.New("Не получилось получить доступ")
|
|
}
|
|
|
|
if err := s.refreshTokensRepo.AddRefreshToken(ctx, user.ID, refreshTokenClaims.ExpiresAt.Time, refreshTokenClaims.ID); err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
return accessToken, refreshToken, nil
|
|
}
|
|
|
|
func (s *UsersService) Refresh(
|
|
ctx context.Context,
|
|
token string,
|
|
) (string, string, error) {
|
|
claims, err := s.processorJWT.GetClaims(token)
|
|
if err != nil {
|
|
return "", "", errors.New("Пользователь не найден")
|
|
}
|
|
|
|
now := time.Now()
|
|
ok, err := s.refreshTokensRepo.ExistsRefreshToken(ctx, claims.UserID, claims.ID, now)
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
if !ok {
|
|
return "", "", errors.New("Пользователь не найден")
|
|
}
|
|
if err := s.refreshTokensRepo.DeleteRefreshTokenByJti(ctx, claims.ID); err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
user, err := s.usersRepo.GetUserByID(ctx, claims.UserID)
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
accessToken, err := s.processorJWT.GenerateAccessToken(user.ID, user.Email, user.Roles)
|
|
if err != nil {
|
|
return "", "", errors.New("Не получилось получить доступ")
|
|
}
|
|
|
|
refreshToken, err := s.processorJWT.GenerateRefreshToken(user.ID)
|
|
if err != nil {
|
|
return "", "", errors.New("Не получилось получить доступ")
|
|
}
|
|
refreshTokenClaims, err := s.processorJWT.GetClaims(refreshToken)
|
|
if err != nil {
|
|
return "", "", errors.New("Не получилось получить доступ")
|
|
}
|
|
|
|
if err := s.refreshTokensRepo.AddRefreshToken(ctx, user.ID, refreshTokenClaims.ExpiresAt.Time, refreshTokenClaims.ID); err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
return accessToken, refreshToken, nil
|
|
}
|