-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdatabase_schema_cloud.sql
More file actions
286 lines (242 loc) · 10.1 KB
/
database_schema_cloud.sql
File metadata and controls
286 lines (242 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
-- AudioBook Organizer - Supabase Database Schema (Cloud Version)
-- Run this in your Supabase SQL editor to set up the required tables
-- Note: The ALTER DATABASE command is not needed for cloud Supabase
-- It's automatically managed by Supabase
-- Create custom profiles table
CREATE TABLE IF NOT EXISTS public.profiles (
id UUID REFERENCES auth.users(id) ON DELETE CASCADE PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
full_name TEXT,
username TEXT UNIQUE,
avatar_url TEXT,
bio TEXT,
preferences JSONB DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create user credits table
CREATE TABLE IF NOT EXISTS public.user_credits (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE UNIQUE NOT NULL,
credits INTEGER DEFAULT 100 CHECK (credits >= 0),
last_updated TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create usage logs table for tracking API usage
CREATE TABLE IF NOT EXISTS public.usage_logs (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE NOT NULL,
action TEXT NOT NULL,
credits_used INTEGER DEFAULT 0,
metadata JSONB DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create credit transactions table for payment tracking
CREATE TABLE IF NOT EXISTS public.credit_transactions (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE NOT NULL,
transaction_type TEXT NOT NULL CHECK (transaction_type IN ('purchase', 'bonus', 'refund', 'usage')),
credits_amount INTEGER NOT NULL,
payment_method TEXT,
payment_id TEXT,
status TEXT DEFAULT 'pending' CHECK (status IN ('pending', 'completed', 'failed', 'refunded')),
metadata JSONB DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create audiobook projects table
CREATE TABLE IF NOT EXISTS public.audiobook_projects (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE NOT NULL,
title TEXT NOT NULL,
description TEXT,
status TEXT DEFAULT 'draft' CHECK (status IN ('draft', 'processing', 'completed', 'failed')),
settings JSONB DEFAULT '{}',
chapters JSONB DEFAULT '[]',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create file uploads table
CREATE TABLE IF NOT EXISTS public.file_uploads (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE NOT NULL,
project_id UUID REFERENCES public.audiobook_projects(id) ON DELETE CASCADE,
filename TEXT NOT NULL,
file_path TEXT NOT NULL,
file_size INTEGER,
file_type TEXT,
upload_status TEXT DEFAULT 'pending' CHECK (upload_status IN ('pending', 'completed', 'failed')),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Enable Row Level Security on all tables
ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.user_credits ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.usage_logs ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.credit_transactions ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.audiobook_projects ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.file_uploads ENABLE ROW LEVEL SECURITY;
-- Create Row Level Security policies
-- Profiles policies
CREATE POLICY "Public profiles are viewable by everyone"
ON public.profiles FOR SELECT
USING (true);
CREATE POLICY "Users can insert their own profile"
ON public.profiles FOR INSERT
WITH CHECK (auth.uid() = id);
CREATE POLICY "Users can update own profile"
ON public.profiles FOR UPDATE
USING (auth.uid() = id);
-- User credits policies
CREATE POLICY "Users can view own credits"
ON public.user_credits FOR SELECT
USING (auth.uid() = user_id);
CREATE POLICY "Users can insert own credits"
ON public.user_credits FOR INSERT
WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users can update own credits"
ON public.user_credits FOR UPDATE
USING (auth.uid() = user_id);
-- Usage logs policies
CREATE POLICY "Users can view own usage logs"
ON public.usage_logs FOR SELECT
USING (auth.uid() = user_id);
CREATE POLICY "Users can insert own usage logs"
ON public.usage_logs FOR INSERT
WITH CHECK (auth.uid() = user_id);
-- Credit transactions policies
CREATE POLICY "Users can view own transactions"
ON public.credit_transactions FOR SELECT
USING (auth.uid() = user_id);
CREATE POLICY "Users can insert own transactions"
ON public.credit_transactions FOR INSERT
WITH CHECK (auth.uid() = user_id);
-- Audiobook projects policies
CREATE POLICY "Users can view own projects"
ON public.audiobook_projects FOR SELECT
USING (auth.uid() = user_id);
CREATE POLICY "Users can insert own projects"
ON public.audiobook_projects FOR INSERT
WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users can update own projects"
ON public.audiobook_projects FOR UPDATE
USING (auth.uid() = user_id);
CREATE POLICY "Users can delete own projects"
ON public.audiobook_projects FOR DELETE
USING (auth.uid() = user_id);
-- File uploads policies
CREATE POLICY "Users can view own uploads"
ON public.file_uploads FOR SELECT
USING (auth.uid() = user_id);
CREATE POLICY "Users can insert own uploads"
ON public.file_uploads FOR INSERT
WITH CHECK (auth.uid() = user_id);
CREATE POLICY "Users can update own uploads"
ON public.file_uploads FOR UPDATE
USING (auth.uid() = user_id);
CREATE POLICY "Users can delete own uploads"
ON public.file_uploads FOR DELETE
USING (auth.uid() = user_id);
-- Create functions and triggers
-- Function to automatically create user profile and credits on signup
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO public.profiles (id, email, full_name)
VALUES (
NEW.id,
NEW.email,
COALESCE(NEW.raw_user_meta_data->>'full_name', '')
);
INSERT INTO public.user_credits (user_id, credits)
VALUES (NEW.id, 100);
RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Trigger to call handle_new_user function on user creation
CREATE OR REPLACE TRIGGER on_auth_user_created
AFTER INSERT ON auth.users
FOR EACH ROW EXECUTE PROCEDURE public.handle_new_user();
-- Function to update updated_at timestamp
CREATE OR REPLACE FUNCTION public.handle_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Triggers for updated_at
CREATE TRIGGER profiles_updated_at
BEFORE UPDATE ON public.profiles
FOR EACH ROW EXECUTE PROCEDURE public.handle_updated_at();
CREATE TRIGGER audiobook_projects_updated_at
BEFORE UPDATE ON public.audiobook_projects
FOR EACH ROW EXECUTE PROCEDURE public.handle_updated_at();
-- Function to update credits last_updated timestamp
CREATE OR REPLACE FUNCTION public.handle_credits_updated()
RETURNS TRIGGER AS $$
BEGIN
NEW.last_updated = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER user_credits_updated
BEFORE UPDATE ON public.user_credits
FOR EACH ROW EXECUTE PROCEDURE public.handle_credits_updated();
-- Create indexes for better performance
CREATE INDEX IF NOT EXISTS idx_profiles_email ON public.profiles(email);
CREATE INDEX IF NOT EXISTS idx_profiles_username ON public.profiles(username);
CREATE INDEX IF NOT EXISTS idx_user_credits_user_id ON public.user_credits(user_id);
CREATE INDEX IF NOT EXISTS idx_usage_logs_user_id ON public.usage_logs(user_id);
CREATE INDEX IF NOT EXISTS idx_usage_logs_created_at ON public.usage_logs(created_at);
CREATE INDEX IF NOT EXISTS idx_credit_transactions_user_id ON public.credit_transactions(user_id);
CREATE INDEX IF NOT EXISTS idx_credit_transactions_status ON public.credit_transactions(status);
CREATE INDEX IF NOT EXISTS idx_audiobook_projects_user_id ON public.audiobook_projects(user_id);
CREATE INDEX IF NOT EXISTS idx_audiobook_projects_status ON public.audiobook_projects(status);
CREATE INDEX IF NOT EXISTS idx_file_uploads_user_id ON public.file_uploads(user_id);
CREATE INDEX IF NOT EXISTS idx_file_uploads_project_id ON public.file_uploads(project_id);
-- Create views for easier data access
-- User stats view
CREATE OR REPLACE VIEW public.user_stats AS
SELECT
p.id,
p.email,
p.full_name,
uc.credits,
COUNT(ap.id) as total_projects,
COUNT(CASE WHEN ap.status = 'completed' THEN 1 END) as completed_projects,
COALESCE(SUM(ul.credits_used), 0) as total_credits_used,
p.created_at as user_since
FROM public.profiles p
LEFT JOIN public.user_credits uc ON p.id = uc.user_id
LEFT JOIN public.audiobook_projects ap ON p.id = ap.user_id
LEFT JOIN public.usage_logs ul ON p.id = ul.user_id
GROUP BY p.id, p.email, p.full_name, uc.credits, p.created_at;
-- Recent activity view
CREATE OR REPLACE VIEW public.recent_activity AS
SELECT
ul.user_id,
ul.action,
ul.credits_used,
ul.metadata,
ul.created_at,
p.email,
p.full_name
FROM public.usage_logs ul
JOIN public.profiles p ON ul.user_id = p.id
ORDER BY ul.created_at DESC;
-- Grant necessary permissions to authenticated users
GRANT USAGE ON SCHEMA public TO authenticated;
GRANT ALL ON ALL TABLES IN SCHEMA public TO authenticated;
GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO authenticated;
GRANT ALL ON ALL FUNCTIONS IN SCHEMA public TO authenticated;
-- Grant permissions to service role (for server-side operations)
GRANT USAGE ON SCHEMA public TO service_role;
GRANT ALL ON ALL TABLES IN SCHEMA public TO service_role;
GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO service_role;
GRANT ALL ON ALL FUNCTIONS IN SCHEMA public TO service_role;
-- Comments for documentation
COMMENT ON TABLE public.profiles IS 'User profile information';
COMMENT ON TABLE public.user_credits IS 'User credit balances for API usage';
COMMENT ON TABLE public.usage_logs IS 'Log of API usage and credit consumption';
COMMENT ON TABLE public.credit_transactions IS 'Credit purchase and transaction history';
COMMENT ON TABLE public.audiobook_projects IS 'User audiobook projects and their settings';
COMMENT ON TABLE public.file_uploads IS 'Tracking of uploaded files and their processing status';