From 88d8469180daccac7125b94c114f8e786de51318 Mon Sep 17 00:00:00 2001 From: Stephen Adamson Date: Sat, 21 Feb 2026 18:47:58 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20add=20email=20verification,=20profile?= =?UTF-8?q?=20pictures,=20deposits,=20and=20calendar=20export=20Backend:?= =?UTF-8?q?=20-=20Add=20email=20verification=20code=20generation=20and=20v?= =?UTF-8?q?erification=20endpoints=20-=20Add=20profile=20picture=20upload?= =?UTF-8?q?=20with=20S3=20storage=20and=20image=20processing=20-=20Add=20d?= =?UTF-8?q?eposit=5Frequired=20field=20to=20users=20with=2048h=20advance?= =?UTF-8?q?=20booking=20=20=20requirement=20-=20Add=20loyalty=20stamps=20t?= =?UTF-8?q?hat=20accumulate=20on=20completed=20bookings=20-=20Auto-transit?= =?UTF-8?q?ion=20bookings:=20confirmed=20=E2=86=92=20in=5Fprogress=20?= =?UTF-8?q?=E2=86=92=20completed=20-=20Add=20booking=20cancellation=20hand?= =?UTF-8?q?ler=20with=20no-show=20detection=20-=20Add=20ICS=20calendar=20f?= =?UTF-8?q?ile=20download=20endpoint=20for=20bookings=20-=20Sync=20booking?= =?UTF-8?q?s=20to=20CalDAV=20on=20confirmation=20=20=20Frontend:=20-=20Add?= =?UTF-8?q?=20schedule=20page=20route=20-=20Add=20avatar=20and=20image-cro?= =?UTF-8?q?pper=20UI=20components=20-=20Update=20shadcn-svelte=20component?= =?UTF-8?q?s=20(button,=20dialog)=20-=20Add=20"Add=20to=20Calendar"=20butt?= =?UTF-8?q?on=20in=20booking=20modal=20=20=20Database:=20-=20Add=20verific?= =?UTF-8?q?ation=5Fcodes=20table=20-=20Add=20profile=5Fpic=5Furl,=20loyalt?= =?UTF-8?q?y=5Fstamps,=20deposits=5Frequired=20to=20users=20-=20Various=20?= =?UTF-8?q?schema=20updates?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- init-scripts/init-script.sql | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/init-scripts/init-script.sql b/init-scripts/init-script.sql index 25f0dcc..ef67384 100644 --- a/init-scripts/init-script.sql +++ b/init-scripts/init-script.sql @@ -127,6 +127,25 @@ CREATE TABLE user_social_logins ( CREATE INDEX idx_users_email_lower ON users (LOWER(email)); CREATE INDEX idx_users_account_role ON users (account_role); +-- ======================================= +-- VERIFICATION CODES TABLE +-- ======================================= +CREATE TYPE verification_purpose AS ENUM ('email_verify', 'password_reset'); + +CREATE TABLE verification_codes ( + id BIGSERIAL PRIMARY KEY, + code CHAR(32) NOT NULL UNIQUE, + user_id CHAR(12) NOT NULL REFERENCES users(id) ON DELETE CASCADE, + purpose verification_purpose NOT NULL, + expires_at TIMESTAMPTZ NOT NULL, + used_at TIMESTAMPTZ, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX idx_verification_codes_code ON verification_codes (code); +CREATE INDEX idx_verification_codes_user_purpose ON verification_codes (user_id, purpose) WHERE used_at IS NULL; +CREATE INDEX idx_verification_codes_expires ON verification_codes (expires_at) WHERE used_at IS NULL; + -- ======================================= -- SERVICES TABLE -- =======================================