-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdatabase_schema.sql
More file actions
206 lines (175 loc) · 7.45 KB
/
database_schema.sql
File metadata and controls
206 lines (175 loc) · 7.45 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
-- Anonymous Chat App Database Schema
-- Created for Supabase
-- Updated with MCP compatibility and optimizations
-- Enable the necessary extensions
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- Create users table to store user sessions and preferences
CREATE TABLE IF NOT EXISTS users (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
username VARCHAR(50) NOT NULL,
is_op BOOLEAN DEFAULT FALSE,
theme VARCHAR(20) DEFAULT 'light',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
last_active TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create messages table for direct chat messages
CREATE TABLE IF NOT EXISTS messages (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
username VARCHAR(50) NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
expires_at TIMESTAMP WITH TIME ZONE DEFAULT (NOW() + INTERVAL '24 hours')
);
-- Create pinned_messages table for OP pinned messages
CREATE TABLE IF NOT EXISTS pinned_messages (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
username VARCHAR(50) NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create indexes for better performance
CREATE INDEX IF NOT EXISTS idx_messages_created_at ON messages(created_at DESC);
CREATE INDEX IF NOT EXISTS idx_messages_expires_at ON messages(expires_at);
CREATE INDEX IF NOT EXISTS idx_pinned_messages_created_at ON pinned_messages(created_at DESC);
CREATE INDEX IF NOT EXISTS idx_users_last_active ON users(last_active DESC);
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
CREATE INDEX IF NOT EXISTS idx_messages_user_id ON messages(user_id);
CREATE INDEX IF NOT EXISTS idx_pinned_messages_user_id ON pinned_messages(user_id);
-- Enable Row Level Security (RLS)
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE messages ENABLE ROW LEVEL SECURITY;
ALTER TABLE pinned_messages ENABLE ROW LEVEL SECURITY;
-- Create policies for users table
CREATE POLICY "Users can view all users" ON users
FOR SELECT USING (true);
CREATE POLICY "Users can insert their own record" ON users
FOR INSERT WITH CHECK (true);
CREATE POLICY "Users can update their own record" ON users
FOR UPDATE USING (true);
-- Create policies for messages table
CREATE POLICY "Anyone can view messages" ON messages
FOR SELECT USING (true);
CREATE POLICY "Anyone can insert messages" ON messages
FOR INSERT WITH CHECK (true);
CREATE POLICY "Users can delete their own messages" ON messages
FOR DELETE USING (true);
-- Create policies for pinned_messages table (only OP can manage)
CREATE POLICY "Anyone can view pinned messages" ON pinned_messages
FOR SELECT USING (true);
CREATE POLICY "Only OP can insert pinned messages" ON pinned_messages
FOR INSERT WITH CHECK (
EXISTS (
SELECT 1 FROM users
WHERE users.id = user_id AND users.is_op = true
)
);
CREATE POLICY "Only OP can update pinned messages" ON pinned_messages
FOR UPDATE USING (
EXISTS (
SELECT 1 FROM users
WHERE users.id = user_id AND users.is_op = true
)
);
CREATE POLICY "Only OP can delete pinned messages" ON pinned_messages
FOR DELETE USING (
EXISTS (
SELECT 1 FROM users
WHERE users.id = user_id AND users.is_op = true
)
);
-- Create function to automatically delete expired messages
CREATE OR REPLACE FUNCTION delete_expired_messages()
RETURNS void AS $$
BEGIN
DELETE FROM messages WHERE expires_at < NOW();
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Create function to update last_active timestamp
CREATE OR REPLACE FUNCTION update_last_active()
RETURNS TRIGGER AS $$
BEGIN
UPDATE users SET last_active = NOW() WHERE id = NEW.user_id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Create trigger to update last_active when user sends a message
DROP TRIGGER IF EXISTS update_user_last_active ON messages;
CREATE TRIGGER update_user_last_active
AFTER INSERT ON messages
FOR EACH ROW
EXECUTE FUNCTION update_last_active();
-- Create function to handle real-time subscriptions
CREATE OR REPLACE FUNCTION notify_message_change()
RETURNS TRIGGER AS $$
BEGIN
PERFORM pg_notify('message_changes', json_build_object(
'type', TG_OP,
'record', row_to_json(NEW),
'old_record', row_to_json(OLD)
)::text);
RETURN COALESCE(NEW, OLD);
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Create triggers for real-time notifications
DROP TRIGGER IF EXISTS messages_notify_trigger ON messages;
CREATE TRIGGER messages_notify_trigger
AFTER INSERT OR UPDATE OR DELETE ON messages
FOR EACH ROW
EXECUTE FUNCTION notify_message_change();
DROP TRIGGER IF EXISTS pinned_messages_notify_trigger ON pinned_messages;
CREATE TRIGGER pinned_messages_notify_trigger
AFTER INSERT OR UPDATE OR DELETE ON pinned_messages
FOR EACH ROW
EXECUTE FUNCTION notify_message_change();
-- Insert default OP user
INSERT INTO users (username, is_op, theme)
VALUES ('Shyamnath-sankar', true, 'light')
ON CONFLICT DO NOTHING;
-- Grant necessary permissions
GRANT USAGE ON SCHEMA public TO anon, authenticated;
GRANT ALL ON ALL TABLES IN SCHEMA public TO anon, authenticated;
GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO anon, authenticated;
GRANT ALL ON ALL FUNCTIONS IN SCHEMA public TO anon, authenticated;
-- Create view for messages with user information (optional)
CREATE OR REPLACE VIEW messages_with_users AS
SELECT
m.*,
u.is_op as sender_is_op
FROM messages m
LEFT JOIN users u ON m.user_id = u.id;
-- Grant permissions on view
GRANT SELECT ON messages_with_users TO anon, authenticated;
-- Comments for documentation
COMMENT ON TABLE users IS 'Stores user sessions and preferences';
COMMENT ON TABLE messages IS 'Direct chat messages that expire after 24 hours';
COMMENT ON TABLE pinned_messages IS 'Important messages pinned by moderators';
COMMENT ON FUNCTION delete_expired_messages() IS 'Removes messages older than 24 hours';
COMMENT ON FUNCTION update_last_active() IS 'Updates user last_active timestamp when they send a message';
COMMENT ON FUNCTION notify_message_change() IS 'Sends real-time notifications for message changes';
-- Create a function to clean up inactive users (optional)
CREATE OR REPLACE FUNCTION cleanup_inactive_users(days_inactive INTEGER DEFAULT 7)
RETURNS INTEGER AS $$
DECLARE
deleted_count INTEGER;
BEGIN
DELETE FROM users
WHERE
is_op = false
AND last_active < NOW() - INTERVAL '1 day' * days_inactive;
GET DIAGNOSTICS deleted_count = ROW_COUNT;
RETURN deleted_count;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
COMMENT ON FUNCTION cleanup_inactive_users(INTEGER) IS 'Removes non-OP users inactive for specified days';
-- Success message
DO $$
BEGIN
RAISE NOTICE 'Anonymous Chat database schema applied successfully!';
RAISE NOTICE 'Tables created: users, messages, pinned_messages';
RAISE NOTICE 'Functions created: delete_expired_messages, update_last_active, notify_message_change, cleanup_inactive_users';
RAISE NOTICE 'RLS policies enabled for security';
RAISE NOTICE 'Real-time triggers configured';
END $$;