219 lines
6.7 KiB
Python
219 lines
6.7 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
|
|
from authlib.integrations.flask_client import OAuth
|
|
from flask import flash
|
|
from flask import Flask
|
|
from flask import jsonify
|
|
from flask import redirect
|
|
from flask import render_template
|
|
from flask import request
|
|
from flask import session
|
|
from flask import url_for
|
|
from flask_security import current_user
|
|
from flask_security import login_user
|
|
from flask_security import logout_user
|
|
from flask_security import Security
|
|
from flask_security import SQLAlchemySessionUserDatastore
|
|
|
|
from QuizTheWord import database
|
|
from QuizTheWord.admin import admin
|
|
|
|
|
|
app = Flask(__name__)
|
|
environment_configuration = os.environ.get('CONFIGURATION_SETUP', "QuizTheWord.config.Development")
|
|
with app.app_context():
|
|
app.config.from_object(environment_configuration)
|
|
user_datastore = SQLAlchemySessionUserDatastore(database.get_session(), database.User, database.Role)
|
|
security = Security(app, user_datastore, False)
|
|
CONF_URL = "https://accounts.google.com/.well-known/openid-configuration"
|
|
oauth = OAuth(app)
|
|
oauth.register(
|
|
name="google",
|
|
server_metadata_url=CONF_URL,
|
|
client_kwargs={
|
|
"scope": "openid email profile",
|
|
},
|
|
)
|
|
app.register_blueprint(admin.Admin)
|
|
|
|
|
|
@app.context_processor
|
|
def func():
|
|
if current_user.is_authenticated:
|
|
data = {
|
|
"user_authenticated": True,
|
|
"has_admin_access": current_user.has_permission("admin_site_access"),
|
|
"is_admin": current_user.has_role("admin"),
|
|
}
|
|
else:
|
|
data = {
|
|
"user_authenticated": False,
|
|
"has_admin_access": False,
|
|
"is_admin": False,
|
|
}
|
|
return data
|
|
|
|
|
|
@app.route("/")
|
|
def index():
|
|
return multiple_choice_category()
|
|
|
|
|
|
@app.route("/category/hidden_answer")
|
|
def hidden_answer_category():
|
|
easy = database.get_random_hidden_answer(1)
|
|
medium = database.get_random_hidden_answer(2)
|
|
hard = database.get_random_hidden_answer(3)
|
|
return render_template(
|
|
"hidden_answer.html",
|
|
title="Hidden Answer",
|
|
easy=easy,
|
|
medium=medium,
|
|
hard=hard,
|
|
)
|
|
|
|
|
|
@app.route("/category/multiple_choice")
|
|
def multiple_choice_category():
|
|
easy = database.get_random_multiple_choice(1)
|
|
medium = database.get_random_multiple_choice(2)
|
|
hard = database.get_random_multiple_choice(3)
|
|
return render_template(
|
|
"multiple_choice.html",
|
|
title="Multiple Choice",
|
|
easy=easy,
|
|
medium=medium,
|
|
hard=hard,
|
|
)
|
|
|
|
|
|
@app.route("/category/multiple_choice/check_answer", methods=["GET"])
|
|
def check_answer():
|
|
question_id = request.args.get("question_id", type=int)
|
|
answer = request.args.get("answer", type=str)
|
|
if question_id is not None and answer is not None:
|
|
return jsonify(database.check_answer(question_id, answer))
|
|
|
|
|
|
@app.route("/category/hidden_answer/next_question")
|
|
def next_hidden_answer():
|
|
if "hidden_answer_ids" not in session:
|
|
session["hidden_answer_ids"] = []
|
|
difficulty = request.args.get("difficulty", 1, int)
|
|
next_question = database.next_hidden_answer(session["hidden_answer_ids"], difficulty)
|
|
if next_question:
|
|
session["hidden_answer_ids"].append(next_question.question_id)
|
|
session.modified = True
|
|
return jsonify(next_question.get_dict())
|
|
else:
|
|
session.pop("hidden_answer_ids", None)
|
|
return jsonify(None), 204
|
|
|
|
|
|
@app.route("/category/multiple_choice/next_question")
|
|
def next_multiple_choice():
|
|
if "multiple_choice_ids" not in session:
|
|
session["multiple_choice_ids"] = []
|
|
difficulty = request.args.get("difficulty", 1, int)
|
|
next_question = database.next_multiple_choice(session["multiple_choice_ids"], difficulty)
|
|
if next_question:
|
|
session["multiple_choice_ids"].append(next_question.question_id)
|
|
session.modified = True
|
|
return jsonify(next_question.get_dict_shuffled_choices())
|
|
else:
|
|
session.pop("multiple_choice_ids", None)
|
|
return jsonify(None), 204
|
|
|
|
|
|
def get_auth_url(redirect_uri, **kwargs):
|
|
rv = oauth.google.create_authorization_url(redirect_uri, **kwargs)
|
|
|
|
if oauth.google.request_token_url:
|
|
request_token = rv.pop('request_token', None)
|
|
oauth.google._save_request_token(request_token)
|
|
|
|
oauth.google.save_authorize_data(request, redirect_uri=redirect_uri, **rv)
|
|
return rv["url"]
|
|
|
|
|
|
@app.route("/login", methods=["GET", "POST"])
|
|
def login():
|
|
redirect_uri = url_for("auth_google", _external=True)
|
|
google_url = get_auth_url(redirect_uri)
|
|
|
|
next_page = request.args.get("next", default=url_for("index"))
|
|
if request.method == "POST":
|
|
email = request.form.get("email")
|
|
password = request.form.get("password")
|
|
remember = request.args.get("remember")
|
|
user = user_datastore.find_user(email=email)
|
|
if user is None or not user.check_password(password):
|
|
flash("invalid email or password")
|
|
return redirect(url_for("login"))
|
|
login_user(user, remember=remember)
|
|
return redirect(next_page)
|
|
return render_template("login.html", title="login", google_url=google_url)
|
|
|
|
|
|
@app.route("/login/auth/google")
|
|
def auth_google():
|
|
token = oauth.google.authorize_access_token()
|
|
user = oauth.google.parse_id_token(token)
|
|
unique_id = user["sub"]
|
|
email = user["email"]
|
|
username = user["given_name"]
|
|
user = database.get_user(google_id=unique_id)
|
|
if user is not None:
|
|
login_user(user)
|
|
else:
|
|
user = database.add_user(email, None, username, google_id=unique_id)
|
|
if user is not None:
|
|
login_user(user)
|
|
else:
|
|
flash("That email is already in use. Login with that email or choose a different account.")
|
|
return redirect(url_for("login"))
|
|
return redirect(url_for("index"))
|
|
|
|
|
|
@app.route("/register", methods=["GET", "POST"])
|
|
def register():
|
|
if request.method == "POST":
|
|
email = request.form.get("email")
|
|
password = request.form.get("password")
|
|
user = database.add_user(email, password)
|
|
if user is None:
|
|
flash("email already in use")
|
|
return redirect(url_for("register"))
|
|
login_user(user)
|
|
return redirect(url_for("index"))
|
|
return render_template("register.html")
|
|
|
|
|
|
@app.route("/logout")
|
|
def logout():
|
|
logout_user()
|
|
return redirect(url_for("index"))
|
|
|
|
|
|
@app.errorhandler(404)
|
|
def error_404(e):
|
|
print(e)
|
|
return render_template("error.html", error_msg="The requested page can not be found.", error_code=404), 404
|
|
|
|
|
|
@app.errorhandler(500)
|
|
def error_500(e):
|
|
print(e)
|
|
msg = "There was an error with the server."
|
|
if app.config["DEBUG"]:
|
|
msg = e
|
|
return render_template("error.html", error_msg=msg, error_code=500), 500
|
|
|
|
|
|
if __name__ == "__main__":
|
|
with app.app_context():
|
|
database.init_db()
|
|
app.run()
|