Skip to content

Commit 23a97f2

Browse files
authored
Merge pull request #16 from hackclub/git-url-validation
Git url validation redone
2 parents 478da2f + 1bba12c commit 23a97f2

File tree

1 file changed

+32
-8
lines changed

1 file changed

+32
-8
lines changed

api/projects/main.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@
1212
from pydantic import BaseModel, ConfigDict, HttpUrl
1313
from sqlalchemy.ext.asyncio import AsyncSession
1414
from sqlalchemy.orm import selectinload
15+
import validators
1516

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

21+
CDN_HOST = "hc-cdn.hel1.your-objectstorage.com"
22+
2023

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

7073

7174
router = APIRouter()
72-
7375
# @protect
7476
# async def create_project(): ...
7577

7678

79+
def validate_repo(repo: HttpUrl | None):
80+
"""Validate repository URL against security criteria"""
81+
if not repo:
82+
raise HTTPException(status_code=400, detail="repo url is missing")
83+
if not repo.host:
84+
raise HTTPException(status_code=400, detail="repo url is missing host")
85+
if not validators.url(str(repo), private=False):
86+
raise HTTPException(
87+
status_code=400, detail="repo url is not valid or is local/private"
88+
)
89+
if len(repo.host) > 256:
90+
raise HTTPException(
91+
status_code=400, detail="repo url host exceeds the length limit"
92+
)
93+
94+
7795
# @protect
7896
@router.post("/api/projects/update")
7997
@require_auth
@@ -100,11 +118,15 @@ async def update_project(
100118

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

126+
# Validate repo URL if being updated
127+
if project_request.repo is not None:
128+
validate_repo(project_request.repo)
129+
108130
update_data = project_request.model_dump(
109131
exclude_unset=True, exclude={"project_id"}, mode="python"
110132
)
@@ -218,11 +240,13 @@ async def create_project(
218240
) # if the user hasn't been created yet they shouldn't be authed
219241

220242
# Validate preview image
221-
if (
222-
project_create_request.preview_image.host
223-
!= "hc-cdn.hel1.your-objectstorage.com"
224-
):
225-
raise HTTPException(status_code=400, detail="image must be hosted on hc cdn")
243+
if project_create_request.preview_image.host != CDN_HOST:
244+
raise HTTPException(
245+
status_code=400, detail="image must be hosted on the Hack Club CDN"
246+
)
247+
248+
# Validate repo URL
249+
validate_repo(project_create_request.repo)
226250

227251
new_project = UserProject(
228252
name=project_create_request.project_name,

0 commit comments

Comments
 (0)