Beispiel #1
0
def login(request: _Parsed):
    json = request.json
    get = json.get
    user = get("user", "").strip().lower()
    password = get("password", "")
    invalids = []
    if not user:
        invalids.append("username")
    if not password:
        invalids.append("password")
    if invalids:
        raise AppException(f"Invalid {' and '.join(invalids)}",
                           HTTPStatus.UNPROCESSABLE_ENTITY)
    user_data = get_user_by_id(user)
    password_hash = user_data.password_hash
    if not check_password_hash(password_hash, password):
        raise AppException("Incorrect Password", HTTPStatus.FORBIDDEN)
    username = user_data.user
    is_admin = user_data.is_admin
    access_token = create_token(issue_access_token(username, is_admin))
    refresh_token = create_token(issue_refresh_token(username, password_hash))

    return json_response(
        {
            "success": True,
            "user_data": user_data.as_json
        },
        headers={
            "x-access-token": access_token,
            "x-refresh-token": refresh_token
        },
    )
Beispiel #2
0
def assert_hunt_running(event):
    ev = get_event_details(event)
    curr_time = time()
    has_not_started = ev["event_start_time"] > curr_time
    is_over = ev["is_over"] or ev["event_end_time"] < curr_time
    if is_over:
        raise AppException("Hunt is over", HTTPStatus.FORBIDDEN)
    if has_not_started:
        raise AppException("Hunt hasn't started yet..", HTTPStatus.FORBIDDEN)
Beispiel #3
0
def check_integrity_error(e):
    # pylint: disable=E1101
    orig = getattr(e, "orig", None)
    if isinstance(orig, UniqueViolation):
        args = orig.args[0]
        ret = get_integrity_error_cause(args)
        if ret is None:
            raise AppException("User exists", HTTPStatus.BAD_REQUEST)
        k, v = ret
        raise AppException(f'Another account exists with the {k} "{v}"')
    raise e
Beispiel #4
0
    def _validate_question_content(self, key, val):
        prefix = f"Error on question {self._id}:"
        if not isinstance(val, dict):
            raise AppException(
                f"{prefix} Please send a JSON object for the question")

        t = val.get("type", "text")
        if t not in ("text", "link", "image-embed"):
            raise AppException(f"{prefix} invalid question content type")
        if not val.get("content"):
            raise AppException(f"{prefix} Question content cannot be blank!")
        return {"type": val["type"], "content": val["content"]}
Beispiel #5
0
    def _handle_permissions(self, visibility):
        if visibility not in PERMISSION:
            raise AppException(EVENTS.REQUEST_EXCEPTION, 422,
                               (EXCODES.WRONG_VALUE,
                                STRINGS.PERMISSION_WRONG_VALUE, 'visibility'))

        if visibility < self._visibility:
            raise AppException(
                EVENTS.REQUEST_EXCEPTION, 422,
                (EXCODES.WRONG_VALUE, STRINGS.PERMISSION_SMALLER_VALUE,
                 'visibility'))

        self._visibility = visibility
Beispiel #6
0
def confirm_email(req: _Parsed):
    token = req.json.get("token")
    data = decode_token(token)
    if data is None:
        raise AppException("Token expired", HTTPStatus.UNAUTHORIZED)
    if data["token_type"] == EMAIL_CONF_TOKEN:
        user = data["user"]
        u = get_user_by_id(user)
        if u.has_verified_email:
            return {"success": True}
        u.has_verified_email = True
        save_to_db()
        return {"success": True}

    raise AppException("Invalid token", HTTPStatus.BAD_REQUEST)
Beispiel #7
0
def delete(user, creds: CredManager = CredManager):
    user_data = get_user_by_id(user)
    if user_data.is_admin:
        raise AppException("Cannot delete an admin account!")
    delete_from_db(user_data)
    send_admin_action_webhook([f"{user} was deleted by {creds.user}"])
    return {"success": True}
Beispiel #8
0
def answer(req: ParsedRequest, event, creds: CredManager = CredManager):
    # assert_hunt_running(event)
    js = req.json
    answer = sanitize(js.get("answer", ""))
    # don't even bother if the user is trying an absurdly large answer
    if len(answer) > 50 or not answer:
        return {"is_correct": False}
    user = get_user_by_id(creds.user)
    if user.event != event:
        raise AppException("Not your event..")
    if user.is_disqualified:
        return {"disqualified": True, "reason": user.disqualification_reason}
    try:
        try:
            q = get_question(event, user.level)
        except AppException:
            return {"game_over": True}
        is_correct = sanitize(q["_secure_"]["answer"]) == answer
        log_answer(user.user, q["question_number"], js["answer"], is_correct)
        if is_correct:
            user.level += 1
            user.points += q["question_points"]
            user.last_question_answered_at = time()
            save_to_db()
            return invalidate(f"{event}-leaderboard", {"is_correct": is_correct})
        return {"is_correct": is_correct}

    except Exception as e:
        print(e)
        raise Exception("An unknown error occured")
Beispiel #9
0
def register(request: _Parsed):
    json = request.json
    get = json.get
    user = get("user")
    name = get("name")
    email = get("email")
    institution = get("institution")
    password = get("password")
    event = get("event")
    if event == "intra":
        raise AppException("Inta is over..see you in the main event")
    try:
        user_data = User(
            user=user,
            name=name,
            email=email,
            institution=institution,
            password=password,
            event=event,
        )
        js = user_data.as_json
        add_to_db(user_data)
        send_acount_creation_webhook(user, name, event)
        return invalidate(f"{event}-leaderboard", js)
    except Exception as e:
        check_integrity_error(e)
Beispiel #10
0
def disqualify(req: ParsedRequest, user, *, creds: CredManager = CredManager):
    json = req.json
    reason = json.get("reason")
    deduct_points = json.get("points")
    if deduct_points < 0:
        raise AppException("You're adding points! Don't use negative symbol")
    user_data = get_user_by_id(user)
    if user_data.is_admin:
        raise AppException("Cannot disqualify an admin!")
    user_data.is_disqualified = True
    user_data.disqualification_reason = reason
    user_data.points -= deduct_points
    js = user_data.as_json
    send_admin_action_webhook([f"{user} was disqualified by {creds.user}"])
    save_to_db()
    return invalidate(f"{user_data.event}-leaderboard", js)
Beispiel #11
0
def verify_password_reset(req: _Parsed, user_name: str):
    token = req.json.get("token")
    new_password = req.json.get("new_password")
    data = decode_token(token)

    if data is None:
        raise AppException("Token expired", HTTPStatus.UNAUTHORIZED)
    if data["token_type"] == RESET_PASSWORD_TOKEN:
        user = data["user"]
        if user != user_name.lower():
            raise AppException("Lol")
        u = get_user_by_id(user)
        state = data["state"]
        if not check_password_hash(state, f"{u.user}{u.password_hash}"):
            raise AppException("Token expired", HTTPStatus.UNAUTHORIZED)
        u.password_hash = new_password
        save_to_db()
        return {"success": True}

    raise AppException("Invalid token", HTTPStatus.BAD_REQUEST)
Beispiel #12
0
 def __init__(
     self,
     question_number: int = None,
     question_points: int = None,
     event: str = None,
     question_content: dict = None,
     question_hints: list = None,
     answer: str = None,
 ):
     raise_if_invalid_data(question_points, event, question_content, answer)
     if question_number < 0 or question_points < 1:
         raise AppException("Invalid question number/points")
     if event not in EVENT_NAMES:
         raise AppException("Invalid event value")
     self._id = f"{event}:{question_number}"
     self.question_number = question_number
     self.question_points = question_points
     self.event = event
     self.question_content = question_content
     self.question_hints = question_hints
     self.answer = answer
Beispiel #13
0
def edit(request: _Parsed, user: str, creds: CredManager = CredManager):
    current_user = creds.user
    if user != current_user and not creds.is_admin:
        raise AppException("Cannot edit ( not allowed )", HTTPStatus.FORBIDDEN)

    json = request.json
    keys = json.keys()

    if any(x not in editable_fields for x in keys) and not creds.is_admin:
        raise AppException("Requested field cannot be edited",
                           HTTPStatus.BAD_REQUEST)

    user_data = get_user_by_id(user)
    text = []
    who = creds.user
    did_change = False
    for k, v in json.items():
        prev = getattr(user_data, k, "N/A")
        if prev == v:
            continue
        did_change = True
        setattr(user_data, k, v)
        if creds.is_admin:
            text.append(
                f"{who} changed {k} of `{user}` from `{prev}` to `{v}`")

        if k == "email":
            user_data.has_verified_email = False
    event = user_data.event
    js = user_data.as_json
    try:
        save_to_db()
    except Exception as e:
        check_integrity_error(e)

    if creds.is_admin and text:
        send_admin_action_webhook(text)
    if did_change:
        return invalidate(f"{event}-leaderboard", js)
    return js
Beispiel #14
0
 def _validate_user(self, _, user: str):
     if not user:
         raise AppException("Username cannot be blank",
                            HTTPStatus.UNPROCESSABLE_ENTITY)
     user = user.strip()
     length = len(user)
     if length > 30:
         raise AppException(
             "Username cannot be longer than 30 characters",
             HTTPStatus.UNPROCESSABLE_ENTITY,
         )
     if length < 3:
         raise AppException(
             "Username cannot be shorter than 3 characters",
             HTTPStatus.UNPROCESSABLE_ENTITY,
         )
     if sanitize(user) != user:
         raise AppException(
             "Username cannot have special characters or whitespace",
             HTTPStatus.UNPROCESSABLE_ENTITY,
         )
     return user
Beispiel #15
0
def get_user_details(user: str, creds: CredManager = CredManager):
    current_user = creds.user
    if user == "me" or current_user == user.lower():
        if current_user is not None:
            return self_details(creds)
        raise AppException("Not Authenticated", HTTPStatus.UNAUTHORIZED)

    user_details = get_user_by_id(user)
    if not creds.is_admin:
        json = clean_secure(user_details)
    else:
        json = user_details.as_json
    return {"user_data": json}
Beispiel #16
0
def question(event, creds: CredManager = CredManager):
    # assert_hunt_running(event)
    user = get_user_by_id(creds.user)
    if user.event != event:
        raise AppException("Not your event..")
    if user.is_disqualified:
        return {"disqualified": True, "reason": user.disqualification_reason}
    try:
        try:
            q = get_question(event, user.level)
        except AppException:
            return {"game_over": True}
        q.pop("_secure_")
        return q
    except:
        raise Exception("Unknown error occured")
Beispiel #17
0
def re_authenticate(req: _Parsed):
    headers = req.headers
    access_token = get_bearer_token(req.headers)
    decoded_access = decode_token(access_token)

    if decoded_access is None:
        refresh_token = headers.get("x-refresh-token")
        decoded_refresh = decode_token(refresh_token)
        access, refresh = regenerate_access_token(decoded_refresh)
        if access is None:
            raise AppException("re-auth", HTTPStatus.FORBIDDEN)

        return json_response(
            {},
            headers={
                "x-access-token": create_token(access),
                "x-refresh-token": create_token(refresh),
            },
        )
Beispiel #18
0
def send_password_reset_email(req: _Parsed, user):
    handler = get_subdomain(req.json.get("handler"))

    user_data = get_user_by_id(user)
    token = create_token(
        issue_password_reset_token(user_data.user, user_data.password_hash))
    qs = urlencode({"token": token, "user": user})
    url = f"https://{handler}.halocrypt.com/-/reset-password?{qs}"

    if not user:
        raise AppException("Invalid request")
    send_email(
        user_data.email,
        "Reset password",
        EMAIL_TEMPLATE.replace(r"{url}", url).replace(
            r"{message}",
            "Our records indicate that you have requested a password reset. You can do so by clicking the button below",
        ).replace(r"{action}", "Reset Password"),
        f"Reset your password here: {url}",
    )
    return {"success": True}
Beispiel #19
0
def get_subdomain(handler):
    if handler not in EVENT_NAMES:
        raise AppException("Invalid handler")
    return "www" if handler == "main" else handler
Beispiel #20
0
def raise_if_invalid_data(*args):
    if any(not x or not ((x).strip() if isinstance(x, str) else True) for x in args):
        raise AppException("Invalid Input")
Beispiel #21
0
 def _validate_email(self, _, email: str):
     email = email.strip() if email else None
     if not email:
         raise AppException("Email cannot be blank")
     return validate_email_address(email)
Beispiel #22
0
 def _validate_password(self, _, password: str):
     length = len(password)
     if length < 4:
         raise AppException("Password cannot be shorter than 4 characters")
     return generate_password_hash(password)
Beispiel #23
0
 def _validate_name(self, _, name: str):
     name = (name or "").strip()
     if not name:
         raise AppException("name cannot be blank")
     return name
Beispiel #24
0
 def _validate_event(self, _, event: str):
     if event not in EVENT_NAMES:
         raise AppException("Invalid event")
     return event
Beispiel #25
0
 def _validate_question_points(self, key, val):
     num = validate_num(val)
     if num <= 0:
         raise AppException("Points should be greater than 0")
     return num