Client
|
| Authorization: Bearer <JWT (user_id, role)>
v
Gin Engine
|
|-- RateLimitMiddleware
|
|-- AuthMiddleware
| └── Extracts user_id + role from JWT
| └── Stores in context
|
|-- RequireRole Middleware
| └── Checks if role ∈ allowed roles
|
|-- Handler
|
|-- Service
|
|-- Repository
|
|-- Database
api-go
|
|-------> cmd/server
| |------> main.go
|
|
|-------> internal
| |
| |------> app
| | |-----> app.go
| |
| |------> auth
| | |-----> jwt.go
| |
| |
| |------> db
| | |-----> postgres.go
| |
| |------> domain
| | |-----> errors.go
| | |
| | |-----> user.go
| | |
| | |-----> website.go
| |
| |------> dto
| | |-----> websites.go
| | |
| | |-----> auth.go
| |
| |
| |------> handlers
| | |-----> websites.go
| | |
| | |-----> users.go
| |
| |
| |------> http
| | |-----> apperror
| | | |-----------> mapper.go
| | |
| | |-----> context
| | | |-----------> context.go
| | |
| | |-----> middleware
| | | |-----------> auth.go
| | | |
| | | |-----------> rateLimit.go
| | | |
| | | |-----------> rbac.go // added
| | |
| | |
| | |
| | |-----> response
| | |-----------> response.go
| |
| |
| |------> repository
| | |-----> website_repository_pg.go
| | |-----> website_repository.go
| | |-----> user_repository.go
| | |-----> user_repository_pg.go
| |
| |
| |------> routes
| | |-----> websites.go
| | |
| | |-----> health.go
| | |
| | |-----> router.go
| | |
| | |-----> user.go
| | |
| | |-----> admin.go // added
| |
| |
| |
| |------> service
| | |-----> websites.go
| | |
| | |-----> users.go
| |
| |
| |------> validation
| |-----> password.go
|
|------> migrations
| |------> 20251226095007_create_websites_table.down.sql
| |------> 20251226095007_create_websites_table.up.sql
|
|------> .env
What is this user allowed to do ?
RBAC = Role → Permissions → Actions
User ──has──▶ Role ──allows──▶ Actions
USER → can create websites, view own data
ADMIN → can manage all websites, users
internal/domain/user.go
type Role string
const (
RoleUser Role = "USER"
RoleAdmin Role = "ADMIN"
)
type User struct {
ID string `db:"id"`
Email string `db:"email"`
Password string `db:"password"`
CreatedAt time.Time `db:"created_at"`
Role Role `db:"role"`
}
migrate create -ext sql -dir migrations alter_users_table
migrations/20260102100925_alter_users_table.up.sql
ALTER TABLE users
ADD COLUMN role TEXT NOT NULL DEFAULT 'USER';
migrations/20260102100925_alter_users_table.down.sql