Change config JWT duration fields to time.Duration
- fix: The AccessTTL and RefreshTTL fields in JWTConfig now use time.Duration type directly instead of string with ParseDuration methods. The config validation now checks for positive durations rather than parsing strings.
This commit is contained in:
@@ -44,8 +44,8 @@ func Bootstrap(cfg *config.Config) (*WebApp, error) {
|
|||||||
authService := service.NewAuthService(
|
authService := service.NewAuthService(
|
||||||
userRepo, sessionRepo, credentialRepo,
|
userRepo, sessionRepo, credentialRepo,
|
||||||
jwtSecret,
|
jwtSecret,
|
||||||
cfg.JWT.AccessDuration(),
|
cfg.JWT.AccessTTL,
|
||||||
cfg.JWT.RefreshDuration(),
|
cfg.JWT.RefreshTTL,
|
||||||
)
|
)
|
||||||
|
|
||||||
return &WebApp{
|
return &WebApp{
|
||||||
|
|||||||
@@ -48,19 +48,9 @@ type LocalStorageConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type JWTConfig struct {
|
type JWTConfig struct {
|
||||||
Secret string `mapstructure:"secret"`
|
Secret string `mapstructure:"secret"`
|
||||||
AccessTTL string `mapstructure:"access_ttl"`
|
AccessTTL time.Duration `mapstructure:"access_ttl"`
|
||||||
RefreshTTL string `mapstructure:"refresh_ttl"`
|
RefreshTTL time.Duration `mapstructure:"refresh_ttl"`
|
||||||
}
|
|
||||||
|
|
||||||
func (j JWTConfig) AccessDuration() time.Duration {
|
|
||||||
d, _ := time.ParseDuration(j.AccessTTL)
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j JWTConfig) RefreshDuration() time.Duration {
|
|
||||||
d, _ := time.ParseDuration(j.RefreshTTL)
|
|
||||||
return d
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Validate() error {
|
func (c *Config) Validate() error {
|
||||||
@@ -104,12 +94,12 @@ func (c *Config) Validate() error {
|
|||||||
errs = append(errs, errors.New("jwt.secret: must not be empty"))
|
errs = append(errs, errors.New("jwt.secret: must not be empty"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := time.ParseDuration(c.JWT.AccessTTL); err != nil {
|
if c.JWT.AccessTTL <= 0 {
|
||||||
errs = append(errs, fmt.Errorf("jwt.access_ttl: %w", err))
|
errs = append(errs, errors.New("jwt.access_ttl: must be positive"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := time.ParseDuration(c.JWT.RefreshTTL); err != nil {
|
if c.JWT.RefreshTTL <= 0 {
|
||||||
errs = append(errs, fmt.Errorf("jwt.refresh_ttl: %w", err))
|
errs = append(errs, errors.New("jwt.refresh_ttl: must be positive"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.Join(errs...)
|
return errors.Join(errs...)
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ func TestDefaults(t *testing.T) {
|
|||||||
{"database.sqlite.path", cfg.Database.SQLite.Path, "data/mygo.db"},
|
{"database.sqlite.path", cfg.Database.SQLite.Path, "data/mygo.db"},
|
||||||
{"storage.driver", cfg.Storage.Driver, "local"},
|
{"storage.driver", cfg.Storage.Driver, "local"},
|
||||||
{"storage.local.path", cfg.Storage.Local.Path, "data/files"},
|
{"storage.local.path", cfg.Storage.Local.Path, "data/files"},
|
||||||
{"jwt.access_ttl", cfg.JWT.AccessTTL, "15m"},
|
{"jwt.access_ttl", cfg.JWT.AccessTTL, 15 * time.Minute},
|
||||||
{"jwt.refresh_ttl", cfg.JWT.RefreshTTL, "168h"},
|
{"jwt.refresh_ttl", cfg.JWT.RefreshTTL, 168 * time.Hour},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@@ -87,11 +87,11 @@ jwt:
|
|||||||
if cfg.JWT.Secret != "test-secret" {
|
if cfg.JWT.Secret != "test-secret" {
|
||||||
t.Errorf("jwt.secret = %q, want %q", cfg.JWT.Secret, "test-secret")
|
t.Errorf("jwt.secret = %q, want %q", cfg.JWT.Secret, "test-secret")
|
||||||
}
|
}
|
||||||
if cfg.JWT.AccessTTL != "30m" {
|
if cfg.JWT.AccessTTL != 30*time.Minute {
|
||||||
t.Errorf("jwt.access_ttl = %q, want %q", cfg.JWT.AccessTTL, "30m")
|
t.Errorf("jwt.access_ttl = %v, want %v", cfg.JWT.AccessTTL, 30*time.Minute)
|
||||||
}
|
}
|
||||||
if cfg.JWT.RefreshTTL != "72h" {
|
if cfg.JWT.RefreshTTL != 72*time.Hour {
|
||||||
t.Errorf("jwt.refresh_ttl = %q, want %q", cfg.JWT.RefreshTTL, "72h")
|
t.Errorf("jwt.refresh_ttl = %v, want %v", cfg.JWT.RefreshTTL, 72*time.Hour)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,15 +198,15 @@ func TestExplicitConfigFileNotFound(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestJWTConfigAccessDuration(t *testing.T) {
|
func TestJWTConfigAccessDuration(t *testing.T) {
|
||||||
j := JWTConfig{AccessTTL: "15m"}
|
j := JWTConfig{AccessTTL: 15 * time.Minute}
|
||||||
if got := j.AccessDuration(); got != 15*time.Minute {
|
if j.AccessTTL != 15*time.Minute {
|
||||||
t.Errorf("AccessDuration() = %v, want %v", got, 15*time.Minute)
|
t.Errorf("AccessTTL = %v, want %v", j.AccessTTL, 15*time.Minute)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestJWTConfigRefreshDuration(t *testing.T) {
|
func TestJWTConfigRefreshDuration(t *testing.T) {
|
||||||
j := JWTConfig{RefreshTTL: "168h"}
|
j := JWTConfig{RefreshTTL: 168 * time.Hour}
|
||||||
if got := j.RefreshDuration(); got != 168*time.Hour {
|
if j.RefreshTTL != 168*time.Hour {
|
||||||
t.Errorf("RefreshDuration() = %v, want %v", got, 168*time.Hour)
|
t.Errorf("RefreshTTL = %v, want %v", j.RefreshTTL, 168*time.Hour)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ func TestVersionRoute(t *testing.T) {
|
|||||||
cfg := &config.Config{
|
cfg := &config.Config{
|
||||||
JWT: config.JWTConfig{
|
JWT: config.JWTConfig{
|
||||||
Secret: "test-secret",
|
Secret: "test-secret",
|
||||||
AccessTTL: "15m",
|
AccessTTL: 15 * time.Minute,
|
||||||
RefreshTTL: "168h",
|
RefreshTTL: 168 * time.Hour,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
authService := service.NewAuthService(nil, nil, nil, nil, 15*time.Minute, 7*24*time.Hour)
|
authService := service.NewAuthService(nil, nil, nil, nil, 15*time.Minute, 7*24*time.Hour)
|
||||||
|
|||||||
Reference in New Issue
Block a user