Skip to content

Task/base360.ai - #238

Open
eslam5464 wants to merge 14 commits into
Base360-AI:mainfrom
eslam5464:main
Open

eslam5464 wants to merge 14 commits into
Base360-AI:mainfrom
eslam5464:main

Conversation

@eslam5464

Copy link
Copy Markdown

No description provided.

Comment on lines 96 to +106
if user_email == "sunset@propertyflow.com":
return "tenant-a"
if user_email == "ocean@propertyflow.com":
return "tenant-b"
if user_email == "candidate@propertyflow.com":
return "tenant-a"

# Default fallback
return "tenant-a"

# No default: an unknown user must never be placed in a real tenant,
# or they would see that tenant's data.
logger.warning(f"No tenant found for user {user_email} ({user_id})")
return None

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Removing default fallback in resolve_tenant_id causes callers omitting token to resolve tenant_id as None for standard users.
Severity: HIGH

Suggested Fix

Update callers (login.py, auth_info.py, city_access_fast.py) to pass token to resolve_tenant_id, or use user.tenant_id already populated by authenticate_request.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: backend/app/core/tenant_resolver.py#L86-L106

Potential issue: `resolve_tenant_id` no longer falls back to 'tenant-a' and returns
`None` for any user without a hardcoded email when called without a `token`. Multiple
existing callers (`login.py`, `auth_info.py`, and `city_access_fast.py`) invoke
`resolve_tenant_id` without passing `token`. Consequently, users not in the hardcoded
email map receive a JWT with `tenant_id: None` on login, `/auth/me` returns `tenant_id:
null` while missing permissions, and city access returns `tenant_resolution_failed`.

Did we get this right? 👍 / 👎 to inform future reviews.

Comment on lines +87 to +93
if token:
try:
tenant_id = TenantResolver.resolve_tenant_from_token(jwt.get_unverified_claims(token))
if tenant_id:
return tenant_id
except JWTError:
logger.warning(f"Could not read tenant claim from token for {user_email}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: resolve_tenant_from_token trusts user-editable user_metadata.tenant_id over admin-controlled metadata or database assignments.
Severity: HIGH

Suggested Fix

Ignore user_metadata for tenant authorization. Retrieve tenant_id strictly from app_metadata or validate the claim against the user_tenants database table.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: backend/app/core/tenant_resolver.py#L87-L93

Potential issue: `resolve_tenant_from_token` resolves `tenant_id` by inspecting
`user_metadata.tenant_id` prior to `app_metadata` or authoritative database records. In
Supabase auth, users can modify their own `user_metadata`. If a token from a
Supabase-authenticated user contains a manipulated `user_metadata.tenant_id`, the system
trusts the claim, allowing unauthorized access to other tenants' cached dashboard data,
revenue, and property records.

Did we get this right? 👍 / 👎 to inform future reviews.

Comment on lines 31 to 41
setLoading(true);
setError('');
try {
// Use SecureAPI to handle authentication automatically
// We pass the simulatedTenant option which SecureAPI will attach as a header
// SecureAPI attaches the auth token; the backend takes the
// tenant from that token only.
const response = await SecureAPI.getDashboardSummary(propertyId, {
simulatedTenant: activeTenant,
month,
year,
timestamp: Date.now()
});
setData(response);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Missing cancellation in useEffect fetch causes race conditions and displays out-of-order revenue data.
Severity: LOW

Suggested Fix

Use an AbortController or an active cancellation flag within useEffect cleanup to ignore responses from superseded requests.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: frontend/src/components/RevenueSummary.tsx#L29-L41

Potential issue: In `RevenueSummary.tsx`, `useEffect` fetches revenue data on changes to
`propertyId`, `month`, or `year` without request cancellation, cleanup flags, or
response ordering guards. When filter settings change rapidly, an earlier asynchronous
request may settle after a later request, overwriting current revenue state with stale
data and clearing the loading state prematurely.

Did we get this right? 👍 / 👎 to inform future reviews.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant