finished backend upgrades to allow multiple courses
This commit is contained in:
100
app/routes.py
100
app/routes.py
@@ -9,6 +9,7 @@ from flask_socketio import join_room
|
||||
import pytz
|
||||
from flask import (
|
||||
Blueprint,
|
||||
Response,
|
||||
abort,
|
||||
current_app,
|
||||
flash,
|
||||
@@ -24,13 +25,14 @@ from . import socketio
|
||||
|
||||
from .auth import check_password, user_loader
|
||||
from .forms import DeckForm, InfoBannerForm, LoginForm, PasswordForm
|
||||
from .models import Deck, InfoBanner, Password, db
|
||||
from .models import Course, Deck, InfoBanner, Password, db
|
||||
from .utils import (
|
||||
create_token,
|
||||
generate_password,
|
||||
get_active_banner,
|
||||
get_all_courses,
|
||||
get_available_decks,
|
||||
get_passwords,
|
||||
get_token,
|
||||
get_unlocked_decks,
|
||||
is_deck_unlocked,
|
||||
@@ -43,7 +45,7 @@ from .utils import (
|
||||
|
||||
main = Blueprint('main', __name__)
|
||||
slidev_deck_pattern = re.compile(r"^\/slides\/[^\/]+\/\d*(?:\?.*)?$")
|
||||
slidev_all_pattern = re.compile(r"^\/slides\/[^\/]+(?:\/presenter)?\/\d+(?:\?.*)?$")
|
||||
slidev_all_pattern = re.compile(r"^\/slides\/([^\/]+)\/([^\/]+)(?:\/presenter)?\/(\d+)(?:\?.*)?$")
|
||||
|
||||
@socketio.on("connect")
|
||||
def on_connect():
|
||||
@@ -100,7 +102,7 @@ def index():
|
||||
if not token:
|
||||
return redirect(url_for("main.set_token"))
|
||||
else:
|
||||
return render_template('index.html', active_banner=get_active_banner(), decks=get_unlocked_decks(token), user_name=token.name, active_course_id=token.active_course_id, courses=get_all_courses())
|
||||
return render_template('index.html', active_banner=get_active_banner(), decks=get_unlocked_decks(token), user_name=token.name, active_course=token.active_course, courses=get_all_courses())
|
||||
|
||||
@main.route('/set_token', methods=['POST', 'GET'])
|
||||
def set_token():
|
||||
@@ -190,6 +192,7 @@ def switch_course(new_course: int):
|
||||
|
||||
return redirect(url_for("main.index"))
|
||||
|
||||
|
||||
@main.route('/admin/login', methods=['POST', 'GET'])
|
||||
def admin_login():
|
||||
form = LoginForm()
|
||||
@@ -214,27 +217,34 @@ def admin_login():
|
||||
return render_template("admin_login.html", form=form)
|
||||
|
||||
|
||||
def process_access_code(access_code: str):
|
||||
password = db.session.execute(
|
||||
db.select(Password)
|
||||
.where(Password.value == access_code)
|
||||
).scalar_one_or_none()
|
||||
|
||||
if password is not None:
|
||||
if not password.is_expired():
|
||||
update_token(password.decks)
|
||||
else:
|
||||
flash('Password has expired. Please obtain a new one.', 'expired')
|
||||
else:
|
||||
flash('Password is not valid. Please check the code and try again.', 'error')
|
||||
return redirect(url_for('main.index'))
|
||||
|
||||
@main.route('/access', methods=['POST'])
|
||||
def access():
|
||||
password = db.session.execute(db.select(Password).where(Password.value == request.form.get('password'))).scalar()
|
||||
assert isinstance(password, Password|None)
|
||||
token = get_token()
|
||||
if password is not None and not password.is_expired():
|
||||
update_token(password.decks)
|
||||
return redirect(url_for('main.index'))
|
||||
return render_template('index.html', error="Invalid password.", decks=get_unlocked_decks(token))
|
||||
|
||||
def access_post():
|
||||
access_code = request.form.get('password')
|
||||
|
||||
if not access_code:
|
||||
return redirect(url_for("main.index"))
|
||||
|
||||
return process_access_code(access_code)
|
||||
|
||||
# Route for direct link/QR code access (GET)
|
||||
@main.route('/access/<access_code>', methods=['GET'])
|
||||
def access_link(access_code: str):
|
||||
password = db.session.execute(db.select(Password).where(Password.value == access_code)).scalar()
|
||||
assert isinstance(password, Password|None)
|
||||
token = get_token()
|
||||
if password is not None and not password.is_expired():
|
||||
update_token(password.decks)
|
||||
return redirect(url_for('main.index'))
|
||||
return render_template('index.html', error="Invalid password.", decks=get_unlocked_decks(token))
|
||||
|
||||
def access_get(access_code: str):
|
||||
return process_access_code(access_code)
|
||||
|
||||
|
||||
@main.route('/confused', methods=['POST'])
|
||||
@@ -248,25 +258,29 @@ def confused():
|
||||
)
|
||||
return ("", 204)
|
||||
|
||||
@main.route('/slides/<deck>/')
|
||||
@main.route('/slides/<deck>/<path:path>')
|
||||
def serve_deck(deck, path='index.html'):
|
||||
if not db.session.execute(db.select(Deck).where(Deck.deck==deck)).scalar():
|
||||
@main.route('/slides/<course_folder>/<deck>/')
|
||||
@main.route('/slides/<course_folder>/<deck>/<path:path>')
|
||||
def serve_deck(deck, course_folder, path='index.html'):
|
||||
course = db.session.execute(db.select(Course).where(Course.folder==course_folder)).scalar()
|
||||
if not course:
|
||||
abort(404)
|
||||
assert isinstance(course, Course)
|
||||
deck = db.session.execute(db.select(Deck).where(Deck.deck==deck and Deck.course_id == course.id)).scalar()
|
||||
if not deck:
|
||||
abort(404)
|
||||
assert isinstance(deck, Deck)
|
||||
|
||||
if not is_deck_unlocked(deck):
|
||||
if not is_deck_unlocked(deck.deck):
|
||||
return redirect(url_for('main.index'))
|
||||
|
||||
slides_dir = current_app.config['SLIDES_DIR']
|
||||
deck_path = os.path.join(slides_dir, deck)
|
||||
slides_dir = os.path.join(current_app.config['SLIDES_DIR'], course.folder)
|
||||
deck_path = os.path.join(slides_dir, deck.deck)
|
||||
|
||||
if not os.path.exists(deck_path):
|
||||
return f"Deck '{deck}' not found.", 404
|
||||
|
||||
if slidev_all_pattern.match(request.path):
|
||||
return send_from_directory(deck_path, 'index.html')
|
||||
|
||||
if deck in ["tut-08","tut-11"] and path == 'index.html':
|
||||
return send_from_directory(deck_path, 'slides.pdf')
|
||||
return send_from_directory(deck_path, deck.index_file)
|
||||
|
||||
requested_file = os.path.join(deck_path, path)
|
||||
if os.path.isfile(requested_file):
|
||||
@@ -277,13 +291,16 @@ def serve_deck(deck, path='index.html'):
|
||||
@main.route('/admin', methods=['GET', 'POST'])
|
||||
@flask_login.login_required
|
||||
def admin():
|
||||
active_course_id = flask_login.current_user.active_course_id
|
||||
active_course = get_course(active_course_id)
|
||||
if active_course is None:
|
||||
raise Exception
|
||||
deck_form = DeckForm()
|
||||
password_form = PasswordForm()
|
||||
if request.method == 'GET':
|
||||
password_form.value.data = generate_password()
|
||||
deck_form.deck.choices = get_available_decks(current_app)
|
||||
decks = db.session.scalars(db.select(Deck).order_by(Deck.name)).all()
|
||||
passwords = db.session.scalars(db.select(Password)).all()
|
||||
deck_form.deck.choices = get_available_decks(current_app, active_course)
|
||||
decks = active_course.decks
|
||||
password_form.decks.choices = [(deck.id, deck.name) for deck in decks]
|
||||
|
||||
|
||||
@@ -292,6 +309,7 @@ def admin():
|
||||
deck = Deck(
|
||||
name=cast(str,deck_form.name.data),
|
||||
deck=deck_form.deck.data,
|
||||
course=active_course,
|
||||
description=cast(str,deck_form.description.data),
|
||||
)
|
||||
db.session.add(deck)
|
||||
@@ -320,7 +338,15 @@ def admin():
|
||||
print(f"Error in {getattr(password_form, field).label.text}: {error}", flush=True)
|
||||
return redirect(url_for('main.admin'))
|
||||
|
||||
return render_template("admin.html", deck_form=deck_form, password_form=password_form, decks=decks, passwords=passwords)
|
||||
return render_template("admin.html", deck_form=deck_form, password_form=password_form, decks=decks, passwords=get_passwords(active_course), courses=get_all_courses(), active_course_id=active_course_id)
|
||||
|
||||
@main.route('/admin/switch_course/<new_course>', methods=['POST'])
|
||||
@flask_login.login_required
|
||||
def switch_course_admin(new_course: int):
|
||||
user = flask_login.current_user
|
||||
if get_course(new_course):
|
||||
user.active_course_id = new_course
|
||||
return redirect(url_for("main.admin"))
|
||||
|
||||
@main.route('/admin/banner', methods=['POST', 'GET'])
|
||||
@flask_login.login_required
|
||||
@@ -340,7 +366,6 @@ def delete_deck(deck_id: int):
|
||||
deck = Deck.query.get_or_404(deck_id)
|
||||
db.session.delete(deck)
|
||||
db.session.commit()
|
||||
flash(f'Deck "{deck.name}" deleted.', 'success')
|
||||
return redirect(url_for('main.admin'))
|
||||
|
||||
@main.route('/admin/passwords/<int:password_id>/delete', methods=['POST'])
|
||||
@@ -349,7 +374,6 @@ def delete_password(password_id: int):
|
||||
password = Password.query.get_or_404(password_id)
|
||||
db.session.delete(password)
|
||||
db.session.commit()
|
||||
flash(f'Password "{password.value}" deleted.', 'success')
|
||||
return redirect(url_for('main.admin'))
|
||||
|
||||
@main.route('/admin/banner/show/<int:banner_id>', methods=['POST'])
|
||||
|
||||
Reference in New Issue
Block a user