Пример #1
0
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)
Пример #2
0
class Import(Model, ModelMixin):
    __tablename__ = "imports"
    file = relationship("ImportFile")
    filename = Column(Text, index=True)
    format = Column(Text, index=True)
    data = Column(mutable_json_type(dbtype=PortableJSON(), nested=True))
    status = Column(Text, index=True)
Пример #3
0
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),
        )
Пример #4
0
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))
Пример #5
0
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")
Пример #6
0
class Meta(Model):
    """Metadata about the table

    This is a simple table used for storing metadata about the database itself. This is mostly
    used for the database versioning, but expandable if we want to use it for other things.
    """

    __tablename__ = "meta"
    key = Column(Text, primary_key=True, nullable=False, index=True)
    value = Column(Text)
Пример #7
0
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)
Пример #8
0
class ModelMixin(object):
    id = Column(PortableUUID(),
                primary_key=True,
                default=_gen_uuid,
                unique=True,
                nullable=False)

    def to_dict(self):
        record_dict = {
            c.key: getattr(self, c.key)
            for c in inspect(self).mapper.column_attrs
        }
        # when outputting info, translate data to metadata
        if "data" in record_dict:
            record_dict["metadata"] = record_dict.pop("data") or {}
        return record_dict

    @classmethod
    def from_dict(cls, **record_dict):
        # because metadata is a reserved attr name, translate it to data
        if "metadata" in record_dict:
            record_dict["data"] = record_dict.pop("metadata") or {}
        return cls(**record_dict)

    def update(self, record_dict):
        if "id" in record_dict:
            record_dict.pop("id")
        values_dict = self.to_dict()
        values_dict.update(record_dict)
        if "metadata" in values_dict:
            values_dict["data"] = values_dict.pop("metadata")
        for key, value in values_dict.items():
            setattr(self, key, value)
Пример #9
0
def upgrade_3(session):
    """Version 3 upgrade

    This upgrade:
        - makes the 'result_id' column of artifacts nullable
        - adds a 'run_id' to the artifacts table
    """
    engine = session.get_bind()
    op = get_upgrade_op(session)
    metadata = MetaData()
    metadata.reflect(bind=engine)
    artifacts = metadata.tables.get("artifacts")
    if ("runs" in metadata.tables and artifacts is not None
            and "run_id" not in [col.name for col in artifacts.columns]):
        op.alter_column("artifacts",
                        "result_id",
                        nullable=True,
                        server_default=null())
        op.add_column("artifacts",
                      Column("run_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_artifacts_run_id",
                "artifacts",
                "runs",
                ["run_id"],
                ["id"],
            )
Пример #10
0
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
Пример #11
0
def upgrade_4(session):
    """Version 4 upgrade

    This upgrade removes the "nullable" constraint on the password field, and adds a "is_superadmin"
    field to the user table.
    """
    engine = session.get_bind()
    op = get_upgrade_op(session)
    metadata = MetaData()
    metadata.reflect(bind=engine)
    users = metadata.tables.get("users")

    if ("users" in metadata.tables and users is not None
            and "is_superadmin" not in [col.name for col in users.columns]):
        op.alter_column("users", "_password", nullable=True)
        op.add_column("users", Column("is_superadmin", Boolean, default=False))
        op.add_column("users", Column("is_active", Boolean, default=False))
        op.add_column("users", Column("activation_code", Text, default=None))
Пример #12
0
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
Пример #13
0
class Run(Model, ModelMixin):
    __tablename__ = "runs"
    artifacts = relationship("Artifact")
    component = Column(Text, index=True)
    created = Column(DateTime, default=datetime.utcnow, 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)
    project_id = Column(PortableUUID(), ForeignKey("projects.id"), index=True)
    results = relationship("Result")
    source = Column(Text, index=True)
    start_time = Column(DateTime, default=datetime.utcnow, index=True)
    summary = Column(mutable_json_type(dbtype=PortableJSON()))
    artifacts = relationship("Artifact", backref="run")
Пример #14
0
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)
Пример #15
0
class FileMixin(ModelMixin):
    content = Column(LargeBinary)

    def to_dict(self):
        record_dict = {
            c.key: getattr(self, c.key)
            for c in inspect(self).mapper.column_attrs
        }
        record_dict.pop("content")
        if "data" in record_dict:
            record_dict["additional_metadata"] = record_dict.pop("data") or {}
        return record_dict
Пример #16
0
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)

    def to_dict(self):
Пример #17
0
class ImportFile(Model, FileMixin):
    __tablename__ = "import_files"
    import_id = Column(PortableUUID(),
                       ForeignKey("imports.id"),
                       nullable=False,
                       index=True)
Пример #18
0
class Group(Model, ModelMixin):
    __tablename__ = "groups"
    name = Column(Text, index=True)
    projects = relationship("Project")
    data = Column(mutable_json_type(dbtype=PortableJSON(), nested=True))
Пример #19
0
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)