Add multi-tenancy with Teams feature

This commit is contained in:
Mondo Diaz
2026-01-28 12:50:58 -06:00
parent a5796f5437
commit 576791d19e
33 changed files with 5493 additions and 115 deletions

View File

@@ -5,8 +5,9 @@ import hashlib
import logging
from sqlalchemy.orm import Session
from .models import Project, Package, Artifact, Tag, Upload, PackageVersion, ArtifactDependency
from .models import Project, Package, Artifact, Tag, Upload, PackageVersion, ArtifactDependency, Team, TeamMembership, User
from .storage import get_storage
from .auth import hash_password
logger = logging.getLogger(__name__)
@@ -149,6 +150,80 @@ def seed_database(db: Session) -> None:
logger.info("Seeding database with test data...")
storage = get_storage()
# Find or use admin user for team ownership
admin_user = db.query(User).filter(User.username == "admin").first()
team_owner_username = admin_user.username if admin_user else "seed-user"
# Create a demo team
demo_team = Team(
name="Demo Team",
slug="demo-team",
description="A demonstration team with sample projects",
created_by=team_owner_username,
)
db.add(demo_team)
db.flush()
# Add admin user as team owner if they exist
if admin_user:
membership = TeamMembership(
team_id=demo_team.id,
user_id=admin_user.id,
role="owner",
invited_by=team_owner_username,
)
db.add(membership)
db.flush()
logger.info(f"Created team: {demo_team.name} ({demo_team.slug})")
# Create test users with various roles
test_users = [
{"username": "alice", "email": "alice@example.com", "role": "admin"},
{"username": "bob", "email": "bob@example.com", "role": "admin"},
{"username": "charlie", "email": "charlie@example.com", "role": "member"},
{"username": "diana", "email": "diana@example.com", "role": "member"},
{"username": "eve", "email": "eve@example.com", "role": "member"},
{"username": "frank", "email": None, "role": "member"},
]
for user_data in test_users:
# Check if user already exists
existing_user = db.query(User).filter(User.username == user_data["username"]).first()
if existing_user:
test_user = existing_user
else:
# Create the user with password same as username
test_user = User(
username=user_data["username"],
email=user_data["email"],
password_hash=hash_password(user_data["username"]),
is_admin=False,
is_active=True,
must_change_password=False,
)
db.add(test_user)
db.flush()
logger.info(f"Created test user: {user_data['username']}")
# Add to demo team with specified role
existing_membership = db.query(TeamMembership).filter(
TeamMembership.team_id == demo_team.id,
TeamMembership.user_id == test_user.id,
).first()
if not existing_membership:
membership = TeamMembership(
team_id=demo_team.id,
user_id=test_user.id,
role=user_data["role"],
invited_by=team_owner_username,
)
db.add(membership)
logger.info(f"Added {user_data['username']} to {demo_team.slug} as {user_data['role']}")
db.flush()
# Create projects and packages
project_map = {}
package_map = {}
@@ -158,7 +233,8 @@ def seed_database(db: Session) -> None:
name=project_data["name"],
description=project_data["description"],
is_public=project_data["is_public"],
created_by="seed-user",
created_by=team_owner_username,
team_id=demo_team.id, # Assign to demo team
)
db.add(project)
db.flush() # Get the ID
@@ -174,7 +250,7 @@ def seed_database(db: Session) -> None:
db.flush()
package_map[(project_data["name"], package_data["name"])] = package
logger.info(f"Created {len(project_map)} projects and {len(package_map)} packages")
logger.info(f"Created {len(project_map)} projects and {len(package_map)} packages (assigned to {demo_team.slug})")
# Create artifacts, tags, and versions
artifact_count = 0
@@ -212,7 +288,7 @@ def seed_database(db: Session) -> None:
size=size,
content_type=artifact_data["content_type"],
original_name=artifact_data["filename"],
created_by="seed-user",
created_by=team_owner_username,
s3_key=s3_key,
ref_count=ref_count,
)
@@ -235,7 +311,7 @@ def seed_database(db: Session) -> None:
artifact_id=sha256_hash,
version=artifact_data["version"],
version_source="explicit",
created_by="seed-user",
created_by=team_owner_username,
)
db.add(version)
version_count += 1
@@ -246,7 +322,7 @@ def seed_database(db: Session) -> None:
package_id=package.id,
name=tag_name,
artifact_id=sha256_hash,
created_by="seed-user",
created_by=team_owner_username,
)
db.add(tag)
tag_count += 1