Files
sasa-maillist/database/schema.sql
2025-10-13 15:05:42 +00:00

138 lines
5.4 KiB
SQL

-- Mail List Manager Database Schema
-- Table: users
-- Stores user authentication and authorization information
CREATE TABLE IF NOT EXISTS users (
user_id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL, -- bcrypt hash
role ENUM('administrator', 'operator', 'read-only') NOT NULL DEFAULT 'read-only',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
last_login TIMESTAMP NULL,
active BOOLEAN DEFAULT TRUE,
INDEX idx_username (username),
INDEX idx_role (role),
INDEX idx_active (active)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Table: user_sessions
-- Stores active user sessions for authentication
CREATE TABLE IF NOT EXISTS user_sessions (
session_id VARCHAR(64) PRIMARY KEY,
user_id INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP NOT NULL,
ip_address VARCHAR(45), -- Supports both IPv4 and IPv6
user_agent TEXT,
active BOOLEAN DEFAULT TRUE,
FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE,
INDEX idx_user_id (user_id),
INDEX idx_expires_at (expires_at),
INDEX idx_active (active)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Table: lists
-- Stores mailing list information
CREATE TABLE IF NOT EXISTS lists (
list_id INT AUTO_INCREMENT PRIMARY KEY,
list_name VARCHAR(100) NOT NULL UNIQUE,
list_email VARCHAR(255) NOT NULL UNIQUE,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
active BOOLEAN DEFAULT TRUE,
INDEX idx_list_email (list_email),
INDEX idx_active (active)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Table: members
-- Stores member information
CREATE TABLE IF NOT EXISTS members (
member_id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
active BOOLEAN DEFAULT TRUE,
bounce_count INT DEFAULT 0,
last_bounce_at TIMESTAMP NULL,
bounce_status ENUM('clean', 'soft_bounce', 'hard_bounce') DEFAULT 'clean',
INDEX idx_email (email),
INDEX idx_active (active),
INDEX idx_bounce_status (bounce_status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Table: list_members
-- Junction table for many-to-many relationship between lists and members
CREATE TABLE IF NOT EXISTS list_members (
id INT AUTO_INCREMENT PRIMARY KEY,
list_id INT NOT NULL,
member_id INT NOT NULL,
subscribed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
active BOOLEAN DEFAULT TRUE,
FOREIGN KEY (list_id) REFERENCES lists(list_id) ON DELETE CASCADE,
FOREIGN KEY (member_id) REFERENCES members(member_id) ON DELETE CASCADE,
UNIQUE KEY unique_list_member (list_id, member_id),
INDEX idx_list_id (list_id),
INDEX idx_member_id (member_id),
INDEX idx_active (active)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Table: bounce_logs
-- Stores bounce notifications from SES SNS
CREATE TABLE IF NOT EXISTS bounce_logs (
bounce_id INT AUTO_INCREMENT PRIMARY KEY,
member_id INT,
email VARCHAR(255) NOT NULL,
bounce_type ENUM('Permanent', 'Transient', 'Undetermined') NOT NULL,
bounce_subtype VARCHAR(50),
diagnostic_code TEXT,
timestamp TIMESTAMP NOT NULL,
sns_message_id VARCHAR(255),
feedback_id VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (member_id) REFERENCES members(member_id) ON DELETE SET NULL,
INDEX idx_member_id (member_id),
INDEX idx_email (email),
INDEX idx_timestamp (timestamp),
INDEX idx_bounce_type (bounce_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Insert sample data
-- Create default admin user (password: 'password')
-- Hash generated with passlib CryptContext using bcrypt
INSERT INTO users (username, password_hash, role) VALUES
('admin', '$2b$12$6Lsp/i.clxyEE9O/4D9RLOfyFlxfjvJBhJ8VXT/t4H/QvrnKrE/YK', 'administrator');
INSERT INTO lists (list_name, list_email, description) VALUES
('Community', 'community@lists.sasalliance.org', 'General community announcements'),
('Board', 'board@lists.sasalliance.org', 'Board members only'),
('Members', 'members@lists.sasalliance.org', 'All members'),
('Announcements', 'announcements@lists.sasalliance.org', 'Important announcements');
INSERT INTO members (name, email) VALUES
('James Pattinson', 'james.pattinson@sasalliance.org'),
('James Pattinson (Personal)', 'james@pattinson.org');
-- Subscribe members to lists
-- Community list - both addresses
INSERT INTO list_members (list_id, member_id) VALUES
(1, 1), -- James (work) on Community
(1, 2); -- James (personal) on Community
-- Board list - work address only
INSERT INTO list_members (list_id, member_id) VALUES
(2, 1); -- James (work) on Board
-- Members list - both addresses
INSERT INTO list_members (list_id, member_id) VALUES
(3, 1), -- James (work) on Members
(3, 2); -- James (personal) on Members
-- Announcements list - both addresses
INSERT INTO list_members (list_id, member_id) VALUES
(4, 1), -- James (work) on Announcements
(4, 2); -- James (personal) on Announcements