fix: require passreset's target user is unsuspended

Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
Kevin Morris 2022-02-03 19:05:01 -08:00
parent ef0285bc7c
commit 9111f645b7
No known key found for this signature in database
GPG key ID: F7E46DED420788F3
2 changed files with 24 additions and 11 deletions

View file

@ -43,18 +43,19 @@ async def passreset_post(request: Request,
context = await make_variable_context(request, "Password Reset")
# The user parameter being required, we can match against
user = db.query(models.User, or_(models.User.Username == user,
models.User.Email == user)).first()
if not user:
criteria = or_(models.User.Username == user, models.User.Email == user)
db_user = db.query(models.User,
and_(criteria, models.User.Suspended == 0)).first()
if db_user is None:
context["errors"] = ["Invalid e-mail."]
return render_template(request, "passreset.html", context,
status_code=HTTPStatus.NOT_FOUND)
db.refresh(user)
db.refresh(db_user)
if resetkey:
context["resetkey"] = resetkey
if not user.ResetKey or resetkey != user.ResetKey:
if not db_user.ResetKey or resetkey != db_user.ResetKey:
context["errors"] = ["Invalid e-mail."]
return render_template(request, "passreset.html", context,
status_code=HTTPStatus.NOT_FOUND)
@ -83,10 +84,10 @@ async def passreset_post(request: Request,
# We got to this point; everything matched up. Update the password
# and remove the ResetKey.
with db.begin():
user.ResetKey = str()
if user.session:
db.delete(user.session)
user.update_password(password)
db_user.ResetKey = str()
if db_user.session:
db.delete(db_user.session)
db_user.update_password(password)
# Render ?step=complete.
return RedirectResponse(url="/passreset?step=complete",
@ -95,9 +96,9 @@ async def passreset_post(request: Request,
# If we got here, we continue with issuing a resetkey for the user.
resetkey = generate_resetkey()
with db.begin():
user.ResetKey = resetkey
db_user.ResetKey = resetkey
ResetKeyNotification(user.ID).send()
ResetKeyNotification(db_user.ID).send()
# Render ?step=confirm.
return RedirectResponse(url="/passreset?step=confirm",

View file

@ -152,6 +152,18 @@ def test_post_passreset_user(client: TestClient, user: User):
assert response.headers.get("location") == "/passreset?step=confirm"
def test_post_passreset_user_suspended(client: TestClient, user: User):
with db.begin():
user.Suspended = True
with client as request:
response = request.post("/passreset", data={"user": TEST_USERNAME})
assert response.status_code == int(HTTPStatus.NOT_FOUND)
errors = get_errors(response.text)
expected = "Invalid e-mail."
assert errors[0].text.strip() == expected
def test_post_passreset_resetkey(client: TestClient, user: User):
with db.begin():
user.session = Session(UsersID=user.ID, SessionID="blah",