64ab1d0412
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
305 lines
11 KiB
Python
305 lines
11 KiB
Python
#!/usr/bin/env python3
|
|
"""Database initialization script for NetEvent platform."""
|
|
|
|
import mysql.connector
|
|
from mysql.connector import Error
|
|
|
|
DB_HOST = 'roast.duckdns.org'
|
|
DB_PORT = 33062
|
|
DB_USER = 'root'
|
|
DB_PASSWORD = 'Tiegl!!!111...'
|
|
DB_NAME = 'netevent'
|
|
APP_USER = 'netevent_app'
|
|
APP_PASSWORD = 'netevent_pass_2024'
|
|
|
|
def create_database():
|
|
"""Create the database and dedicated user."""
|
|
try:
|
|
conn = mysql.connector.connect(
|
|
host=DB_HOST,
|
|
port=DB_PORT,
|
|
user=DB_USER,
|
|
password=DB_PASSWORD
|
|
)
|
|
cursor = conn.cursor()
|
|
|
|
# Create database if not exists
|
|
cursor.execute(f"CREATE DATABASE IF NOT EXISTS {DB_NAME}")
|
|
print(f"Database '{DB_NAME}' created or already exists.")
|
|
|
|
# Create dedicated application user
|
|
cursor.execute(f"CREATE USER IF NOT EXISTS '{APP_USER}'@'%' IDENTIFIED BY '{APP_PASSWORD}'")
|
|
cursor.execute(f"GRANT ALL PRIVILEGES ON {DB_NAME}.* TO '{APP_USER}'@'%'")
|
|
cursor.execute("FLUSH PRIVILEGES")
|
|
print(f"User '{APP_USER}' created with privileges on '{DB_NAME}'.")
|
|
|
|
conn.commit()
|
|
cursor.close()
|
|
conn.close()
|
|
return True
|
|
except Error as e:
|
|
print(f"Error creating database/user: {e}")
|
|
return False
|
|
|
|
def create_tables():
|
|
"""Create all required tables."""
|
|
tables = [
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS organizers (
|
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
email VARCHAR(255) UNIQUE NOT NULL,
|
|
password_hash VARCHAR(255) NOT NULL,
|
|
name VARCHAR(255) NOT NULL,
|
|
staff_code VARCHAR(10) UNIQUE DEFAULT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
)
|
|
""",
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS events (
|
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
organizer_id INT NOT NULL,
|
|
code VARCHAR(10) UNIQUE NOT NULL,
|
|
name VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
start_time DATETIME NOT NULL,
|
|
end_time DATETIME,
|
|
location VARCHAR(255),
|
|
max_attendees INT DEFAULT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (organizer_id) REFERENCES organizers(id) ON DELETE CASCADE
|
|
)
|
|
""",
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS attendees (
|
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
event_id INT NOT NULL,
|
|
email VARCHAR(255) NOT NULL,
|
|
password_hash VARCHAR(255) NOT NULL,
|
|
first_name VARCHAR(100) NOT NULL,
|
|
last_name VARCHAR(100) NOT NULL,
|
|
organisation VARCHAR(255),
|
|
role VARCHAR(255),
|
|
introduction TEXT,
|
|
profile_picture VARCHAR(255) DEFAULT NULL,
|
|
checked_in BOOLEAN DEFAULT FALSE,
|
|
attendance_status ENUM('attending', 'not_attending') DEFAULT 'attending',
|
|
confirmation_token VARCHAR(64) DEFAULT NULL,
|
|
attendee_code VARCHAR(10) UNIQUE,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE,
|
|
UNIQUE KEY unique_attendee_event (event_id, email)
|
|
)
|
|
""",
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS connections (
|
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
attendee_id INT NOT NULL,
|
|
connected_attendee_id INT NOT NULL,
|
|
status ENUM('pending', 'accepted', 'rejected') DEFAULT 'pending',
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (attendee_id) REFERENCES attendees(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (connected_attendee_id) REFERENCES attendees(id) ON DELETE CASCADE,
|
|
UNIQUE KEY unique_connection (attendee_id, connected_attendee_id)
|
|
)
|
|
""",
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS appointments (
|
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
event_id INT NOT NULL,
|
|
requester_id INT NOT NULL,
|
|
target_id INT NOT NULL,
|
|
appointment_time DATETIME NOT NULL,
|
|
location VARCHAR(255),
|
|
notes TEXT,
|
|
status ENUM('pending', 'accepted', 'rejected') DEFAULT 'pending',
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (requester_id) REFERENCES attendees(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (target_id) REFERENCES attendees(id) ON DELETE CASCADE
|
|
)
|
|
""",
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS breakout_sessions (
|
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
code VARCHAR(10) NOT NULL UNIQUE,
|
|
event_id INT NOT NULL,
|
|
name VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
start_time DATETIME NOT NULL,
|
|
end_time DATETIME NOT NULL,
|
|
location VARCHAR(255),
|
|
max_attendees INT DEFAULT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE
|
|
)
|
|
""",
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS breakout_session_organizers (
|
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
breakout_session_id INT NOT NULL,
|
|
organizer_id INT NOT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (breakout_session_id) REFERENCES breakout_sessions(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (organizer_id) REFERENCES organizers(id) ON DELETE CASCADE,
|
|
UNIQUE KEY unique_session_organizer (breakout_session_id, organizer_id)
|
|
)
|
|
""",
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS breakout_session_rsvps (
|
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
breakout_session_id INT NOT NULL,
|
|
attendee_id INT NOT NULL,
|
|
status ENUM('registered', 'cancelled') DEFAULT 'registered',
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (breakout_session_id) REFERENCES breakout_sessions(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (attendee_id) REFERENCES attendees(id) ON DELETE CASCADE,
|
|
UNIQUE KEY unique_rsvp (breakout_session_id, attendee_id)
|
|
)
|
|
""",
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS staff (
|
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
event_id INT NOT NULL,
|
|
email VARCHAR(255) NOT NULL,
|
|
password_hash VARCHAR(255) DEFAULT NULL,
|
|
first_name VARCHAR(100) NOT NULL,
|
|
last_name VARCHAR(100) NOT NULL,
|
|
staff_code VARCHAR(10) UNIQUE DEFAULT NULL,
|
|
invite_token VARCHAR(64) DEFAULT NULL,
|
|
invite_used BOOLEAN DEFAULT FALSE,
|
|
preferred_language VARCHAR(5) DEFAULT 'en',
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE,
|
|
UNIQUE KEY unique_staff_event (event_id, email)
|
|
)
|
|
""",
|
|
# Languages table
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS languages (
|
|
code VARCHAR(5) PRIMARY KEY,
|
|
name VARCHAR(50) NOT NULL,
|
|
native_name VARCHAR(50) NOT NULL,
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
is_default BOOLEAN DEFAULT FALSE,
|
|
date_format VARCHAR(30) DEFAULT '%B %d, %Y at %H:%M',
|
|
sort_order INT DEFAULT 0
|
|
)
|
|
""",
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS attendee_types (
|
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
event_id INT NOT NULL,
|
|
code VARCHAR(10) UNIQUE NOT NULL,
|
|
name VARCHAR(100) NOT NULL,
|
|
price DECIMAL(10,2) DEFAULT 0.00,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE
|
|
)
|
|
"""
|
|
]
|
|
|
|
# Alter existing tables to add preferred_language column
|
|
alter_statements = [
|
|
"ALTER TABLE organizers ADD COLUMN preferred_language VARCHAR(5) DEFAULT 'en'",
|
|
"ALTER TABLE attendees ADD COLUMN preferred_language VARCHAR(5) DEFAULT 'en'",
|
|
"ALTER TABLE attendees ADD COLUMN attendee_code VARCHAR(10) UNIQUE",
|
|
"ALTER TABLE attendees ADD COLUMN phone VARCHAR(50) DEFAULT ''",
|
|
"ALTER TABLE attendees ADD COLUMN linkedin VARCHAR(255) DEFAULT ''",
|
|
"ALTER TABLE attendees ADD COLUMN attendee_type_id INT DEFAULT NULL",
|
|
]
|
|
|
|
try:
|
|
conn = mysql.connector.connect(
|
|
host=DB_HOST,
|
|
port=DB_PORT,
|
|
user=APP_USER,
|
|
password=APP_PASSWORD,
|
|
database=DB_NAME
|
|
)
|
|
cursor = conn.cursor()
|
|
|
|
for table_sql in tables:
|
|
cursor.execute(table_sql)
|
|
|
|
# Alter existing tables
|
|
for alter_sql in alter_statements:
|
|
try:
|
|
cursor.execute(alter_sql)
|
|
except Error as e:
|
|
# Column might already exist
|
|
if e.errno != 1060: # Duplicate column name
|
|
print(f"Warning: {e}")
|
|
|
|
# Add foreign key constraint for attendee_type_id
|
|
try:
|
|
cursor.execute("""
|
|
ALTER TABLE attendees
|
|
ADD CONSTRAINT fk_attendee_type
|
|
FOREIGN KEY (attendee_type_id) REFERENCES attendee_types(id) ON DELETE SET NULL
|
|
""")
|
|
except Error as e:
|
|
if e.errno != 1060 and e.errno != 1826: # Not duplicate column or duplicate FK
|
|
print(f"Warning adding FK: {e}")
|
|
|
|
conn.commit()
|
|
cursor.close()
|
|
conn.close()
|
|
print("All tables created successfully.")
|
|
return True
|
|
except Error as e:
|
|
print(f"Error creating tables: {e}")
|
|
return False
|
|
|
|
|
|
def seed_languages():
|
|
"""Seed the languages table with EU languages."""
|
|
languages = [
|
|
('en', 'English', 'English', True, True, '%B %d, %Y at %H:%M', 1),
|
|
('nl', 'Dutch', 'Nederlands', True, False, '%d %B %Y om %H:%M', 2),
|
|
('de', 'German', 'Deutsch', True, False, '%d. %B %Y um %H:%M', 3),
|
|
('fr', 'French', 'Français', True, False, '%d %B %Y à %H:%M', 4),
|
|
('es', 'Spanish', 'Español', True, False, '%d de %B de %Y a las %H:%M', 5),
|
|
('it', 'Italian', 'Italiano', True, False, '%d %B %Y alle %H:%M', 6),
|
|
('pl', 'Polish', 'Polski', True, False, '%d %B %Y o %H:%M', 7),
|
|
]
|
|
|
|
try:
|
|
conn = mysql.connector.connect(
|
|
host=DB_HOST,
|
|
port=DB_PORT,
|
|
user=APP_USER,
|
|
password=APP_PASSWORD,
|
|
database=DB_NAME
|
|
)
|
|
cursor = conn.cursor()
|
|
|
|
for lang in languages:
|
|
cursor.execute("""
|
|
INSERT IGNORE INTO languages (code, name, native_name, is_active, is_default, date_format, sort_order)
|
|
VALUES (%s, %s, %s, %s, %s, %s, %s)
|
|
""", lang)
|
|
|
|
conn.commit()
|
|
cursor.close()
|
|
conn.close()
|
|
print("Languages seeded successfully.")
|
|
return True
|
|
except Error as e:
|
|
print(f"Error seeding languages: {e}")
|
|
return False
|
|
|
|
|
|
def init_database():
|
|
"""Initialize the complete database."""
|
|
print("Initializing NetEvent database...")
|
|
if create_database():
|
|
if create_tables():
|
|
seed_languages()
|
|
print("Database initialization complete!")
|
|
return True
|
|
print("Database initialization failed.")
|
|
return False
|
|
|
|
if __name__ == '__main__':
|
|
init_database()
|