from flask import current_app, g from flask_security import UserMixin, RoleMixin import sqlalchemy from typing import Union, Optional, Literal, Type, List, Tuple import random from sqlalchemy import Column, JSON, String, Integer, create_engine, ForeignKey, func, ARRAY, Boolean, UnicodeText, \ DateTime from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.orm import sessionmaker, relationship, scoped_session def get_scoped_session(): engine = create_engine(current_app.config["DB_URL"]) session_factory = sessionmaker(bind=engine) Base.query = scoped_session(session_factory).query_property() # This is for compatibility with Flask-Security-Too which assumes usage of Flask-Sqlalchemy return scoped_session(session_factory) def get_session() -> sqlalchemy.orm.session.Session: if "session" not in g: Session = get_scoped_session() Session.query_property() g.session = Session() return g.session def init_db(): engine = create_engine(current_app.config["DB_URL"]) Base.metadata.create_all(engine) Base = declarative_base() class User(Base, UserMixin): __tablename__ = "users" user_id = Column(Integer, primary_key=True) email = Column(String, unique=True, nullable=False) username = Column(String, unique=True) password = Column(String, nullable=False) active = Column(Boolean, nullable=False) last_login_at = Column(DateTime()) current_login_at = Column(DateTime()) last_login_ip = Column(String(100)) current_login_ip = Column(String(100)) login_count = Column(Integer) fs_uniquifier = Column(String, unique=True, nullable=False) roles = relationship("Role", secondary="users_roles") class Role(Base, RoleMixin): __tablename__ = "roles" role_id = Column(Integer, primary_key=True) name = Column(String, unique=True) description = Column(String) permissions = Column(UnicodeText) class UsersRoles(Base): __tablename__ = "users_roles" user_role_id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey("users.user_id")) role_id = Column(Integer, ForeignKey("roles.role_id")) class AllQuestions(Base): __tablename__ = "all_questions" question_id = Column(Integer, primary_key=True, nullable=False) question_text = Column(String) answer = Column(String) addresses = Column(String) multiple_choice = relationship("MultipleChoice", uselist=False, back_populates="all_question_relationship") hidden_answer = relationship("HiddenAnswer", uselist=False, back_populates="all_question_relationship") def __init__(self, question_id, question, answer, addresses): self.question_id = question_id self.question_text = question self.answer = answer self.addresses = addresses def __repr__(self): return f"" def get_dict(self): result = { "question_id": self.question_id, "question": self.question_text, "answer": self.answer, "addresses": self.addresses, } if self.hidden_answer: result["hidden_answer"] = self.hidden_answer.get_dict() if self.multiple_choice: result["multiple_choice"] = self.multiple_choice.get_dict() return result class HiddenAnswer(Base): __tablename__ = "category_hidden_answer" question_id = Column(Integer, ForeignKey("all_questions.question_id"), primary_key=True) hidden_answer_difficulty = Column(Integer) hidden_answer_hint = Column(JSON) all_question_relationship = relationship("AllQuestions", lazy="joined", back_populates="hidden_answer") question_text = association_proxy("all_question_relationship", "question_text") answer = association_proxy("all_question_relationship", "answer") addresses = association_proxy("all_question_relationship", "addresses") def __init__(self, question_id, difficulty, hint, base_question): self.question_id = question_id self.hidden_answer_difficulty = difficulty self.hidden_answer_hint = hint self.all_question_relationship = base_question def __repr__(self): return f"