Forbid password resets after 15 minutes.
This commit is contained in:
parent
ae1a743855
commit
7800c24f99
|
@ -1,7 +1,8 @@
|
||||||
from uuid import uuid4, UUID
|
|
||||||
import os
|
import os
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from datetime import datetime, timedelta
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
from uuid import uuid4, UUID
|
||||||
|
|
||||||
import bcrypt
|
import bcrypt
|
||||||
import psycopg
|
import psycopg
|
||||||
|
@ -134,14 +135,18 @@ def initiate_password_reset(email: str) -> Optional[UUID]:
|
||||||
return reset_id
|
return reset_id
|
||||||
|
|
||||||
|
|
||||||
|
RESET_TIME = timedelta(minutes=-1 * 15)
|
||||||
|
|
||||||
|
|
||||||
def complete_reset(reset_id: str, new_password: str):
|
def complete_reset(reset_id: str, new_password: str):
|
||||||
with connect() as con:
|
with connect() as con:
|
||||||
cur = con.cursor()
|
cur = con.cursor()
|
||||||
cur.execute("SELECT reset_time, user_id FROM resets WHERE id = %s", (reset_id,))
|
cur.execute("SELECT reset_time, user_id FROM resets WHERE id = %s", (reset_id,))
|
||||||
row = cur.fetchone()
|
row = cur.fetchone()
|
||||||
if row:
|
if not row or not row[0]:
|
||||||
|
return False
|
||||||
reset_time, user_id = row
|
reset_time, user_id = row
|
||||||
if reset_time: # TODO: And reset_time is not too far in the past
|
if reset_time > (datetime.utcnow() + RESET_TIME):
|
||||||
cur.execute("DELETE FROM resets WHERE id = %s", (reset_id,))
|
cur.execute("DELETE FROM resets WHERE id = %s", (reset_id,))
|
||||||
password_hash = __gen_pw_hash(new_password)
|
password_hash = __gen_pw_hash(new_password)
|
||||||
cur.execute("UPDATE users SET password = %s WHERE id = %s", (password_hash, user_id))
|
cur.execute("UPDATE users SET password = %s WHERE id = %s", (password_hash, user_id))
|
||||||
|
|
|
@ -166,7 +166,8 @@ def reset_password():
|
||||||
elif existing_reset_id:
|
elif existing_reset_id:
|
||||||
# TODO: Eventually remove db entry whether or not link is clicked
|
# TODO: Eventually remove db entry whether or not link is clicked
|
||||||
new_password = request.form['password']
|
new_password = request.form['password']
|
||||||
db.complete_reset(existing_reset_id, new_password)
|
if not db.complete_reset(existing_reset_id, new_password):
|
||||||
|
return render_index(error="Password reset failed. Your reset link may have expired.", status=500)
|
||||||
# TODO: Log in?
|
# TODO: Log in?
|
||||||
|
|
||||||
return redirect('/')
|
return redirect('/')
|
||||||
|
|
Loading…
Reference in New Issue