more cart
This commit is contained in:
+41
-1
@@ -8,9 +8,11 @@ import (
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/mail"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.k6n.net/mats/go-cart-actor/internal/customerauth"
|
||||
@@ -55,6 +57,32 @@ func buildAuthStorage(ctx context.Context, profileDir string) (customerauth.Cred
|
||||
// authSecret returns the HMAC key for customer session cookies. It reads
|
||||
// CUSTOMER_AUTH_SECRET; when unset it generates an ephemeral random key and
|
||||
// warns that issued sessions will not survive a restart (fine for dev).
|
||||
// selectAuthNotifier picks the transactional auth-message sender. When
|
||||
// MAILERSEND_API_KEY is set it returns a MailerSend-backed notifier; otherwise
|
||||
// it returns nil (the server defaults to LogNotifier, which is fine for dev).
|
||||
func selectAuthNotifier() customerauth.Notifier {
|
||||
apiKey := os.Getenv("MAILERSEND_API_KEY")
|
||||
if apiKey == "" {
|
||||
return nil
|
||||
}
|
||||
fromAddr := strings.TrimSpace(os.Getenv("PROFILE_EMAIL_FROM_ADDRESS"))
|
||||
if fromAddr == "" {
|
||||
log.Print("warning: MAILERSEND_API_KEY set but PROFILE_EMAIL_FROM_ADDRESS is empty — falling back to LogNotifier")
|
||||
return nil
|
||||
}
|
||||
from := mail.Address{
|
||||
Name: strings.TrimSpace(os.Getenv("PROFILE_EMAIL_FROM_NAME")),
|
||||
Address: fromAddr,
|
||||
}
|
||||
n, err := customerauth.NewMailerSendNotifier(apiKey, from)
|
||||
if err != nil {
|
||||
log.Printf("warning: mailersend notifier: %v — falling back to LogNotifier", err)
|
||||
return nil
|
||||
}
|
||||
log.Print("customer-auth: using MailerSend notifier for verification and reset emails")
|
||||
return n
|
||||
}
|
||||
|
||||
func authSecret() []byte {
|
||||
if v := os.Getenv("CUSTOMER_AUTH_SECRET"); v != "" {
|
||||
return []byte(v)
|
||||
@@ -172,9 +200,19 @@ func main() {
|
||||
// CUSTOMER_AUTH_SECRET is all they need to work across replicas.
|
||||
credStore, limiter := buildAuthStorage(ctx, profileDir)
|
||||
|
||||
// Email index: in-memory email→profileID map so the order service can
|
||||
// look up email preferences without scanning all profiles. Built from
|
||||
// the event log on disk at startup, then kept live by the UCP handlers.
|
||||
emailIndex := profile.NewProfileEmailIndex()
|
||||
stateStorage := actor.NewState(reg)
|
||||
profile.BuildEmailIndex(profileDir, stateStorage, reg, emailIndex)
|
||||
|
||||
// UCP Customer REST adapter
|
||||
auditLogPath := filepath.Join(profileDir, "audit.log")
|
||||
customerUCP := ucp.CustomerHandler(pool, auditLogPath, credStore)
|
||||
customerUCP := ucp.CustomerHandler(pool, auditLogPath,
|
||||
ucp.WithEmailIndex(emailIndex),
|
||||
ucp.WithCredentialDeleter(credStore),
|
||||
)
|
||||
if signer := loadUCPProfileSigner(); signer != nil {
|
||||
customerUCP = ucp.WithSigning(customerUCP, signer)
|
||||
log.Print("ucp customer signing enabled")
|
||||
@@ -185,7 +223,9 @@ func main() {
|
||||
mux.Handle("/ucp/v1/customers/", http.StripPrefix("/ucp/v1/customers", customerUCP))
|
||||
|
||||
// Customer auth: password signup/login + session cookies + identity linking.
|
||||
authNotifier := selectAuthNotifier()
|
||||
authHandler := customerauth.NewServer(credStore, pool, customerauth.NewSigner(authSecret()), 0, customerauth.Options{
|
||||
Notifier: authNotifier,
|
||||
Limiter: limiter,
|
||||
BaseURL: os.Getenv("CUSTOMER_AUTH_BASE_URL"),
|
||||
RequireVerifiedEmail: os.Getenv("CUSTOMER_AUTH_REQUIRE_VERIFIED") == "true",
|
||||
|
||||
Reference in New Issue
Block a user