feat(PROJ-28): Self-Service Onboarding — Signup, Verify, Password Reset, Invites
- internal/mailer: SMTP-Out via net/smtp (TLS + STARTTLS), HTML+Text-Templates - internal/tokenstore: auth_tokens Tabelle, SHA-256-Hash, TTL, einmalig verwendbar - userstore: CreateInactive(), Activate(), GetByEmail(), SetPassword() - API: POST /signup, GET /verify, POST /forgot-password, POST /reset-password - API: POST /admin/invite (domain_admin+), GET /auth/invite?token (check) - Login-Seite: Links zu "Passwort vergessen" und "Registrieren" - Frontend: /signup, /verify, /forgot-password, /reset-password Seiten - server.fqdn nicht konfiguriert → Startup-Warnung, Self-Service deaktiviert - LDAP-Nutzer: Passwort-Reset abgewiesen Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -18,10 +18,12 @@ import (
|
||||
"github.com/archivmail/internal/index"
|
||||
"github.com/archivmail/internal/labelstore"
|
||||
ldapcfg "github.com/archivmail/internal/ldapconfig"
|
||||
"github.com/archivmail/internal/mailer"
|
||||
pop3store "github.com/archivmail/internal/pop3"
|
||||
"github.com/archivmail/internal/smtpd"
|
||||
"github.com/archivmail/internal/storage"
|
||||
"github.com/archivmail/internal/tenantstore"
|
||||
"github.com/archivmail/internal/tokenstore"
|
||||
"github.com/archivmail/internal/userstore"
|
||||
)
|
||||
|
||||
@@ -81,6 +83,9 @@ type Server struct {
|
||||
appVersion string
|
||||
moduleVersions map[string]string
|
||||
globalRetentionDays int // from storage config (PROJ-34)
|
||||
mailer *mailer.Mailer
|
||||
tokenStore *tokenstore.Store
|
||||
fqdn string // from server.fqdn config (PROJ-28)
|
||||
}
|
||||
|
||||
// SetSMTPDaemon wires the SMTP daemon into the API server after construction.
|
||||
@@ -117,6 +122,21 @@ func (s *Server) SetGlobalRetentionDays(days int) {
|
||||
s.globalRetentionDays = days
|
||||
}
|
||||
|
||||
// SetMailer wires the SMTP-Out mailer into the API server (PROJ-28).
|
||||
func (s *Server) SetMailer(m *mailer.Mailer) {
|
||||
s.mailer = m
|
||||
}
|
||||
|
||||
// SetTokenStore wires the token store into the API server (PROJ-28).
|
||||
func (s *Server) SetTokenStore(ts *tokenstore.Store) {
|
||||
s.tokenStore = ts
|
||||
}
|
||||
|
||||
// SetFQDN wires the server FQDN for link generation (PROJ-28).
|
||||
func (s *Server) SetFQDN(fqdn string) {
|
||||
s.fqdn = fqdn
|
||||
}
|
||||
|
||||
// New creates and wires up a new API server.
|
||||
func New(
|
||||
cfg config.APIConfig,
|
||||
@@ -157,6 +177,14 @@ func (s *Server) routes() {
|
||||
s.mux.HandleFunc("POST /api/auth/login", s.handleLogin)
|
||||
s.mux.HandleFunc("GET /api/auth/me", s.auth(s.handleMe))
|
||||
s.mux.HandleFunc("POST /api/auth/logout", s.auth(s.handleLogout))
|
||||
|
||||
// PROJ-28: Self-Service Onboarding
|
||||
s.mux.HandleFunc("POST /api/auth/signup", s.handleSignup)
|
||||
s.mux.HandleFunc("GET /api/auth/verify", s.handleVerifyEmail)
|
||||
s.mux.HandleFunc("POST /api/auth/forgot-password", s.handleForgotPassword)
|
||||
s.mux.HandleFunc("POST /api/auth/reset-password", s.handleResetPassword)
|
||||
s.mux.HandleFunc("GET /api/auth/invite", s.handleCheckInvite)
|
||||
s.mux.HandleFunc("POST /api/admin/invite", s.authAdmin(s.handleCreateInvite))
|
||||
s.mux.HandleFunc("GET /api/users", s.authAdmin(s.handleListUsers))
|
||||
s.mux.HandleFunc("POST /api/users", s.authAdmin(s.handleCreateUser))
|
||||
s.mux.HandleFunc("PATCH /api/users/{id}", s.authAdmin(s.handleUpdateUser))
|
||||
|
||||
Reference in New Issue
Block a user