panel-notifications: schema and store

Migration 0004_notifications.sql, DDL only: users.notify, a user's own
switch, on by default; notify_state, one row per subject the panel has
written about (dns:<domain>, cert, queue, limit:<domain>:<login>), so that
each thing is said once and a restart says nothing again.

Store: the instance switch as a settings key, on unless turned off;
SetUserNotify; NotifyRecipients - global users for everything, domain users
for the domains on their list or all of them, only with an e-mail and their
switch on, a shared mailbox once; the state's get, set, delete and list by
prefix; LimitRefusalsSince, the mail refused under a level-2 limit per domain
and application.

Nothing is sent yet. Checked on Windows: go vet clean, go test
./internal/store passes with the schema test at user_version 4. The page
guards fail from the design commit 87fa0a4 until the pages are built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mix
2026-10-12 15:48:56 +03:00
co-authored by Claude Opus 5.5
parent 87fa0a4381
commit 06ad174fb9
9 changed files with 421 additions and 17 deletions
+8 -5
View File
@@ -43,12 +43,15 @@ type User struct {
// are then ignored.
AllDomains bool
AllInboundDomains bool
CreatedAt time.Time
DomainIDs []int64
InboundDomainIDs []int64
// Notify is the user's own switch for notification e-mails (Account). It
// is on for a new user and does nothing without an e-mail.
Notify bool
CreatedAt time.Time
DomainIDs []int64
InboundDomainIDs []int64
}
const userColumns = "id, username, password_hash, role, email, all_domains, all_inbound_domains, created_at"
const userColumns = "id, username, password_hash, role, email, all_domains, all_inbound_domains, notify, created_at"
func scanUser(r scanRow) (User, error) {
var (
@@ -56,7 +59,7 @@ func scanUser(r scanRow) (User, error) {
createdAt string
)
err := r.Scan(&u.ID, &u.Username, &u.PasswordHash, &u.Role, &u.Email,
&u.AllDomains, &u.AllInboundDomains, &createdAt)
&u.AllDomains, &u.AllInboundDomains, &u.Notify, &createdAt)
if err != nil {
return User{}, err
}