First Commit
This commit is contained in:
242
create_database.py
Normal file
242
create_database.py
Normal file
@@ -0,0 +1,242 @@
|
||||
"""
|
||||
Script per creare il database di Proxmox Manager.
|
||||
|
||||
Uso:
|
||||
python create_database.py
|
||||
|
||||
Requisiti:
|
||||
- MySQL/MariaDB in esecuzione
|
||||
- File .env configurato con DB_HOST, DB_USER, DB_PASSWORD, DB_NAME
|
||||
- pip install -r requirements.txt
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import bcrypt
|
||||
import pymysql
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Carica le variabili dal file .env
|
||||
load_dotenv()
|
||||
|
||||
DB_HOST = os.getenv('DB_HOST', 'localhost')
|
||||
DB_USER = os.getenv('DB_USER', 'root')
|
||||
DB_PASSWORD = os.getenv('DB_PASSWORD', '')
|
||||
DB_NAME = os.getenv('DB_NAME', 'proxmox_manager')
|
||||
|
||||
|
||||
def hash_password(password: str) -> str:
|
||||
"""Genera un hash bcrypt sicuro per la password."""
|
||||
return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt(12)).decode('utf-8')
|
||||
|
||||
|
||||
def get_connection(database=None):
|
||||
"""Apre una connessione a MySQL."""
|
||||
try:
|
||||
conn = pymysql.connect(
|
||||
host=DB_HOST,
|
||||
user=DB_USER,
|
||||
password=DB_PASSWORD,
|
||||
database=database,
|
||||
charset='utf8mb4',
|
||||
cursorclass=pymysql.cursors.DictCursor,
|
||||
autocommit=True,
|
||||
)
|
||||
return conn
|
||||
except pymysql.Error as e:
|
||||
print(f"\n[ERRORE] Impossibile connettersi a MySQL: {e}")
|
||||
print("\nVerifica che:")
|
||||
print(f" - MySQL/MariaDB sia in esecuzione su {DB_HOST}")
|
||||
print(f" - Le credenziali nel file .env siano corrette (utente: {DB_USER})")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def create_database(conn):
|
||||
"""Crea il database se non esiste."""
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
f"CREATE DATABASE IF NOT EXISTS `{DB_NAME}` "
|
||||
f"CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
|
||||
)
|
||||
print(f" [OK] Database '{DB_NAME}' pronto.")
|
||||
|
||||
|
||||
def create_tables(conn):
|
||||
"""Crea tutte le tabelle necessarie."""
|
||||
|
||||
tables = {
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# 1. UTENTI #
|
||||
# ------------------------------------------------------------------ #
|
||||
'users': """
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(50) UNIQUE NOT NULL,
|
||||
email VARCHAR(100) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
is_admin BOOLEAN DEFAULT FALSE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
last_login TIMESTAMP NULL,
|
||||
active BOOLEAN DEFAULT TRUE,
|
||||
INDEX idx_username (username),
|
||||
INDEX idx_email (email)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
""",
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# 2. ASSOCIAZIONE UTENTE ↔ VM #
|
||||
# ------------------------------------------------------------------ #
|
||||
'user_vms': """
|
||||
CREATE TABLE IF NOT EXISTS user_vms (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
vm_id INT NOT NULL,
|
||||
vm_name VARCHAR(100),
|
||||
notes TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
UNIQUE KEY unique_user_vm (user_id, vm_id),
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_vm_id (vm_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
""",
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# 3. LOG AZIONI (audit trail) #
|
||||
# ------------------------------------------------------------------ #
|
||||
'action_logs': """
|
||||
CREATE TABLE IF NOT EXISTS action_logs (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
vm_id INT NOT NULL,
|
||||
action_type ENUM(
|
||||
'start','stop','restart','shutdown',
|
||||
'backup','login','snapshot',
|
||||
'subdomain_create','subdomain_delete','ip_assign'
|
||||
) NOT NULL,
|
||||
status ENUM('success','failed') NOT NULL,
|
||||
error_message TEXT,
|
||||
ip_address VARCHAR(45),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_vm_id (vm_id),
|
||||
INDEX idx_created_at (created_at),
|
||||
INDEX idx_action_type(action_type)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
""",
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# 4. SOTTODOMINI CLOUDFLARE #
|
||||
# ------------------------------------------------------------------ #
|
||||
'subdomains': """
|
||||
CREATE TABLE IF NOT EXISTS subdomains (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
subdomain VARCHAR(100) NOT NULL,
|
||||
ip_address VARCHAR(45) NOT NULL,
|
||||
vm_id INT NULL,
|
||||
proxied BOOLEAN DEFAULT FALSE,
|
||||
cloudflare_record_id VARCHAR(100),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_subdomain(subdomain)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
""",
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# 5. ASSEGNAZIONI IP (IPAM) #
|
||||
# ------------------------------------------------------------------ #
|
||||
'ip_assignments': """
|
||||
CREATE TABLE IF NOT EXISTS ip_assignments (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
vm_id INT UNIQUE NOT NULL,
|
||||
ip_address VARCHAR(45) NOT NULL,
|
||||
mac_address VARCHAR(17) NULL,
|
||||
notes TEXT NULL,
|
||||
assigned_by INT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (assigned_by) REFERENCES users(id) ON DELETE SET NULL,
|
||||
INDEX idx_vm_id (vm_id),
|
||||
INDEX idx_ip_address(ip_address)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
""",
|
||||
}
|
||||
|
||||
with conn.cursor() as cur:
|
||||
for name, ddl in tables.items():
|
||||
cur.execute(ddl)
|
||||
print(f" [OK] Tabella '{name}' pronta.")
|
||||
|
||||
|
||||
def create_default_users(conn):
|
||||
"""Inserisce gli utenti di default (admin e testuser)."""
|
||||
|
||||
users = [
|
||||
{
|
||||
'username': 'admin',
|
||||
'email': 'admin@localhost',
|
||||
'password': 'admin123',
|
||||
'is_admin': True,
|
||||
},
|
||||
{
|
||||
'username': 'testuser',
|
||||
'email': 'test@localhost',
|
||||
'password': 'test123',
|
||||
'is_admin': False,
|
||||
},
|
||||
]
|
||||
|
||||
with conn.cursor() as cur:
|
||||
for u in users:
|
||||
pw_hash = hash_password(u['password'])
|
||||
cur.execute(
|
||||
"""
|
||||
INSERT INTO users (username, email, password_hash, is_admin)
|
||||
VALUES (%s, %s, %s, %s)
|
||||
ON DUPLICATE KEY UPDATE username = username
|
||||
""",
|
||||
(u['username'], u['email'], pw_hash, u['is_admin']),
|
||||
)
|
||||
print(f" [OK] Utente '{u['username']}' (password: {u['password']}) pronto.")
|
||||
|
||||
|
||||
def main():
|
||||
print("=" * 55)
|
||||
print(" Proxmox Manager — Creazione Database")
|
||||
print("=" * 55)
|
||||
print(f"\nConnessione a MySQL ({DB_USER}@{DB_HOST})...")
|
||||
|
||||
# Prima connessione senza database (per crearlo)
|
||||
conn_no_db = get_connection(database=None)
|
||||
create_database(conn_no_db)
|
||||
conn_no_db.close()
|
||||
|
||||
# Seconda connessione al database appena creato
|
||||
conn = get_connection(database=DB_NAME)
|
||||
|
||||
print("\nCreazione tabelle...")
|
||||
create_tables(conn)
|
||||
|
||||
print("\nCreazione utenti di default...")
|
||||
create_default_users(conn)
|
||||
|
||||
conn.close()
|
||||
|
||||
print("\n" + "=" * 55)
|
||||
print(" Database creato con successo!")
|
||||
print("=" * 55)
|
||||
print("\nCredenziali di accesso:")
|
||||
print(" Amministratore : admin / admin123")
|
||||
print(" Utente di test : testuser / test123")
|
||||
print("\n IMPORTANTE: Cambia le password dopo il primo login!\n")
|
||||
print("Per avviare l'applicazione:")
|
||||
print(" python app.py")
|
||||
print("\nPoi apri il browser su: http://localhost:5000\n")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user