first commit
Made-with: Cursor
This commit is contained in:
174
migrations/000001_init.up.sql
Normal file
174
migrations/000001_init.up.sql
Normal file
@@ -0,0 +1,174 @@
|
||||
-- Calendar & Contacts API Schema
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
||||
|
||||
-- Users
|
||||
CREATE TABLE users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
email TEXT NOT NULL,
|
||||
password_hash TEXT NOT NULL,
|
||||
timezone TEXT NOT NULL DEFAULT 'UTC',
|
||||
is_active BOOLEAN NOT NULL DEFAULT true,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX idx_users_email ON users (email) WHERE deleted_at IS NULL;
|
||||
|
||||
-- Refresh Tokens
|
||||
CREATE TABLE refresh_tokens (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id),
|
||||
token_hash TEXT NOT NULL UNIQUE,
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
revoked_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_refresh_tokens_user_id ON refresh_tokens (user_id);
|
||||
|
||||
-- API Keys
|
||||
CREATE TABLE api_keys (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id),
|
||||
name TEXT NOT NULL,
|
||||
key_hash TEXT NOT NULL UNIQUE,
|
||||
scopes JSONB NOT NULL DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
revoked_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX idx_api_keys_user_id ON api_keys (user_id);
|
||||
|
||||
-- Calendars
|
||||
CREATE TABLE calendars (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
owner_id UUID NOT NULL REFERENCES users(id),
|
||||
name TEXT NOT NULL,
|
||||
color TEXT NOT NULL DEFAULT '#3B82F6',
|
||||
is_public BOOLEAN NOT NULL DEFAULT false,
|
||||
public_token TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX idx_calendars_owner_id ON calendars (owner_id);
|
||||
|
||||
-- Calendar Members
|
||||
CREATE TABLE calendar_members (
|
||||
calendar_id UUID NOT NULL REFERENCES calendars(id),
|
||||
user_id UUID NOT NULL REFERENCES users(id),
|
||||
role TEXT NOT NULL CHECK (role IN ('owner', 'editor', 'viewer')),
|
||||
PRIMARY KEY (calendar_id, user_id)
|
||||
);
|
||||
|
||||
-- Events
|
||||
CREATE TABLE events (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
calendar_id UUID NOT NULL REFERENCES calendars(id),
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
location TEXT,
|
||||
start_time TIMESTAMPTZ NOT NULL,
|
||||
end_time TIMESTAMPTZ NOT NULL,
|
||||
timezone TEXT NOT NULL DEFAULT 'UTC',
|
||||
all_day BOOLEAN NOT NULL DEFAULT false,
|
||||
recurrence_rule TEXT,
|
||||
tags TEXT[] NOT NULL DEFAULT '{}',
|
||||
created_by UUID NOT NULL REFERENCES users(id),
|
||||
updated_by UUID NOT NULL REFERENCES users(id),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX idx_events_calendar_start ON events (calendar_id, start_time);
|
||||
CREATE INDEX idx_events_start_time ON events (start_time);
|
||||
CREATE INDEX idx_events_tags ON events USING GIN (tags);
|
||||
|
||||
-- Event Reminders
|
||||
CREATE TABLE event_reminders (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
event_id UUID NOT NULL REFERENCES events(id),
|
||||
minutes_before INTEGER NOT NULL CHECK (minutes_before >= 0 AND minutes_before <= 10080)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_event_reminders_event_id ON event_reminders (event_id);
|
||||
|
||||
-- Event Attendees
|
||||
CREATE TABLE event_attendees (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
event_id UUID NOT NULL REFERENCES events(id),
|
||||
user_id UUID REFERENCES users(id),
|
||||
email TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'accepted', 'declined', 'tentative'))
|
||||
);
|
||||
|
||||
CREATE INDEX idx_event_attendees_event_id ON event_attendees (event_id);
|
||||
|
||||
-- Event Exceptions (for recurrence)
|
||||
CREATE TABLE event_exceptions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
event_id UUID NOT NULL REFERENCES events(id),
|
||||
exception_date DATE NOT NULL,
|
||||
action TEXT NOT NULL DEFAULT 'skip' CHECK (action IN ('skip'))
|
||||
);
|
||||
|
||||
CREATE INDEX idx_event_exceptions_event_id ON event_exceptions (event_id);
|
||||
|
||||
-- Event Attachments
|
||||
CREATE TABLE event_attachments (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
event_id UUID NOT NULL REFERENCES events(id),
|
||||
file_url TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX idx_event_attachments_event_id ON event_attachments (event_id);
|
||||
|
||||
-- Contacts
|
||||
CREATE TABLE contacts (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
owner_id UUID NOT NULL REFERENCES users(id),
|
||||
first_name TEXT,
|
||||
last_name TEXT,
|
||||
email TEXT,
|
||||
phone TEXT,
|
||||
company TEXT,
|
||||
notes TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX idx_contacts_owner_id ON contacts (owner_id);
|
||||
CREATE INDEX idx_contacts_search ON contacts (owner_id, first_name, last_name, email, company);
|
||||
|
||||
-- Booking Links
|
||||
CREATE TABLE booking_links (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
calendar_id UUID NOT NULL REFERENCES calendars(id),
|
||||
token TEXT NOT NULL UNIQUE,
|
||||
duration_minutes INTEGER NOT NULL,
|
||||
buffer_minutes INTEGER NOT NULL DEFAULT 0,
|
||||
timezone TEXT NOT NULL DEFAULT 'UTC',
|
||||
working_hours JSONB NOT NULL DEFAULT '{}',
|
||||
active BOOLEAN NOT NULL DEFAULT true,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_booking_links_token ON booking_links (token);
|
||||
|
||||
-- Audit Logs
|
||||
CREATE TABLE audit_logs (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
entity_type TEXT NOT NULL,
|
||||
entity_id UUID NOT NULL,
|
||||
action TEXT NOT NULL,
|
||||
user_id UUID NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_audit_logs_entity ON audit_logs (entity_type, entity_id);
|
||||
Reference in New Issue
Block a user