Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 8 additions & 27 deletions warehouse/oidc/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
OIDC_ISSUER_SERVICE_NAMES,
lookup_custom_issuer_type,
)
from warehouse.organizations.models import OrganizationProject
from warehouse.packaging.interfaces import IProjectService
from warehouse.packaging.models import ProjectFactory
from warehouse.rate_limiting.interfaces import IRateLimiter
Expand Down Expand Up @@ -218,32 +217,14 @@ def mint_token(
# Try creating the new project
project_service = request.find_service(IProjectService)
try:
# Check if this pending publisher is for an organization
if pending_publisher.organization_id:
# For organization-owned projects,
# create without making the user an owner
new_project = project_service.create_project(
pending_publisher.project_name,
pending_publisher.added_by,
request,
creator_is_owner=False,
ratelimited=False,
)
# Add the project to the organization
request.db.add(
OrganizationProject(
organization_id=pending_publisher.organization_id,
project_id=new_project.id,
)
)
else:
# For user-owned projects, create normally
new_project = project_service.create_project(
pending_publisher.project_name,
pending_publisher.added_by,
request,
ratelimited=False,
)
new_project = project_service.create_project(
pending_publisher.project_name,
pending_publisher.added_by,
request,
creator_is_owner=pending_publisher.organization_id is None,
ratelimited=False,
organization_id=pending_publisher.organization_id,
)
except HTTPException as exc:
return _invalid(
errors=[{"code": "invalid-payload", "description": str(exc)}],
Expand Down
11 changes: 10 additions & 1 deletion warehouse/packaging/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

import typing

from uuid import UUID

from zope.interface import Interface

from warehouse.rate_limiting.interfaces import RateLimiterException
Expand Down Expand Up @@ -76,7 +78,14 @@ def check_project_name(name):
Check if a project name is valid and available for use.
"""

def create_project(name, creator, request, *, creator_is_owner=True):
def create_project(
name,
creator,
request,
*,
creator_is_owner=True,
organization_id: UUID | None = None,
):
"""
Creates a new project, recording a user as its creator.

Expand Down
22 changes: 19 additions & 3 deletions warehouse/packaging/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from warehouse.helpdesk.interfaces import IAdminNotificationService
from warehouse.metrics import IMetricsService
from warehouse.oidc.models import PendingOIDCPublisher
from warehouse.organizations.models import OrganizationProject
from warehouse.packaging.interfaces import (
IDocsStorage,
IFileStorage,
Expand Down Expand Up @@ -494,7 +495,14 @@ def check_project_name(self, name: str) -> None:
return None

def create_project(
self, name, creator, request, *, creator_is_owner=True, ratelimited=True
self,
name,
creator,
request,
*,
creator_is_owner=True,
ratelimited=True,
organization_id=None,
):
if ratelimited:
self._check_ratelimits(request, creator)
Expand Down Expand Up @@ -640,6 +648,7 @@ def create_project(
# The project name is valid: create it and add it
project = Project(name=name)
self.db.add(project)
self.db.flush() # To get the new ID

# TODO: This should be handled by some sort of database trigger or a
# SQLAlchemy hook or the like instead of doing it inline in this
Expand All @@ -657,8 +666,15 @@ def create_project(
additional={"created_by": creator.username},
)

# Mark the creator as the newly created project's owner, if configured.
if creator_is_owner:
if organization_id:
# If an organization ID is provided, we never set the creator to owner
self.db.add(
OrganizationProject(
organization_id=organization_id, project_id=project.id
)
)
elif creator_is_owner:
# Mark the creator as the newly created project's owner, if configured.
self.db.add(Role(user=creator, project=project, role_name="Owner"))
# TODO: This should be handled by some sort of database trigger or a
# SQLAlchemy hook or the like instead of doing it inline in this
Expand Down