Skip to content
This repository was archived by the owner on Dec 8, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CodeChallenge/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def send_landing(path):
def catch_all(path):

# show landing page
if core.current_rank() == -1 and not path or path == "home":
if core.current_rank() == -1 and (not path or path == "home"):
return redirect("/landing")

return send_from_directory(app.config["DIST_DIR"], "index.html")
Expand Down
15 changes: 14 additions & 1 deletion CodeChallenge/api/questions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os
from hashlib import blake2s
from hmac import compare_digest as str_cmp

from flask import Blueprint, current_app, jsonify, request
Expand Down Expand Up @@ -52,10 +54,21 @@ def next_question():
return jsonify(status="error",
reason=f"no questions for rank {rank!r}"), 404

# make filename less predictable
data = bytes(current_app.config["SECRET_KEY"] + str(q.rank), "ascii")
filename = blake2s(data).hexdigest()

asset = f"assets/{filename}{q.asset_ext}"
asset_path = os.path.join(current_app.config["APP_DIR"], asset)

if not os.path.isfile(asset_path):
with open(asset_path, "wb") as fhandle:
fhandle.write(q.asset)

return jsonify(status="success",
question=q.title,
rank=rank,
asset=f"assets/{q.asset}"), 200
asset=asset), 200


def answer_limit_attempts():
Expand Down
11 changes: 7 additions & 4 deletions CodeChallenge/cli/questions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os.path

import click
from flask import Blueprint
from tabulate import tabulate
Expand All @@ -22,6 +24,7 @@ def q_add(title, answer, rank, asset):
ASSET is a path to a file to upload for a question
"""

asset = os.path.abspath(asset)
qid = add_question(title, answer, rank, asset)

click.echo(f"added question id {qid}")
Expand All @@ -33,11 +36,11 @@ def q_ls(tablefmt):
"""List all questions in the database"""
table = []

for q in Question.query.all():
table.append((q.id, q.title, q.answer, q.rank, q.asset))
for q in Question.query.all(): # type: Question
table.append((q.id, q.title, q.answer, q.rank, f"{len(q.asset)} length blob", q.asset_ext))

click.echo(tabulate(table,
("id", "title", "answer", "rank", "asset"),
("id", "title", "answer", "rank", "asset", "asset_ext"),
tablefmt=tablefmt))

if not table:
Expand Down Expand Up @@ -71,7 +74,7 @@ def q_replace(title, answer, rank, asset):
success = del_question(oldq.id)

if not success:
print("error occured while trying to delete original question")
print("error occurred while trying to delete original question")
print(f"old question id was: {oldq.id}")
return
else:
Expand Down
1 change: 1 addition & 0 deletions CodeChallenge/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class ProductionConfig(DefaultConfig):
class DevelopmentConfig(ProductionConfig):
SQLALCHEMY_DATABASE_URI = "mysql://cc-user:password@localhost" \
"/code_challenge_local"
# SQLALCHEMY_DATABASE_URI = "mysql+mysqldb://codechallenge:cHALcw9Z0HqB2gD9B1Kkmy83GvTI19x0NzRNO3zqZhqbIKqY9P@learndb002.cm1f2l4z67tv.us-west-2.rds.amazonaws.com/code_challenge"
JWT_COOKIE_SECURE = False
CODE_CHALLENGE_START = os.getenv("CODE_CHALLENGE_START", "1578596347")
JWT_SECRET_KEY = "SuperSecret"
Expand Down
30 changes: 5 additions & 25 deletions CodeChallenge/manage.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import os
import secrets
import shutil

from flask import current_app

from .models import Question, db

Expand All @@ -14,19 +10,14 @@ def add_question(title, answer, rank, asset) -> Question:
if q is not None:
raise ValueError(f"a question with rank {rank} already exists")

ext = os.path.splitext(asset)[1]
asset_dir = os.path.join(current_app.config["APP_DIR"], "assets")

filename = secrets.token_urlsafe() + ext

save_path = os.path.join(asset_dir, filename)

shutil.copyfile(asset, save_path)

q = Question()
q.title = title
q.answer = answer
q.asset = filename

with open(asset, "rb") as fhandle:
q.asset = fhandle.read()

q.asset_ext = os.path.splitext(asset)[1]
q.rank = rank

db.session.add(q)
Expand All @@ -42,17 +33,6 @@ def del_question(question_id):
if q is None:
return False

if q.asset is not None:

asset_dir = os.path.join(current_app.config["APP_DIR"], "assets")
filename = os.path.join(asset_dir, q.asset)
try:
os.remove(filename)
except FileNotFoundError:
print("warning: could not delete asset; "
f"file not found: {filename}")
pass

Question.query.filter_by(id=q.id).delete()

return True
3 changes: 2 additions & 1 deletion CodeChallenge/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ class Question(db.Model):
title = db.Column(db.String(5000), nullable=False)
answer = db.Column(db.String(255), nullable=False)
rank = db.Column(db.Integer, nullable=False)
asset = db.Column(db.String(255))
asset = db.Column(db.BLOB)
asset_ext = db.Column(db.String(10))

def __repr__(self):
return '<Question %r>' % self.id
Expand Down
85 changes: 0 additions & 85 deletions alembic.ini

This file was deleted.