1+ CREATE TABLE users (
2+ user_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
3+ first_name VARCHAR (100 ) NOT NULL ,
4+ last_name VARCHAR (100 ) NOT NULL ,
5+ email VARCHAR (255 ) NOT NULL UNIQUE,
6+ username VARCHAR (100 ) NOT NULL UNIQUE,
7+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP ,
8+ profile_image VARCHAR (255 ),
9+ bio TEXT ,
10+ phone VARCHAR (20 ),
11+ date_of_birth DATE ,
12+ location VARCHAR (255 ),
13+ website VARCHAR (255 ),
14+ is_private BOOLEAN DEFAULT FALSE,
15+
16+ -- Subscription fields
17+ subscription_status VARCHAR (20 ) CHECK (subscription_status IN (' free' , ' active' , ' past_due' , ' canceled' , ' trialing' , ' incomplete' , ' incomplete_expired' )) DEFAULT ' free' ,
18+ subscription_tier VARCHAR (10 ) CHECK (subscription_tier IN (' free' , ' pro' )) DEFAULT ' free' ,
19+ stripe_customer_id VARCHAR (100 ),
20+ stripe_subscription_id VARCHAR (100 ),
21+ subscription_period_start TIMESTAMP WITH TIME ZONE ,
22+ subscription_period_end TIMESTAMP WITH TIME ZONE ,
23+ subscription_canceled_at TIMESTAMP WITH TIME ZONE ,
24+ grace_period_end TIMESTAMP WITH TIME ZONE
25+ );
26+
27+ CREATE INDEX idx_users_email ON users(email);
28+ CREATE INDEX idx_users_username ON users(username);
29+ CREATE INDEX idx_users_stripe_customer_id ON users(stripe_customer_id);
30+ CREATE INDEX idx_users_stripe_subscription_id ON users(stripe_subscription_id);
31+
32+ CREATE TABLE content (
33+ content_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
34+ creator_id UUID NOT NULL REFERENCES users(user_id) ON DELETE CASCADE ,
35+ title VARCHAR (255 ) NOT NULL ,
36+ content TEXT NOT NULL ,
37+ summary TEXT ,
38+ thumbnail VARCHAR (255 ),
39+ date_created TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP ,
40+ date_updated TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP ,
41+ read_time INTEGER ,
42+ likes INTEGER DEFAULT 0 ,
43+ views INTEGER DEFAULT 0 ,
44+ shares INTEGER DEFAULT 0 ,
45+ score REAL
46+ );
47+
48+ CREATE INDEX idx_content_creator_id ON content(creator_id);
49+ CREATE INDEX idx_content_date_created ON content(date_created);
50+
51+ CREATE TABLE comments (
52+ comment_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
53+ content_id UUID NOT NULL REFERENCES content(content_id) ON DELETE CASCADE ,
54+ owner_id UUID NOT NULL REFERENCES users(user_id) ON DELETE CASCADE ,
55+ text TEXT NOT NULL ,
56+ timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP ,
57+ last_edited_timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP ,
58+ like_count INTEGER DEFAULT 0
59+ );
60+
61+ CREATE INDEX idx_comments_content_id ON comments(content_id);
62+ CREATE INDEX idx_comments_owner_id ON comments(owner_id);
63+
64+
65+ CREATE TABLE notifications (
66+ notification_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
67+ user_id UUID NOT NULL REFERENCES users(user_id) ON DELETE CASCADE ,
68+ sender_id UUID NOT NULL REFERENCES users(user_id) ON DELETE CASCADE ,
69+ type VARCHAR (20 ) NOT NULL CHECK (type IN (' comment' , ' like' , ' share' , ' follow' , ' followedContent' , ' followedShare' )),
70+ text_preview VARCHAR (255 ),
71+ content_id UUID REFERENCES content(content_id) ON DELETE SET NULL ,
72+ comment_id UUID REFERENCES comments(comment_id) ON DELETE SET NULL ,
73+ timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP ,
74+ is_read BOOLEAN DEFAULT FALSE
75+ );
76+
77+ CREATE INDEX idx_notifications_user_id ON notifications(user_id);
78+ CREATE INDEX idx_notifications_timestamp ON notifications(timestamp );
79+
80+
81+ CREATE TABLE user_relationships (
82+ id SERIAL PRIMARY KEY ,
83+ follower_id UUID NOT NULL REFERENCES users(user_id) ON DELETE CASCADE ,
84+ following_id UUID NOT NULL REFERENCES users(user_id) ON DELETE CASCADE ,
85+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP ,
86+ UNIQUE (follower_id, following_id)
87+ );
88+
89+ CREATE INDEX idx_user_relationships_follower ON user_relationships(follower_id);
90+ CREATE INDEX idx_user_relationships_following ON user_relationships(following_id);
91+
92+
93+ CREATE TABLE follow_requests (
94+ id SERIAL PRIMARY KEY ,
95+ requester_id UUID NOT NULL REFERENCES users(user_id) ON DELETE CASCADE ,
96+ target_id UUID NOT NULL REFERENCES users(user_id) ON DELETE CASCADE ,
97+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP ,
98+ UNIQUE (requester_id, target_id)
99+ );
100+
101+ CREATE INDEX idx_follow_requests_requester ON follow_requests(requester_id);
102+ CREATE INDEX idx_follow_requests_target ON follow_requests(target_id);
103+
104+
105+ CREATE TABLE user_content_interactions (
106+ id SERIAL PRIMARY KEY ,
107+ user_id UUID NOT NULL REFERENCES users(user_id) ON DELETE CASCADE ,
108+ content_id UUID NOT NULL REFERENCES content(content_id) ON DELETE CASCADE ,
109+ interaction_type VARCHAR (10 ) NOT NULL CHECK (interaction_type IN (' like' , ' bookmark' , ' share' )),
110+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP ,
111+ UNIQUE (user_id, content_id, interaction_type)
112+ );
113+
114+ CREATE INDEX idx_user_content_interactions_combined ON user_content_interactions(user_id, content_id);
115+ CREATE INDEX idx_user_content_interactions_type ON user_content_interactions(interaction_type);
116+
117+
118+ CREATE TABLE pending_subscriptions (
119+ subscription_id VARCHAR (100 ) PRIMARY KEY ,
120+ stripe_customer_id VARCHAR (100 ) NOT NULL ,
121+ status VARCHAR (20 ) NOT NULL CHECK (status IN (' active' , ' past_due' , ' canceled' , ' trialing' , ' incomplete' , ' incomplete_expired' )),
122+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP ,
123+ period_start TIMESTAMP WITH TIME ZONE ,
124+ period_end TIMESTAMP WITH TIME ZONE ,
125+ canceled_at TIMESTAMP WITH TIME ZONE ,
126+ updated_at TIMESTAMP WITH TIME ZONE ,
127+ processed BOOLEAN DEFAULT FALSE
128+ );
129+
130+ CREATE INDEX idx_pending_subscriptions_customer_id ON pending_subscriptions(stripe_customer_id);
131+ CREATE INDEX idx_pending_subscriptions_processed ON pending_subscriptions(processed);
132+
133+
134+ CREATE TABLE oauth_connections (
135+ id SERIAL PRIMARY KEY ,
136+ user_id UUID NOT NULL REFERENCES users(user_id) ON DELETE CASCADE ,
137+ provider VARCHAR (20 ) NOT NULL CHECK (provider IN (' google' , ' github' )),
138+ provider_user_id VARCHAR (255 ) NOT NULL ,
139+ access_token VARCHAR (255 ),
140+ refresh_token VARCHAR (255 ),
141+ token_expires_at TIMESTAMP WITH TIME ZONE ,
142+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP ,
143+ UNIQUE (user_id, provider),
144+ UNIQUE (provider, provider_user_id)
145+ );
146+
147+ CREATE INDEX idx_oauth_connections_user_id ON oauth_connections(user_id);
148+
149+
150+ CREATE TABLE password_reset_tokens (
151+ id SERIAL PRIMARY KEY ,
152+ user_id UUID NOT NULL REFERENCES users(user_id) ON DELETE CASCADE ,
153+ token VARCHAR (255 ) NOT NULL UNIQUE,
154+ expires_at TIMESTAMP WITH TIME ZONE NOT NULL ,
155+ used BOOLEAN DEFAULT FALSE
156+ );
157+
158+ CREATE INDEX idx_password_reset_tokens_user_id ON password_reset_tokens(user_id);
159+ CREATE INDEX idx_password_reset_tokens_expires_at ON password_reset_tokens(expires_at);
0 commit comments