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

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions CodeChallenge/api/questions.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def json_error(reason, status=400):
def end_code_challenge():
if core.challenge_ended():
r = jsonify(status="error",
message="code challenge has ended")
reason="code challenge has ended")
r.status_code = 403
abort(r)

Expand Down Expand Up @@ -84,7 +84,7 @@ def next_question():


def answer_limit_attempts():
return current_app.config.get("ANSWER_ATTEMPT_LIMIT", "3 per 30 minutes")
return current_app.config.get("ANSWER_ATTEMPT_LIMIT", "1 per 1 minutes")


@bp.route("/answer", methods=["POST"])
Expand Down Expand Up @@ -163,10 +163,10 @@ def reset_all():

db.session.commit()

return jsonify(status="success", message="all answers and rank reset")
return jsonify(status="success", reason="all answers and rank reset")

return jsonify(status="error",
message="resetting not allowed at this time"), 403
reason="resetting not allowed at this time"), 403


@bp.route("/final", methods=["POST"])
Expand Down
12 changes: 9 additions & 3 deletions CodeChallenge/cli/questions.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,21 @@
@click.argument("answer")
@click.argument("rank")
@click.argument("asset")
def q_add(title, answer, rank, asset):
@click.argument("hint1")
@click.argument("hint2")
def q_add(title, answer, rank, asset, hint1, hint2):
"""Add a new question to the database

TITLE is the text for the title of the question
ANSWER is the answer stored only in the database
RANK is the day rank the queestion should be revealed on
ASSET is a path to a file to upload for a question
HINT1 is a hint string
HINT2 is a hint string
"""

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

click.echo(f"added question id {qid}")

Expand Down Expand Up @@ -66,7 +70,9 @@ def q_del(qid):
@click.argument("answer")
@click.argument("rank")
@click.argument("asset")
def q_replace(title, answer, rank, asset):
@click.argument("hint1")
@click.argument("hint2")
def q_replace(title, answer, rank, asset, hint1, hint2):
"""Replace an existing rank's question.

This basically deletes the previous rank then adds the new rank
Expand Down
4 changes: 3 additions & 1 deletion CodeChallenge/manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from .models import Question, db


def add_question(title, answer, rank, asset) -> Question:
def add_question(title, answer, rank, asset, hint1=None, hint2=None) -> Question:

q = Question.query.filter_by(rank=rank).first()

Expand All @@ -19,6 +19,8 @@ def add_question(title, answer, rank, asset) -> Question:

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

db.session.add(q)
db.session.commit()
Expand Down
8 changes: 8 additions & 0 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"moment": "^2.24.0",
"serialize-javascript": "^2.1.2",
"vue": "^2.6.10",
"vue-codemirror": "^4.0.6",
"vue-moment": "^4.1.0",
"vue-router": "^3.1.3",
"vue-the-mask": "^0.11.1",
Expand All @@ -33,6 +34,7 @@
"prettier": "^1.18.2",
"sass": "^1.19.0",
"sass-loader": "^8.0.0",
"vue-cli-plugin-codemirror": "^0.0.6",
"vue-cli-plugin-vuetify": "^2.0.2",
"vue-template-compiler": "^2.6.10",
"vuetify-loader": "^1.3.0"
Expand Down
18 changes: 17 additions & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,23 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
<link rel='shortcut icon' type='image/x-icon' href='/favicon.ico' />
<link rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192" href="/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">
<title>CodeWizardsHQ CODE CHALLENGE</title>
</head>

Expand Down
17 changes: 15 additions & 2 deletions src/api/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ async function createAccount(data) {
await login(data.username, data.password, false);
}

async function requestPasswordReset(email) {
await request(routes.userapi_forgot, { data: { email } });
}

async function fetchState() {
const userData = await request(routes.userapi_hello, {}, state.auth);
await setState({
Expand Down Expand Up @@ -75,11 +79,19 @@ function currentUser() {
}

async function forgotPassword(email) {
return await request(routes.userapi_forgot_password, { data: { email } }, false);
return await request(
routes.userapi_forgot_password,
{ data: { email } },
false
);
}

async function resetPassword(token, password) {
return await request(routes.userapi_reset_password, { data: { token, password } }, false)
return await request(
routes.userapi_reset_password,
{ data: { token, password } },
false
);
}

export default {
Expand All @@ -89,6 +101,7 @@ export default {
fetchState,
createAccount,
currentUser,
requestPasswordReset,
onAuthStateChange,
offAuthStateChange,
forgotPassword,
Expand Down
14 changes: 13 additions & 1 deletion src/api/quiz.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ async function getQuestion() {
}

async function getRank() {
return (await request(routes.questionsapi_get_rank)).rank;
return request(routes.questionsapi_get_rank);
}

async function resetRank() {
Expand All @@ -22,9 +22,21 @@ async function submit(answer) {
return result.correct;
}

async function submitFinal(answer, language, checkOnly) {
const result = await request(routes.questionsapi_answer_final_question, {
data: {
checkOnly,
text: answer,
language
}
});
return result;
}

export default {
getQuestion,
submit,
submitFinal,
getRank,
resetRank
};
38 changes: 24 additions & 14 deletions src/api/request.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,42 @@
import axios from "axios";
import routes from "./routes";
// import routes from "./routes";

export default async function request(route, options = {}, tryRefresh = true) {
export default async function request(route, options = {}, _tryRefresh = true) {
if (_tryRefresh) {
// satisfy linter
}
try {
// attempt initial request and return great response
const response = await axios({
method: route.type,
url: route.path,
...options
});
return response.data;
} catch (err) {
if (err.response.status == 401 && tryRefresh) {
// our tokens have possibly expired, send refresh
// TODO: THIS IS UNFINISHED
await axios({
method: "POST",
url: routes.userapi_refresh.path
});

// try and return original request marked with no refresh
return request(route, options, false);
}
return {
...response.data,
headers: response.headers
};
} catch (err) {
// console.log(err.response);
// if (err.response.status == 401 && tryRefresh) {
// console.log("Trying refresh");
// // our tokens have possibly expired, send refresh
// // TODO: THIS IS UNFINISHED
// await axios({
// method: "POST",
// url: routes.userapi_refresh.path
// });

// // try and return original request marked with no refresh
// return request(route, options, false);
// }
// return original error
// console.log()
return Promise.reject({
status: err.response.status,
headers: err.response.headers,
data: err.response.data,
message:
!!err.response.data && !!err.response.data.reason
? err.response.data.reason
Expand Down
4 changes: 3 additions & 1 deletion src/api/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ export default {
userapi_login: route("/api/v1/users/token/auth", "POST"),
userapi_logout: route("/api/v1/users/token/remove", "POST"),
userapi_hello: route("/api/v1/users/hello", "GET"),
userapi_forgot: route("/api/v1/users/forgot", "POST"),
userapi_refresh: route("/api/v1/users/token/refresh", "POST"),
userapi_forgot_password: route("/api/v1/users/forgot", "POST"),
userapi_reset_password: route("/api/v1/users/reset-password", "POST"),
questionsapi_rank_reset: route("/api/v1/questions/reset", "DELETE"),
questionsapi_answer_next_question: route("/api/v1/questions/answer", "POST"),
questionsapi_answer_final_question: route("/api/v1/questions/final", "POST"),
questionsapi_get_rank: route("/api/v1/questions/rank", "GET"),
questions_api_next_question: route("/api/v1/questions/next", "GET"),
questions_api_next_question: route("/api/v1/questions/next", "GET")
};

// export default {
Expand Down
Loading