neurosight / models.py
dhineshkmar's picture
Upload 18 files
04a16eb verified
"""
Database models for NeuroSight authentication system
"""
from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime
import secrets
db = SQLAlchemy()
class User(UserMixin, db.Model):
"""User model for doctors and radiologists"""
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255), unique=True, nullable=False, index=True)
password_hash = db.Column(db.String(255), nullable=True) # Nullable for OAuth users
full_name = db.Column(db.String(255), nullable=False)
role = db.Column(db.String(50), nullable=False) # 'doctor' or 'radiologist'
hospital = db.Column(db.String(255))
license_number = db.Column(db.String(100))
phone = db.Column(db.String(20))
is_verified = db.Column(db.Boolean, default=False)
is_active = db.Column(db.Boolean, default=True)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
last_login = db.Column(db.DateTime)
# OAuth fields
google_id = db.Column(db.String(255), unique=True, index=True)
profile_photo_url = db.Column(db.String(500))
# Password reset fields
reset_token = db.Column(db.String(255))
reset_token_expiry = db.Column(db.DateTime)
# Doctor Details (for onboarding)
medical_registration_no = db.Column(db.String(100))
specialization = db.Column(db.String(100))
years_of_experience = db.Column(db.Integer)
clinic_timing = db.Column(db.String(255))
# Hospital Details (for onboarding)
hospital_id = db.Column(db.String(100))
hospital_address = db.Column(db.Text)
department = db.Column(db.String(100))
hospital_logo_url = db.Column(db.String(500))
hospital_phone = db.Column(db.String(20))
# Onboarding tracking
onboarding_completed = db.Column(db.Boolean, default=False)
# Email verification with OTP
email_verified = db.Column(db.Boolean, default=False)
otp_code = db.Column(db.String(6))
otp_expiry = db.Column(db.DateTime)
otp_attempts = db.Column(db.Integer, default=0)
# Relationships
analyses = db.relationship('AnalysisHistory', backref='user', lazy='dynamic', cascade='all, delete-orphan')
def set_password(self, password):
"""Hash and set password"""
self.password_hash = generate_password_hash(password)
def check_password(self, password):
"""Verify password against hash"""
if not self.password_hash:
return False
return check_password_hash(self.password_hash, password)
def generate_reset_token(self):
"""Generate a secure password reset token"""
self.reset_token = secrets.token_urlsafe(32)
return self.reset_token
def generate_otp(self):
"""Generate a 6-digit OTP for email verification"""
import random
from datetime import datetime, timedelta
self.otp_code = ''.join([str(random.randint(0, 9)) for _ in range(6)])
self.otp_expiry = datetime.utcnow() + timedelta(minutes=10) # OTP valid for 10 minutes
self.otp_attempts = 0
return self.otp_code
def verify_otp(self, otp):
"""Verify the OTP code"""
from datetime import datetime
# Check if OTP exists
if not self.otp_code:
return False, "No OTP generated"
# Check if OTP has expired
if datetime.utcnow() > self.otp_expiry:
return False, "OTP has expired"
# Check attempt limit (max 5 attempts)
if self.otp_attempts >= 5:
return False, "Too many failed attempts. Please request a new OTP"
# Verify OTP
if self.otp_code == otp:
self.email_verified = True
self.otp_code = None
self.otp_expiry = None
self.otp_attempts = 0
return True, "Email verified successfully"
else:
self.otp_attempts += 1
remaining = 5 - self.otp_attempts
return False, f"Invalid OTP. {remaining} attempts remaining"
def needs_onboarding(self):
"""Check if user needs to complete onboarding"""
return not self.onboarding_completed
def has_required_doctor_details(self):
"""Check if user has all required doctor details"""
return all([
self.full_name,
self.medical_registration_no,
self.specialization,
self.phone,
self.email,
self.years_of_experience is not None
])
def has_required_hospital_details(self):
"""Check if user has all required hospital details"""
return all([
self.hospital,
self.hospital_id,
self.department
])
def can_complete_onboarding(self):
"""Check if user can complete onboarding (all required fields filled)"""
return self.has_required_doctor_details() and self.has_required_hospital_details()
def __repr__(self):
return f'<User {self.email}>'
class AnalysisHistory(db.Model):
"""Analysis history for tracking patient scans"""
__tablename__ = 'analysis_history'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, index=True)
# Patient information
patient_name = db.Column(db.String(255))
patient_id = db.Column(db.String(100))
patient_age = db.Column(db.Integer)
scan_date = db.Column(db.Date)
# Analysis results
disease_type = db.Column(db.String(50), nullable=False) # 'ms', 'alzheimer', 'dementia', 'stroke'
prediction = db.Column(db.String(255), nullable=False)
confidence = db.Column(db.Float)
# File paths
image_path = db.Column(db.String(500))
report_path = db.Column(db.String(500))
# Metadata
created_at = db.Column(db.DateTime, default=datetime.utcnow, index=True)
notes = db.Column(db.Text) # Doctor's notes
def __repr__(self):
return f'<Analysis {self.id} - {self.disease_type}>'
def init_db(app):
"""Initialize database"""
db.init_app(app)
with app.app_context():
db.create_all()
print("✓ Database tables created successfully")