fixing folders and image rendering in client
This commit is contained in:
+55
-6
@@ -6,6 +6,7 @@ package db
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
@@ -211,7 +212,15 @@ CREATE TABLE IF NOT EXISTS esrv_mailboxes (
|
||||
mfa_exempt INTEGER NOT NULL DEFAULT 0,
|
||||
-- Off by default: collapse a run of same-subject messages in a folder view into one
|
||||
-- expandable row. Per-mailbox, not global, since this is purely a display preference.
|
||||
group_messages INTEGER NOT NULL DEFAULT 0
|
||||
group_messages INTEGER NOT NULL DEFAULT 0,
|
||||
-- Remote (http/https) images in an HTML email body are a classic tracking-pixel /
|
||||
-- read-receipt leak, so they're never auto-loaded — this controls when they show at
|
||||
-- all: 'ask' (default) strips them and offers a per-message "Show images" reveal;
|
||||
-- 'trusted' auto-shows only for senders on this mailbox's own
|
||||
-- esrv_mailbox_trusted_image_senders list; 'always' never blocks (not recommended,
|
||||
-- offered anyway since it's the mailbox owner's own call). See
|
||||
-- webmail_mail.go's loadMessageForView / stripRemoteImages.
|
||||
remote_images_mode TEXT NOT NULL DEFAULT 'ask'
|
||||
);
|
||||
|
||||
-- Self-service webmail portal sessions — deliberately a parallel schema to
|
||||
@@ -297,6 +306,18 @@ CREATE TABLE IF NOT EXISTS esrv_mailbox_filter_rules (
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Senders a mailbox owner has explicitly said to always show remote images from
|
||||
-- (esrv_mailboxes.remote_images_mode = 'trusted') — added either from the account
|
||||
-- settings page or via the "always allow images from this sender" checkbox offered
|
||||
-- alongside the per-message "Show images" reveal.
|
||||
CREATE TABLE IF NOT EXISTS esrv_mailbox_trusted_image_senders (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
mailbox_id INTEGER NOT NULL REFERENCES esrv_mailboxes(id),
|
||||
email TEXT NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(mailbox_id, email)
|
||||
);
|
||||
|
||||
-- One row per stored message. cached_from/cached_subject are deliberately plaintext
|
||||
-- (a narrow, confirmed exception to "encrypted at rest") so IMAP LIST/basic SEARCH
|
||||
-- don't need to decrypt every message in a folder; body and every other header stay
|
||||
@@ -485,11 +506,9 @@ func migrateAddedColumns(db *sql.DB) {
|
||||
`ALTER TABLE esrv_domains ADD COLUMN mfa_exempt INTEGER NOT NULL DEFAULT 0`,
|
||||
`ALTER TABLE esrv_mailboxes ADD COLUMN mfa_exempt INTEGER NOT NULL DEFAULT 0`,
|
||||
`ALTER TABLE esrv_mailbox_messages ADD COLUMN cached_to TEXT NOT NULL DEFAULT ''`,
|
||||
// conditions_json/match_type are retrofittable via ALTER TABLE, but the action
|
||||
// CHECK constraint (adding 'mark_as_spam') is not — SQLite doesn't support
|
||||
// altering a CHECK on an existing table. A dev DB created before this change
|
||||
// would need recreating to accept a mark_as_spam rule; a fresh install gets it
|
||||
// for free from the CREATE TABLE above.
|
||||
// The action CHECK constraint (adding 'mark_as_spam') isn't retrofittable via
|
||||
// ALTER TABLE — see migrateFilterRulesMarkAsSpamCheck below, called at the end
|
||||
// of this function, which rebuilds the table for DBs that predate it.
|
||||
`ALTER TABLE esrv_mailbox_filter_rules ADD COLUMN conditions_json TEXT NOT NULL DEFAULT ''`,
|
||||
`ALTER TABLE esrv_mailbox_filter_rules ADD COLUMN match_type TEXT NOT NULL DEFAULT 'all'`,
|
||||
// key_pem replaces the old passphrase-wrapped key_ciphertext/key_nonce/key_salt
|
||||
@@ -505,6 +524,7 @@ func migrateAddedColumns(db *sql.DB) {
|
||||
`ALTER TABLE esrv_mailbox_folders ADD COLUMN restore_parent_id INTEGER REFERENCES esrv_mailbox_folders(id)`,
|
||||
`ALTER TABLE esrv_mailbox_folders ADD COLUMN restore_parent_root TEXT NOT NULL DEFAULT ''`,
|
||||
`ALTER TABLE esrv_mailbox_messages ADD COLUMN restore_folder TEXT NOT NULL DEFAULT ''`,
|
||||
`ALTER TABLE esrv_mailboxes ADD COLUMN remote_images_mode TEXT NOT NULL DEFAULT 'ask'`,
|
||||
}
|
||||
// The three old columns above were NOT NULL with no default, so simply adding
|
||||
// key_pem left them behind still blocking every new insert (which only ever sets
|
||||
@@ -523,6 +543,35 @@ func migrateAddedColumns(db *sql.DB) {
|
||||
// account skip its username change entirely once it re-hits /first-login next.
|
||||
db.Exec(`UPDATE esrv_admin_users SET must_change_username = 1 WHERE username = ? AND must_change_password = 1`, DefaultAdminUsername)
|
||||
migrateSpamRenamedToJunk(db)
|
||||
migrateFilterRulesMarkAsSpamCheck(db)
|
||||
}
|
||||
|
||||
// migrateFilterRulesMarkAsSpamCheck rebuilds esrv_mailbox_filter_rules for any DB
|
||||
// created before 'mark_as_spam' was added to the action CHECK constraint (webmail's
|
||||
// "Mark as Junk" auto-blacklist rule, see webmail_mail.go's ensureJunkRuleForSender) —
|
||||
// SQLite can't ALTER a CHECK constraint on an existing table, so the only way to widen
|
||||
// it is to recreate the table under the current schema and copy the rows across.
|
||||
// Detects the stale constraint by inspecting sqlite_master rather than tracking a
|
||||
// schema-version number, so it stays a no-op forever once a DB is caught up.
|
||||
func migrateFilterRulesMarkAsSpamCheck(db *sql.DB) {
|
||||
var tableSQL string
|
||||
if err := db.QueryRow(`SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'esrv_mailbox_filter_rules'`).Scan(&tableSQL); err != nil {
|
||||
return
|
||||
}
|
||||
if strings.Contains(tableSQL, "mark_as_spam") {
|
||||
return
|
||||
}
|
||||
if _, err := db.Exec(`ALTER TABLE esrv_mailbox_filter_rules RENAME TO esrv_mailbox_filter_rules_old`); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err := db.Exec(schema); err != nil {
|
||||
return
|
||||
}
|
||||
db.Exec(`INSERT INTO esrv_mailbox_filter_rules
|
||||
(id, mailbox_id, priority, condition_field, condition_op, condition_value, action, action_value, is_active, conditions_json, match_type, created_at)
|
||||
SELECT id, mailbox_id, priority, condition_field, condition_op, condition_value, action, action_value, is_active, conditions_json, match_type, created_at
|
||||
FROM esrv_mailbox_filter_rules_old`)
|
||||
db.Exec(`DROP TABLE esrv_mailbox_filter_rules_old`)
|
||||
}
|
||||
|
||||
// migrateSpamRenamedToJunk renames the standard "Spam" folder to "Junk" for mailboxes
|
||||
|
||||
Reference in New Issue
Block a user