safety commit
This commit is contained in:
110
app/routes.py
110
app/routes.py
@@ -1,13 +1,16 @@
|
||||
from datetime import datetime, timezone
|
||||
import os
|
||||
import re
|
||||
from typing import cast, List
|
||||
from datetime import datetime
|
||||
from typing import List, cast
|
||||
|
||||
import flask_login
|
||||
import pytz
|
||||
from flask import (
|
||||
Blueprint,
|
||||
abort,
|
||||
current_app,
|
||||
flash,
|
||||
jsonify,
|
||||
make_response,
|
||||
redirect,
|
||||
render_template,
|
||||
@@ -15,33 +18,76 @@ from flask import (
|
||||
send_from_directory,
|
||||
url_for,
|
||||
)
|
||||
import flask_login
|
||||
import pytz
|
||||
from sqlalchemy.sql import expression
|
||||
|
||||
from .auth import check_password, user_loader
|
||||
from .forms import DeckForm, LoginForm, PasswordForm
|
||||
from .models import Deck, Password, db
|
||||
from .forms import DeckForm, InfoBannerForm, LoginForm, PasswordForm
|
||||
from .models import Deck, InfoBanner, Password, db
|
||||
from .utils import (
|
||||
generate_password,
|
||||
generate_token,
|
||||
get_active_banner,
|
||||
get_available_decks,
|
||||
get_token,
|
||||
get_unlocked_decks,
|
||||
serialize_token,
|
||||
is_deck_unlocked,
|
||||
serialize_token,
|
||||
update_token,
|
||||
generate_password,
|
||||
)
|
||||
|
||||
main = Blueprint('main', __name__)
|
||||
slidev_slide_pattern = re.compile(r'\d+$')
|
||||
slidev_deck_pattern = re.compile(r"^\/slides\/[^\/]+\/\d*(?:\?.*)?$")
|
||||
slidev_all_pattern = re.compile(r"^\/slides\/[^\/]+(?:\/presenter)?\/\d+(?:\?.*)?$")
|
||||
|
||||
@main.after_request
|
||||
def inject_confused_button(response):
|
||||
if True:
|
||||
if (slidev_deck_pattern.match(request.path) or request.path == '/')and response.content_type.startswith('text/html'):
|
||||
if response.direct_passthrough:
|
||||
response.direct_passthrough = False
|
||||
body = response.get_data(as_text=True)
|
||||
insert_at = body.find('</body>')
|
||||
if insert_at != -1:
|
||||
button_html = """
|
||||
<button id="confused-button" style="
|
||||
position: fixed;
|
||||
bottom: 1.5rem;
|
||||
right: 1.5rem;
|
||||
z-index: 9999;
|
||||
background-color: #4f8cff;
|
||||
color: white;
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
border-radius: 9999px;
|
||||
padding: 1rem;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s, transform 0.2s;"
|
||||
title="Didn't understand? Click!">
|
||||
Ich habe das nicht verstanden
|
||||
</button>
|
||||
<script>
|
||||
document.getElementById('confused-button').addEventListener('click', () => {
|
||||
fetch('/confused', {method: 'POST'})
|
||||
.then(response => {
|
||||
if (response.ok) {
|
||||
alert('Alles klar! Ich versuche es besser zu erklären. Melde dich, wenn du eine spezifische Frage hast oder noch etwas unklar bleibt.');
|
||||
}
|
||||
}).catch(error => console.error('Error:', error));
|
||||
});
|
||||
</script>
|
||||
"""
|
||||
body = body[:insert_at] + button_html + body[insert_at:]
|
||||
response.set_data(body)
|
||||
return response
|
||||
|
||||
|
||||
@main.route('/')
|
||||
def index():
|
||||
token = get_token()
|
||||
if not token:
|
||||
token = generate_token()
|
||||
resp = make_response(render_template('index.html', decks=get_unlocked_decks(token), user_name=token.name))
|
||||
resp = make_response(render_template('index.html', active_banner=get_active_banner(), decks=get_unlocked_decks(token), user_name=token.name))
|
||||
resp.set_cookie('access_token', serialize_token(token), httponly=True)
|
||||
return resp
|
||||
|
||||
@@ -81,6 +127,12 @@ def access():
|
||||
return redirect('/')
|
||||
return render_template('index.html', error="Invalid password.", decks=get_unlocked_decks(token))
|
||||
|
||||
@main.route('/confused', methods=['POST'])
|
||||
|
||||
def confused():
|
||||
resp = jsonify(success=True)
|
||||
return resp
|
||||
|
||||
|
||||
@main.route('/slides/<deck>/')
|
||||
@main.route('/slides/<deck>/<path:path>')
|
||||
@@ -96,7 +148,7 @@ def serve_deck(deck, path='index.html'):
|
||||
if not os.path.exists(deck_path):
|
||||
return f"Deck '{deck}' not found.", 404
|
||||
|
||||
if slidev_slide_pattern.match(path):
|
||||
if slidev_all_pattern.match(request.path):
|
||||
return send_from_directory(deck_path, 'index.html')
|
||||
|
||||
requested_file = os.path.join(deck_path, path)
|
||||
@@ -152,6 +204,17 @@ def admin():
|
||||
|
||||
return render_template("admin.html", deck_form=deck_form, password_form=password_form, decks=decks, passwords=passwords)
|
||||
|
||||
@main.route('/admin/banner', methods=['POST', 'GET'])
|
||||
@flask_login.login_required
|
||||
def banner():
|
||||
banner_form = InfoBannerForm()
|
||||
if banner_form.validate_on_submit():
|
||||
assert isinstance(banner_form.content.data, str)
|
||||
content : str = banner_form.content.data
|
||||
banner = InfoBanner(content=content)
|
||||
db.session.add(banner)
|
||||
db.session.commit()
|
||||
return render_template("banner.html", banner_form=banner_form, banners=db.session.execute(db.select(InfoBanner)).scalars())
|
||||
|
||||
@main.route('/admin/decks/<int:deck_id>/delete', methods=['POST'])
|
||||
@flask_login.login_required
|
||||
@@ -170,3 +233,26 @@ def delete_password(password_id: int):
|
||||
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'])
|
||||
@flask_login.login_required
|
||||
def set_active_banner(banner_id):
|
||||
banner = InfoBanner.query.get(banner_id)
|
||||
if banner:
|
||||
# ensures that only one banner is active at all times
|
||||
active_banner = get_active_banner()
|
||||
if active_banner:
|
||||
active_banner.is_active = False
|
||||
banner.is_active = True
|
||||
db.session.commit()
|
||||
return redirect(url_for('main.banner'))
|
||||
|
||||
@main.route('/admin/banner/hide', methods=['POST'])
|
||||
@flask_login.login_required
|
||||
def hide_active_banner():
|
||||
banner = get_active_banner()
|
||||
if banner:
|
||||
banner.is_active = False
|
||||
db.session.commit()
|
||||
return redirect(url_for('main.banner'))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user