-- 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, INDEX idx_email (email), INDEX idx_active (active) ) 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; -- Insert sample data -- Create default admin user (password: 'password') -- $2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewKv0AhDoLlZ7G.i is bcrypt hash of 'password' INSERT INTO users (username, password_hash, role) VALUES ('admin', '$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewKv0AhDoLlZ7G.i', '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