forked from eibrahim/freeresend
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdatabase.sql
More file actions
140 lines (126 loc) · 5.5 KB
/
Copy pathdatabase.sql
File metadata and controls
140 lines (126 loc) · 5.5 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
-- FreeResend Database Schema
-- Users table
CREATE TABLE IF NOT EXISTS users (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
name VARCHAR(255),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Domains table
CREATE TABLE IF NOT EXISTS domains (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
domain VARCHAR(255) UNIQUE NOT NULL,
status VARCHAR(50) DEFAULT 'pending', -- pending, verified, failed
ses_identity_arn VARCHAR(255),
ses_configuration_set VARCHAR(255),
do_domain_id VARCHAR(255),
dns_records JSONB DEFAULT '[]',
verification_token VARCHAR(255),
smtp_credentials JSONB, -- Stores encrypted SMTP username/password
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- API Keys table
CREATE TABLE IF NOT EXISTS api_keys (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
domain_id UUID REFERENCES domains(id) ON DELETE CASCADE,
key_name VARCHAR(255) NOT NULL,
key_hash VARCHAR(255) NOT NULL,
key_prefix VARCHAR(20) NOT NULL, -- First few chars of the key for identification
permissions JSONB DEFAULT '["send"]', -- ["send", "receive", "webhooks"]
last_used_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(user_id, key_name)
);
-- Email logs table
CREATE TABLE IF NOT EXISTS email_logs (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
api_key_id UUID REFERENCES api_keys(id) ON DELETE SET NULL,
domain_id UUID REFERENCES domains(id) ON DELETE CASCADE,
message_id VARCHAR(255),
from_email VARCHAR(255) NOT NULL,
to_emails JSONB NOT NULL, -- Array of email addresses
cc_emails JSONB DEFAULT '[]',
bcc_emails JSONB DEFAULT '[]',
subject VARCHAR(500),
html_content TEXT,
text_content TEXT,
attachments JSONB DEFAULT '[]',
status VARCHAR(50) DEFAULT 'pending', -- pending, sent, failed, delivered, bounced, complained
ses_message_id VARCHAR(255),
error_message TEXT,
webhook_data JSONB,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Webhook events table
CREATE TABLE IF NOT EXISTS webhook_events (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
email_log_id UUID REFERENCES email_logs(id) ON DELETE CASCADE,
event_type VARCHAR(50) NOT NULL, -- sent, delivered, bounced, complained, etc.
event_data JSONB NOT NULL,
processed BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Waitlist signups table
CREATE TABLE IF NOT EXISTS waitlist_signups (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
estimated_volume INTEGER,
current_provider VARCHAR(100),
referral_source VARCHAR(100),
user_agent TEXT,
ip_address INET,
utm_source VARCHAR(100),
utm_medium VARCHAR(100),
utm_campaign VARCHAR(100),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Indexes for performance
CREATE INDEX IF NOT EXISTS idx_domains_user_id ON domains(user_id);
CREATE INDEX IF NOT EXISTS idx_domains_domain ON domains(domain);
CREATE INDEX IF NOT EXISTS idx_api_keys_user_id ON api_keys(user_id);
CREATE INDEX IF NOT EXISTS idx_api_keys_domain_id ON api_keys(domain_id);
CREATE INDEX IF NOT EXISTS idx_api_keys_key_hash ON api_keys(key_hash);
CREATE INDEX IF NOT EXISTS idx_email_logs_api_key_id ON email_logs(api_key_id);
CREATE INDEX IF NOT EXISTS idx_email_logs_domain_id ON email_logs(domain_id);
CREATE INDEX IF NOT EXISTS idx_email_logs_message_id ON email_logs(message_id);
CREATE INDEX IF NOT EXISTS idx_email_logs_created_at ON email_logs(created_at);
CREATE INDEX IF NOT EXISTS idx_webhook_events_email_log_id ON webhook_events(email_log_id);
CREATE INDEX IF NOT EXISTS idx_webhook_events_processed ON webhook_events(processed);
CREATE INDEX IF NOT EXISTS idx_waitlist_signups_email ON waitlist_signups(email);
CREATE INDEX IF NOT EXISTS idx_waitlist_signups_created_at ON waitlist_signups(created_at);
CREATE INDEX IF NOT EXISTS idx_waitlist_signups_utm_source ON waitlist_signups(utm_source);
-- Trigger function to automatically update updated_at timestamps
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ language 'plpgsql';
-- Create triggers for updated_at automation
CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON users
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_domains_updated_at BEFORE UPDATE ON domains
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_api_keys_updated_at BEFORE UPDATE ON api_keys
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_email_logs_updated_at BEFORE UPDATE ON email_logs
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_waitlist_signups_updated_at BEFORE UPDATE ON waitlist_signups
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- Initial data: Create default admin user (password: changeme123)
-- Note: Change this password after first login!
INSERT INTO users (email, password_hash, name)
VALUES (
'admin@freeresend.com',
'$2b$10$rHOuGCOB2xzvf1YqnHjlUuB9AKnp.xeL0JOV5E7zlM1QIFhW7qYGS',
'Admin User'
) ON CONFLICT (email) DO NOTHING;