feat(admin): self-hosted customer accounts with email verification
Mirrors the pattern sitesvc already proves: 32 random bytes, only the SHA-256 hash stored, a 24-hour expiry, and the token cleared on use -- so a leaked database yields no working links. Unverified login returns a distinct "verify your email address first" rather than the generic error. The address is already known to be theirs, so there is nothing to disclose and that is the only useful thing to say. Licence blobs are emailed inline. A blob is signed public data, not a secret: it is useless on any instance other than the one it names. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/mrhid6/vantage/admin/internal/db"
|
||||
"github.com/mrhid6/vantage/admin/internal/inject"
|
||||
"github.com/mrhid6/vantage/admin/internal/licensing"
|
||||
"github.com/mrhid6/vantage/admin/internal/mail"
|
||||
"github.com/mrhid6/vantage/admin/internal/models"
|
||||
)
|
||||
|
||||
@@ -29,6 +30,15 @@ func main() {
|
||||
|
||||
licensing.SetSigningKey(cfg.SigningKey)
|
||||
|
||||
mail.Init(mail.Config{
|
||||
Host: cfg.SMTPHost, Port: cfg.SMTPPort, From: cfg.SMTPFrom,
|
||||
Username: cfg.SMTPUsername, Password: cfg.SMTPPassword,
|
||||
PublicURL: cfg.PublicURL,
|
||||
})
|
||||
if !mail.Enabled() {
|
||||
log.Println("warning: SMTP not configured; verification and licence emails will fail")
|
||||
}
|
||||
|
||||
auth.InitRedis(cfg.RedisAddr)
|
||||
pingCtx, pingCancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
if err := auth.Ping(pingCtx); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user