class Artifact(Model, FileMixin): __tablename__ = "artifacts" result_id = Column(PortableUUID(), ForeignKey("results.id"), index=True) run_id = Column(PortableUUID(), ForeignKey("runs.id"), index=True) filename = Column(Text, index=True) data = Column(mutable_json_type(dbtype=PortableJSON(), nested=True)) upload_date = Column(DateTime, default=datetime.utcnow, index=True)
class Dashboard(Model, ModelMixin): __tablename__ = "dashboards" title = Column(Text, index=True) description = Column(Text, default="") filters = Column(Text, default="") project_id = Column(PortableUUID(), ForeignKey("projects.id"), index=True) user_id = Column(PortableUUID(), ForeignKey("users.id"), index=True) widgets = relationship("WidgetConfig")
class WidgetConfig(Model, ModelMixin): __tablename__ = "widget_configs" navigable = Column(Boolean, index=True) params = Column(mutable_json_type(dbtype=PortableJSON())) project_id = Column(PortableUUID(), ForeignKey("projects.id"), index=True) dashboard_id = Column(PortableUUID(), ForeignKey("dashboards.id"), index=True) title = Column(Text, index=True) type = Column(Text, index=True) weight = Column(Integer, index=True) widget = Column(Text, index=True)
def upgrade_1(session): """Version 1 upgrade This upgrade adds a dashboard_id to the widget_configs table """ engine = session.get_bind() op = get_upgrade_op(session) metadata = MetaData() metadata.reflect(bind=engine) widget_configs = metadata.tables.get("widget_configs") if ("dashboards" in metadata.tables and widget_configs is not None and "dashboard_id" not in [col.name for col in widget_configs.columns]): op.add_column( "widget_configs", Column("dashboard_id", PortableUUID, server_default=null())) if engine.url.get_dialect().name != "sqlite": # SQLite doesn't support ALTER TABLE ADD CONSTRAINT op.create_foreign_key( "fk_widget_configs_dashboard_id", "widget_configs", "dashboards", ["dashboard_id"], ["id"], ) if metadata.tables["projects"].columns["owner_id"].type in [ "TEXT", "CLOB" ]: op.alter_column( "projects", "owner_id", schema=Column(PortableUUID(), ForeignKey("users.id"), index=True), )
class User(Model, ModelMixin): __tablename__ = "users" email = Column(Text, index=True, nullable=False, unique=True) _password = Column(Text, nullable=True) name = Column(Text) activation_code = Column(Text, nullable=True) is_superadmin = Column(Boolean, default=False) is_active = Column(Boolean, default=False) group_id = Column(PortableUUID(), ForeignKey("groups.id"), index=True) dashboards = relationship("Dashboard") owned_projects = relationship("Project", backref="owner") tokens = relationship("Token", backref="user") projects = relationship("Project", secondary=users_projects, backref=backref("users", lazy="subquery")) @hybrid_property def password(self): return self._password @password.setter def password(self, value): self._password = bcrypt.generate_password_hash(value).decode("utf8") def check_password(self, plaintext): return bcrypt.check_password_hash(self.password, plaintext) def to_dict(self, with_projects=False): """An overridden method to include projects""" user_dict = super().to_dict() if with_projects: user_dict["projects"] = [ project.to_dict() for project in self.projects ] return user_dict
class Result(Model, ModelMixin): __tablename__ = "results" artifacts = relationship("Artifact") component = Column(Text, index=True) # this is metadata but it is a reserved attr data = Column(mutable_json_type(dbtype=PortableJSON(), nested=True)) duration = Column(Float, index=True) env = Column(Text, index=True) params = Column(mutable_json_type(dbtype=PortableJSON())) project_id = Column(PortableUUID(), ForeignKey("projects.id"), index=True) result = Column(Text, index=True) run_id = Column(PortableUUID(), ForeignKey("runs.id"), index=True) source = Column(Text, index=True) start_time = Column(DateTime, default=datetime.utcnow, index=True) test_id = Column(Text, index=True) artifacts = relationship("Artifact", backref="result")
class ReportFile(Model, FileMixin): __tablename__ = "report_files" report_id = Column(PortableUUID(), ForeignKey("reports.id"), nullable=False, index=True) filename = Column(Text, index=True) data = Column(mutable_json_type(dbtype=PortableJSON(), nested=True))
class Project(Model, ModelMixin): __tablename__ = "projects" name = Column(Text, index=True) title = Column(Text, index=True) owner_id = Column(PortableUUID(), ForeignKey("users.id"), index=True) group_id = Column(PortableUUID(), ForeignKey("groups.id"), index=True) reports = relationship("Report") results = relationship("Result", backref="project") runs = relationship("Run", backref="project") dashboards = relationship("Dashboard", backref="project") widget_configs = relationship("WidgetConfig", backref="project") def to_dict(self, with_owner=False): """An overridden method to include the owner""" project_dict = super().to_dict() if with_owner and self.owner: project_dict["owner"] = self.owner.to_dict() return project_dict
class Report(Model, ModelMixin): __tablename__ = "reports" created = Column(DateTime, default=datetime.utcnow, index=True) download_url = Column(Text, index=True) filename = Column(Text, index=True) mimetype = Column(Text, index=True) name = Column(Text, index=True) params = Column(mutable_json_type(dbtype=PortableJSON())) project_id = Column(PortableUUID(), ForeignKey("projects.id"), index=True) file = relationship("ReportFile") status = Column(Text, index=True) url = Column(Text, index=True) view_url = Column(Text, index=True)
class Token(Model, ModelMixin): __tablename__ = "tokens" name = Column(Text, nullable=False) token = Column(Text, nullable=False) expires = Column(DateTime) user_id = Column(PortableUUID(), ForeignKey("users.id"), index=True)
class ImportFile(Model, FileMixin): __tablename__ = "import_files" import_id = Column(PortableUUID(), ForeignKey("imports.id"), nullable=False, index=True)
from ibutsu_server.db.types import PortableUUID from sqlalchemy.exc import DBAPIError from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.orm import backref from sqlalchemy_json import mutable_json_type def _gen_uuid(): """Generate a UUID""" return str(uuid4()) users_projects = Table( "users_projects", Column("user_id", PortableUUID(), ForeignKey("users.id"), primary_key=True), Column("project_id", PortableUUID(), ForeignKey("projects.id"), primary_key=True), ) class ModelMixin(object): id = Column(PortableUUID(), primary_key=True, default=_gen_uuid, unique=True, nullable=False)