Skip to content

fix(companion): event type links for org user#20

Open
tomerqodo wants to merge 7 commits intoqodo_action_req_base_fixcompanion_event_type_links_for_org_user_pr5from
qodo_action_req_head_fixcompanion_event_type_links_for_org_user_pr5
Open

fix(companion): event type links for org user#20
tomerqodo wants to merge 7 commits intoqodo_action_req_base_fixcompanion_event_type_links_for_org_user_pr5from
qodo_action_req_head_fixcompanion_event_type_links_for_org_user_pr5

Conversation

@tomerqodo
Copy link
Copy Markdown

Benchmark PR from agentic-review-benchmarks#5

dhairyashiil and others added 7 commits January 25, 2026 12:01
Addresses Cubic AI review feedback (confidence 9/10): The username was
hardcoded to 'username' but still used by BasicsTab as a fallback for
URL display when bookingUrl is unavailable. This restores the useEffect
that fetches the actual username from CalComAPIService.getUsername().

Co-Authored-By: unknown <>
@qodo-code-review
Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (2) 📎 Requirement gaps (0)

Grey Divider


Action required

1. getUsername() throws generic Error 📘 Rule violation ⛯ Reliability
Description
getUsername() catches an unknown failure from getUserProfile() and throws a generic Error
  without a typed code/status or structured context, which makes downstream handling and debugging
  inconsistent.
• The original error is discarded, so callers lose the root-cause details (and cannot reliably
  branch on error type), reducing robustness of error handling.
Code

companion/services/calcom.ts[R1654-1662]

+// Helper to get username
+async function getUsername(): Promise<string> {
+  try {
+    const profile = await getUserProfile();
+    return profile.username;
+  } catch (error) {
+    throw new Error("Failed to get username");
+  }
+}
Evidence
Compliance ID 15 requires hierarchical custom errors with typed codes and relevant context; the new
code instead throws a generic Error and drops the original cause. This also weakens error
diagnosability by removing the original error information.

AGENTS.md
companion/services/calcom.ts[1654-1662]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`getUsername()` throws a generic `Error(&quot;Failed to get username&quot;)` and drops the original exception, violating the requirement for hierarchical typed errors with context.

## Issue Context
This is a core service helper; callers need consistent error types/codes and the original cause for debugging and reliable handling.

## Fix Focus Areas
- companion/services/calcom.ts[1654-1662]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Unvalidated bookingUrl navigation 📘 Rule violation ⛨ Security
Description
• The code uses eventType.bookingUrl (originating from external/API data) directly in navigation
  actions like window.open(...) / openInAppBrowser(...) without validating scheme/host, which can
  enable opening attacker-controlled URLs.
• This violates the requirement that external inputs are validated/sanitized before use, especially
  when used for navigation and data handling.
Code

companion/app/(tabs)/(event-types)/index.tsx[R287-297]

  const handlePreview = async (eventType: EventType) => {
+    if (!eventType.bookingUrl) {
+      showErrorAlert("Error", "Booking URL not available for this event type.");
+      return;
+    }
    try {
-      const link = await CalComAPIService.buildEventTypeLink(eventType.slug);
-      // Open in browser
      if (Platform.OS === "web") {
-        window.open(link, "_blank");
+        window.open(eventType.bookingUrl, "_blank");
      } else {
-        // For mobile, use in-app browser
-        await openInAppBrowser(link, "event type preview");
+        await openInAppBrowser(eventType.bookingUrl, "event type preview");
      }
Evidence
Compliance ID 6 requires validation/sanitization of external inputs; bookingUrl is consumed as a
full URL and is used to open external pages without allowlisting/validation. The cited locations
demonstrate direct use of bookingUrl in navigation actions.

Rule 6: Generic: Security-First Input Validation and Data Handling
companion/app/(tabs)/(event-types)/index.tsx[287-297]
companion/extension/entrypoints/content.ts[1079-1087]
companion/extension/lib/linkedin.ts[667-672]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`bookingUrl` is treated as a trusted full URL and opened directly in browser contexts without validation.

## Issue Context
`bookingUrl` is API-provided (external input). Navigation actions should only allow expected schemes/hosts (e.g., https + cal.com domains) and reject/replace anything else.

## Fix Focus Areas
- companion/app/(tabs)/(event-types)/index.tsx[287-297]
- companion/extension/entrypoints/content.ts[1079-1087]
- companion/extension/lib/linkedin.ts[667-672]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Booking URL never populated 🐞 Bug ✓ Correctness
Description
EventTypeDetail now gates Preview/Copy on a local bookingUrl state, but the state is
  initialized empty and is never set from fetched event type data.
• As a result, Preview/Copy will always show “Booking URL not available…” even for existing event
  types.
• This is a functional regression that blocks core actions on the Event Type detail screen.
Code

companion/app/(tabs)/(event-types)/event-type-detail.tsx[R949-963]

+    if (!bookingUrl) {
+      showErrorAlert("Error", "Booking URL not available. Please save the event type first.");
      return;
    }
-    await openInAppBrowser(link, "event type preview");
+    await openInAppBrowser(bookingUrl, "event type preview");
  };

  const handleCopyLink = async () => {
-    const eventTypeSlug = eventSlug || "event-link";
-    let link: string;
-    try {
-      link = await CalComAPIService.buildEventTypeLink(eventTypeSlug);
-    } catch (error) {
-      safeLogError("Failed to copy link:", error);
-      showErrorAlert("Error", "Failed to copy link. Please try again.");
+    if (!bookingUrl) {
+      showErrorAlert("Error", "Booking URL not available. Please save the event type first.");
      return;
    }
-    await Clipboard.setStringAsync(link);
+    await Clipboard.setStringAsync(bookingUrl);
    showSuccessAlert("Success", "Link copied!");
  };
Evidence
bookingUrl is declared as local state but is only read (for preview/copy and passed down to
BasicsTab). The fetch path calls applyEventTypeData(eventType) and applyEventTypeData sets many
fields (title/slug/etc.) but never sets bookingUrl, so it remains the initial empty string and the
new guards always trigger.

companion/app/(tabs)/(event-types)/event-type-detail.tsx[174-183]
companion/app/(tabs)/(event-types)/event-type-detail.tsx[451-460]
companion/app/(tabs)/(event-types)/event-type-detail.tsx[826-840]
companion/app/(tabs)/(event-types)/event-type-detail.tsx[948-963]
companion/app/(tabs)/(event-types)/event-type-detail.tsx[1405-1431]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`EventTypeDetail` introduced a `bookingUrl` state and now blocks Preview/Copy unless it is non-empty. However, `bookingUrl` is never set from fetched event type data, so the Preview/Copy actions always error.

### Issue Context
- `fetchEventTypeData()` fetches an `EventType` and calls `applyEventTypeData(eventType)`.
- `applyEventTypeData()` sets many UI states (title/slug/hidden/etc.) but does not set `bookingUrl`.
- `handlePreview` / `handleCopyLink` require `bookingUrl`.

### Fix Focus Areas
- companion/app/(tabs)/(event-types)/event-type-detail.tsx[451-520]
- companion/app/(tabs)/(event-types)/event-type-detail.tsx[826-840]
- companion/app/(tabs)/(event-types)/event-type-detail.tsx[948-963]

### Suggested implementation notes
- In `applyEventTypeData(eventType)`, add `setBookingUrl(eventType.bookingUrl ?? &quot;&quot;)`.
- Consider a safe fallback for preview/copy when `eventType.bookingUrl` is absent, e.g. `https://cal.com/${username}/${eventType.slug}` (using already-fetched `username` state) or the pre-existing behavior.
- Ensure `bookingUrl` is refreshed after save/refresh (it already calls `fetchEventTypeData()` after update).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



ⓘ The new review experience is currently in Beta. Learn more

Qodo Logo

Comment on lines +1654 to +1662
// Helper to get username
async function getUsername(): Promise<string> {
try {
const profile = await getUserProfile();
return profile.username;
} catch (error) {
throw new Error("Failed to get username");
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. getusername() throws generic error 📘 Rule violation ⛯ Reliability

getUsername() catches an unknown failure from getUserProfile() and throws a generic Error
  without a typed code/status or structured context, which makes downstream handling and debugging
  inconsistent.
• The original error is discarded, so callers lose the root-cause details (and cannot reliably
  branch on error type), reducing robustness of error handling.
Agent prompt
## Issue description
`getUsername()` throws a generic `Error("Failed to get username")` and drops the original exception, violating the requirement for hierarchical typed errors with context.

## Issue Context
This is a core service helper; callers need consistent error types/codes and the original cause for debugging and reliable handling.

## Fix Focus Areas
- companion/services/calcom.ts[1654-1662]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines 287 to 297
const handlePreview = async (eventType: EventType) => {
if (!eventType.bookingUrl) {
showErrorAlert("Error", "Booking URL not available for this event type.");
return;
}
try {
const link = await CalComAPIService.buildEventTypeLink(eventType.slug);
// Open in browser
if (Platform.OS === "web") {
window.open(link, "_blank");
window.open(eventType.bookingUrl, "_blank");
} else {
// For mobile, use in-app browser
await openInAppBrowser(link, "event type preview");
await openInAppBrowser(eventType.bookingUrl, "event type preview");
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Unvalidated bookingurl navigation 📘 Rule violation ⛨ Security

• The code uses eventType.bookingUrl (originating from external/API data) directly in navigation
  actions like window.open(...) / openInAppBrowser(...) without validating scheme/host, which can
  enable opening attacker-controlled URLs.
• This violates the requirement that external inputs are validated/sanitized before use, especially
  when used for navigation and data handling.
Agent prompt
## Issue description
`bookingUrl` is treated as a trusted full URL and opened directly in browser contexts without validation.

## Issue Context
`bookingUrl` is API-provided (external input). Navigation actions should only allow expected schemes/hosts (e.g., https + cal.com domains) and reject/replace anything else.

## Fix Focus Areas
- companion/app/(tabs)/(event-types)/index.tsx[287-297]
- companion/extension/entrypoints/content.ts[1079-1087]
- companion/extension/lib/linkedin.ts[667-672]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +949 to 963
if (!bookingUrl) {
showErrorAlert("Error", "Booking URL not available. Please save the event type first.");
return;
}
await openInAppBrowser(link, "event type preview");
await openInAppBrowser(bookingUrl, "event type preview");
};

const handleCopyLink = async () => {
const eventTypeSlug = eventSlug || "event-link";
let link: string;
try {
link = await CalComAPIService.buildEventTypeLink(eventTypeSlug);
} catch (error) {
safeLogError("Failed to copy link:", error);
showErrorAlert("Error", "Failed to copy link. Please try again.");
if (!bookingUrl) {
showErrorAlert("Error", "Booking URL not available. Please save the event type first.");
return;
}
await Clipboard.setStringAsync(link);
await Clipboard.setStringAsync(bookingUrl);
showSuccessAlert("Success", "Link copied!");
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

3. Booking url never populated 🐞 Bug ✓ Correctness

EventTypeDetail now gates Preview/Copy on a local bookingUrl state, but the state is
  initialized empty and is never set from fetched event type data.
• As a result, Preview/Copy will always show “Booking URL not available…” even for existing event
  types.
• This is a functional regression that blocks core actions on the Event Type detail screen.
Agent prompt
### Issue description
`EventTypeDetail` introduced a `bookingUrl` state and now blocks Preview/Copy unless it is non-empty. However, `bookingUrl` is never set from fetched event type data, so the Preview/Copy actions always error.

### Issue Context
- `fetchEventTypeData()` fetches an `EventType` and calls `applyEventTypeData(eventType)`.
- `applyEventTypeData()` sets many UI states (title/slug/hidden/etc.) but does not set `bookingUrl`.
- `handlePreview` / `handleCopyLink` require `bookingUrl`.

### Fix Focus Areas
- companion/app/(tabs)/(event-types)/event-type-detail.tsx[451-520]
- companion/app/(tabs)/(event-types)/event-type-detail.tsx[826-840]
- companion/app/(tabs)/(event-types)/event-type-detail.tsx[948-963]

### Suggested implementation notes
- In `applyEventTypeData(eventType)`, add `setBookingUrl(eventType.bookingUrl ?? "")`.
- Consider a safe fallback for preview/copy when `eventType.bookingUrl` is absent, e.g. `https://cal.com/${username}/${eventType.slug}` (using already-fetched `username` state) or the pre-existing behavior.
- Ensure `bookingUrl` is refreshed after save/refresh (it already calls `fetchEventTypeData()` after update).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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.

2 participants