Skip to content

Commit

Permalink
feature(models): add workflow run sharing tables
Browse files Browse the repository at this point in the history
Adds a table and an enum to the database. The `user_workflow` table
makes it possible to verify whether a specific workflow has been shared
with a user. The `accesstype` enum defines the different access types
that can be granted to a user. For now, only `read` access is supported.

Closes reanahub#206
  • Loading branch information
DaanRosendal authored and mdonadoni committed Aug 9, 2024
1 parent 67a7254 commit 1889863
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 19 deletions.
1 change: 1 addition & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ The list of contributors in alphabetical order:

- [Audrius Mecionis](https://orcid.org/0000-0002-3759-1663)
- [Camila Diaz](https://orcid.org/0000-0001-5543-797X)
- [Daan Rosendal](https://orcid.org/0000-0002-3447-9000)
- [Diego Rodriguez](https://orcid.org/0000-0003-0649-2002)
- [Dinos Kousidis](https://orcid.org/0000-0002-4914-4289)
- [Giuseppe Steduto](https://orcid.org/0009-0002-1258-8553)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""Workflow sharing.
Revision ID: 4543cde7c9fb
Revises: eb5309f3d8ee
Create Date: 2023-11-02 20:03:01.234086
Rebase Date: 2024-08-09
"""
import sqlalchemy as sa
import sqlalchemy_utils
from alembic import op

# revision identifiers, used by Alembic.
revision = "4543cde7c9fb"
down_revision = "eb5309f3d8ee"
branch_labels = None
depends_on = None


def upgrade():
"""Upgrade to 4543cde7c9fb revision."""
op.create_table(
"user_workflow",
sa.Column(
"workflow_id", sqlalchemy_utils.types.uuid.UUIDType(), nullable=False
),
sa.Column("user_id", sqlalchemy_utils.types.uuid.UUIDType(), nullable=False),
sa.Column("access_type", sa.Enum("read", name="accesstype"), nullable=False),
sa.Column("message", sa.Text(), nullable=True),
sa.Column("valid_until", sa.DateTime(), nullable=True),
sa.ForeignKeyConstraint(
["user_id"],
["__reana.user_.id_"],
),
sa.ForeignKeyConstraint(
["workflow_id"],
["__reana.workflow.id_"],
),
sa.PrimaryKeyConstraint("workflow_id", "user_id"),
schema="__reana",
)


def downgrade():
"""Downgrade to 377cfbfccf75 revision."""
op.drop_table("user_workflow", schema="__reana")
sa.Enum(name="accesstype").drop(op.get_bind())
68 changes: 49 additions & 19 deletions reana_db/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
from __future__ import absolute_import

import enum
import math
import logging
import math
import uuid
from datetime import datetime
from functools import reduce
Expand All @@ -26,6 +26,22 @@
)
from reana_commons.errors import REANAValidationError
from reana_commons.utils import get_disk_usage
from reana_db.config import (
DB_SECRET_KEY,
DEFAULT_QUOTA_LIMITS,
DEFAULT_QUOTA_RESOURCES,
LIMIT_RESTARTS,
WORKFLOW_TERMINATION_QUOTA_UPDATE_POLICY,
)
from reana_db.utils import (
build_workspace_path,
split_run_number,
store_workflow_disk_quota,
update_users_cpu_quota,
update_users_disk_quota,
update_workflow_cpu_quota,
update_workspace_retention_rules,
)
from sqlalchemy import (
BigInteger,
Boolean,
Expand All @@ -43,30 +59,13 @@
func,
or_,
)
from sqlalchemy.dialects.postgresql import ARRAY
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship
from sqlalchemy_utils import EncryptedType, JSONType, UUIDType
from sqlalchemy_utils.models import Timestamp
from sqlalchemy_utils.types.encrypted.encrypted_type import AesEngine
from sqlalchemy.dialects.postgresql import ARRAY

from reana_db.config import (
DB_SECRET_KEY,
DEFAULT_QUOTA_LIMITS,
DEFAULT_QUOTA_RESOURCES,
WORKFLOW_TERMINATION_QUOTA_UPDATE_POLICY,
)
from reana_db.utils import (
build_workspace_path,
store_workflow_disk_quota,
split_run_number,
update_users_cpu_quota,
update_users_disk_quota,
update_workflow_cpu_quota,
update_workspace_retention_rules,
)


convention = {
"ix": "ix_%(column_0_label)s",
Expand Down Expand Up @@ -159,6 +158,12 @@ class User(Base, Timestamp, QuotaBase):
username = Column(String(length=255))
tokens = relationship("UserToken", backref="user_", lazy="dynamic")
workflows = relationship("Workflow", backref="owner", lazy="dynamic")
shared_workflows = relationship(
"Workflow",
secondary="__reana.user_workflow",
backref="shared_users",
lazy="dynamic",
)
audit_logs = relationship("AuditLog", backref="user_")

def __init__(self, access_token=None, **kwargs):
Expand Down Expand Up @@ -1182,3 +1187,28 @@ class QuotaHealth(enum.Enum):
healthy = 0
warning = 1
critical = 2


class AccessType(enum.Enum):
"""Enumeration of access types."""

read = 0


class UserWorkflow(Base):
"""UserWorkflow table."""

__tablename__ = "user_workflow"
__table_args__ = {"schema": "__reana"}

workflow_id = Column(UUIDType, ForeignKey("__reana.workflow.id_"), primary_key=True)
user_id = Column(UUIDType, ForeignKey("__reana.user_.id_"), primary_key=True)
access_type = Column(Enum(AccessType), default=AccessType.read, nullable=False)
message = Column(Text)
valid_until = Column(DateTime)

user = relationship("User", backref="user_workflows")

def __repr__(self):
"""User Workflow string representation."""
return "<UserWorkflow {} {}>".format(self.workflow_id, self.user_id)

0 comments on commit 1889863

Please sign in to comment.