Add JWT authentication

- Create register and login use cases
- Implement JWT service for token generation and validation
- Add authentication middleware to protect habit endpoints
- Create auth HTTP handlers (register, login)
- Update habit handlers to extract userID from JWT token
- Register/login endpoints: POST /auth/register, POST /auth/login
- Habit endpoints now require Bearer token in Authorization header
- Tested: register -> create habit -> list habits works correctly
This commit is contained in:
2025-11-26 01:05:08 +01:00
parent 3e8883d878
commit b2894fca70
8 changed files with 375 additions and 4 deletions
@@ -0,0 +1,50 @@
package queries
import (
"context"
"habit-tracker-api/internal/domain/repositories"
"habit-tracker-api/internal/shared/errors"
"golang.org/x/crypto/bcrypt"
)
type LoginUserQuery struct {
Email string
Password string
}
type LoginUserResult struct {
UserID string
Email string
Timezone string
}
type LoginUserHandler struct {
userRepo repositories.UserRepository
}
func NewLoginUserHandler(userRepo repositories.UserRepository) *LoginUserHandler {
return &LoginUserHandler{userRepo: userRepo}
}
func (h *LoginUserHandler) Handle(ctx context.Context, query LoginUserQuery) (*LoginUserResult, error) {
if query.Email == "" || query.Password == "" {
return nil, errors.ErrInvalidInput
}
user, err := h.userRepo.FindByEmail(ctx, query.Email)
if err != nil {
return nil, errors.ErrNotFound
}
if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(query.Password)); err != nil {
return nil, errors.ErrNotFound
}
return &LoginUserResult{
UserID: user.ID,
Email: user.Email,
Timezone: user.Timezone,
}, nil
}