153 lines
6.6 KiB
Python
153 lines
6.6 KiB
Python
import click
|
|
from flask.cli import with_appcontext
|
|
|
|
from .extensions import db
|
|
from .models import AppSettings, User
|
|
|
|
|
|
def _ensure_schema_and_settings() -> None:
|
|
"""Create tables + run lightweight SQLite migrations + ensure settings row exists."""
|
|
db.create_all()
|
|
|
|
# Lightweight migration for older SQLite DBs: ensure columns exist.
|
|
# This avoids requiring Alembic for this small project.
|
|
try:
|
|
cols = [r[1] for r in db.session.execute(db.text("PRAGMA table_info(user)")).fetchall()]
|
|
if "email" not in cols:
|
|
db.session.execute(db.text("ALTER TABLE user ADD COLUMN email VARCHAR(255)"))
|
|
db.session.commit()
|
|
|
|
display_cols = [r[1] for r in db.session.execute(db.text("PRAGMA table_info(display)")).fetchall()]
|
|
if "description" not in display_cols:
|
|
db.session.execute(db.text("ALTER TABLE display ADD COLUMN description VARCHAR(200)"))
|
|
db.session.commit()
|
|
|
|
if "transition" not in display_cols:
|
|
db.session.execute(db.text("ALTER TABLE display ADD COLUMN transition VARCHAR(20)"))
|
|
db.session.commit()
|
|
|
|
if "show_overlay" not in display_cols:
|
|
db.session.execute(db.text("ALTER TABLE display ADD COLUMN show_overlay BOOLEAN NOT NULL DEFAULT 0"))
|
|
db.session.commit()
|
|
|
|
# Optional ticker tape (RSS headlines)
|
|
if "ticker_enabled" not in display_cols:
|
|
db.session.execute(db.text("ALTER TABLE display ADD COLUMN ticker_enabled BOOLEAN NOT NULL DEFAULT 0"))
|
|
db.session.commit()
|
|
if "ticker_rss_url" not in display_cols:
|
|
db.session.execute(db.text("ALTER TABLE display ADD COLUMN ticker_rss_url VARCHAR(1000)"))
|
|
db.session.commit()
|
|
if "ticker_color" not in display_cols:
|
|
db.session.execute(db.text("ALTER TABLE display ADD COLUMN ticker_color VARCHAR(32)"))
|
|
db.session.commit()
|
|
if "ticker_bg_color" not in display_cols:
|
|
db.session.execute(db.text("ALTER TABLE display ADD COLUMN ticker_bg_color VARCHAR(32)"))
|
|
db.session.commit()
|
|
if "ticker_bg_opacity" not in display_cols:
|
|
db.session.execute(db.text("ALTER TABLE display ADD COLUMN ticker_bg_opacity INTEGER"))
|
|
db.session.commit()
|
|
if "ticker_font_family" not in display_cols:
|
|
db.session.execute(db.text("ALTER TABLE display ADD COLUMN ticker_font_family VARCHAR(120)"))
|
|
db.session.commit()
|
|
if "ticker_font_size_px" not in display_cols:
|
|
db.session.execute(db.text("ALTER TABLE display ADD COLUMN ticker_font_size_px INTEGER"))
|
|
db.session.commit()
|
|
if "ticker_speed" not in display_cols:
|
|
db.session.execute(db.text("ALTER TABLE display ADD COLUMN ticker_speed INTEGER"))
|
|
db.session.commit()
|
|
|
|
company_cols = [r[1] for r in db.session.execute(db.text("PRAGMA table_info(company)")).fetchall()]
|
|
if "storage_max_bytes" not in company_cols:
|
|
db.session.execute(db.text("ALTER TABLE company ADD COLUMN storage_max_bytes BIGINT"))
|
|
db.session.commit()
|
|
|
|
if "overlay_file_path" not in company_cols:
|
|
db.session.execute(db.text("ALTER TABLE company ADD COLUMN overlay_file_path VARCHAR(400)"))
|
|
db.session.commit()
|
|
|
|
# Companies: ticker tape settings (RSS + styling)
|
|
if "ticker_rss_url" not in company_cols:
|
|
db.session.execute(db.text("ALTER TABLE company ADD COLUMN ticker_rss_url VARCHAR(1000)"))
|
|
db.session.commit()
|
|
if "ticker_color" not in company_cols:
|
|
db.session.execute(db.text("ALTER TABLE company ADD COLUMN ticker_color VARCHAR(32)"))
|
|
db.session.commit()
|
|
if "ticker_bg_color" not in company_cols:
|
|
db.session.execute(db.text("ALTER TABLE company ADD COLUMN ticker_bg_color VARCHAR(32)"))
|
|
db.session.commit()
|
|
if "ticker_bg_opacity" not in company_cols:
|
|
db.session.execute(db.text("ALTER TABLE company ADD COLUMN ticker_bg_opacity INTEGER"))
|
|
db.session.commit()
|
|
if "ticker_font_family" not in company_cols:
|
|
db.session.execute(db.text("ALTER TABLE company ADD COLUMN ticker_font_family VARCHAR(120)"))
|
|
db.session.commit()
|
|
if "ticker_font_size_px" not in company_cols:
|
|
db.session.execute(db.text("ALTER TABLE company ADD COLUMN ticker_font_size_px INTEGER"))
|
|
db.session.commit()
|
|
if "ticker_speed" not in company_cols:
|
|
db.session.execute(db.text("ALTER TABLE company ADD COLUMN ticker_speed INTEGER"))
|
|
db.session.commit()
|
|
|
|
settings_cols = [r[1] for r in db.session.execute(db.text("PRAGMA table_info(app_settings)")).fetchall()]
|
|
if settings_cols and "public_domain" not in settings_cols:
|
|
db.session.execute(db.text("ALTER TABLE app_settings ADD COLUMN public_domain VARCHAR(255)"))
|
|
db.session.commit()
|
|
except Exception:
|
|
# Best-effort; if it fails we continue so fresh DBs still work.
|
|
db.session.rollback()
|
|
|
|
# Ensure AppSettings row exists.
|
|
if not db.session.get(AppSettings, 1):
|
|
db.session.add(AppSettings(id=1))
|
|
db.session.commit()
|
|
|
|
|
|
@click.command("ensure-db")
|
|
@with_appcontext
|
|
def ensure_db_command():
|
|
"""Create tables / apply lightweight migrations.
|
|
|
|
This is useful for container startup where you want schema readiness,
|
|
without requiring admin credentials.
|
|
"""
|
|
_ensure_schema_and_settings()
|
|
click.echo("Database ready.")
|
|
|
|
|
|
@click.command("init-db")
|
|
@click.option(
|
|
"--admin-email",
|
|
required=False,
|
|
default="beheer@alphen.cloud",
|
|
show_default=True,
|
|
help="Email for the initial admin",
|
|
)
|
|
@click.option("--admin-pass", required=True, help="Password for the initial admin")
|
|
@with_appcontext
|
|
def init_db_command(admin_email: str, admin_pass: str):
|
|
"""Create tables and ensure an admin account exists."""
|
|
_ensure_schema_and_settings()
|
|
|
|
admin_email = (admin_email or "").strip().lower()
|
|
if not admin_email:
|
|
raise click.UsageError("--admin-email is required")
|
|
|
|
existing = User.query.filter_by(email=admin_email).first()
|
|
if existing:
|
|
if not existing.is_admin:
|
|
existing.is_admin = True
|
|
existing.email = admin_email
|
|
existing.username = admin_email
|
|
existing.set_password(admin_pass)
|
|
db.session.commit()
|
|
click.echo(f"Updated admin user '{admin_email}'.")
|
|
return
|
|
|
|
u = User(is_admin=True)
|
|
u.email = admin_email
|
|
u.username = admin_email
|
|
u.set_password(admin_pass)
|
|
db.session.add(u)
|
|
db.session.commit()
|
|
click.echo(f"Created admin user '{admin_email}'.")
|