feat: email service — SMTP + deadline reminders + invitations (t-paliad-021)
- internal/services/mail_service.go: SMTP/TLS sender (implicit TLS on 465), html/template rendering, branded base layout + content templates, silent no-op when SMTP_* unset. - internal/services/reminder_service.go: hourly scanner for Fristen that are overdue / due tomorrow / due within the week (Monday digest). Dedup via paliad.reminder_log (24h window). - internal/services/invite_service.go: POST /api/invite flow with domain whitelist, in-memory 10/day/user rate limit, audit row in paliad.invitations. - internal/handlers/invite.go: POST + GET /api/invite handlers. - Sidebar "Kolleg:in einladen" button + modal on every page. - migration 016: paliad.reminder_log, paliad.invitations, users.lang column. - docker-compose: SMTP_* + PALIAD_BASE_URL env vars. - docs/feature-roadmap.md: documented Supabase auth-SMTP routing as open question; current pilot keeps identity mails on Supabase default sender. Rationale: get Paliad off Supabase's best-effort outbound for the inbox-facing stuff (reminders, invitations) and move deadline nudges from passive dashboard to active email. Custom Supabase auth SMTP is blocked on the shared ydb.youpc.org instance — deferred until Paliad has its own project or GoTrue webhook relay.
This commit is contained in:
@@ -21,8 +21,12 @@ type User struct {
|
||||
PracticeGroup *string `db:"practice_group" json:"practice_group,omitempty"`
|
||||
Role string `db:"role" json:"role"`
|
||||
Dezernat *string `db:"dezernat" json:"dezernat,omitempty"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
// Lang is the preferred UI language for transactional email ("de"/"en").
|
||||
// NULL → MailService falls back to German. Not collected at onboarding
|
||||
// today; reserved for a future profile-edit screen.
|
||||
Lang *string `db:"lang" json:"lang,omitempty"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
}
|
||||
|
||||
// Akte is a matter (case file). Office-scoped visibility: see paliad.can_see_akte.
|
||||
|
||||
Reference in New Issue
Block a user