feat: Add UUID validation for organization IDs in backend API endpoints and frontend logic.
This commit is contained in:
parent
e564501c05
commit
8a6acc911e
4 changed files with 33 additions and 3 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import json
|
||||
import logging
|
||||
import secrets
|
||||
import uuid
|
||||
|
||||
import requests
|
||||
from django.conf import settings
|
||||
|
|
@ -293,6 +294,13 @@ class LoginView(APIView):
|
|||
default_org = None
|
||||
|
||||
if org_id:
|
||||
try:
|
||||
uuid.UUID(str(org_id))
|
||||
except (ValueError, AttributeError):
|
||||
return Response(
|
||||
{"error": "org_id must be a valid UUID"},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
# Use specified org if user has access
|
||||
try:
|
||||
profile = profiles.get(org_id=org_id)
|
||||
|
|
@ -547,6 +555,14 @@ class OrgSwitchView(APIView):
|
|||
{"error": "org_id is required"}, status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
try:
|
||||
uuid.UUID(str(org_id))
|
||||
except (ValueError, AttributeError):
|
||||
return Response(
|
||||
{"error": "org_id must be a valid UUID"},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
# Get current org for audit logging
|
||||
from_org = getattr(request, "org", None)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import axios from 'axios';
|
|||
import { env } from '$env/dynamic/public';
|
||||
|
||||
const API_BASE_URL = `${env.PUBLIC_DJANGO_API_URL}/api`;
|
||||
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
||||
|
||||
/**
|
||||
* @typedef {{ default_currency?: string, currency_symbol?: string, default_country?: string|null }} OrgSettingsPayload
|
||||
|
|
@ -169,7 +170,10 @@ export const handle = sequence(Sentry.sentryHandle(), async function _handle({ e
|
|||
};
|
||||
|
||||
// Check if org cookie is set and token has org context
|
||||
if (orgId) {
|
||||
if (orgId && !UUID_RE.test(orgId)) {
|
||||
// Invalid org cookie value, clear it
|
||||
event.cookies.delete('org', { path: '/' });
|
||||
} else if (orgId) {
|
||||
const token = /** @type {string} */ (accessToken);
|
||||
|
||||
if (tokenHasOrgContext(token, orgId)) {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
import { env } from '$env/dynamic/public';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
||||
|
||||
// API Base URL from environment variables
|
||||
// Note: VITE_ prefix is required for client-side env vars
|
||||
const API_BASE_URL = env.PUBLIC_DJANGO_API_URL
|
||||
|
|
@ -231,6 +233,9 @@ export const auth = {
|
|||
/** @type {Record<string, string>} */
|
||||
const body = { email, password };
|
||||
if (orgId) {
|
||||
if (!UUID_RE.test(orgId)) {
|
||||
throw new Error('Invalid organization ID format');
|
||||
}
|
||||
body.org_id = orgId;
|
||||
}
|
||||
|
||||
|
|
@ -276,6 +281,9 @@ export const auth = {
|
|||
* @returns {Promise<any>} New tokens and org data
|
||||
*/
|
||||
async switchOrg(orgId) {
|
||||
if (!orgId || !UUID_RE.test(orgId)) {
|
||||
throw new Error('Invalid organization ID format');
|
||||
}
|
||||
/** @type {any} */
|
||||
const data = await apiRequest('/auth/switch-org/', {
|
||||
method: 'POST',
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ import { env as publicEnv } from '$env/dynamic/public';
|
|||
import { redirect, fail } from '@sveltejs/kit';
|
||||
import axios from 'axios';
|
||||
|
||||
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
||||
|
||||
/** @type {import('./$types').PageServerLoad} */
|
||||
export async function load({ cookies, locals }) {
|
||||
const user = locals.user;
|
||||
|
|
@ -65,8 +67,8 @@ export const actions = {
|
|||
const orgId = formData.get('org_id')?.toString();
|
||||
const orgName = formData.get('org_name')?.toString();
|
||||
|
||||
if (!orgId) {
|
||||
return fail(400, { error: 'Organization ID is required' });
|
||||
if (!orgId || !UUID_RE.test(orgId)) {
|
||||
return fail(400, { error: 'Invalid Organization ID' });
|
||||
}
|
||||
|
||||
const jwtAccess = cookies.get('jwt_access');
|
||||
|
|
|
|||
Loading…
Reference in a new issue