feat(PROJ-53): Konfigurierbare Listenanzahl pro Seite

- users.list_page_size (Default 25), PATCH /api/auth/preferences,
  Whitelist 25/50/100/200, Wert in login/me-Response
- Settings-UI mit Select, /search nutzt gespeicherte Seitengröße
- /api/search page_size serverseitig auf max. 500 gecappt

fix(PROJ-46): login_attempts-Migration nutzte s.db statt s.pool
(Backend kompilierte nicht)

feat(PROJ-50): DSGVO-Löschersuchen Backend (dsgvo_requests, Handler,
cc_addr/bcc_addr Indexerweiterung) — noch nicht QA'd/deployed
This commit is contained in:
sysops
2026-06-14 22:25:02 +02:00
parent b73ef55a65
commit 472ba6a087
25 changed files with 1078 additions and 111 deletions
+26 -10
View File
@@ -113,6 +113,8 @@ func (idx *manticoreIndex) ensureTable() error {
subject text,
from_addr text,
to_addr text,
cc_addr text,
bcc_addr text,
body text,
attachment_names text,
attachment_text text,
@@ -128,6 +130,15 @@ func (idx *manticoreIndex) ensureTable() error {
if err := idx.ensureColumn("attachment_text", "text"); err != nil {
return err
}
// PROJ-50: ALTER existing tables to add cc_addr/bcc_addr so DSGVO address
// searches can match CC/BCC recipients. Existing mails need `archivmail
// reindex` to backfill these fields.
if err := idx.ensureColumn("cc_addr", "text"); err != nil {
return err
}
if err := idx.ensureColumn("bcc_addr", "text"); err != nil {
return err
}
return nil
}
@@ -172,13 +183,15 @@ func (idx *manticoreIndex) IndexSync(doc MailDocument) error {
_, err := idx.db.Exec(
fmt.Sprintf(`REPLACE INTO %s
(id, mail_id, subject, from_addr, to_addr, body, attachment_names, attachment_text, has_attachment, date_ts, size_bytes)
VALUES (?,?,?,?,?,?,?,?,?,?,?)`, idx.table),
(id, mail_id, subject, from_addr, to_addr, cc_addr, bcc_addr, body, attachment_names, attachment_text, has_attachment, date_ts, size_bytes)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)`, idx.table),
rowID,
doc.ID,
doc.Subject,
doc.From,
doc.To,
doc.CC,
doc.BCC,
doc.Body,
doc.AttachNames,
doc.AttachmentText,
@@ -202,24 +215,24 @@ func (idx *manticoreIndex) IndexSync(doc MailDocument) error {
func (idx *manticoreIndex) UpdateAttachmentText(mailID, text string) error {
rowID := hashMailID(mailID)
row := idx.db.QueryRow(fmt.Sprintf(
`SELECT mail_id, subject, from_addr, to_addr, body, attachment_names,
`SELECT mail_id, subject, from_addr, to_addr, cc_addr, bcc_addr, body, attachment_names,
has_attachment, date_ts, size_bytes
FROM %s WHERE id = ? LIMIT 1`, idx.table),
rowID,
)
var (
mid, subj, from, to, body, attachNames string
hasAttach uint64
dateTS, sizeBytes int64
mid, subj, from, to, cc, bcc, body, attachNames string
hasAttach uint64
dateTS, sizeBytes int64
)
if err := row.Scan(&mid, &subj, &from, &to, &body, &attachNames, &hasAttach, &dateTS, &sizeBytes); err != nil {
if err := row.Scan(&mid, &subj, &from, &to, &cc, &bcc, &body, &attachNames, &hasAttach, &dateTS, &sizeBytes); err != nil {
return fmt.Errorf("manticore UpdateAttachmentText %s: load row: %w", idx.table, err)
}
if _, err := idx.db.Exec(
fmt.Sprintf(`REPLACE INTO %s
(id, mail_id, subject, from_addr, to_addr, body, attachment_names, attachment_text, has_attachment, date_ts, size_bytes)
VALUES (?,?,?,?,?,?,?,?,?,?,?)`, idx.table),
rowID, mid, subj, from, to, body, attachNames, text, hasAttach, dateTS, sizeBytes,
(id, mail_id, subject, from_addr, to_addr, cc_addr, bcc_addr, body, attachment_names, attachment_text, has_attachment, date_ts, size_bytes)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)`, idx.table),
rowID, mid, subj, from, to, cc, bcc, body, attachNames, text, hasAttach, dateTS, sizeBytes,
); err != nil {
return fmt.Errorf("manticore UpdateAttachmentText %s: replace: %w", idx.table, err)
}
@@ -276,6 +289,9 @@ func (idx *manticoreIndex) Search(req SearchRequest) (*SearchResult, error) {
if req.OwnEmail != "" {
matchParts = append(matchParts, fmt.Sprintf("@(from_addr,to_addr) %s", escapeManticoreMatch(req.OwnEmail)))
}
if req.AnyAddress != "" {
matchParts = append(matchParts, fmt.Sprintf("@(from_addr,to_addr,cc_addr,bcc_addr) %s", escapeManticoreMatch(req.AnyAddress)))
}
hasMatch := len(matchParts) > 0