trying to add gitea

This commit is contained in:
2026-02-22 03:08:09 +01:00
parent 7564da1148
commit a033efad5b
6 changed files with 111 additions and 1 deletions

View File

@@ -46,10 +46,12 @@ def create_app(config_class=Config):
from .routes import main
from .blueprints.slides import slides_bp
from .blueprints.admin import admin_bp
from .blueprints.internal import internal_bp
app.register_blueprint(main)
app.register_blueprint(slides_bp)
app.register_blueprint(admin_bp)
app.register_blueprint(internal_bp)
@app.template_filter('md')
def render_markdown(text):

View File

@@ -0,0 +1,5 @@
from flask import Blueprint
internal_bp = Blueprint('internal', __name__, url_prefix='/internal')
from . import routes #noqa

View File

@@ -0,0 +1,87 @@
import hmac
from datetime import datetime
import pytz
from flask import request, jsonify, current_app
from app.models import db, Deck, Course, Password
from . import internal_bp
@internal_bp.route('/register-deck', methods=['POST'])
def register_deck():
# Verify shared secret
token = request.headers.get('X-Internal-Token', '')
if not hmac.compare_digest(token, current_app.config['INTERNAL_TOKEN']):
return jsonify({'error': 'Unauthorized'}), 401
data = request.get_json()
if not data:
return jsonify({'error': 'Invalid JSON'}), 400
for field in ('course', 'deck', 'name'):
if not data.get(field):
return jsonify({'error': f'Missing required field: {field}'}), 400
# Look up course by folder name
course = db.session.execute(
db.select(Course).where(Course.folder == data['course'])
).scalar_one_or_none()
if not course:
return jsonify({'error': f"Course '{data['course']}' not found"}), 404
# Upsert deck
# NOTE: Deck.__init__ takes course= (object), not course_id=
deck = db.session.execute(
db.select(Deck).where(
Deck.deck == data['deck'],
Deck.course_id == course.id
)
).scalar_one_or_none()
if deck:
deck.name = data['name']
deck.description = data['description']
deck.export_file = data.get('export_file') or None
else:
deck = Deck(
name = data['name'],
deck = data['deck'],
course = course, # pass object, not course_id
description = data['description'],
index_file = data.get('index_file', 'index.html'),
export_file = data.get('export_file') or None,
)
db.session.add(deck)
db.session.flush() # populate deck.id before linking password
# Upsert password if provided
if data.get('password'):
expires_at = None
if data.get('password_expires'):
try:
# Parse ISO string and convert to UTC naive (matches UTCDateTime model)
expires_at = datetime.fromisoformat(
data['password_expires'].replace('Z', '+00:00')
).astimezone(pytz.utc)
except ValueError:
current_app.logger.warning(
f"Invalid password_expires format: {data['password_expires']}"
)
existing_pw = db.session.execute(
db.select(Password).where(Password.value == data['password'])
).scalar_one_or_none()
if existing_pw:
existing_pw.expires_at = expires_at
if deck not in existing_pw.decks:
existing_pw.decks.append(deck)
else:
pw = Password(value=data['password'], expires_at=expires_at)
pw.decks.append(deck)
db.session.add(pw)
db.session.commit()
current_app.logger.info(
f"Registered deck '{data['deck']}' for course '{data['course']}'"
)
return jsonify({'status': 'ok', 'deck': data['deck']}), 200

View File

@@ -8,6 +8,7 @@ class Config:
SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URL")
SQLALCHEMY_TRACK_MODIFICATIONS = False
ADMIN_PASSWORD = os.environ.get("ADMIN_PASSWORD")
INTERNAL_TOKEN = os.environ.get("INTERNAL_TOKEN")
COURSE_MAP = {
"GRNVS25": "GRNVS Tutorium SS 25",
"IT-Sec25": "IT-Sec Tutorium WS 25/26",

View File

@@ -83,7 +83,7 @@ class Deck(db.Model):
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(60), unique=True, nullable=False)
deck: Mapped[str] = mapped_column(String(60), nullable=False)
description: Mapped[str] = mapped_column(String(60))
description: Mapped[str] = mapped_column(String(200))
index_file: Mapped[str] = mapped_column(String(40), nullable=False)
export_file: Mapped[Optional[str]] = mapped_column(String(40), nullable=True)