Exemplo n.º 1
0
class Schedule(db.Model):  # type: ignore
    __bind_key__ = 'experiment_service'
    id = db.Column(UUIDType(binary=False),
                   primary_key=True,
                   default=uuid.uuid4)
    account_id = db.Column(UUIDType(binary=False), nullable=False, index=True)
    scheduled = db.Column(db.DateTime(), nullable=False)
    status = db.Column(db.Enum(ScheduleStatus),
                       nullable=False,
                       default=ScheduleStatus.pending)
    org_id = db.Column(UUIDType(binary=False), nullable=False, index=True)
    workspace_id = db.Column(UUIDType(binary=False),
                             nullable=False,
                             index=True)
    experiment_id = db.Column(UUIDType(binary=False),
                              nullable=False,
                              index=True)
    token_id = db.Column(UUIDType(binary=False), nullable=False)
    definition = db.Column(JSONB())
    info = db.Column(JSONB())

    def to_dict(self):
        return {
            "id": shortuuid.encode(self.id),
            "account_id": shortuuid.encode(self.account_id),
            "org_id": shortuuid.encode(self.org_id),
            "workspace_id": shortuuid.encode(self.workspace_id),
            "experiment_id": shortuuid.encode(self.experiment_id),
            "token_id": shortuuid.encode(self.token_id),
            "scheduled": "{}Z".format(self.scheduled.isoformat()),
            "definition": self.definition,
            "info": self.info
        }
Exemplo n.º 2
0
class AccessToken(db.Model, OAuth2TokenMixin):  # type: ignore
    __bind_key__ = 'auth_service'
    id = db.Column(UUIDType(binary=False),
                   primary_key=True,
                   unique=True,
                   default=uuid.uuid4)
    name = db.Column(db.String(), nullable=False)
    account_id = db.Column(UUIDType(binary=False),
                           db.ForeignKey('account.id', ondelete='CASCADE'),
                           nullable=False)
    last_used_on = db.Column(db.DateTime())

    def to_dict(self):
        last_used = None
        if self.last_used_on:
            last_used = "{}Z".format(self.last_used_on.isoformat())

        return {
            "id": shortuuid.encode(self.id),
            "name": self.name,
            "account_id": shortuuid.encode(self.account_id),
            "access_token": self.access_token,
            "refresh_token": self.refresh_token,
            "client_id": self.client_id,
            "scope": self.scope,
            "token_type": self.token_type,
            "issued_at": self.issued_at,
            "expires_in": self.expires_in,
            "last_used": last_used,
            "revoked": self.revoked
        }
Exemplo n.º 3
0
class RecommendationTagsAssoc(db.Model):  # type: ignore
    __bind_key__ = 'experiment_service'
    __tablename__ = "recommendation_tags_assoc"
    recommendation_id = db.Column(UUIDType,
                                  db.ForeignKey('recommendation.id'),
                                  primary_key=True)
    tag_id = db.Column(db.Integer,
                       db.ForeignKey('recommendation_tag.id'),
                       primary_key=True)
Exemplo n.º 4
0
class UserPrivacy(db.Model):  # type: ignore
    __bind_key__ = 'dashboard_service'
    id = db.Column(UUIDType(binary=False),
                   primary_key=True,
                   default=uuid.uuid4)
    account_id = db.Column(UUIDType(binary=False),
                           db.ForeignKey('user_account.id'),
                           nullable=False)
    last_changed = db.Column(db.DateTime(), server_default=func.now())
    details = db.Column(JSONB())
Exemplo n.º 5
0
class Discovery(db.Model):  # type: ignore
    __bind_key__ = 'experiment_service'
    id = db.Column(UUIDType(binary=False),
                   primary_key=True,
                   default=uuid.uuid4)
    account_id = db.Column(UUIDType(binary=False), nullable=False, index=True)
    received_date = db.Column(db.DateTime(), server_default=func.now())
    workspace_id = db.Column(UUIDType(binary=False),
                             nullable=False,
                             index=True)
    payload = db.Column(JSONB())
Exemplo n.º 6
0
class OrgsMembers(db.Model):  # type: ignore
    __bind_key__ = 'dashboard_service'
    __tablename__ = "orgs_members"
    org_id = db.Column(UUIDType(binary=False),
                       db.ForeignKey('org.id'),
                       primary_key=True)
    account_id = db.Column(UUIDType(binary=False),
                           db.ForeignKey('user_account.id'),
                           primary_key=True)
    is_owner = db.Column(db.Boolean(), default=False)
    account = db.relationship('UserAccount')
    organization = db.relationship('Org')
Exemplo n.º 7
0
class WorkpacesMembers(db.Model):  # type: ignore
    __bind_key__ = 'dashboard_service'
    __tablename__ = "workspaces_members"
    workspace_id = db.Column(UUIDType(binary=False),
                             db.ForeignKey('workspace.id'),
                             primary_key=True)
    account_id = db.Column(UUIDType(binary=False),
                           db.ForeignKey('user_account.id'),
                           primary_key=True)
    is_owner = db.Column(db.Boolean(), default=False)
    account = db.relationship('UserAccount')
    workspace = db.relationship('Workspace')
Exemplo n.º 8
0
class Client(db.Model, OAuth2ClientMixin):  # type: ignore
    __bind_key__ = 'auth_service'
    id = db.Column(db.Integer, primary_key=True)
    account_id = db.Column(UUIDType(binary=False),
                           db.ForeignKey('account.id', ondelete='CASCADE'),
                           nullable=False)

    def to_dict(self):
        return {
            "id": self.id,
            "client_id": self.client_id,
            "client_secret": self.client_secret
        }
Exemplo n.º 9
0
class LocalAccount(db.Model):  # type: ignore
    __bind_key__ = 'auth_service'

    id = db.Column(UUIDType(binary=False),
                   primary_key=True,
                   unique=True,
                   default=uuid.uuid4)
    account_id = db.Column(UUIDType(binary=False),
                           db.ForeignKey('account.id', ondelete='CASCADE'),
                           nullable=False)
    username = db.Column(db.String, nullable=False, unique=True, index=True)
    password = db.Column(PasswordType(schemes=['pbkdf2_sha512'], ),
                         unique=False,
                         nullable=False)
Exemplo n.º 10
0
class ProviderToken(db.Model, OAuth2TokenMixin):  # type: ignore
    __bind_key__ = 'auth_service'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20), nullable=False)
    account_id = db.Column(UUIDType(binary=False),
                           db.ForeignKey('account.id', ondelete='CASCADE'))
    account = db.relationship('Account')

    def to_dict(self):
        return {
            "id": self.id,
            "access_token": self.access_token,
            "token_type": self.token_type,
            "refresh_token": self.refresh_token,
            "expires_at": self.expires_in,
            "revoked": self.revoked
        }
Exemplo n.º 11
0
class Recommendation(db.Model):  # type: ignore
    __bind_key__ = 'experiment_service'
    id = db.Column(UUIDType(binary=False),
                   primary_key=True,
                   default=uuid.uuid4)
    recommendation_type = db.Column(db.String(), index=True)
    tags = db.relationship('RecommendationTag',
                           secondary="recommendation_tags_assoc",
                           backref=db.backref('recommendations', lazy=True))
    checksum = db.Column(db.String(), nullable=False)
    last_updated = db.Column(db.DateTime())
    rating = db.Column(db.Float, default=3.0)
    meta = db.Column(JSONB())
    data = db.Column(JSONB(), nullable=False)

    def to_dict(self):
        data = self.data
        if self.recommendation_type == "experiment":
            data = data["hashed"]
        return {
            "id": str(self.id),
            "type": self.recommendation_type,
            "tags": [tag.value for tag in self.tags],
            "checksum": self.checksum,
            "last_updated": "{}Z".format(self.last_updated.isoformat()),
            "meta": self.meta,
            "data": data
        }
Exemplo n.º 12
0
class UserAccount(db.Model):  # type: ignore
    __bind_key__ = 'dashboard_service'
    __tablename__ = 'user_account'
    id = db.Column(UUIDType(binary=False),
                   primary_key=True,
                   default=uuid.uuid4)
    joined_dt = db.Column(db.DateTime(), server_default=func.now())
    closed_dt = db.Column(db.DateTime())
    inactive_dt = db.Column(db.DateTime())
    is_closed = db.Column(db.Boolean, default=False)
    is_active = db.Column(db.Boolean, default=True)
    info = db.relationship('UserInfo',
                           backref='account',
                           uselist=False,
                           cascade="all, delete-orphan")
    privacy = db.relationship('UserPrivacy',
                              backref='account',
                              uselist=False,
                              cascade="all, delete-orphan")
    workspaces = db.relationship('Workspace',
                                 secondary="workspaces_members",
                                 lazy='subquery',
                                 backref=db.backref('accounts', lazy=True))
    orgs = db.relationship('Org',
                           secondary="orgs_members",
                           lazy='subquery',
                           backref=db.backref('accounts', lazy=True))
    # direct access to the unique personal org
    # but this org is also part of the many to many relationship
    personal_org = db.relationship('Org',
                                   backref='account',
                                   uselist=False,
                                   cascade="all, delete-orphan")

    def to_public_dict(self):
        return {
            "id": shortuuid.encode(self.id),
            "joined": "{}Z".format(self.joined_dt.isoformat()),
            "workspaces": [w.to_dict() for w in self.workspaces],
            "orgs": [o.to_dict() for o in self.orgs]
        }

    def to_short_dict(self):
        return {
            "id": shortuuid.encode(self.id),
            "joined": "{}Z".format(self.joined_dt.isoformat()),
            "org": {
                "name": self.personal_org.name
            },
            "profile": self.info.to_public_dict()
        }
Exemplo n.º 13
0
class Execution(db.Model):  # type: ignore
    __bind_key__ = 'experiment_service'
    __table_args__ = (db.UniqueConstraint('timestamp',
                                          'experiment_id',
                                          name='index_per_experiment_uniq'), )

    id = db.Column(UUIDType(binary=False),
                   primary_key=True,
                   default=uuid.uuid4)
    account_id = db.Column(UUIDType(binary=False), nullable=False, index=True)
    timestamp = db.Column(
        db.BigInteger,
        default=lambda: int(datetime.utcnow().timestamp() * 1000))
    org_id = db.Column(UUIDType(binary=False), nullable=False, index=True)
    workspace_id = db.Column(UUIDType(binary=False),
                             nullable=False,
                             index=True)
    experiment_id = db.Column(UUIDType(binary=False),
                              db.ForeignKey('experiment.id',
                                            ondelete='CASCADE'),
                              nullable=False)
    status = db.Column(db.String)
    payload = db.Column(JSONB())

    def to_dict(self, visibility: str = "status") -> Dict[str, Any]:
        result = {
            "id": shortuuid.encode(self.id),
            "timestamp": self.timestamp,
            "org": shortuuid.encode(self.org_id),
            "workspace": shortuuid.encode(self.workspace_id),
            "experiment": shortuuid.encode(self.experiment_id)
        }

        if visibility == "full":
            result["status"] = self.status
            result["result"] = self.payload
        elif visibility == "full":
            result["status"] = self.status
        return result
Exemplo n.º 14
0
class UserInfo(db.Model):  # type: ignore
    __bind_key__ = 'dashboard_service'
    id = db.Column(UUIDType(binary=False),
                   primary_key=True,
                   default=uuid.uuid4)
    account_id = db.Column(UUIDType(binary=False),
                           db.ForeignKey('user_account.id'),
                           nullable=False)
    last_updated = db.Column(db.DateTime(),
                             server_default=func.now(),
                             onupdate=func.current_timestamp())
    verified_email = db.Column(db.Boolean(), default=False)

    # values for search purpose mostly
    username = db.Column(db.String, index=True, nullable=True)
    fullname = db.Column(db.String, index=True, nullable=True)

    details = db.Column(EncryptedType(db.String, get_user_info_secret_key,
                                      AesEngine, 'pkcs5'),
                        nullable=False)

    @staticmethod
    def get_for_account(account_id: Union[str, uuid.UUID]) -> 'UserInfo':
        """
        Lookup user info for the given user account
        """
        return UserInfo.query.filter(UserInfo.account_id == account_id).first()

    @property
    def profile(self) -> Dict[str, Any]:
        """
        The user's profile
        """
        return json.loads(self.details)

    @profile.setter
    def profile(self, p: Dict[str, Any]):
        """
        Set the user's profile from the given payload

        The payload is serialized to JSON and stored in the `details`
        property
        """
        self.details = json.dumps(p)

    def to_dict(self):
        return {
            "id": shortuuid.encode(self.id),
            "account": shortuuid.encode(self.account.id),
            "profile": self.profile
        }

    def to_public_dict(self):
        p = self.profile

        return {
            "id": shortuuid.encode(self.id),
            "username": p.get("preferred_username"),
            "name": p.get("name"),
            "picture": p.get("picture")
        }
Exemplo n.º 15
0
class Workspace(db.Model):  # type: ignore
    __bind_key__ = 'dashboard_service'
    __table_args__ = (db.UniqueConstraint('name',
                                          'org_id',
                                          name='workspace_org_uniq'), )

    id = db.Column(UUIDType(binary=False),
                   primary_key=True,
                   default=uuid.uuid4)
    name = db.Column(db.String(), nullable=False)
    name_lower = db.Column(db.String(), nullable=False)
    kind = db.Column(db.Enum(WorkspaceType),
                     nullable=False,
                     default=WorkspaceType.personal)
    org_id = db.Column(UUIDType(binary=False),
                       db.ForeignKey('org.id'),
                       nullable=False)
    settings = db.Column(JSONB(),
                         nullable=False,
                         default=DEFAULT_WORKSPACE_SETTINGS)

    def to_dict(self):
        return {
            "id": shortuuid.encode(self.id),
            "name": self.name,
            "type": self.kind.value,
            "org": {
                "id": shortuuid.encode(self.org_id),
                "name": self.org.name,
                "type": self.org.kind.value
            },
            "settings": self.settings
        }

    def to_short_dict(self):
        return {
            "id": shortuuid.encode(self.id),
            "name": self.name,
            "type": self.kind.value,
            "settings": self.settings
        }

    @staticmethod
    def find_by_name(workspace_name: str) -> 'Workspace':
        """
        Get a workspace by its name
        """
        return Workspace.query.filter(
            Workspace.name_lower == workspace_name.lower()).first()

    @staticmethod
    def get_by_id(workspace_id: Union[str, uuid.UUID]) -> 'Workspace':
        """
        Get a workspace by its identifier
        """
        return Workspace.query.filter(Workspace.id == workspace_id).first()

    def is_collaborator(self, account_id: Union[str, uuid.UUID]) -> bool:
        """
        Return `True` when the given account is a collaborator to this
        workspace
        """
        return WorkpacesMembers.query.filter(
            WorkpacesMembers.workspace_id == self.id,
            WorkpacesMembers.account_id == account_id).first() is not None

    def is_owner(self, account_id: Union[str, uuid.UUID]) -> bool:
        """
        Return `True` when the given account is an owner of the workspace
        """
        return WorkpacesMembers.query.filter(
            WorkpacesMembers.workspace_id == self.id,
            WorkpacesMembers.is_owner == True,
            WorkpacesMembers.account_id == account_id).first() is not None

    def has_single_owner(self) -> bool:
        """
        Return `True` if only one owner exists for this workspace
        """
        return WorkpacesMembers.query.filter(
            WorkpacesMembers.workspace_id == self.id,
            WorkpacesMembers.is_owner == True).count() == 1

    def make_collaborator(self, account_id: Union[str, uuid.UUID]):
        """
        Turn an user as a collaborator only of this workspace.
        """
        membership = WorkpacesMembers.query.filter(
            WorkpacesMembers.workspace_id == self.id,
            WorkpacesMembers.account_id == account_id).first()
        if membership:
            membership.is_owner = False

    def make_owner(self, account_id: Union[str, uuid.UUID]):
        """
        Turn an user as an owner of this workspace.
        """
        membership = WorkpacesMembers.query.filter(
            WorkpacesMembers.workspace_id == self.id,
            WorkpacesMembers.account_id == account_id).first()
        if membership:
            membership.is_owner = True

    def add_collaborator(self, account_id: Union[str, uuid.UUID]) \
            -> WorkpacesMembers:
        """
        Add this user to the organization as a collaborator
        """
        membership = WorkpacesMembers(workspace_id=self.id,
                                      account_id=account_id)
        db.session.add(membership)
        return membership

    def remove_collaborator(self, account_id: Union[str, uuid.UUID]):
        """
        Remove this collaborator from the organization
        """
        WorkpacesMembers.query.filter(
            WorkpacesMembers.workspace_id == self.id,
            WorkpacesMembers.account_id == account_id).delete()
Exemplo n.º 16
0
class Account(db.Model):  # type: ignore
    __bind_key__ = 'auth_service'
    __table_args__ = (db.UniqueConstraint('oauth_provider',
                                          'oauth_provider_sub',
                                          name='oauth_provider_sub_uniq'), )

    id = db.Column(UUIDType(binary=False),
                   primary_key=True,
                   unique=True,
                   default=uuid.uuid4)
    joined_on = db.Column(db.DateTime(timezone=True),
                          server_default=func.now(),
                          nullable=False)
    closed_since = db.Column(db.DateTime(timezone=True), nullable=True)
    inactive_since = db.Column(db.DateTime(timezone=True), nullable=True)
    is_closed = db.Column(db.Boolean, default=False)
    is_active = db.Column(db.Boolean, default=True)
    oauth_provider = db.Column(db.String, nullable=True)
    oauth_provider_sub = db.Column(db.String, nullable=True)

    access_tokens = db.relationship('AccessToken',
                                    backref='account',
                                    cascade="all, delete-orphan")
    client = db.relationship('Client',
                             backref='account',
                             uselist=False,
                             cascade="all, delete-orphan")
    local = db.relationship('LocalAccount',
                            backref='account',
                            uselist=False,
                            cascade="all, delete-orphan")

    def to_dict(self):
        inactive = closed = None
        if self.inactive_since:
            inactive = "{}Z".format(self.inactive_since.isoformat())
        if self.closed_since:
            closed = "{}Z".format(self.closed_since.isoformat())

        return {
            "id": str(self.id),
            "short_id": shortuuid.encode(self.id),
            "closed": self.is_closed,
            "active": self.is_active,
            "joined_on": "{}Z".format(self.joined_on.isoformat()),
            "inactive_since": inactive,
            "closed_since": closed,
            "client": self.client.to_dict() if self.client else None,
            "tokens": [t.to_dict() for t in self.access_tokens]
        }

    def turn_inactive(self):
        self.is_active = False
        self.inactive_since = datetime.utcnow()

    def turn_active(self):
        self.is_active = True
        self.inactive_since = None

    def close_account(self):
        self.is_closed = False
        self.closed_since = datetime.utcnow()
Exemplo n.º 17
0
class Org(db.Model):  # type: ignore
    __bind_key__ = 'dashboard_service'

    id = db.Column(UUIDType(binary=False),
                   primary_key=True,
                   default=uuid.uuid4)
    # only set when this is a personal org linked to a single account,
    # otherwise it's not set
    account_id = db.Column(UUIDType(binary=False),
                           db.ForeignKey('user_account.id'),
                           nullable=True)
    name = db.Column(db.String(), nullable=False, unique=True)
    name_lower = db.Column(db.String(), nullable=False, unique=True)
    kind = db.Column(db.Enum(OrgType),
                     nullable=False,
                     default=OrgType.personal)
    created_on = db.Column(db.DateTime(), server_default=func.now())
    workspaces = db.relationship('Workspace',
                                 backref='org',
                                 cascade="all, delete-orphan")
    settings = db.Column(JSONB(), nullable=False, default=DEFAULT_ORG_SETTINGS)

    def to_dict(self, public_workspaces_only: bool = False):
        workspaces = []
        for w in self.workspaces:
            if public_workspaces_only and w.kind != WorkspaceType.public:
                continue

            workspaces.append({"id": shortuuid.encode(w.id), "name": w.name})

        return {
            "id": shortuuid.encode(self.id),
            "name": self.name,
            "settings": self.settings,
            "type": self.kind.value,
            "created_on": "{}Z".format(self.created_on.isoformat()),
            "workspaces": workspaces
        }

    def to_short_dict(self):
        return {
            "id": shortuuid.encode(self.id),
            "name": self.name,
            "created_on": "{}Z".format(self.created_on.isoformat()),
            "settings": self.settings,
            "type": self.kind.value
        }

    @staticmethod
    def get_next_available_name(suggested_name: str) -> str:
        """
        Return the next available name prefixed by the given suggested name and
        suffixed by a number between 0 and 1000.

        If `suggested_name` is not used yet, return it as the available name
        """
        while True:
            has_org = Org.query.filter(Org.name == suggested_name).first()
            if not has_org:
                return suggested_name
            suggested_name = "{}{}".format(suggested_name,
                                           secrets.randbelow(1000))

    @staticmethod
    def get_by_id(org_id: Union[str, uuid.UUID]) -> 'Org':
        """
        Lookup an organization by its identifier
        """
        return Org.query.filter(Org.id == org_id).first()

    @staticmethod
    def find_by_name(org_name: str) -> 'Org':
        """
        Lookup an organization by its name
        """
        return Org.query.filter(Org.name_lower == org_name.lower()).first()

    def find_workspace_by_name(self,
                               workspace_name: str) -> Optional[Workspace]:
        """
        Lookup a workspace in the organization by its name
        """
        w_name = workspace_name.lower()
        for workspace in self.workspaces:
            if workspace.name_lower == w_name:
                return workspace

        return None

    def is_member(self, account_id: Union[str, uuid.UUID]) -> bool:
        """
        Return `True` when the given account is a member of the organization
        """
        return OrgsMembers.query.filter(
            OrgsMembers.org_id == self.id,
            OrgsMembers.account_id == account_id).first() is not None

    def is_owner(self, account_id: Union[str, uuid.UUID]) -> bool:
        """
        Return `True` when the given account is an owner of the organization
        """
        return OrgsMembers.query.filter(
            OrgsMembers.org_id == self.id, OrgsMembers.is_owner == True,
            OrgsMembers.account_id == account_id).first() is not None

    def has_single_owner(self) -> bool:
        """
        Return `True` if only one owner exists for this organization
        """
        return OrgsMembers.query.filter(
            OrgsMembers.org_id == self.id,
            OrgsMembers.is_owner == True).count() == 1

    def make_member(self, account_id: Union[str, uuid.UUID]):
        """
        Turn an user as a member only of this organization.

        The user must already be part of this organization, this is mostly
        therefore useful when moving an owner down to simple member.
        """
        membership = OrgsMembers.query.filter(
            OrgsMembers.org_id == self.id,
            OrgsMembers.account_id == account_id).first()
        if membership:
            membership.is_owner = False

    def make_owner(self, account_id: Union[str, uuid.UUID]):
        """
        Turn an user as an owner of this organization.
        """
        membership = OrgsMembers.query.filter(
            OrgsMembers.org_id == self.id,
            OrgsMembers.account_id == account_id).first()
        if membership:
            membership.is_owner = True

    def add_member(self, account_id: Union[str, uuid.UUID]) -> OrgsMembers:
        """
        Add this user to the organization as a member
        """
        membership = OrgsMembers(org_id=self.id, account_id=account_id)
        db.session.add(membership)
        return membership

    def remove_member(self, account_id: Union[str, uuid.UUID]):
        """
        Remove this member from the organization
        """
        OrgsMembers.query.filter(
            OrgsMembers.org_id == self.id,
            OrgsMembers.account_id == account_id).delete()

    def get_public_workspace_ids(self) -> List[uuid.UUID]:
        """
        List all public workspaces in this organization and return their
        identifiers
        """
        result = db.session.query(Workspace.id).filter(
            Workspace.org_id == self.id,
            Workspace.kind == WorkspaceType.public).all()
        if not result:
            return []

        return result[0]
Exemplo n.º 18
0
class Activity(db.Model):  # type: ignore
    __bind_key__ = 'dashboard_service'

    id = db.Column(UUIDType(binary=False),
                   primary_key=True,
                   default=uuid.uuid4)
    account_id = db.Column(UUIDType(binary=False), nullable=True)
    org_id = db.Column(UUIDType(binary=False), nullable=True)
    workspace_id = db.Column(UUIDType(binary=False), nullable=True)
    experiment_id = db.Column(UUIDType(binary=False), nullable=True)
    execution_id = db.Column(UUIDType(binary=False), nullable=True)
    timestamp = db.Column(
        db.BigInteger,
        default=lambda: int(datetime.utcnow().timestamp() * 1000))
    kind = db.Column(db.String, nullable=True)
    visibility = db.Column(db.Enum(ActivityVisibility),
                           nullable=False,
                           default=ActivityVisibility.authenticated)
    title = db.Column(db.String, nullable=False)
    info = db.Column(db.String, nullable=True)
    extra = db.Column(JSONB(), nullable=True)

    def to_dict(self):
        org_id = shortuuid.encode(self.org_id) if self.org_id else None
        workspace_id = None
        if self.workspace_id:
            workspace_id = shortuuid.encode(self.workspace_id)
        experiment_id = None
        if self.experiment_id:
            experiment_id = shortuuid.encode(self.experiment_id)
        execution_id = None
        if self.execution_id:
            execution_id = shortuuid.encode(self.execution_id)

        return {
            "id": shortuuid.encode(self.id),
            "account_id": shortuuid.encode(self.account_id),
            "workspace_id": workspace_id,
            "org_id": org_id,
            "experiment_id": experiment_id,
            "execution_id": execution_id,
            "type": self.kind,
            "visibility": self.visibility.value,
            "timestamp": self.timestamp,
            "title": self.title,
            "info": self.info,
            "extra": self.extra
        }

    @staticmethod
    def from_dict(activity: Dict[str, Any]) -> 'Activity':
        visibility = activity["visibility"]
        if visibility in (1, "anonymous"):
            visibility = ActivityVisibility.anonymous
        elif visibility in (2, "authenticated"):
            visibility = ActivityVisibility.authenticated
        elif visibility in (3, "collaborator"):
            visibility = ActivityVisibility.collaborator
        elif visibility in (4, "owner"):
            visibility = ActivityVisibility.owner

        org_id = activity.get("org_id")
        if org_id:
            org_id = shortuuid.decode(org_id)

        workspace_id = activity.get("workspace_id")
        if workspace_id:
            workspace_id = shortuuid.decode(workspace_id)

        experiment_id = activity.get("experiment_id")
        if experiment_id:
            experiment_id = shortuuid.decode(experiment_id)

        execution_id = activity.get("execution_id")
        if execution_id:
            execution_id = shortuuid.decode(execution_id)

        return Activity(account_id=shortuuid.decode(
            activity.get("account_id")),
                        org_id=org_id,
                        workspace_id=workspace_id,
                        experiment_id=experiment_id,
                        execution_id=execution_id,
                        kind=activity.get("type"),
                        visibility=visibility,
                        title=activity.get("title"),
                        info=activity.get("info"),
                        extra=activity.get("extra"),
                        timestamp=activity.get("timestamp"))

    @staticmethod
    def get_recents_for_account(account_id: Union[str, uuid.UUID],
                                visibility: ActivityVisibility,
                                last: int = 10) -> List['Activity']:
        return Activity.query.filter(
            Activity.account_id==account_id,
            Activity.visibility<=visibility)\
            .order_by(Activity.timestamp.desc())\
            .limit(last)

    @staticmethod
    def get_recents_for_org(org_id: Union[str, uuid.UUID],
                            visibility: ActivityVisibility,
                            last: int = 10) -> List['Activity']:
        return Activity.query.filter(
            Activity.org_id==org_id,
            Activity.visibility<=visibility)\
            .order_by(Activity.timestamp.desc())\
            .limit(last)

    @staticmethod
    def get_recents_for_workspace(workspace_id: Union[str, uuid.UUID],
                                  visibility: ActivityVisibility,
                                  last: int = 10) -> List['Activity']:
        return Activity.query.filter(
            Activity.workspace_id==workspace_id,
            Activity.visibility<=visibility)\
            .order_by(Activity.timestamp.desc())\
            .limit(last)
Exemplo n.º 19
0
class APIAccessToken(db.Model):  # type: ignore
    __bind_key__ = 'api_service'
    __tablename__ = 'api_access_token'
    __table_args__ = (db.UniqueConstraint('name',
                                          'account_id',
                                          name='name_account_uniq'), )

    id = db.Column(UUIDType(binary=False),
                   primary_key=True,
                   default=uuid.uuid4)
    name = db.Column(db.String, nullable=False)
    account_id = db.Column(UUIDType(binary=False), nullable=False)
    last_used_on = db.Column(db.DateTime())
    client_id = db.Column(db.String(48))
    token_type = db.Column(db.String(40))
    access_token = db.Column(db.String(255), unique=True, nullable=False)
    refresh_token = db.Column(db.String(255), index=True)
    scope = db.Column(db.Text, default='')
    # be conservative
    revoked = db.Column(db.Boolean, nullable=False, default=True)
    issued_at = db.Column(db.Integer, nullable=False)
    expires_in = db.Column(db.Integer, nullable=False, default=0)

    def get_scope(self):
        return self.scope

    def get_expires_in(self):
        return self.expires_in

    def get_expires_at(self):
        return self.issued_at + self.expires_in

    def is_expired(self):
        now = datetime.utcnow().timestamp()
        return self.get_expires_at() < now

    def is_active(self):
        now = datetime.utcnow().timestamp()
        return self.get_expires_at() >= now

    def revoke(self):
        self.revoked = True

    def to_dict(self):
        last_used = None
        if self.last_used_on:
            last_used = self.last_used_on.replace(
                tzinfo=timezone.utc).timestamp()

        return {
            "id": str(self.id),
            "account_id": str(self.account_id),
            "access_token": self.access_token,
            "refresh_token": self.refresh_token,
            "client_id": self.client_id,
            "scope": self.scope,
            "token_type": self.token_type,
            "issued_at": self.issued_at,
            "expires_in": self.expires_in,
            "last_used": last_used,
            "revoked": self.revoked
        }

    @staticmethod
    def from_dict(token: Dict[str, Any]) -> 'APIAccessToken':
        """
        Create or update a token from the source access token.

        On update, only the scope, revoked and dates properties are changed.
        Others are left as they are.
        """
        access_token = APIAccessToken.get_by_token(token["access_token"])
        if not access_token:
            access_token = APIAccessToken()
            access_token.id = shortuuid.decode(token["id"])
            access_token.account_id = shortuuid.decode(token["account_id"])
            access_token.access_token = token["access_token"]
            access_token.client_id = token["client_id"]

        access_token.name = token["name"]
        access_token.refresh_token = token["refresh_token"]
        access_token.scope = token["scope"]
        access_token.revoked = token["revoked"]
        access_token.issued_at = token["issued_at"]
        access_token.expires_in = token["expires_in"]

        return access_token

    @staticmethod
    def get_by_token(access_token: str) -> Optional['APIAccessToken']:
        return APIAccessToken.query.filter(
            APIAccessToken.access_token == access_token).first()

    @staticmethod
    def get_by_id_for_account(account_id: str,
                              token_id: str) -> Optional['APIAccessToken']:
        return APIAccessToken.query.filter(
            APIAccessToken.account_id == account_id,
            APIAccessToken.id == token_id).first()

    @staticmethod
    def get_all_for_account(account_id: str) -> List['APIAccessToken']:
        return APIAccessToken.query.filter(
            APIAccessToken.account_id == account_id).all()

    @staticmethod
    def get_active_for_account(account_id: str) -> List['APIAccessToken']:
        non_revoked_tokens = APIAccessToken.query.filter(
            APIAccessToken.revoked == False,
            APIAccessToken.account_id == account_id).all()

        return [token for token in non_revoked_tokens if token.is_active()]
Exemplo n.º 20
0
class Experiment(db.Model):  # type: ignore
    __bind_key__ = 'experiment_service'
    id = db.Column(UUIDType(binary=False),
                   primary_key=True,
                   default=uuid.uuid4)
    shared_ref = db.Column(UUIDType(binary=False), nullable=False, index=True)
    account_id = db.Column(UUIDType(binary=False), nullable=False, index=True)
    created_date = db.Column(db.DateTime(), server_default=func.now())
    updated_date = db.Column(db.DateTime(),
                             server_default=func.now(),
                             server_onupdate=func.now())
    suggested_experiment_id = db.Column(UUIDType(binary=False), index=True)
    org_id = db.Column(UUIDType(binary=False), nullable=False, index=True)
    workspace_id = db.Column(UUIDType(binary=False),
                             nullable=False,
                             index=True)
    executions = db.relationship('Execution',
                                 backref='experiment',
                                 cascade="all, delete-orphan")
    payload = db.Column(NestedMutable.as_mutable(JSONB), nullable=False)

    def to_dict(self, with_payload: bool = True):
        updated_date = None
        timestamp = self.created_date.timestamp()
        if self.updated_date:
            updated_date = "{}Z".format(self.updated_date.isoformat())
            timestamp = self.updated_date.timestamp()

        d = {
            "id": shortuuid.encode(self.id),
            "ref": shortuuid.encode(self.shared_ref),
            "created_date": "{}Z".format(self.created_date.isoformat()),
            "updated_date": updated_date,
            "timestamp": timestamp,
            "org": shortuuid.encode(self.org_id),
            "workspace": shortuuid.encode(self.workspace_id),
            "title": self.payload.get("title"),
            "description": self.payload.get("description")
        }

        if with_payload:
            d["payload"] = self.payload

        return d

    def to_public_dict(self, with_payload: bool = True):
        updated_date = None
        timestamp = self.created_date.timestamp()
        if self.updated_date:
            updated_date = "{}Z".format(self.updated_date.isoformat())
            timestamp = self.updated_date.timestamp()

        d = {
            "id": shortuuid.encode(self.id),
            "ref": shortuuid.encode(self.shared_ref),
            "created_date": "{}Z".format(self.created_date.isoformat()),
            "updated_date": updated_date,
            "timestamp": timestamp,
            "org": shortuuid.encode(self.org_id),
            "workspace": shortuuid.encode(self.workspace_id),
            "title": self.payload.get("title"),
            "description": self.payload.get("description"),
            "tags": [tag for tag in self.payload.get("tags", [])]
        }

        if with_payload:
            d["payload"] = self.payload

        return d

    @staticmethod
    def get_by_id(exp_id: Union[str, uuid.UUID]) -> Optional['Experiment']:
        if not exp_id:
            return None

        if isinstance(exp_id, str):
            try:
                exp_id = shortuuid.decode(exp_id)
            except ValueError:
                return None

        return Experiment.query.filter(Experiment.id == exp_id).first()

    def get_execution(self, timestamp: int) -> Optional['Execution']:
        return Execution.query.filter(
            Execution.experiment_id == self.id,
            Execution.timestamp == timestamp).first()
Exemplo n.º 21
0
class RecommendationTag(db.Model):  # type: ignore
    __bind_key__ = 'experiment_service'
    __tablename__ = "recommendation_tag"
    id = db.Column(db.Integer, primary_key=True)
    value = db.Column(db.String(), nullable=False, unique=True)