dataflow-core 2.1.14rc1__py3-none-any.whl → 2.1.15rc2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of dataflow-core might be problematic. Click here for more details.

@@ -0,0 +1,79 @@
1
+ from sqlalchemy import (
2
+ Column, Integer, String, Enum, DateTime, ForeignKey, Index
3
+ )
4
+ import uuid, enum
5
+ from sqlalchemy.dialects.postgresql import JSONB, UUID
6
+ from sqlalchemy.sql import func
7
+ from sqlalchemy.orm import relationship
8
+ from datetime import datetime
9
+ from dataflow.db import Base
10
+
11
+
12
+ class Organization(Base):
13
+ """
14
+ Organization model for the database.
15
+ """
16
+ __tablename__ = "ORGANIZATION"
17
+
18
+ id = Column(Integer, primary_key=True, autoincrement=True)
19
+ uid = Column(UUID(as_uuid=True), default=uuid.uuid4, nullable=False, unique=True)
20
+ name = Column(String(255), nullable=False, unique=True)
21
+ invite_code = Column(String(64), nullable=False, unique=True)
22
+ email_domain = Column(String(255), nullable=False, unique=True)
23
+ spark_enabled_zones = Column(JSONB, default=func.json([])) # List of zone IDs where Spark is enabled
24
+ created_at = Column(DateTime, default=datetime.utcnow)
25
+
26
+ # Association object link
27
+ org_user_assocs = relationship("OrganizationUser", back_populates="organization", cascade="all, delete-orphan")
28
+ custom_servers = relationship("CustomServerConfig")
29
+ onboarding_requests = relationship("UserOnboarding", back_populates="organization", cascade="all, delete-orphan")
30
+ servers = relationship("ServerConfig", secondary="ORGANIZATION_SERVER", back_populates="organizations")
31
+ apps = relationship("AppType", secondary="ORGANIZATION_APP_TYPE", back_populates="organizations")
32
+ roles = relationship("Role", cascade="all, delete-orphan")
33
+ environments = relationship("Environment", back_populates="organization")
34
+
35
+ class OnboardingStatus(enum.Enum):
36
+ pending = 'pending'
37
+ rejected = 'rejected'
38
+ accepted = 'accepted'
39
+
40
+ class OrganizationOnboarding(Base):
41
+ __tablename__ = 'ORGANIZATION_ONBOARDING'
42
+ # This prevents an org from having more than one active ('pending' or 'accepted') application
43
+ # while allowing multiple 'rejected' entries.
44
+ __table_args__ = (
45
+ Index(
46
+ 'idx_pending_org_application',
47
+ 'name',
48
+ unique=True,
49
+ postgresql_where=Column('status').in_([
50
+ OnboardingStatus.pending.value,
51
+ OnboardingStatus.accepted.value
52
+ ])
53
+ ),
54
+ )
55
+
56
+ id = Column(Integer, primary_key=True, autoincrement=True)
57
+
58
+ name = Column(String(255), nullable=False)
59
+ age = Column(Integer, nullable=True)
60
+ domain = Column(String(255), nullable=True)
61
+ no_of_employees = Column(String(50), nullable=True)
62
+ address = Column(String(500), nullable=True)
63
+
64
+ admin_first_name = Column(String(100), nullable=False)
65
+ admin_last_name = Column(String(100), nullable=True)
66
+ admin_designation = Column(String(100), nullable=False)
67
+ admin_email = Column(String(255), nullable=False, unique=True)
68
+ admin_username = Column(String(100), nullable=False, unique=True)
69
+ admin_password = Column(String(255), nullable=False)
70
+
71
+ # New fields
72
+ discovery_source = Column(String(255), nullable=True)
73
+ additional_info = Column(String(1000), nullable=True)
74
+ size_of_data = Column(String(100), nullable=True)
75
+
76
+ user_id = Column(Integer, ForeignKey('USER.user_id'), nullable=False)
77
+ status = Column(Enum(OnboardingStatus), default=OnboardingStatus.pending, nullable=False)
78
+
79
+ user = relationship("User", back_populates="organization_onboarding")
@@ -1,23 +1,25 @@
1
- from sqlalchemy import Column, String, Enum, DateTime, Integer, func, ForeignKey
1
+ from sqlalchemy import Column, String, Enum, DateTime, Integer, func, ForeignKey, UniqueConstraint
2
2
  from sqlalchemy.orm import relationship
3
3
  from dataflow.db import Base
4
4
 
5
5
  class ProjectDetails(Base):
6
6
  __tablename__ = "PROJECT_DETAIL"
7
+ __table_args__ = (UniqueConstraint('org_id', 'slug', name='uq_project_org_slug'),)
7
8
 
8
9
  project_id = Column(Integer, primary_key=True, autoincrement=True)
9
10
  project_name = Column(String, nullable=False)
10
11
  git_url = Column(String)
11
12
  git_branch = Column(String, nullable=True)
12
13
  git_folder = Column(String, nullable=True)
13
- type = Column(String, ForeignKey('RUNTIME_APP_TYPE.name', ondelete="CASCADE"), nullable=False)
14
- slug = Column(String, nullable=False, unique=True)
14
+ type = Column(String, ForeignKey('APP_TYPE.name'), nullable=False)
15
+ slug = Column(String, nullable=False)
15
16
  runtime = Column(String, nullable=False)
16
- py_env = Column(String, nullable=True)
17
+ py_env = Column(Integer, nullable=True)
17
18
  launch_url = Column(String, nullable=True)
18
19
  status = Column(Enum("pending", "created" ,"deployed", "stopped", "failed", name="deployment_status"), default="created")
19
20
  last_deployed = Column(DateTime, nullable=True)
20
21
  created_at = Column(DateTime, nullable=False, server_default=func.now())
21
22
  created_by = Column(String, nullable=False)
23
+ org_id = Column(Integer, ForeignKey('ORGANIZATION.id', ondelete='CASCADE'), nullable=False)
22
24
 
23
- app_type = relationship("AppType")
25
+ app_type = relationship("AppType")
dataflow/models/role.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """models.py"""
2
- from sqlalchemy import Column, Integer, String, Enum
2
+ from sqlalchemy import Column, Integer, String, Enum, ForeignKey, UniqueConstraint
3
3
  from sqlalchemy.orm import relationship
4
4
  from dataflow.db import Base
5
5
  import enum
@@ -11,19 +11,25 @@ class BaseRoleField(enum.Enum):
11
11
 
12
12
  class Role(Base):
13
13
  """
14
- Table Role
14
+ Table ROLE
15
15
  """
16
16
 
17
17
  __tablename__='ROLE'
18
+ __table_args__ = (
19
+ UniqueConstraint('name', 'org_id', name='uq_role_name_org'),
20
+ )
18
21
 
19
22
  id = Column(Integer, primary_key=True, index=True, autoincrement=True, nullable=False)
20
- name = Column(String, unique=True, nullable=False)
23
+ name = Column(String, nullable=False)
24
+ org_id = Column(Integer, ForeignKey('ORGANIZATION.id'))
21
25
  description = Column(String, nullable=True)
22
26
  base_role = Column(Enum(BaseRoleField), nullable=False, default=BaseRoleField.user)
23
27
 
24
- users = relationship("User", back_populates="role_details", cascade="all, delete-orphan")
25
- role_server_assocs = relationship("RoleServer", back_populates="role")
28
+ # Relationships
26
29
  role_zone_assocs = relationship("RoleZone", back_populates="role")
30
+ org_user_assocs = relationship("OrganizationUser", back_populates="role", cascade="all, delete-orphan")
31
+ organization = relationship("Organization", back_populates="roles")
32
+ servers = relationship("CustomServerConfig", secondary="ROLE_SERVER", back_populates="roles")
27
33
 
28
34
  def __repr__(self):
29
35
  return f"<Role(id={self.id}, name='{self.name}', base_role='{self.base_role}')>"
@@ -5,10 +5,7 @@ from dataflow.db import Base
5
5
 
6
6
  class RoleServer(Base):
7
7
  __tablename__ = 'ROLE_SERVER'
8
- __table_args__ = (UniqueConstraint('role_id', 'server_id', name='_role_server_uc'),)
8
+ __table_args__ = (UniqueConstraint('role_id', 'custom_server_id', name='_role_server_uc'),)
9
9
 
10
10
  role_id = Column(Integer, ForeignKey('ROLE.id', ondelete="CASCADE"), nullable=False, primary_key=True)
11
- server_id = Column(Integer, ForeignKey('CUSTOM_SERVER.id', ondelete="CASCADE"), nullable=False, primary_key=True)
12
-
13
- role = relationship("Role", back_populates="role_server_assocs")
14
- server = relationship("CustomServerConfig", back_populates="role_server_assocs")
11
+ custom_server_id = Column(Integer, ForeignKey('CUSTOM_SERVER.id', ondelete="CASCADE"), nullable=False, primary_key=True)
@@ -19,15 +19,19 @@ class ServerConfig(Base):
19
19
  description = Column(Text, nullable=True)
20
20
  kubespawner_override = Column(JSONB, default=func.json({}))
21
21
 
22
+ # Relationships
23
+ organizations = relationship("Organization", secondary="ORGANIZATION_SERVER", back_populates="servers")
22
24
 
23
25
  class CustomServerConfig(Base):
24
26
  __tablename__ = "CUSTOM_SERVER"
25
27
 
26
28
  id = Column(Integer, primary_key=True, autoincrement=True)
27
29
  base_server_id = Column(Integer, ForeignKey(ServerConfig.id, ondelete="CASCADE"), nullable=False)
30
+ org_id = Column(Integer, ForeignKey('ORGANIZATION.id'), nullable=False)
28
31
  display_name = Column(String, nullable=False, unique=True, index=True)
29
32
  description = Column(Text, nullable=True)
30
33
 
31
34
  # Relationship to the server_config table
32
35
  server_config = relationship(ServerConfig)
33
- role_server_assocs = relationship("RoleServer", back_populates="server", cascade="all, delete-orphan")
36
+ organization = relationship("Organization", back_populates="custom_servers")
37
+ roles = relationship("Role", secondary="ROLE_SERVER", back_populates="servers")
dataflow/models/team.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """models.py"""
2
- from sqlalchemy import Column, Integer, String
2
+ from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint
3
3
  from sqlalchemy.orm import relationship
4
4
  from dataflow.db import Base
5
5
 
@@ -9,9 +9,15 @@ class Team(Base):
9
9
  """
10
10
 
11
11
  __tablename__='TEAM'
12
+ __table_args__ = (
13
+ UniqueConstraint('team_name', 'org_id', name='uc_team_name_org_id'),
14
+ )
12
15
 
13
16
  team_id = Column(Integer, primary_key=True, index=True, autoincrement=True, nullable=False)
14
- team_name = Column(String, unique=True, nullable=False)
17
+ team_name = Column(String, nullable=False)
18
+ org_id = Column(Integer, ForeignKey('ORGANIZATION.id', ondelete="CASCADE"), nullable=False)
15
19
  description = Column(String, nullable=True)
16
-
17
- user_team_assocs = relationship("UserTeam", back_populates="team")
20
+
21
+ # relationships
22
+ users = relationship("User", secondary="USER_TEAM", back_populates="teams")
23
+ organization = relationship("Organization")
dataflow/models/user.py CHANGED
@@ -1,31 +1,68 @@
1
1
  """models.py"""
2
- from sqlalchemy import Column, Integer, String, Boolean, LargeBinary, ForeignKey
2
+ from sqlalchemy import Column, Integer, String, Boolean, LargeBinary, Enum, ForeignKey, DateTime, func
3
+ from sqlalchemy.dialects.postgresql import ENUM
4
+ from sqlalchemy import Index
3
5
  from sqlalchemy.orm import relationship
4
6
  from dataflow.db import Base
7
+ import enum
5
8
 
6
9
  class User(Base):
7
10
  """
8
11
  Table USER
9
12
  """
10
-
11
- __tablename__='USER'
13
+ __tablename__ = 'USER'
12
14
 
13
15
  user_id = Column(Integer, primary_key=True, index=True, autoincrement=True, nullable=False)
14
16
  user_name = Column(String, unique=True, nullable=False)
15
17
  first_name = Column(String)
16
18
  last_name = Column(String)
17
19
  email = Column(String, unique=True)
18
- role_id = Column(Integer, ForeignKey('ROLE.id'), nullable=False)
19
20
  image = Column(LargeBinary)
20
21
  image_url = Column(String, nullable=True)
21
22
  active = Column(Boolean, nullable=False, default=True)
22
23
  password = Column(String, nullable=False)
23
- active_env = Column(String)
24
- active_env_type = Column(String, nullable=True)
25
- current_server = Column(String)
26
- show_server_page = Column(Boolean, default = True)
27
- monthly_allocation = Column(Integer, nullable=True, default=0)
24
+ active_org_id = Column(Integer, ForeignKey('ORGANIZATION.id'))
25
+
26
+ # Relationships
27
+ org_user_assocs = relationship("OrganizationUser", back_populates="user", cascade="all, delete-orphan")
28
+ teams = relationship("Team", secondary="USER_TEAM", back_populates="users")
29
+ onboarding_requests = relationship("UserOnboarding", back_populates="user", cascade="all, delete-orphan")
30
+ organization_onboarding = relationship("OrganizationOnboarding", back_populates="user", cascade="all, delete-orphan")
31
+
32
+
33
+ class OnboardingStatus(enum.Enum):
34
+ pending = 'pending'
35
+ rejected = 'rejected'
36
+ accepted = 'accepted'
37
+
38
+ class UserOnboarding(Base):
39
+ """
40
+ SQLAlchemy model for the "USER_ONBOARDING" table.
41
+ This table stores user applications to organizations.
42
+ """
43
+ __tablename__ = "USER_ONBOARDING"
44
+ # This prevents a user from having more than one active ('pending' or 'accepted') application
45
+ # for a given organization, while allowing multiple 'rejected' entries.
46
+ __table_args__ = (
47
+ Index(
48
+ 'idx_pending_user_org_application',
49
+ 'user_id',
50
+ 'org_id',
51
+ unique=True,
52
+ postgresql_where=Column('status').in_([
53
+ OnboardingStatus.pending.value,
54
+ OnboardingStatus.accepted.value
55
+ ])
56
+ ),
57
+ )
28
58
 
29
- role_details = relationship("Role")
59
+ id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
60
+ user_id = Column(Integer, ForeignKey("USER.user_id", ondelete="CASCADE"), nullable=False)
61
+ org_id = Column(Integer, ForeignKey("ORGANIZATION.id", ondelete="CASCADE"), nullable=False)
62
+ status = Column(Enum(OnboardingStatus, name='onboarding_status'), nullable=False, default=OnboardingStatus.pending.value)
63
+ created_at = Column(DateTime, default=func.now(), nullable=False)
64
+ updated_at = Column(DateTime, default=func.now(), onupdate=func.now(), nullable=False)
30
65
 
31
- user_team_assocs = relationship("UserTeam", back_populates="user")
66
+ # Relationships
67
+ user = relationship("User", back_populates="onboarding_requests")
68
+ organization = relationship("Organization", back_populates="onboarding_requests")
@@ -8,7 +8,4 @@ class UserTeam(Base):
8
8
  __table_args__ = (UniqueConstraint('user_id', 'team_id', name='_user_team_uc'),)
9
9
 
10
10
  user_id = Column(Integer, ForeignKey('USER.user_id', ondelete="CASCADE"), nullable=False, primary_key=True)
11
- team_id = Column(Integer, ForeignKey('TEAM.team_id', ondelete="CASCADE"), nullable=False, primary_key=True)
12
-
13
- user = relationship("User", back_populates="user_team_assocs")
14
- team = relationship("Team", back_populates="user_team_assocs")
11
+ team_id = Column(Integer, ForeignKey('TEAM.team_id', ondelete="CASCADE"), nullable=False, primary_key=True)
@@ -14,7 +14,8 @@ class Variable(Base):
14
14
  __tablename__ = 'VARIABLE'
15
15
 
16
16
  id = Column(Integer, primary_key=True, index=True, autoincrement=True, nullable=False)
17
- key = Column(String, nullable=False)
17
+ key = Column(String, index=True, nullable=False)
18
+ org_id = Column(Integer, ForeignKey("ORGANIZATION.id"), index=True, nullable=False)
18
19
  value = Column(Text, nullable=False)
19
20
  type = Column(String, nullable=False)
20
21
  description = Column(Text, nullable=True)
@@ -30,5 +31,5 @@ class Variable(Base):
30
31
 
31
32
  __table_args__ = (
32
33
  CheckConstraint(type.in_(['variable', 'secret']), name='check_variable_type'),
33
- UniqueConstraint('key', 'runtime', 'slug', 'created_by', name='unique_key'),
34
+ UniqueConstraint('key', 'org_id', 'runtime', 'slug', 'created_by', name='unique_key'),
34
35
  )
@@ -3,6 +3,7 @@ import os
3
3
  from .interface import SecretManager
4
4
  from .providers.aws_manager import AWSSecretsManager
5
5
  from .providers.azure_manager import AzureKeyVault
6
+ from .providers.gcp_manager import GCPSecretsManager
6
7
  from ..configuration import ConfigurationManager
7
8
 
8
9
  # A custom exception for clear error messages
@@ -17,10 +18,6 @@ def get_secret_manager() -> SecretManager:
17
18
  to determine which cloud provider's secret manager to instantiate.
18
19
  """
19
20
  try:
20
- # dataflow_config = None
21
- # if os.getenv('HOSTNAME'):
22
- # dataflow_config = ConfigurationManager('/dataflow/app/auth_config/dataflow_auth.cfg')
23
- # else:
24
21
  dataflow_config = ConfigurationManager('/dataflow/app/config/dataflow.cfg')
25
22
  except Exception as e:
26
23
  raise SecretProviderError(
@@ -49,11 +46,20 @@ def get_secret_manager() -> SecretManager:
49
46
  )
50
47
  return AzureKeyVault(vault_url=vault_url)
51
48
 
52
- # You can easily add more providers here in the future
53
- # elif provider == "gcp":
54
- # return GCPSecretManager()
49
+ elif provider == "gcp":
50
+ project_id = dataflow_config.get_config_value('cloudProvider', 'gcp_project_id')
51
+ region = dataflow_config.get_config_value('cloudProvider', 'gcp_region')
52
+ if not project_id:
53
+ raise SecretProviderError(
54
+ "GCP_PROJECT_ID must be set when using the GCP provider."
55
+ )
56
+ if not region:
57
+ raise SecretProviderError(
58
+ "GCP_REGION must be set when using the GCP provider."
59
+ )
60
+ return GCPSecretsManager(project_id=project_id, region=region)
55
61
 
56
62
  else:
57
63
  raise SecretProviderError(
58
- f"Unsupported secret provider: '{provider}'. Supported providers are: aws, azure."
64
+ f"Unsupported secret provider: '{provider}'. Supported providers are: aws, azure and gcp"
59
65
  )