Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
SERVER_HOST=localhost
SERVER_PORT=8080

DB_NAME=doit
DB_USER=islamghany
DB_PASSWORD=secret
DB_DISABLE_TLS=true
DB_MAX_OPEN_CONNS=11
DB_MAX_IDLE_CONNS=11
DB_HOST=localhost
DB_PORT=5432
DB_PORT=5432

JWT_SECRET=dpkow94v4LtqqDvvSuzXCuID11AtnAfLuXbdG8VG3mc=
JWT_REFRESH_SECRET=Do7Tb1NdL2E9Fk1FGWbYdK2nfTPFLKIyd7wG8FUQq0Q=
JWT_ACCESS_TOKEN_EXP=900
JWT_REFRESH_TOKEN_EXP=604800

REDIS_ADDR=localhost:6379
REDIS_PASSWORD=
REDIS_DB=0
5 changes: 4 additions & 1 deletion api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ func Run(ctx context.Context, logger *logger.Logger, cfg *config.Config) error {
defer dbPool.Close()

// Starting the HTTP server with graceful shutdown
srv := NewServer(logger, cfg, dbPool)
srv, err := NewServer(logger, cfg, dbPool)
if err != nil {
return fmt.Errorf("failed to create server: %w", err)
}

server := &http.Server{
Addr: fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port),
Expand Down
18 changes: 14 additions & 4 deletions api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@ import (
"doit/internal/config"
"doit/internal/middlewares"
"doit/internal/service"
"doit/internal/token"
"doit/internal/web"
"doit/pkg/database"
"doit/pkg/logger"
"net/http"
)

func NewServer(logger *logger.Logger, cfg *config.Config, dbPool *database.Pool) http.Handler {
func NewServer(logger *logger.Logger, cfg *config.Config, dbPool *database.Pool) (http.Handler, error) {

// Helpers
tokenMaker, err := token.NewJWTToken(cfg.JWT.Secret)
if err != nil {
return nil, err
}

// Middlewares
errorMiddleware := middlewares.ErrorMiddleware(logger)
Expand All @@ -20,10 +27,13 @@ func NewServer(logger *logger.Logger, cfg *config.Config, dbPool *database.Pool)
app := web.NewApp(errorMiddleware)

// Services
authService := service.NewAuthService(dbPool, logger)
userService := service.NewUserService(dbPool)
tokenService := service.NewTokenService(dbPool, tokenMaker,
cfg.JWT.AccessTokenExp,
cfg.JWT.RefreshTokenExp)

// Handlers
authHandler := auth.NewHandler(logger, authService, cfg)
authHandler := auth.NewHandler(logger, userService, tokenService, cfg)

// Routes
auth.RegisterRoutes(app, authHandler)
Expand All @@ -32,5 +42,5 @@ func NewServer(logger *logger.Logger, cfg *config.Config, dbPool *database.Pool)
return web.RespondOK(w, r, map[string]string{"status": "ok"})
})

return app
return app, nil
}
29 changes: 22 additions & 7 deletions api/v1/auth/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ import (

type Handler struct {
log *logger.Logger
authService *service.AuthService
userService *service.UserService
tokenService *service.TokenService
config *config.Config
}

func NewHandler(log *logger.Logger, authService *service.AuthService, config *config.Config) *Handler {
return &Handler{log: log, authService: authService, config: config}
func NewHandler(log *logger.Logger, userService *service.UserService, tokenService *service.TokenService, config *config.Config) *Handler {
return &Handler{log: log, userService: userService, tokenService: tokenService, config: config}
}

func (h *Handler) Login(w http.ResponseWriter, r *http.Request) error {
Expand All @@ -30,7 +31,7 @@ func (h *Handler) Login(w http.ResponseWriter, r *http.Request) error {
return web.NewError(err, http.StatusBadRequest)
}

user, err := h.authService.AuthenticateUser(ctx, model.LoginInput{
user, err := h.userService.AuthenticateUser(ctx, model.LoginInput{
Email: input.Email,
Password: input.Password,
})
Expand All @@ -39,7 +40,21 @@ func (h *Handler) Login(w http.ResponseWriter, r *http.Request) error {
return h.handleAuthError(err)
}

return web.RespondOK(w, r, user)
deviceInfo := model.DeviceInfo{
IPAddress: web.GetClientIP(r),
UserAgent: web.GetUserAgent(r),
DeviceName: web.GetDeviceName(r),
}

tokens, err := h.tokenService.CreateTokenPair(ctx, *user, deviceInfo)
if err != nil {
return web.NewError(err, http.StatusInternalServerError)
}
response := map[string]interface{}{
"user": user,
"tokens": tokens,
}
return web.RespondOK(w, r, response)
}

// handleAuthError maps service errors to appropriate HTTP responses
Expand All @@ -48,8 +63,8 @@ func (h *Handler) handleAuthError( err error) error {
switch {
case errors.Is(err, service.ErrInvalidCredentials):
return web.NewError(errors.New("invalid credentials"), http.StatusUnauthorized)
case errors.Is(err, service.ErrUserInactive):
return web.NewError(errors.New("user account is inactive"), http.StatusForbidden)
// case errors.Is(err, service.ErrUserInactive):
// return web.NewError(errors.New("user account is inactive"), http.StatusForbidden)
default:
return web.NewError(errors.New("internal server error"), http.StatusInternalServerError)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/doit/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ var version = "v0.0.1"
func main() {
// Create a context for the application.
ctx := context.Background()

// Load configuration
cfg, err := config.LoadConfig()
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/go-playground/locales v0.14.1
github.com/go-playground/universal-translator v0.18.1
github.com/go-playground/validator/v10 v10.28.0
github.com/golang-jwt/jwt/v5 v5.3.0
github.com/google/uuid v1.6.0
github.com/islamghany/enfl v1.0.0
github.com/jackc/pgx/v5 v5.7.2
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.28.0 h1:Q7ibns33JjyW48gHkuFT91qX48KG0ktULL6FgHdG688=
github.com/go-playground/validator/v10 v10.28.0/go.mod h1:GoI6I1SjPBh9p7ykNE/yj3fFYbyDOpwMn5KXd+m2hUU=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/islamghany/enfl v1.0.0 h1:mR77orybPguSo/WZL4Ma7D/vyioD0r/Qv/rRmU1xRfY=
Expand Down
3 changes: 2 additions & 1 deletion internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type RedisConfig struct {

type JWTConfig struct {
Secret string `env:"SECRET" flag:"jwt_secret" required:"true"`
RefreshSecret string `env:"REFRESH_SECRET" flag:"refresh_secret" required:"true"`
AccessTokenExp int `env:"ACCESS_TOKEN_EXP" flag:"access_token_exp" required:"true"`
RefreshTokenExp int `env:"REFRESH_TOKEN_EXP" flag:"refresh_token_exp" required:"true"`
}
Expand All @@ -65,7 +66,7 @@ type Config struct {
Server ServerConfig `prefix:"SERVER_"`
App AppConfig `prefix:"APP_"`
Database DatabaseConfig `prefix:"DB_"`
// JWT JWTConfig `prefix:"JWT_"`
JWT JWTConfig `prefix:"JWT_"`
// Redis RedisConfig `prefix:"REDIS_"`
}

Expand Down
13 changes: 13 additions & 0 deletions internal/data/db/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions internal/data/db/querier.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading