This commit is contained in:
141
internal/usecase/auth/service.go
Normal file
141
internal/usecase/auth/service.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"counter/internal/domain/entities"
|
||||
"counter/internal/domain/repositories"
|
||||
"counter/internal/infrastructure/security"
|
||||
)
|
||||
|
||||
// AuthService handles authentication business logic
|
||||
type AuthService struct {
|
||||
userRepo repositories.UserRepository
|
||||
passwordService security.PasswordService
|
||||
jwtService security.JWTService
|
||||
}
|
||||
|
||||
// NewAuthService creates a new authentication service
|
||||
func NewAuthService(
|
||||
userRepo repositories.UserRepository,
|
||||
passwordService security.PasswordService,
|
||||
jwtService security.JWTService,
|
||||
) *AuthService {
|
||||
return &AuthService{
|
||||
userRepo: userRepo,
|
||||
passwordService: passwordService,
|
||||
jwtService: jwtService,
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterRequest represents a user registration request
|
||||
type RegisterRequest struct {
|
||||
Username string `json:"username" binding:"required,min=3,max=50"`
|
||||
Email string `json:"email" binding:"required,email"`
|
||||
Password string `json:"password" binding:"required,min=6"`
|
||||
}
|
||||
|
||||
// LoginRequest represents a user login request
|
||||
type LoginRequest struct {
|
||||
Username string `json:"username" binding:"required"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
}
|
||||
|
||||
// AuthResponse represents an authentication response
|
||||
type AuthResponse struct {
|
||||
Token string `json:"token"`
|
||||
User *entities.User `json:"user"`
|
||||
}
|
||||
|
||||
// Register registers a new user
|
||||
func (s *AuthService) Register(ctx context.Context, req *RegisterRequest) (*AuthResponse, error) {
|
||||
// Check if username already exists
|
||||
_, err := s.userRepo.FindByUsername(ctx, req.Username)
|
||||
if err == nil {
|
||||
return nil, entities.ErrUserAlreadyExists
|
||||
}
|
||||
if err != entities.ErrUserNotFound {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check if email already exists
|
||||
_, err = s.userRepo.FindByEmail(ctx, req.Email)
|
||||
if err == nil {
|
||||
return nil, entities.ErrUserAlreadyExists
|
||||
}
|
||||
if err != entities.ErrUserNotFound {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Hash password
|
||||
hashedPassword, err := s.passwordService.HashPassword(req.Password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create user
|
||||
user := &entities.User{
|
||||
Username: req.Username,
|
||||
Email: req.Email,
|
||||
Password: hashedPassword,
|
||||
}
|
||||
|
||||
if err := s.userRepo.Create(ctx, user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Generate token
|
||||
token, err := s.jwtService.GenerateToken(user.ID, user.Username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Clear password from response
|
||||
user.ClearPassword()
|
||||
|
||||
return &AuthResponse{
|
||||
Token: token,
|
||||
User: user,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Login authenticates a user
|
||||
func (s *AuthService) Login(ctx context.Context, req *LoginRequest) (*AuthResponse, error) {
|
||||
// Find user
|
||||
user, err := s.userRepo.FindByUsername(ctx, req.Username)
|
||||
if err != nil {
|
||||
return nil, entities.ErrInvalidCredentials
|
||||
}
|
||||
|
||||
// Check password
|
||||
if !s.passwordService.CheckPasswordHash(req.Password, user.Password) {
|
||||
return nil, entities.ErrInvalidCredentials
|
||||
}
|
||||
|
||||
// Generate token
|
||||
token, err := s.jwtService.GenerateToken(user.ID, user.Username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Clear password from response
|
||||
user.ClearPassword()
|
||||
|
||||
return &AuthResponse{
|
||||
Token: token,
|
||||
User: user,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetCurrentUser retrieves the current authenticated user
|
||||
func (s *AuthService) GetCurrentUser(ctx context.Context, userID int) (*entities.User, error) {
|
||||
user, err := s.userRepo.FindByID(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Clear password from response
|
||||
user.ClearPassword()
|
||||
|
||||
return user, nil
|
||||
}
|
||||
133
internal/usecase/counter/service.go
Normal file
133
internal/usecase/counter/service.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package counter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"counter/internal/domain/entities"
|
||||
"counter/internal/domain/repositories"
|
||||
)
|
||||
|
||||
// CounterService handles counter business logic
|
||||
type CounterService struct {
|
||||
counterRepo repositories.CounterRepository
|
||||
}
|
||||
|
||||
// NewCounterService creates a new counter service
|
||||
func NewCounterService(counterRepo repositories.CounterRepository) *CounterService {
|
||||
return &CounterService{
|
||||
counterRepo: counterRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// CreateCounterRequest represents a counter creation request
|
||||
type CreateCounterRequest struct {
|
||||
Name string `json:"name" binding:"required,min=1,max=100"`
|
||||
Description string `json:"description" max:"500"`
|
||||
}
|
||||
|
||||
// UpdateCounterRequest represents a counter update request
|
||||
type UpdateCounterRequest struct {
|
||||
Name string `json:"name" binding:"required,min=1,max=100"`
|
||||
Description string `json:"description" max:"500"`
|
||||
}
|
||||
|
||||
// IncrementRequest represents a counter increment request
|
||||
type IncrementRequest struct {
|
||||
Value int `json:"value" binding:"required"`
|
||||
}
|
||||
|
||||
// Create creates a new counter
|
||||
func (s *CounterService) Create(ctx context.Context, userID int, req *CreateCounterRequest) (*entities.Counter, error) {
|
||||
counter := &entities.Counter{
|
||||
UserID: userID,
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
}
|
||||
|
||||
if err := counter.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.counterRepo.Create(ctx, counter); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return counter, nil
|
||||
}
|
||||
|
||||
// Get retrieves a counter by ID
|
||||
func (s *CounterService) Get(ctx context.Context, counterID, userID int) (*entities.CounterWithStats, error) {
|
||||
return s.counterRepo.FindByID(ctx, counterID, userID)
|
||||
}
|
||||
|
||||
// List retrieves all counters for a user
|
||||
func (s *CounterService) List(ctx context.Context, userID int, search string) ([]*entities.CounterWithStats, error) {
|
||||
return s.counterRepo.FindByUserID(ctx, userID, search)
|
||||
}
|
||||
|
||||
// Update updates a counter
|
||||
func (s *CounterService) Update(ctx context.Context, counterID, userID int, req *UpdateCounterRequest) (*entities.Counter, error) {
|
||||
counter := &entities.Counter{
|
||||
ID: counterID,
|
||||
UserID: userID,
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
}
|
||||
|
||||
if err := counter.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.counterRepo.Update(ctx, counter); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return counter, nil
|
||||
}
|
||||
|
||||
// Delete deletes a counter
|
||||
func (s *CounterService) Delete(ctx context.Context, counterID, userID int) error {
|
||||
return s.counterRepo.Delete(ctx, counterID, userID)
|
||||
}
|
||||
|
||||
// Increment increments/decrements a counter
|
||||
func (s *CounterService) Increment(ctx context.Context, counterID, userID int, req *IncrementRequest) (*entities.CounterEntry, error) {
|
||||
// Verify counter exists and belongs to user
|
||||
exists, err := s.counterRepo.Exists(ctx, counterID, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, entities.ErrCounterNotFound
|
||||
}
|
||||
|
||||
entry := &entities.CounterEntry{
|
||||
CounterID: counterID,
|
||||
Value: req.Value,
|
||||
Date: time.Now().Truncate(24 * time.Hour), // Truncate to date only
|
||||
}
|
||||
|
||||
if err := entry.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.counterRepo.AddEntry(ctx, entry); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return entry, nil
|
||||
}
|
||||
|
||||
// GetEntries retrieves entries for a counter
|
||||
func (s *CounterService) GetEntries(ctx context.Context, counterID, userID int, startDate, endDate *time.Time) ([]*entities.CounterEntry, error) {
|
||||
return s.counterRepo.GetEntries(ctx, counterID, userID, startDate, endDate)
|
||||
}
|
||||
|
||||
// GetStats retrieves statistics for a counter
|
||||
func (s *CounterService) GetStats(ctx context.Context, counterID, userID int, days int) ([]*entities.DailyStat, error) {
|
||||
if days <= 0 {
|
||||
days = 30 // Default to 30 days
|
||||
}
|
||||
return s.counterRepo.GetDailyStats(ctx, counterID, userID, days)
|
||||
}
|
||||
Reference in New Issue
Block a user