分享码有效期,支持表达式
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
@@ -17,7 +18,7 @@ type Config struct {
|
||||
S3 S3Config
|
||||
EnablePersistTask bool
|
||||
ShareCodeMaxPerMac int
|
||||
ShareCodeTTLMin int
|
||||
ShareCodeTTL time.Duration
|
||||
}
|
||||
|
||||
func Load() (*Config, error) {
|
||||
@@ -49,6 +50,11 @@ func Load() (*Config, error) {
|
||||
eq := loadEqualize(env)
|
||||
s3cfg := loadS3(env)
|
||||
|
||||
shareCodeTTL, err := parseShareCodeTTL(getEnv("SHARE_CODE_TTL_MIN", "30"))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid SHARE_CODE_TTL_MIN: %w", err)
|
||||
}
|
||||
|
||||
return &Config{
|
||||
Env: env,
|
||||
Host: getEnv("APP_HOST", "0.0.0.0"),
|
||||
@@ -60,7 +66,7 @@ func Load() (*Config, error) {
|
||||
S3: s3cfg,
|
||||
EnablePersistTask: getEnv("ENABLE_PERSIST_TASK", "false") == "true",
|
||||
ShareCodeMaxPerMac: getEnvInt("SHARE_CODE_MAX_PER_MAC", 1),
|
||||
ShareCodeTTLMin: getEnvInt("SHARE_CODE_TTL_MIN", 30),
|
||||
ShareCodeTTL: shareCodeTTL,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const shareCodeTTLMax = 365 * 24 * time.Hour
|
||||
|
||||
// parseShareCodeTTL parses SHARE_CODE_TTL_MIN values:
|
||||
// - bare number (e.g. "30") = minutes (backward compatible)
|
||||
// - with suffix: m (minutes), h (hours), d (days), e.g. "30m", "24h", "30d"
|
||||
func parseShareCodeTTL(raw string) (time.Duration, error) {
|
||||
raw = strings.TrimSpace(raw)
|
||||
if raw == "" {
|
||||
return 30 * time.Minute, nil
|
||||
}
|
||||
|
||||
if n, err := strconv.Atoi(raw); err == nil {
|
||||
if n <= 0 {
|
||||
return 0, fmt.Errorf("must be positive")
|
||||
}
|
||||
d := time.Duration(n) * time.Minute
|
||||
if d > shareCodeTTLMax {
|
||||
return 0, fmt.Errorf("exceeds maximum of 365d")
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
if len(raw) < 2 {
|
||||
return 0, fmt.Errorf("invalid format %q", raw)
|
||||
}
|
||||
|
||||
unit := strings.ToLower(string(raw[len(raw)-1]))
|
||||
numStr := raw[:len(raw)-1]
|
||||
n, err := strconv.Atoi(numStr)
|
||||
if err != nil || n <= 0 {
|
||||
return 0, fmt.Errorf("invalid format %q", raw)
|
||||
}
|
||||
|
||||
var d time.Duration
|
||||
switch unit {
|
||||
case "m":
|
||||
d = time.Duration(n) * time.Minute
|
||||
case "h":
|
||||
d = time.Duration(n) * time.Hour
|
||||
case "d":
|
||||
d = time.Duration(n) * 24 * time.Hour
|
||||
default:
|
||||
return 0, fmt.Errorf("unknown unit %q (use m, h, or d)", unit)
|
||||
}
|
||||
|
||||
if d > shareCodeTTLMax {
|
||||
return 0, fmt.Errorf("exceeds maximum of 365d")
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestParseShareCodeTTL(t *testing.T) {
|
||||
tests := []struct {
|
||||
raw string
|
||||
want time.Duration
|
||||
wantErr bool
|
||||
}{
|
||||
{"", 30 * time.Minute, false},
|
||||
{"30", 30 * time.Minute, false},
|
||||
{"30m", 30 * time.Minute, false},
|
||||
{"30M", 30 * time.Minute, false},
|
||||
{"24h", 24 * time.Hour, false},
|
||||
{"24H", 24 * time.Hour, false},
|
||||
{"30d", 30 * 24 * time.Hour, false},
|
||||
{"365d", 365 * 24 * time.Hour, false},
|
||||
{"0", 0, true},
|
||||
{"-1", 0, true},
|
||||
{"0m", 0, true},
|
||||
{"abc", 0, true},
|
||||
{"30x", 0, true},
|
||||
{"366d", 0, true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.raw, func(t *testing.T) {
|
||||
got, err := parseShareCodeTTL(tt.raw)
|
||||
if tt.wantErr {
|
||||
if err == nil {
|
||||
t.Fatalf("expected error for %q", tt.raw)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error for %q: %v", tt.raw, err)
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Fatalf("parseShareCodeTTL(%q) = %v, want %v", tt.raw, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user