Skip to content

Commit 5e7895c

Browse files
committed
implementing auth module
1 parent da0054a commit 5e7895c

16 files changed

Lines changed: 596 additions & 76 deletions

File tree

cmd/genmodule/main.go

Lines changed: 57 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"bufio"
45
"fmt"
56
"os"
67
"path/filepath"
@@ -25,8 +26,9 @@ import (
2526
{{.ModuleName}}Services "{{.ProjectRoot}}/internal/app/modules/{{.ModuleName}}/services"
2627
"{{.ProjectRoot}}/pkg/logger"
2728
"{{.ProjectRoot}}/pkg/validators"
28-
"github.com/go-chi/chi/v5"
29+
"github.com/go-chi/chi"
2930
"gorm.io/gorm"
31+
"net/http"
3032
)
3133
3234
// Module represents the {{.CapitalizedModuleName}} module.
@@ -37,7 +39,7 @@ type Module struct {
3739
3840
// NewModule initializes {{.CapitalizedModuleName}} module.
3941
func NewModule(db *gorm.DB, log logger.Logger, validator *validators.Validator) *Module {
40-
repo := {{.ModuleName}}Repositories.NewGorm{{.CapitalizedModuleName}}Repository(db, log)
42+
repo := {{.ModuleName}}Repositories.New{{.CapitalizedModuleName}}Repository(db, log)
4143
service := {{.ModuleName}}Services.New{{.CapitalizedModuleName}}Service(repo, validator, log)
4244
handler := {{.ModuleName}}Handlers.New{{.CapitalizedModuleName}}Handler(service, log)
4345
@@ -49,31 +51,35 @@ func NewModule(db *gorm.DB, log logger.Logger, validator *validators.Validator)
4951
// RegisterRoutes registers the routes for the {{.CapitalizedModuleName}} module.
5052
func (m *Module) RegisterRoutes(r chi.Router) {
5153
// Register the routes for the {{.ModuleName}} module
52-
r.Route("/{{.ModuleName}}s", func(r chi.Router) {
53-
r.Post("/", m.Handlers.Create{{.CapitalizedModuleName}})
54-
r.Get("/", m.Handlers.GetAll{{.CapitalizedModuleName}}s)
54+
r.Route("/{{.ModuleName}}", func(r chi.Router) {
55+
r.Get("/test", func(w http.ResponseWriter, r *http.Request) {
56+
w.WriteHeader(http.StatusOK)
57+
w.Write([]byte("Module {{.ModuleName}} is working!"))
58+
})
59+
//r.Post("/", m.Handlers.Create{{.CapitalizedModuleName}})
60+
//r.Get("/", m.Handlers.GetAll{{.CapitalizedModuleName}}s)
5561
5662
})
5763
}
5864
`
5965

6066
const handlersGoTemplate = `package handlers
6167
import (
62-
"context"
63-
"net/http"
68+
// "context"
69+
//"net/http"
6470
{{.ModuleName}}Services "{{.ProjectRoot}}/internal/app/modules/{{.ModuleName}}/services"
6571
"{{.ProjectRoot}}/pkg/logger"
66-
"{{.ProjectRoot}}/pkg/web"
67-
"{{.ProjectRoot}}/internal/app/modules/{{.ModuleName}}/models"
72+
//"{{.ProjectRoot}}/pkg/web"
73+
//"{{.ProjectRoot}}/internal/app/modules/{{.ModuleName}}/models"
6874
)
6975
7076
type {{.CapitalizedModuleName}}Handler struct {
71-
{{.ModuleName}}Service *{{.ModuleName}}Services.{{.CapitalizedModuleName}}Service
77+
{{.ModuleName}}Service {{.ModuleName}}Services.{{.CapitalizedModuleName}}Service
7278
log logger.Logger
7379
}
7480
7581
// constructor for {{.CapitalizedModuleName}}Handler
76-
func New{{.CapitalizedModuleName}}Handler({{.ModuleName}}Service *{{.ModuleName}}Services.{{.CapitalizedModuleName}}Service, log logger.Logger) *{{.CapitalizedModuleName}}Handler {
82+
func New{{.CapitalizedModuleName}}Handler({{.ModuleName}}Service {{.ModuleName}}Services.{{.CapitalizedModuleName}}Service, log logger.Logger) *{{.CapitalizedModuleName}}Handler {
7783
return &{{.CapitalizedModuleName}}Handler{
7884
{{.ModuleName}}Service: {{.ModuleName}}Service,
7985
log: log,
@@ -93,9 +99,9 @@ func New{{.CapitalizedModuleName}}Handler({{.ModuleName}}Service *{{.ModuleName}
9399

94100
const servicesGoTemplate = `package services
95101
import (
96-
"context"
102+
//"context"
97103
{{.ModuleName}}Repositories "{{.ProjectRoot}}/internal/app/modules/{{.ModuleName}}/repositories"
98-
"{{.ProjectRoot}}/internal/app/modules/{{.ModuleName}}/models"
104+
//"{{.ProjectRoot}}/internal/app/modules/{{.ModuleName}}/models"
99105
"{{.ProjectRoot}}/pkg/logger"
100106
"{{.ProjectRoot}}/pkg/validators"
101107
)
@@ -105,15 +111,15 @@ type {{.CapitalizedModuleName}}Service interface {
105111
//Get{{.CapitalizedModuleName}}ByID(ctx context.Context, id int) (*models.{{.CapitalizedModuleName}}, error)
106112
}
107113
108-
type {{.CapitalizedModuleName}}Service struct {
109-
{{.ModuleName}}Repo {{.ModuleName}}Repositories.{{.CapitalizedModuleName}}Repository
114+
type {{.ModuleName}}Service struct {
115+
Repo {{.ModuleName}}Repositories.{{.CapitalizedModuleName}}Repository
110116
validator *validators.Validator
111117
log logger.Logger
112118
}
113119
114120
//service constructor
115-
func New{{.CapitalizedModuleName}}Service({{.ModuleName}}Repo {{.ModuleName}}Repositories.{{.CapitalizedModuleName}}Repository, validator *validators.Validator, log logger.Logger) *{{.CapitalizedModuleName}}Service {
116-
return &{{.CapitalizedModuleName}}Service{
121+
func New{{.CapitalizedModuleName}}Service(Repo {{.ModuleName}}Repositories.{{.CapitalizedModuleName}}Repository, validator *validators.Validator, log logger.Logger) {{.CapitalizedModuleName}}Service {
122+
return &{{.ModuleName}}Service{
117123
Repo: Repo,
118124
validator: validator,
119125
log: log,
@@ -129,8 +135,8 @@ func New{{.CapitalizedModuleName}}Service({{.ModuleName}}Repo {{.ModuleName}}Rep
129135
`
130136
const repositoriesGoTemplate = `package repositories
131137
import (
132-
"context"
133-
"{{.ProjectRoot}}/internal/app/modules/{{.ModuleName}}/models"
138+
// "context"
139+
// "{{.ProjectRoot}}/internal/app/modules/{{.ModuleName}}/models"
134140
"{{.ProjectRoot}}/pkg/logger"
135141
"gorm.io/gorm"
136142
)
@@ -139,11 +145,17 @@ const repositoriesGoTemplate = `package repositories
139145
// Example method:
140146
// Create{{.CapitalizedModuleName}}(ctx context.Context, {{.ModuleName}} *models.{{.CapitalizedModuleName}}) error
141147
}
142-
type gorm{{.CapitalizedModuleName}}Repository struct {
148+
type {{.ModuleName}}Repository struct {
143149
db *gorm.DB
144150
log logger.Logger
145151
}
146-
152+
// repo constructor
153+
func New{{.CapitalizedModuleName}}Repository(db *gorm.DB, log logger.Logger) {{.CapitalizedModuleName}}Repository {
154+
return &{{.ModuleName}}Repository{
155+
db: db,
156+
log: log,
157+
}
158+
}
147159
//repos methods
148160
//eg.
149161
// func (r *gorm{{.CapitalizedModuleName}}Repository) Create{{.CapitalizedModuleName}}(ctx context.Context, {{.ModuleName}} *models.{{.CapitalizedModuleName}}) error {
@@ -162,13 +174,36 @@ func main(){
162174
moduleName := strings.ToLower(os.Args[1])
163175
capitalizedModuleName := strings.ToUpper(moduleName[:1]) + moduleName[1:]
164176

177+
if strings.Contains(moduleName, "-") || strings.Contains(moduleName, "_") {
178+
fmt.Println("Module name cannot contain '-' or '_' characters. Please use a valid module name.")
179+
os.Exit(1)
180+
}
181+
if moduleName == "main" || moduleName == "cmd" || moduleName == "internal" || moduleName == "pkg" {
182+
fmt.Printf("Module name '%s' is reserved. Please choose a different name.\n", moduleName)
183+
os.Exit(1)
184+
}
185+
165186
moduleData := ModuleData{
166187
ModuleName: moduleName,
167188
CapitalizedModuleName: capitalizedModuleName,
168189
ProjectRoot: projectGoModulePath,
169190
}
170191
basePath := filepath.Join("internal", "app", "modules", moduleName)
171192

193+
if _, err := os.Stat(basePath); !os.IsNotExist(err) {
194+
reader := bufio.NewReader(os.Stdin)
195+
fmt.Printf("Module '%s' already exists at %s . Overwrite? (Y/N): ", moduleName, basePath)
196+
197+
response, _ := reader.ReadString('\n')
198+
response = strings.ToLower(strings.TrimSpace(response))
199+
200+
if response != "y"{
201+
fmt.Println("Operation cancelled")
202+
os.Exit(0)
203+
}
204+
fmt.Printf("proceeding to overwrite module '%s'....\n", moduleName)
205+
}
206+
172207
dirs := []string{
173208
basePath,
174209
filepath.Join(basePath, "handlers"),
@@ -216,7 +251,7 @@ func main(){
216251

217252
fmt.Printf("\nModule '%s' generated successfully. Remember to:\n", moduleName)
218253
fmt.Println("- Add it to 'internal/bootstrap/app.go' in the appModules slice.")
219-
fmt.Printf("- **Crucially, create your model file(s) in 'internal/app/modules/%s/models/' (e.g., %s.go) and define your structs with 'package models'.**", moduleName, moduleName)
254+
fmt.Printf("- **Crucially, create your model file(s) in 'internal/app/modules/%s/models/'.**\n", moduleName)
220255
fmt.Println("- Adjust generated boilerplate code (e.g., imports, methods, model usage).")
221256
fmt.Println("- Run 'go mod tidy' after adding to app.go.")
222257

config/config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"os"
66
"strconv"
7+
"time"
78

89
"github.com/codetheuri/todolist/pkg/errors"
910
"gorm.io/driver/mysql"
@@ -27,6 +28,7 @@ type Config struct {
2728
ServerPort int
2829
LOG_LEVEL string
2930
JWTSecret string
31+
AccessTokenTTL time.Duration `mapstructure:"ACCESS_TOKEN_TTL"`
3032
AppName string
3133
AppVersion string
3234
AppMode string
@@ -50,6 +52,7 @@ func LoadConfig() (*Config, error) {
5052
DBDriver: os.Getenv("DB_DRIVER"),
5153
LOG_LEVEL: os.Getenv("LOG_LEVEL"),
5254
JWTSecret: os.Getenv("JWT_SECRET"),
55+
// AccessTokenTTL: os.Getenv("ACCESS_TOKEN_TTL"),
5356
AppName: os.Getenv("APP_NAME"),
5457
AppVersion: os.Getenv("APP_VERSION"),
5558
AppMode: os.Getenv("APP_MODE"),
@@ -82,6 +85,7 @@ func LoadConfig() (*Config, error) {
8285
if err != nil {
8386
return nil, errors.ConfigError(fmt.Sprintf("Invalid SERVER_PORT value : %s", serverPortStr), err)
8487
}
88+
8589
cfg.ServerPort = serverPort
8690

8791
//basic validation
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package migrations
2+
3+
import (
4+
"log"
5+
6+
"github.com/codetheuri/todolist/internal/app/modules/auth/models"
7+
"gorm.io/gorm"
8+
)
9+
10+
// Createauthtables struct implements migration interface
11+
type Createauthtables struct {}
12+
13+
func (m *Createauthtables) Version() string{
14+
return "20250717130322"
15+
}
16+
func (m *Createauthtables) Name() string {
17+
return "create_auth_tables"
18+
}
19+
//up migration method
20+
func (m *Createauthtables) Up(tx *gorm.DB) error {
21+
log.Printf("Running Up migration: %s", m.Name())
22+
// Add your migration logic here
23+
//example :
24+
// 1. using SQL calls
25+
// if err := tx.Exec("CREATE TABLE IF NOT EXISTS example (id INT PRIMARY KEY)").Error; err != nil {
26+
// return err
27+
// }
28+
29+
// 2. using gorm methods
30+
//type NewModel struct {
31+
// gorm.Model
32+
// Field1 string
33+
//}
34+
// if err := tx.AutoMigrate(&NewModel{}); err != nil {
35+
// return err
36+
// }
37+
if err:= tx.AutoMigrate(&models.User{}); err!= nil {
38+
return err
39+
}
40+
if err := tx.AutoMigrate(&models.RevokedToken{}); err != nil {
41+
return err
42+
}
43+
log.Printf("Successfully applied Up migration: %s", m.Name())
44+
return nil
45+
}
46+
//down migration method
47+
func (m *Createauthtables) Down(tx *gorm.DB) error {
48+
log.Printf("Running Down migration: %s", m.Name())
49+
// Example:
50+
// 1. using SQL calls
51+
// if err := tx.Exec("DROP TABLE IF EXISTS example").Error; err != nil {
52+
// return err
53+
// }
54+
55+
// 2. using gorm methods
56+
// if err := tx.Migrator().DropTable("new_models"); err != nil {
57+
// return err
58+
// }
59+
if err := tx.Migrator().DropTable(&models.User{}); err != nil {
60+
return err
61+
}
62+
if err := tx.Migrator().DropTable(&models.RevokedToken{}); err != nil {
63+
return err
64+
}
65+
log.Printf("Successfully applied Down migration: %s", m.Name())
66+
return nil
67+
}
68+
69+
func init() {
70+
// Register the migration
71+
RegisteredMigrations = append(RegisteredMigrations, &Createauthtables{})
72+
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ require (
2828
github.com/go-playground/validator/v10 v10.26.0
2929
github.com/leodido/go-urn v1.4.0 // indirect
3030
github.com/lib/pq v1.10.9
31-
golang.org/x/crypto v0.33.0 // indirect
31+
golang.org/x/crypto v0.33.0
3232
golang.org/x/net v0.34.0
3333
golang.org/x/sys v0.30.0 // indirect
3434
golang.org/x/text v0.22.0 // indirect

internal/app/modules/auth/handlers/handler.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
package handlers
2-
32
import (
3+
// "context"
4+
//"net/http"
45
authServices "github.com/codetheuri/todolist/internal/app/modules/auth/services"
56
"github.com/codetheuri/todolist/pkg/logger"
7+
//"github.com/codetheuri/todolist/pkg/web"
8+
//"github.com/codetheuri/todolist/internal/app/modules/auth/models"
69
)
710

811
type AuthHandler struct {
9-
authService *authServices.AuthService
10-
log logger.Logger
12+
authService authServices.AuthService
13+
log logger.Logger
1114
}
1215

1316
// constructor for AuthHandler
14-
func NewAuthHandler(authService *authServices.AuthService, log logger.Logger) *AuthHandler {
17+
func NewAuthHandler(authService authServices.AuthService, log logger.Logger) *AuthHandler {
1518
return &AuthHandler{
1619
authService: authService,
17-
log: log,
20+
log: log,
1821
}
1922
}
2023

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package models
2+
3+
import (
4+
"time"
5+
6+
"gorm.io/gorm"
7+
)
8+
9+
type RevokedToken struct {
10+
gorm.Model
11+
JTI string `gorm:"unique;not null;size:255" json:"jti"`
12+
ExpiresAt time.Time `gorm:"not null" json:"expires_at"`
13+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package models
2+
3+
import "gorm.io/gorm"
4+
5+
type User struct {
6+
gorm.Model
7+
Email string `gorm:"unique;not null" json:"email" validate:"required,email"`
8+
Password string `gorm:"not null" json:"-" validate:"required,min=8"`
9+
Role string `gorm:"not null;default:'user'" json:"role"`
10+
}

0 commit comments

Comments
 (0)