Skip to content
Merged
Changes from all commits
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
40 changes: 32 additions & 8 deletions api/projects/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@
from pydantic import BaseModel, ConfigDict, HttpUrl
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
import validators

from api.auth import require_auth # type: ignore
from db import get_db # , engine
from models.user import User, UserProject

CDN_HOST = "hc-cdn.hel1.your-objectstorage.com"


class CreateProjectRequest(BaseModel):
"""Create project request from client"""
Expand Down Expand Up @@ -69,11 +72,26 @@ def from_model(cls, project: UserProject) -> "ProjectResponse":


router = APIRouter()

# @protect
# async def create_project(): ...


def validate_repo(repo: HttpUrl | None):
"""Validate repository URL against security criteria"""
if not repo:
raise HTTPException(status_code=400, detail="repo url is missing")
if not repo.host:
raise HTTPException(status_code=400, detail="repo url is missing host")
if not validators.url(str(repo), private=False):
raise HTTPException(
status_code=400, detail="repo url is not valid or is local/private"
)
if len(repo.host) > 256:
raise HTTPException(
status_code=400, detail="repo url host exceeds the length limit"
)


# @protect
@router.post("/api/projects/update")
@require_auth
Expand All @@ -100,11 +118,15 @@ async def update_project(

# Validate preview image if being updated
if project_request.preview_image is not None:
if project_request.preview_image.host != "hc-cdn.hel1.your-objectstorage.com":
if project_request.preview_image.host != CDN_HOST:
raise HTTPException(
status_code=400, detail="image must be hosted on hc cdn"
status_code=400, detail="image must be hosted on the Hack Club CDN"
)

# Validate repo URL if being updated
if project_request.repo is not None:
validate_repo(project_request.repo)

update_data = project_request.model_dump(
exclude_unset=True, exclude={"project_id"}, mode="python"
)
Expand Down Expand Up @@ -218,11 +240,13 @@ async def create_project(
) # if the user hasn't been created yet they shouldn't be authed

# Validate preview image
if (
project_create_request.preview_image.host
!= "hc-cdn.hel1.your-objectstorage.com"
):
raise HTTPException(status_code=400, detail="image must be hosted on hc cdn")
if project_create_request.preview_image.host != CDN_HOST:
raise HTTPException(
status_code=400, detail="image must be hosted on the Hack Club CDN"
)

# Validate repo URL
validate_repo(project_create_request.repo)

new_project = UserProject(
name=project_create_request.project_name,
Expand Down