from app import db import sqlalchemy as sa from flask_login import UserMixin from datetime import datetime from werkzeug.security import generate_password_hash, check_password_hash enrollment = db.Table( "enrollment", sa.Column("user_id", sa.ForeignKey("user.id"), primary_key=True), sa.Column("course_id", sa.ForeignKey("course.id"), primary_key=True), ) class User(UserMixin, db.Model): id = sa.Column(sa.Integer, primary_key=True) username = sa.Column(sa.String(64), index=True, unique=True) role = sa.Column(sa.String(32), index=True) email = sa.Column(sa.String(120), index=True, unique=True) password_hash = sa.Column(sa.String(128)) last_seen = sa.Column(sa.DateTime, default=datetime.utcnow) token = sa.Column(sa.String(32), index=True, unique=True) enrolled_courses = db.relationship( "Course", secondary=enrollment, backref=db.backref("students", lazy="dynamic"), lazy="dynamic", ) def __repr__(self) -> str: return f"" def set_password(self, password) -> None: self.password_hash = generate_password_hash(password) def check_password(self, password) -> bool: return check_password_hash(self.password_hash, password) def is_enrolled(self, c) -> bool: return self.enrolled_courses.filter(enrollment.c.course_id == c.id).count() > 0 def enroll(self, c) -> bool: if not self.is_enrolled(c): self.enrolled_courses.append(c) return True return False def to_dict(self) -> dict: return { "id": self.id, "username": self.username, "email": self.email, } def from_dict(self, data, new_user=False) -> None: for field in ["role", "username", "email"]: if field in data: setattr(self, field, data[field]) if new_user and "password" in data: self.set_password(data["password"]) class Course(db.Model): id = sa.Column(sa.Integer, primary_key=True) name = sa.Column(sa.String(128), index=True) description = sa.Column(sa.Text, index=True) instructor = sa.Column(sa.ForeignKey(User.id), index=True) created_at = sa.Column(sa.DateTime) def __repr__(self) -> str: return f"" def from_dict(self, data) -> None: for field in ["name", "description", "instructor"]: if field in data: setattr(self, field, data[field]) if not self.created_at: self.created_at = datetime.now() def to_dict(self) -> dict: d = {} for f in ["id", "name", "description", "instructor", "created_at"]: d[f] = getattr(self, f) return d