Skip to content
Open
Show file tree
Hide file tree
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
10 changes: 7 additions & 3 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -141,17 +141,21 @@ jobs:
- name: Create auth directory
run: mkdir -p e2e/.auth

# List Playwright projects (for visibility)
- name: List Playwright projects
run: npx playwright test --list --reporter=list

# Run Playwright tests
- name: Run Playwright tests
run: npx playwright test --reporter=list
env:
CI: true

# Upload test results on failure
# Upload Playwright HTML report
- uses: actions/upload-artifact@v4
if: failure()
if: always()
with:
name: playwright-report
name: playwright-html-report
path: playwright-report/
retention-days: 30

Expand Down
12 changes: 7 additions & 5 deletions api/auth/user_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ async def _get_user_info(api_token: str) -> Optional[Dict[str, Any]]:
"""
query = """
MATCH (i:Identity)-[:HAS_TOKEN]->(t:Token {id: $api_token})
RETURN i.email, i.name, i.picture, (t IS NOT NULL AND timestamp() <= t.expires_at) AS token_valid
RETURN i.provider_user_id, i.email, i.name, i.picture, i.provider, (t IS NOT NULL AND timestamp() <= t.expires_at) AS token_valid
"""

try:
Expand All @@ -56,13 +56,15 @@ async def _get_user_info(api_token: str) -> Optional[Dict[str, Any]]:

if result.result_set:
single_result = result.result_set[0]
token_valid = single_result[3]
token_valid = single_result[5] # Updated index due to new fields

if token_valid:
return {
"email": single_result[0],
"name": single_result[1],
"picture": single_result[2],
"id": single_result[0], # provider_user_id as id
"email": single_result[1],
"name": single_result[2],
"picture": single_result[3],
"provider": single_result[4],
}
# Delete invalid/expired token from DB for cleanup
await delete_user_token(api_token)
Expand Down
40 changes: 31 additions & 9 deletions api/routes/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,18 @@ def _verify_password(password: str, stored_password_hex: str) -> bool:
return False

def _sanitize_for_log(value: str) -> str:
"""Sanitize user input for logging by removing newlines and carriage returns."""
"""Sanitize user input for logging by removing all newlines and separator characters."""
if not isinstance(value, str):
return str(value)
return value.replace('\r\n', '').replace('\n', '').replace('\r', '')
value = str(value)
# Remove CR, LF, CRLF, and Unicode line/paragraph separators
return (
value
.replace('\r\n', '')
.replace('\n', '')
.replace('\r', '')
.replace('\u2028', '')
.replace('\u2029', '')
)

def _validate_email(email: str) -> bool:
"""Basic email validation."""
Expand Down Expand Up @@ -256,19 +264,33 @@ async def email_signup(request: Request, signup_data: EmailSignupRequest) -> JSO
success, user_info = await ensure_user_in_organizations(email, email,
f"{first_name} {last_name}", "email", api_token)

if success and user_info and user_info["new_identity"]:
logging.info("New user created: %s", _sanitize_for_log(email))
# Check for system errors (success=False and user_info=None)
if not success and user_info is None:
logging.error("System error during user creation: [%s]", _sanitize_for_log(email))
return JSONResponse(
{"success": False, "error": "Registration failed. Please try again later."},
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
)

# Check if user already exists (success=False and user_info is not None)
if not success and user_info is not None:
logging.info("Signup attempt for existing user: [%s]", _sanitize_for_log(email))
return JSONResponse(
{"success": False, "error": "Registration failed. Please try again."},
status_code=status.HTTP_400_BAD_REQUEST
)

# New user created successfully (success=True and user_info["new_identity"]=True)
if success and user_info and user_info.get("new_identity"):
logging.info("New user created: [%s]", _sanitize_for_log(email))

# Hash password
password_hash = _hash_password(password)

# Set email hash
await _set_mail_hash(email, password_hash)

else:
logging.info("User already exists: %s", _sanitize_for_log(email))

logging.info("User registration successful: %s", _sanitize_for_log(email))
logging.info("User registration successful: [%s]", _sanitize_for_log(email))

response = JSONResponse({
"success": True,
Expand Down
Loading
Loading