Add optional email verification and registration control

Implemented email service infrastructure with SMTP support and optional email verification for self-hosted deployments. Registration flow now supports open/closed modes and hardcoded Apocapoc branding.

Key features:
- Email service with SMTP and template rendering
- Optional email verification (auto-verified without SMTP config)
- Registration modes: open/closed for access control
- Hardcoded Apocapoc branding (AppName, AppURL, DefaultFrom)
- Separate registration and login flows (registration no longer returns tokens)
This commit is contained in:
2025-11-28 08:21:51 +01:00
parent a95a703905
commit 00f6b51228
28 changed files with 890 additions and 99 deletions
@@ -41,7 +41,7 @@ func setupTestServer(t *testing.T) *TestServer {
entryRepo := sqlite.NewHabitEntryRepository(db)
refreshTokenRepo := sqlite.NewRefreshTokenRepository(db)
registerHandler := commands.NewRegisterUserHandler(userRepo, passwordHasher)
registerHandler := commands.NewRegisterUserHandler(userRepo, passwordHasher, nil, "", "open")
loginHandler := queries.NewLoginUserHandler(userRepo, passwordHasher)
refreshTokenHandler := queries.NewRefreshTokenHandler(refreshTokenRepo, userRepo)
revokeTokenHandler := commands.NewRevokeTokenHandler(refreshTokenRepo)
@@ -104,3 +104,22 @@ func decodeResponse(t *testing.T, rr *httptest.ResponseRecorder, target interfac
t.Fatalf("Failed to decode response: %v", err)
}
}
func registerAndLogin(t *testing.T, router http.Handler, email, password string) string {
registerBody := RegisterRequest{
Email: email,
Password: password,
Timezone: "UTC",
}
makeRequest(t, router, "POST", "/api/v1/auth/register", registerBody, "")
loginBody := LoginRequest{
Email: email,
Password: password,
}
rr := makeRequest(t, router, "POST", "/api/v1/auth/login", loginBody, "")
var authResp AuthResponse
decodeResponse(t, rr, &authResp)
return authResp.Token
}