Skip to content

Commit

Permalink
404 & 500 pages (hedyorg#992)
Browse files Browse the repository at this point in the history
* Nice 404 & 500 pages.
* Return proper status codes in 404 and 500 pages
  • Loading branch information
fpereiro authored Oct 15, 2021
1 parent 07e4f31 commit 2d82964
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 16 deletions.
22 changes: 11 additions & 11 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ def programs_page(request):
@app.route('/quiz/start/<level>', methods=['GET'])
def get_quiz_start(level):
if not config.get('quiz-enabled') and g.lang != 'nl':
return 'Hedy quiz disabled!', 404
return utils.page_404 (TRANSLATIONS, render_main_menu('adventures'), current_user(request) ['username'], requested_lang (), 'Hedy quiz disabled!')
else:
g.lang = lang = requested_lang()
g.prefix = '/hedy'
Expand All @@ -469,7 +469,7 @@ def quiz_data_file_for(level):
@app.route('/quiz/quiz_questions/<level_source>/<question_nr>/<attempt>', methods=['GET'])
def get_quiz(level_source, question_nr, attempt):
if not config.get('quiz-enabled') and g.lang != 'nl':
return 'Hedy quiz disabled!', 404
return utils.page_404 (TRANSLATIONS, render_main_menu('adventures'), current_user(request) ['username'], requested_lang (), 'Hedy quiz disabled!')
else:
# Reading the yaml file
quiz_data = quiz_data_file_for(level_source)
Expand Down Expand Up @@ -516,7 +516,7 @@ def get_quiz(level_source, question_nr, attempt):
@app.route('/quiz/submit_answer/<level_source>/<question_nr>/<attempt>', methods=["POST"])
def submit_answer(level_source, question_nr, attempt):
if not config.get('quiz-enabled') and g.lang != 'nl':
return 'Hedy quiz disabled!', 404
return utils.page_404 (TRANSLATIONS, render_main_menu('adventures'), current_user(request) ['username'], requested_lang (), 'Hedy quiz disabled!')
else:
# Get the chosen option from the request form with radio buttons
option = request.form["radio_option"]
Expand Down Expand Up @@ -610,7 +610,7 @@ def adventure_page(adventure_name, level):

# If requested adventure does not exist, return 404
if not adventure_name in adventures:
return 'No such Hedy adventure!', 404
return utils.page_404 (TRANSLATIONS, render_main_menu('adventures'), current_user(request) ['username'], requested_lang (), TRANSLATIONS.get_translations (requested_lang (), 'ui').get ('no_such_adventure'))

adventure = adventures[adventure_name]

Expand All @@ -636,7 +636,7 @@ def adventure_page(adventure_name, level):

# If requested level is not in adventure, return 404
if not level in adventure['levels']:
abort(404)
return utils.page_404 (TRANSLATIONS, render_main_menu('adventures'), current_user(request) ['username'], requested_lang (), TRANSLATIONS.get_translations (requested_lang (), 'ui').get ('no_such_adventure_level'))

adventures_for_level = load_adventures_per_level(requested_lang(), level)
level_defaults_for_lang = LEVEL_DEFAULTS[requested_lang()]
Expand Down Expand Up @@ -671,9 +671,9 @@ def index(level, step):
try:
g.level = level = int(level)
except:
return 'No such Hedy level!', 404
return utils.page_404 (TRANSLATIONS, render_main_menu('hedy'), current_user(request) ['username'], requested_lang (), TRANSLATIONS.get_translations (requested_lang (), 'ui').get ('no_such_level'))
else:
return 'No such Hedy level!', 404
return utils.page_404 (TRANSLATIONS, render_main_menu('hedy'), current_user(request) ['username'], requested_lang (), TRANSLATIONS.get_translations (requested_lang (), 'ui').get ('no_such_level'))

g.lang = requested_lang()
g.prefix = '/hedy'
Expand All @@ -685,12 +685,12 @@ def index(level, step):
if step and isinstance(step, str) and len(step) > 2:
result = DATABASE.program_by_id(step)
if not result:
return 'No such program', 404
return utils.page_404 (TRANSLATIONS, render_main_menu('hedy'), current_user(request) ['username'], requested_lang (), TRANSLATIONS.get_translations (requested_lang (), 'ui').get ('no_such_program'))
# If the program is not public, allow only the owner of the program, the admin user and the teacher users to access the program
user = current_user(request)
public_program = 'public' in result and result['public']
if not public_program and user['username'] != result['username'] and not is_admin(request) and not is_teacher(request):
return 'No such program!', 404
return utils.page_404 (TRANSLATIONS, render_main_menu('hedy'), current_user(request) ['username'], requested_lang (), TRANSLATIONS.get_translations (requested_lang (), 'ui').get ('no_such_program'))
loaded_program = {'code': result['code'], 'name': result['name'], 'adventure_name': result.get('adventure_name')}
if 'adventure_name' in result:
adventure_name = result['adventure_name']
Expand Down Expand Up @@ -720,7 +720,7 @@ def view_program(id):

result = DATABASE.program_by_id(id)
if not result:
return 'No such program', 404
return utils.page_404 (TRANSLATIONS, render_main_menu('hedy'), current_user(request) ['username'], requested_lang (), TRANSLATIONS.get_translations (requested_lang (), 'ui').get ('no_such_program'))

# Default to the language of the program's author(but still respect)
# the switch if given.
Expand Down Expand Up @@ -771,7 +771,7 @@ def client_messages():
def internal_error(exception):
import traceback
print(traceback.format_exc())
return "<h1>500 Internal Server Error</h1>", 500
return utils.page_500 (TRANSLATIONS, render_main_menu('hedy'), current_user(request) ['username'], requested_lang ())

@app.route('/index.html')
@app.route('/')
Expand Down
9 changes: 9 additions & 0 deletions coursedata/texts/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ ui:
commands_title: "Commands"
by: "by"
start_quiz: "Start quiz"
default_404: "We could not find that page..."
default_500: "Something went wrong..."
go_back_to_main: "Go back to the main page"
no_such_level: "No such Hedy level!"
no_such_class: "No such Hedy class!"
invalid_class_link: "Invalid link for joining the class"
no_such_adventure: "No such Hedy adventure!"
no_such_adventure_level: "No such level for this Hedy adventure!"
no_such_program: "No such Hedy program!"
ClientErrorMessages:
Transpile_warning: "Warning!"
Transpile_error: "We can't run your program."
Expand Down
2 changes: 1 addition & 1 deletion hedyweb.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def get_translations(self, language, section):
def render_code_editor_with_tabs(request, level_defaults, lang, max_level, level_number, menu, translations, version, loaded_program, adventures, adventure_name):

if not level_defaults:
abort(404)
return utils.page_404 (translations, menu, current_user(request) ['username'], lang, translations.get_translations (lang, 'ui').get ('no_such_level'))


arguments_dict = {}
Expand Down
Binary file added static/images/404.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/images/500.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions templates/404.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{% extends "layout.html" %}

{% block body %}
<div class="w-full text-center"><img class="inline-block" src="/images/404.jpeg" style="width: 40%;"></div>
<div class="w-full text-center"><p class="text-lg font-bold">{{page_error or ui.default_404}}</p></div>
<div class="w-full text-center mt-8"><button class="green-btn" style="width: 40%;" onclick="window.location.href = '{{localize_link ('/')}}'">{{ui.go_back_to_main}}</button></div>
{% endblock %}
7 changes: 7 additions & 0 deletions templates/500.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{% extends "layout.html" %}

{% block body %}
<div class="w-full text-center"><img class="inline-block" src="/images/500.jpeg" style="width: 40%;"></div>
<div class="w-full text-center"><p class="text-lg font-bold">{{page_error or ui.default_500}}</p></div>
<div class="w-full text-center mt-8"><button class="green-btn" style="width: 40%;" onclick="window.location.href = '{{localize_link ('/')}}'">{{ui.go_back_to_main}}</button></div>
{% endblock %}
11 changes: 11 additions & 0 deletions utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
commonmark_parser = commonmark.Parser ()
commonmark_renderer = commonmark.HtmlRenderer ()
from bs4 import BeautifulSoup
from flask_helpers import render_template

IS_WINDOWS = os.name == 'nt'

Expand Down Expand Up @@ -177,3 +178,13 @@ def markdown_to_html_tags (markdown):
_html = commonmark_renderer.render(commonmark_parser.parse (markdown))
soup = BeautifulSoup(_html, 'html.parser')
return soup.find_all ()

def page_404 (translations, menu, lang, username, *page_error):
if page_error:
page_error = page_error [0]
return render_template("404.html", menu=menu, username=username, auth=translations.get_translations(lang, 'Auth'), ui=translations.get_translations(lang, 'ui'), page_error=page_error or ''), 404

def page_500 (translations, menu, lang, username, *page_error):
if page_error:
page_error = page_error [0]
return render_template("500.html", menu=menu, username=username, auth=translations.get_translations(lang, 'Auth'), ui=translations.get_translations(lang, 'ui'), page_error=page_error or ''), 500
8 changes: 4 additions & 4 deletions website/teacher.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def get_class (user, class_id):
return 'Only teachers can retrieve classes', 403
Class = DATABASE.get_class (class_id)
if not Class or Class ['teacher'] != user ['username']:
return 'No such class', 404
return utils.page_404 (TRANSLATIONS, render_main_menu('my-profile'), current_user(request) ['username'], requested_lang (), TRANSLATIONS.get_translations (requested_lang (), 'ui').get ('no_such_class'))
students = []
for student_username in Class.get ('students', []):
student = DATABASE.user_by_username (student_username)
Expand Down Expand Up @@ -108,7 +108,7 @@ def delete_class (user, class_id):
def prejoin_class (class_id, link):
Class = DATABASE.get_class (class_id)
if not Class or Class ['link'] != link:
return 'No such class', 404
return utils.page_404 (TRANSLATIONS, render_main_menu('my-profile'), current_user(request) ['username'], requested_lang (), TRANSLATIONS.get_translations (requested_lang (), 'ui').get ('invalid_class_link'))
user = {}
if request.cookies.get (cookie_name):
token = DATABASE.get_token(request.cookies.get (cookie_name))
Expand All @@ -124,7 +124,7 @@ def prejoin_class (class_id, link):
def join_class (user, class_id, link):
Class = DATABASE.get_class (class_id)
if not Class or Class ['link'] != link:
return 'No such class', 404
return utils.page_404 (TRANSLATIONS, render_main_menu('my-profile'), current_user(request) ['username'], requested_lang (), TRANSLATIONS.get_translations (requested_lang (), 'ui').get ('invalid_class_link'))

DATABASE.add_student_to_class (Class ['id'], user ['username'])

Expand All @@ -146,5 +146,5 @@ def leave_class (user, class_id, student_id):
def resolve_class_link (link_id):
Class = DATABASE.resolve_class_link (link_id)
if not Class:
return 'Invalid link', 404
return utils.page_404 (TRANSLATIONS, render_main_menu('my-profile'), current_user(request) ['username'], requested_lang (), TRANSLATIONS.get_translations (requested_lang (), 'ui').get ('invalid_class_link'))
return redirect(request.url.replace('/hedy/l/' + link_id, '/class/' + Class ['id'] + '/prejoin/' + link_id), code=302)

0 comments on commit 2d82964

Please sign in to comment.