Skip to content
Open
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
40 changes: 36 additions & 4 deletions frontend/src/routes/team.invite.$inviteId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,20 @@ function TeamInviteAcceptance() {

const handleAcceptInvite = async () => {
if (!userEmail) {
setError("Unable to determine your email address");
setError("Unable to determine your email address. Please refresh the page and try again.");
return;
}

setIsProcessing(true);
setError(null);

try {
console.log("[TeamInvite] Attempting to accept invite:", inviteId);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Do not log the invite token; treat it as sensitive

Invite IDs often function as bearer tokens. Avoid printing them to console.

Apply this diff:

-      console.log("[TeamInvite] Attempting to accept invite:", inviteId);
+      console.log("[TeamInvite] Attempting to accept invite");
@@
-      console.error("[TeamInvite] Failed to accept invite:", err);
+      console.error("[TeamInvite] Failed to accept invite", err);

Also applies to: 83-83

🤖 Prompt for AI Agents
In frontend/src/routes/team.invite.$inviteId.tsx around lines 66 and 83, the
code logs the inviteId to the console which exposes a sensitive token; remove or
redact any console.log or other debug statements that print inviteId and instead
log non-sensitive context (e.g., "Attempting to accept invite" without the
token) or use conditional/local-only debugging that never prints the token in
production; ensure both occurrences at lines 66 and 83 are updated accordingly.

const billingService = getBillingService();
await billingService.acceptTeamInvite(inviteId, { email: userEmail });

console.log("[TeamInvite] Successfully accepted invite");

// Invalidate relevant queries
await queryClient.invalidateQueries({ queryKey: ["teamStatus"] });
await queryClient.invalidateQueries({ queryKey: ["billingStatus"] });
Expand All @@ -77,8 +80,29 @@ function TeamInviteAcceptance() {
navigate({ to: "/" });
}, 2000);
} catch (err) {
console.error("Failed to accept invite:", err);
setError(err instanceof Error ? err.message : "Failed to accept invitation");
console.error("[TeamInvite] Failed to accept invite:", err);

// Provide user-friendly error messages
let errorMessage = "Failed to accept invitation. Please try again.";

if (err instanceof Error) {
const message = err.message.toLowerCase();

if (message.includes("unauthorized") || message.includes("401")) {
errorMessage = "Your session has expired. Please refresh the page and try again.";
} else if (message.includes("already a member")) {
errorMessage = "You are already a member of this team.";
} else if (message.includes("invalid") || message.includes("expired")) {
errorMessage = "This invitation link is no longer valid.";
} else if (message.includes("network") || message.includes("fetch")) {
errorMessage = "Network error. Please check your connection and try again.";
} else if (err.message) {
// Use the actual error message if it's specific enough
errorMessage = err.message;
}
}

setError(errorMessage);
} finally {
setIsProcessing(false);
}
Expand Down Expand Up @@ -203,7 +227,15 @@ function TeamInviteAcceptance() {
{error && (
<Alert variant="destructive">
<AlertCircle className="h-4 w-4" />
<AlertDescription>{error}</AlertDescription>
<AlertDescription>
<div className="space-y-2">
<p>{error}</p>
{!error.includes("already a member") &&
!error.includes("no longer valid") && (
<p className="text-xs">Click "Accept Invitation" to try again.</p>
)}
</div>
</AlertDescription>
</Alert>
)}

Expand Down
Loading