Sanitize codebase, reorganize docs, and add missing deploy files

Remove dead code identified in docs/SANITIZATION-REVIEW.md:
- app/blueprints/content_old.py and app/blueprints/playlist.py
- app/models/group.py, app/utils/nginx_config_reader.py
- orphaned templates (content_list, edit_content, upload_content,
  player_page) and the related group/Template references

Result: 6 blueprints, 82 routes, no dead modules or orphan templates.

Add files that deploy.sh and docker-entrypoint.sh already require but
which were never tracked:
- https_manager.py       (referenced by deploy.sh, migrate_network.sh,
                          docker-entrypoint.sh)
- Caddyfile.example      (seeded by deploy.sh; its absence aborts deploy)

Relocate generated Graphify artifacts from graphify-out/ to
docs/graphify-out/ (110 files, no content change) and archive the
superseded docs under docs/.

Ignore hygiene:
- ignore ad-hoc .env backups (.env.bak*) — they contain live secrets
- keep the pre-sanitization snapshots (docs/legacy code/,
  docs/old_code_documentation/) on disk but out of the repo

Fix .env.example: drop a duplicated config block, genericize the
hardcoded host IP, and document HOSTNAME_INTERNAL.
This commit is contained in:
2026-09-11 12:18:34 +03:00
parent 1c5186463a
commit 46602f1933
226 changed files with 3999 additions and 15737 deletions
+119
View File
@@ -0,0 +1,119 @@
"""Verify the HTTPS-verify + automatic HTTP fallback in https_manager._apply.
This is the safety net the user asked for: if HTTPS is enabled but does not
actually work, the server must not be left unreachable — it falls back to HTTP.
The TLS probe is monkey-patched so no live server is required.
Run: PYTHONPATH=$(pwd) ./.venv/bin/python docs/tools/test_https_fallback.py
"""
import importlib.util
import os
import shutil
import tempfile
TMPDIR = tempfile.mkdtemp()
os.environ['DATABASE_URL'] = f'sqlite:///{TMPDIR}/fb.db'
from app.app import create_app # noqa: E402
from app.extensions import db # noqa: E402
from app.models.https_config import HTTPSConfig # noqa: E402
REPO = '/home/scheianu/digiserver-v2'
TARGET = os.path.join(TMPDIR, 'Caddyfile')
app = create_app('production')
with app.app_context():
db.create_all()
def load_manager(verify_result):
"""Import https_manager with I/O redirected and the probe stubbed."""
spec = importlib.util.spec_from_file_location(
'hm_fb', os.path.join(REPO, 'https_manager.py'))
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
mod.CaddyConfigGenerator.write_caddyfile = staticmethod(
lambda content, path=TARGET: (open(TARGET, 'w').write(content), True)[1])
mod.CaddyConfigGenerator.reload_caddy = staticmethod(lambda: True)
mod.verify_https = lambda *a, **k: verify_result
return mod
def blocks():
return [ln.strip() for ln in open(TARGET).read().splitlines()
if ln.strip().startswith(('http://', 'https://', ':80'))]
def config():
with app.app_context():
return HTTPSConfig.get_config()
print('=' * 68)
print('CASE A — HTTPS verifies OK -> stays enabled')
print('=' * 68)
open(TARGET, 'w').write(':80 {\n respond "x"\n}\n')
hm = load_manager((True, 'HTTP 200 from https://192.168.0.152:443/api/health'))
rc = hm._apply(app, https_enabled=True, hostname='digiserver', domain='',
email=None, ip_address='192.168.0.152', port=443,
http_fallback=True, verify=True)
c = config()
print('exit code:', rc, '| https_enabled:', c.https_enabled)
print('blocks:', blocks())
assert rc == 0
assert c.https_enabled is True
assert 'tls internal' in open(TARGET).read()
print('PASS: HTTPS left enabled\n')
print('=' * 68)
print('CASE B — HTTPS probe FAILS -> automatic HTTP fallback')
print('=' * 68)
open(TARGET, 'w').write(':80 {\n respond "x"\n}\n')
hm = load_manager((False, 'ConnectionRefusedError: refused'))
rc = hm._apply(app, https_enabled=True, hostname='digiserver', domain='',
email=None, ip_address='192.168.0.152', port=443,
http_fallback=True, verify=True)
c = config()
text = open(TARGET).read()
print('exit code:', rc, '| https_enabled:', c.https_enabled)
print('blocks:', blocks())
assert rc == 1, f'expected exit 1 signalling the fallback, got {rc}'
assert c.https_enabled is False, 'must revert to HTTP-only'
assert 'tls internal' not in text, 'TLS must be removed after fallback'
assert ':80 {' in text, 'HTTP must still be served'
print('PASS: reverted to plain HTTP so the site stays reachable\n')
print('=' * 68)
print('CASE C — verify disabled -> trusts the config, no probe')
print('=' * 68)
open(TARGET, 'w').write(':80 {\n respond "x"\n}\n')
hm = load_manager((False, 'should never be called'))
rc = hm._apply(app, https_enabled=True, hostname='digiserver', domain='',
email=None, ip_address='192.168.0.152', port=443,
http_fallback=True, verify=False)
c = config()
print('exit code:', rc, '| https_enabled:', c.https_enabled)
assert rc == 0
assert c.https_enabled is True, 'no probe => config trusted'
assert 'tls internal' in open(TARGET).read()
print('PASS: configuration trusted without probing\n')
print('=' * 68)
print('CASE D — HTTP only (https disabled) is never probed')
print('=' * 68)
open(TARGET, 'w').write(':80 {\n respond "x"\n}\n')
hm = load_manager((False, 'n/a'))
rc = hm._apply(app, https_enabled=False, hostname=None, domain=None,
email=None, ip_address=None, port=443,
http_fallback=True, verify=True)
c = config()
print('exit code:', rc, '| https_enabled:', c.https_enabled)
assert rc == 0
assert c.https_enabled is False
assert 'tls internal' not in open(TARGET).read()
print('PASS: no TLS emitted, no probe performed\n')
shutil.rmtree(TMPDIR, ignore_errors=True)
print('ALL FALLBACK CASES PASSED')