From 7fe1cc164b7ef4bd783ee01d1a1a1bef4e3d272e Mon Sep 17 00:00:00 2001 From: Username Date: Mon, 16 Feb 2026 20:26:39 +0100 Subject: [PATCH] database: add short_urls table schema --- app/database.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/app/database.py b/app/database.py index 645bac9..560429b 100644 --- a/app/database.py +++ b/app/database.py @@ -94,6 +94,22 @@ CREATE TABLE IF NOT EXISTS audit_log ( CREATE INDEX IF NOT EXISTS idx_audit_timestamp ON audit_log(timestamp); CREATE INDEX IF NOT EXISTS idx_audit_event_type ON audit_log(event_type); CREATE INDEX IF NOT EXISTS idx_audit_client_id ON audit_log(client_id); + +-- URL shortener +CREATE TABLE IF NOT EXISTS short_urls ( + id TEXT PRIMARY KEY, + target_url TEXT NOT NULL, + url_hash TEXT NOT NULL, + owner TEXT, + created_at INTEGER NOT NULL, + last_accessed INTEGER NOT NULL, + access_count INTEGER NOT NULL DEFAULT 0, + expires_at INTEGER +); + +CREATE INDEX IF NOT EXISTS idx_short_urls_owner ON short_urls(owner); +CREATE INDEX IF NOT EXISTS idx_short_urls_created_at ON short_urls(created_at); +CREATE INDEX IF NOT EXISTS idx_short_urls_url_hash ON short_urls(url_hash); """ # Password hashing constants @@ -251,6 +267,31 @@ def cleanup_expired_hashes() -> int: return cursor.rowcount +def cleanup_expired_short_urls() -> int: + """Delete short URLs that have expired. + + Short URLs expire based on: + - Custom expires_at timestamp if set + - Default expiry from last_accessed if expires_at is NULL + + Returns number of deleted short URLs. + """ + expiry_seconds = current_app.config["PASTE_EXPIRY_SECONDS"] + now = int(time.time()) + default_cutoff = now - expiry_seconds + + db = get_db() + cursor = db.execute( + """DELETE FROM short_urls WHERE + (expires_at IS NOT NULL AND expires_at < ?) + OR (expires_at IS NULL AND last_accessed < ?)""", + (now, default_cutoff), + ) + db.commit() + + return cursor.rowcount + + def check_content_hash(content_hash: str) -> tuple[bool, int]: """Check if content hash exceeds dedup threshold.