- auth.py/auth_routes.py: Login Flow v2 (verified against real NC source/docs) - no OAuth2 client registration needed, backend polls server-side so no CORS issues. Sessions are hashed-token cookies; NC app passwords encrypted at rest (Fernet). Every /api/* route guarded by a blueprint-wide before_request, not per-route decorators, so future routes are protected by default. - receipts/groups scoped per owner_nc_user_id; cross-user access 404s. - nc_client/cospend_client take (username, app_password) per call instead of one shared global credential - each user's uploads/shares/ bills now happen as themselves. - Frontend: LoginGate component drives the login flow (open NC login in a new tab, poll our backend, done). - Merged the old separate review step into the split screen, redesigned with Tailwind (was unstyled/broken), default-excluded-per-item splitting with one-click "include everyone" fixed, DD.MM.YYYY date field, receipt-icon branding. - Dropped LLM bounding-box highlighting - unreliable on real receipts, plain photo upload instead. - Only mention who a bill is split with in its title when there's more than one bill off the same receipt to disambiguate.
47 lines
1.9 KiB
SQL
47 lines
1.9 KiB
SQL
CREATE TABLE IF NOT EXISTS users (
|
|
nc_user_id TEXT PRIMARY KEY,
|
|
-- Fernet-encrypted NC app password obtained via Login Flow v2. Never
|
|
-- returned by any API response.
|
|
nc_app_password_encrypted BLOB NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
last_login_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
-- SHA-256 hex digest of the actual session cookie value - never the raw
|
|
-- token, so a DB read alone can't yield a usable session (same
|
|
-- principle as password hashing).
|
|
session_id_hash TEXT PRIMARY KEY,
|
|
nc_user_id TEXT NOT NULL REFERENCES users(nc_user_id) ON DELETE CASCADE,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
expires_at TEXT NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS receipts (
|
|
id TEXT PRIMARY KEY,
|
|
owner_nc_user_id TEXT NOT NULL REFERENCES users(nc_user_id) ON DELETE CASCADE,
|
|
image_path TEXT NOT NULL,
|
|
image_width INTEGER,
|
|
image_height INTEGER,
|
|
items_json TEXT NOT NULL DEFAULT '[]',
|
|
store_name TEXT, -- extracted from the receipt, editable
|
|
receipt_date TEXT, -- YYYY-MM-DD, extracted; falls back to
|
|
-- today's date if unreadable/unset
|
|
status TEXT NOT NULL DEFAULT 'extracted', -- extracted | grouped | done
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS groups (
|
|
id TEXT PRIMARY KEY,
|
|
receipt_id TEXT NOT NULL REFERENCES receipts(id) ON DELETE CASCADE,
|
|
cospend_project_id TEXT NOT NULL,
|
|
payer_member_id TEXT NOT NULL,
|
|
member_ids_json TEXT NOT NULL, -- json list of cospend member ids (owers)
|
|
item_ids_json TEXT NOT NULL, -- json list of item ids from receipts.items_json
|
|
status TEXT NOT NULL DEFAULT 'pending', -- pending | submitted | failed
|
|
share_url TEXT,
|
|
cospend_bill_id TEXT,
|
|
error TEXT,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
);
|