Skip to content

Commit

Permalink
feat(models): add workflow run sharing tables (reanahub#216)
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 19, 2024
1 parent 67a7254 commit 365ee81
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 17 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,51 @@
"""Workflow sharing.
Revision ID: 2e82f33ee37d
Revises: eb5309f3d8ee
Create Date: 2024-03-14 13:12:01.029714
"""

import sqlalchemy_utils
import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision = "2e82f33ee37d"
down_revision = "eb5309f3d8ee"
branch_labels = None
depends_on = None


def upgrade():
"""Upgrade to 2e82f33ee37d 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.String(length=5000), nullable=True),
sa.Column("valid_until", sa.DateTime(), nullable=True),
sa.ForeignKeyConstraint(
["user_id"],
["__reana.user_.id_"],
name=op.f("fk_user_workflow_user_id_user_"),
),
sa.ForeignKeyConstraint(
["workflow_id"],
["__reana.workflow.id_"],
name=op.f("fk_user_workflow_workflow_id_workflow"),
),
sa.PrimaryKeyConstraint(
"workflow_id", "user_id", name=op.f("pk_user_workflow")
),
schema="__reana",
)


def downgrade():
"""Downgrade to eb5309f3d8ee revision."""
op.drop_table("user_workflow", schema="__reana")
sa.Enum(name="accesstype").drop(op.get_bind())
65 changes: 48 additions & 17 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,21 @@
)
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,
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,
)
from sqlalchemy import (
BigInteger,
Boolean,
Expand All @@ -43,6 +58,7 @@
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
Expand All @@ -51,22 +67,6 @@
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 +159,14 @@ class User(Base, Timestamp, QuotaBase):
username = Column(String(length=255))
tokens = relationship("UserToken", backref="user_", lazy="dynamic")
workflows = relationship("Workflow", backref="owner", lazy="dynamic")
workflows_shared_with_me = relationship(
"Workflow",
secondary="__reana.user_workflow",
backref="users_it_is_shared_with",
lazy="dynamic",
viewonly=True,
sync_backref=False,
)
audit_logs = relationship("AuditLog", backref="user_")

def __init__(self, access_token=None, **kwargs):
Expand Down Expand Up @@ -1182,3 +1190,26 @@ 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(String(5000))
valid_until = Column(DateTime)

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

0 comments on commit 365ee81

Please sign in to comment.