Add password reset mechanism (Issue #1)
- Added reset_token and reset_token_expiry fields to User model - Implemented generate_reset_token(), verify_reset_token(), and clear_reset_token() methods - Created password reset request form (/password-reset-request) - Created password reset form (/password-reset/<token>) - Added "Forgot password?" link to login page - Reset tokens expire after 1 hour for security - Created migration script to add new database columns - Reset links are logged (would be emailed in production) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
30
models.py
30
models.py
@@ -41,6 +41,10 @@ class User(UserMixin, db.Model):
|
||||
# User settings (JSON stored as text)
|
||||
settings = db.Column(db.Text, default='{}')
|
||||
|
||||
# Password reset
|
||||
reset_token = db.Column(db.String(100), nullable=True, unique=True, index=True)
|
||||
reset_token_expiry = db.Column(db.DateTime, nullable=True)
|
||||
|
||||
def __init__(self, username, email, password=None, is_admin=False, auth0_id=None):
|
||||
"""
|
||||
Initialize a new user.
|
||||
@@ -102,6 +106,32 @@ class User(UserMixin, db.Model):
|
||||
self.last_login = datetime.utcnow()
|
||||
db.session.commit()
|
||||
|
||||
def generate_reset_token(self):
|
||||
"""Generate a password reset token that expires in 1 hour"""
|
||||
import secrets
|
||||
from datetime import timedelta
|
||||
|
||||
self.reset_token = secrets.token_urlsafe(32)
|
||||
self.reset_token_expiry = datetime.utcnow() + timedelta(hours=1)
|
||||
db.session.commit()
|
||||
return self.reset_token
|
||||
|
||||
def verify_reset_token(self, token):
|
||||
"""Verify if the provided reset token is valid and not expired"""
|
||||
if not self.reset_token or not self.reset_token_expiry:
|
||||
return False
|
||||
if self.reset_token != token:
|
||||
return False
|
||||
if datetime.utcnow() > self.reset_token_expiry:
|
||||
return False
|
||||
return True
|
||||
|
||||
def clear_reset_token(self):
|
||||
"""Clear the reset token after use"""
|
||||
self.reset_token = None
|
||||
self.reset_token_expiry = None
|
||||
db.session.commit()
|
||||
|
||||
def get_id(self):
|
||||
"""Required by Flask-Login"""
|
||||
return self.id
|
||||
|
||||
Reference in New Issue
Block a user