feat(auth): Add option to disable registration and tenant creation
This commit is contained in:
@@ -22,8 +22,10 @@ type Config struct {
|
||||
RedisPort string
|
||||
RedisPassword string
|
||||
JwtSecret string
|
||||
ENV string
|
||||
UNPROTECTED_ENDPOINTS []string
|
||||
Environment string
|
||||
UnprotectedEndpoints []string
|
||||
AllowRegistration bool
|
||||
AllowTenantCreation bool
|
||||
}
|
||||
|
||||
var CONFIG *Config
|
||||
@@ -33,11 +35,11 @@ func generateSecret() string {
|
||||
}
|
||||
|
||||
func NewConfig() *Config {
|
||||
ENV := utils.GetEnv("ENV", "development")
|
||||
UNPROTECTED_ENDPOINTS := strings.Split(utils.GetEnv("UNPROTECTED_ENDPOINTS", ""), ",")
|
||||
Environment := utils.GetEnv("ENV", "development")
|
||||
UnprotectedEndpoints := strings.Split(utils.GetEnv("UNPROTECTED_ENDPOINTS", ""), ",")
|
||||
|
||||
if ENV == "development" {
|
||||
UNPROTECTED_ENDPOINTS = append(UNPROTECTED_ENDPOINTS, "/api_keys")
|
||||
if Environment == "development" {
|
||||
UnprotectedEndpoints = append(UnprotectedEndpoints, "/api_keys")
|
||||
}
|
||||
|
||||
c := &Config{
|
||||
@@ -56,8 +58,10 @@ func NewConfig() *Config {
|
||||
RedisHost: utils.GetEnv("REDIS_HOST", "localhost"),
|
||||
RedisPort: utils.GetEnv("REDIS_PORT", "6379"),
|
||||
RedisPassword: utils.GetEnv("REDIS_PASSWORD", ""),
|
||||
ENV: ENV,
|
||||
UNPROTECTED_ENDPOINTS: UNPROTECTED_ENDPOINTS,
|
||||
AllowRegistration: utils.GetEnvBool("ALLOW_REGISTRATION", false),
|
||||
AllowTenantCreation: utils.GetEnvBool("ALLOW_TENANT_CREATION", false),
|
||||
Environment: Environment,
|
||||
UnprotectedEndpoints: UnprotectedEndpoints,
|
||||
}
|
||||
CONFIG = c
|
||||
return c
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"git.secnex.io/secnex/auth-api/config"
|
||||
"git.secnex.io/secnex/auth-api/services"
|
||||
"git.secnex.io/secnex/auth-api/utils"
|
||||
"github.com/go-playground/validator/v10"
|
||||
@@ -16,6 +17,11 @@ type RegisterRequest struct {
|
||||
}
|
||||
|
||||
func RegisterController(c *fiber.Ctx) error {
|
||||
if !config.CONFIG.AllowRegistration {
|
||||
return utils.NewErrorResponse(fiber.StatusForbidden, &fiber.Map{
|
||||
"message": "Registration is not allowed",
|
||||
}).Send(c)
|
||||
}
|
||||
var request RegisterRequest
|
||||
if err := c.BodyParser(&request); err != nil {
|
||||
return utils.NewErrorResponse(fiber.StatusBadRequest, &fiber.Map{
|
||||
|
||||
@@ -8,6 +8,7 @@ require (
|
||||
github.com/gofiber/fiber/v2 v2.52.10
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/valkey-io/valkey-go v1.0.70
|
||||
golang.org/x/crypto v0.46.0
|
||||
gorm.io/driver/postgres v1.6.0
|
||||
gorm.io/gorm v1.31.1
|
||||
@@ -30,7 +31,6 @@ require (
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/valkey-io/valkey-go v1.0.70 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasthttp v1.51.0 // indirect
|
||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||
|
||||
@@ -19,6 +19,8 @@ github.com/gofiber/fiber/v2 v2.52.10 h1:jRHROi2BuNti6NYXmZ6gbNSfT3zj/8c0xy94GOU5
|
||||
github.com/gofiber/fiber/v2 v2.52.10/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
|
||||
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/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
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/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
@@ -44,6 +46,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/onsi/gomega v1.38.3 h1:eTX+W6dobAYfFeGC2PV6RwXRu/MyT+cQguijutvkpSM=
|
||||
github.com/onsi/gomega v1.38.3/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
@@ -61,8 +65,12 @@ github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1S
|
||||
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
|
||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
||||
@@ -68,7 +68,7 @@ func main() {
|
||||
app.Post("/logout", controllers.LogoutController)
|
||||
app.Post("/session/info", controllers.SessionInfoController)
|
||||
|
||||
if config.ENV == "development" {
|
||||
if config.Environment == "development" {
|
||||
app.Get("/api_keys", controllers.CreateApiKeyController)
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
|
||||
func AuthMiddleware() fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
if slices.Contains(config.CONFIG.UNPROTECTED_ENDPOINTS, c.Path()) {
|
||||
if slices.Contains(config.CONFIG.UnprotectedEndpoints, c.Path()) {
|
||||
masterlog.Debug("Unprotected endpoint", map[string]interface{}{"path": c.Path()})
|
||||
return c.Next()
|
||||
}
|
||||
|
||||
39
app/models/user.go
Normal file
39
app/models/user.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"git.secnex.io/secnex/auth-api/utils"
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
|
||||
FirstName string `gorm:"not null" json:"first_name"`
|
||||
LastName string `gorm:"not null" json:"last_name"`
|
||||
Username string `gorm:"not null;unique" json:"username"`
|
||||
Password string `gorm:"not null" json:"password"`
|
||||
Email string `gorm:"not null;unique" json:"email"`
|
||||
Verified bool `gorm:"not null;default:false" json:"verified"`
|
||||
TenantID *uuid.UUID `gorm:"type:uuid" json:"tenant_id"`
|
||||
ExternalID *uuid.UUID `gorm:"type:uuid" json:"external_id"`
|
||||
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
|
||||
|
||||
Tenant *Tenant `gorm:"foreignKey:TenantID" json:"-"`
|
||||
}
|
||||
|
||||
func (User) TableName() string {
|
||||
return "users"
|
||||
}
|
||||
|
||||
func (user *User) BeforeCreate(tx *gorm.DB) (err error) {
|
||||
passwordHash, err := utils.Hash(user.Password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
user.Password = passwordHash
|
||||
return nil
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"git.secnex.io/secnex/auth-api/utils"
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
|
||||
FirstName string `gorm:"not null" json:"first_name"`
|
||||
LastName string `gorm:"not null" json:"last_name"`
|
||||
Username string `gorm:"not null;unique" json:"username"`
|
||||
Password string `gorm:"not null" json:"password"`
|
||||
Email string `gorm:"not null;unique" json:"email"`
|
||||
Verified bool `gorm:"not null;default:false" json:"verified"`
|
||||
TenantID *uuid.UUID `gorm:"type:uuid" json:"tenant_id"`
|
||||
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
|
||||
|
||||
Tenant *Tenant `gorm:"foreignKey:TenantID" json:"tenant"`
|
||||
}
|
||||
|
||||
func (User) TableName() string {
|
||||
return "users"
|
||||
}
|
||||
|
||||
func (user *User) BeforeCreate(tx *gorm.DB) (err error) {
|
||||
passwordHash, err := utils.Hash(user.Password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
user.Password = passwordHash
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
networks:
|
||||
secnex:
|
||||
driver: bridge
|
||||
|
||||
services:
|
||||
db:
|
||||
container_name: secnex-db
|
||||
image: postgres:latest
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 5432:5432
|
||||
environment:
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
- POSTGRES_DB=secnex
|
||||
volumes:
|
||||
- secnex-db-data:/var/lib/postgresql
|
||||
networks:
|
||||
- secnex
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
valkey:
|
||||
container_name: secnex-valkey
|
||||
image: valkey/valkey:latest
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 6379:6379
|
||||
networks:
|
||||
- secnex
|
||||
|
||||
login-api:
|
||||
container_name: secnex-login-api
|
||||
image: git.secnex.io/secnex.platform/login-api:latest
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 3001:3000
|
||||
environment:
|
||||
- ENV=development
|
||||
- DEBUG=true
|
||||
- DATABASE_HOST=db
|
||||
- DATABASE_PORT=5432
|
||||
- DATABASE_USER=postgres
|
||||
- DATABASE_PASSWORD=postgres
|
||||
- DATABASE_NAME=secnex
|
||||
- REDIS_HOST=valkey
|
||||
- REDIS_PORT=6379
|
||||
networks:
|
||||
- secnex
|
||||
depends_on:
|
||||
- db
|
||||
- valkey
|
||||
|
||||
volumes:
|
||||
secnex-db-data:
|
||||
Reference in New Issue
Block a user