Add slug validation and test (#1891)

Fixes #1890 

Adds validation for org slugs, ensuring that they contain only ASCII
alphanumeric characters and dashes (`-`). If an invalid slug is
provided, an HTTPException is returned with status code 400 and detail
`invalid_slug`.
This commit is contained in:
Tessa Walsh 2024-06-26 15:04:54 -04:00 committed by GitHub
parent 6df10d5fb0
commit b7631d1b91
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 30 additions and 3 deletions

View File

@ -41,7 +41,7 @@ from .models import (
PaginatedResponse, PaginatedResponse,
) )
from .pagination import DEFAULT_PAGE_SIZE, paginated_format from .pagination import DEFAULT_PAGE_SIZE, paginated_format
from .utils import slug_from_name from .utils import slug_from_name, validate_slug
if TYPE_CHECKING: if TYPE_CHECKING:
from .invites import InviteOps from .invites import InviteOps
@ -775,8 +775,10 @@ def init_orgs_api(app, mdb, user_manager, invites, user_dep):
id_ = uuid4() id_ = uuid4()
slug = new_org.slug if new_org.slug:
if not slug: validate_slug(new_org.slug)
slug = new_org.slug
else:
slug = slug_from_name(new_org.name) slug = slug_from_name(new_org.name)
org = Organization( org = Organization(
@ -803,6 +805,7 @@ def init_orgs_api(app, mdb, user_manager, invites, user_dep):
): ):
org.name = rename.name org.name = rename.name
if rename.slug: if rename.slug:
validate_slug(rename.slug)
org.slug = rename.slug org.slug = rename.slug
else: else:
org.slug = slug_from_name(rename.name) org.slug = slug_from_name(rename.name)

View File

@ -8,6 +8,7 @@ import json
import signal import signal
import os import os
import sys import sys
import re
from datetime import datetime from datetime import datetime
from typing import Optional, Dict, Union, List from typing import Optional, Dict, Union, List
@ -123,6 +124,15 @@ def slug_from_name(name: str) -> str:
return slugify(name.replace("'", "")) return slugify(name.replace("'", ""))
def validate_slug(slug: str) -> None:
"""Validate org slug, raise HTTPException if invalid
Slugs must contain alphanumeric characters and dashes (-) only.
"""
if re.match(r"^[\w-]+$", slug) is None:
raise HTTPException(status_code=400, detail="invalid_slug")
def stream_dict_list_as_csv(data: List[Dict[str, Union[str, int]]], filename: str): def stream_dict_list_as_csv(data: List[Dict[str, Union[str, int]]], filename: str):
"""Stream list of dictionaries as CSV with attachment filename header""" """Stream list of dictionaries as CSV with attachment filename header"""
if not data: if not data:

View File

@ -72,6 +72,20 @@ def test_rename_org(admin_auth_headers, default_org_id):
assert data["slug"] == UPDATED_SLUG assert data["slug"] == UPDATED_SLUG
def test_rename_org_invalid_slug(admin_auth_headers, default_org_id):
UPDATED_NAME = "updated org name"
UPDATED_SLUG = "not a valid slug"
rename_data = {"name": UPDATED_NAME, "slug": UPDATED_SLUG}
r = requests.post(
f"{API_PREFIX}/orgs/{default_org_id}/rename",
headers=admin_auth_headers,
json=rename_data,
)
assert r.status_code == 400
assert r.json()["detail"] == "invalid_slug"
def test_create_org(admin_auth_headers): def test_create_org(admin_auth_headers):
NEW_ORG_NAME = "New Org" NEW_ORG_NAME = "New Org"
r = requests.post( r = requests.post(