Skip to content

feat(frontend): update oauth flow and add load testing script#127

Merged
omsherikar merged 3 commits intomainfrom
feat/oauth-and-load-testing-updates
Mar 29, 2026
Merged

feat(frontend): update oauth flow and add load testing script#127
omsherikar merged 3 commits intomainfrom
feat/oauth-and-load-testing-updates

Conversation

@omsherikar
Copy link
Copy Markdown
Collaborator

@omsherikar omsherikar commented Mar 29, 2026

Summary by CodeRabbit

  • New Features

    • GitHub disconnect option in Account Settings.
    • Sidebar collapse preference now persists across sessions.
  • Improvements

    • Contact/booking links updated to use external calendar scheduling and open in a new tab.
    • Support/contact email addresses updated to om@refactron.dev.
    • Cleaner profile display and clearer GitHub connect status in the dashboard.
  • Behavior

    • OAuth connect flows now update user state without replacing session tokens.

Copilot AI review requested due to automatic review settings March 29, 2026 21:08
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 29, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
refactron Ready Ready Preview, Comment Mar 29, 2026 9:12pm

@github-actions github-actions bot added type:refactor Code refactoring type:feature New feature labels Mar 29, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 29, 2026

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Snapshot Warnings

⚠️: No snapshots were found for the head SHA c37a26e.
Ensure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice.

Scanned Files

None

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 29, 2026

Warning

Rate limit exceeded

@omsherikar has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 22 minutes and 48 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 22 minutes and 48 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b02c7639-2801-48c7-a564-982e5815c2aa

📥 Commits

Reviewing files that changed from the base of the PR and between 05b7a93 and c37a26e.

📒 Files selected for processing (4)
  • src/components/DashboardLayout.tsx
  • src/components/EarlyAccessForm.tsx
  • src/components/EarlyAccessModal.tsx
  • src/components/OAuthCallback.tsx
📝 Walkthrough

Walkthrough

Adds GitHub disconnect UI and a GitHub "connect" OAuth path; persists sidebar collapsed state to localStorage and refactors header/avatar helpers; replaces several mailto contact addresses with om@refactron.dev or external Cal.com scheduling links; updates OAuth exchange to support authenticated connect flows.

Changes

Cohort / File(s) Summary
Email Address Migration
src/components/EarlyAccessForm.tsx, src/components/EarlyAccessModal.tsx, src/components/ErrorBoundary.tsx, src/components/PricingSection.tsx
Fallback and displayed support email changed from hello@refactron.dev to om@refactron.dev.
Contact Link Updates to Cal.com
src/components/AboutPage.tsx, src/components/CaseStudiesPage.tsx, src/components/FAQSection.tsx, src/components/Footer.tsx
Replaced mailto: contact links with https://cal.com/omsherikar/queries-refactron; added target="_blank" and rel="noopener noreferrer".
GitHub Integration (Account Settings)
src/components/AccountSettings.tsx
Added disconnect UI and state (disconnecting, confirmDisconnect, disconnectError), handleDisconnectGitHub POST to /api/auth/disconnect/github, and conditional confirmation panel + error handling.
Dashboard Layout Refactor
src/components/DashboardLayout.tsx
Persisted sidebar collapse state to localStorage; extracted NavItem, Avatar, and helper functions (getInitial, planBadgeLabel, formatOrgName, toOrgSlug); unified dropdown outside-click handling; adjusted profile/GitHub label and dropdown widths for collapsed state.
OAuth Flow Enhancement
src/utils/oauth.ts, src/components/OAuthCallback.tsx
handleOAuthCallback now computes redirectUri once and branches: for connect uses authenticated POST to /api/auth/connect/:provider with Bearer token and returns isConnect; for login/signup uses /api/auth/callback/:provider. OAuthCallback now uses updateUser for connect flows and login for login/signup flows. Return type updated to include isConnect.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Browser
    participant GitHub
    participant Server

    rect rgba(100,150,255,0.5)
    Note over User,Server: Authenticated "Connect" Flow
    User->>Browser: Click "Connect GitHub"
    Browser->>GitHub: Redirect to GitHub auth
    GitHub->>User: Approve
    GitHub->>Browser: Redirect to /auth/callback with code
    Browser->>Server: POST /api/auth/connect/github (Bearer token + code + redirectUri)
    Server->>Server: Validate token, exchange code, attach provider to account
    Server->>Browser: Return updated user data
    Browser->>Browser: updateUser(data.user) — keep existing session
    end

    rect rgba(100,200,100,0.5)
    Note over User,Server: Login/Signup Flow (New Session)
    User->>Browser: Click "Login with GitHub"
    Browser->>GitHub: Redirect to GitHub auth
    GitHub->>User: Approve
    GitHub->>Browser: Redirect to /auth/callback with code+state
    Browser->>Server: POST /api/auth/callback/github (code, state, type, redirectUri)
    Server->>Server: Exchange code for tokens, create/return session
    Server->>Browser: Return accessToken + user
    Browser->>Browser: login(accessToken, user) — replace session
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through code, a nimble stitch,
Connected GitHub without a hitch,
Emails hopped from old to new,
Sidebar rests where I left you,
OAuth branches — cookies stay rich. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title mentions 'update oauth flow' which directly relates to the OAuth changes in src/utils/oauth.ts and OAuthCallback.tsx, but omits the substantial email/link updates across multiple components and sidebar refactoring, which constitute the majority of the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/oauth-and-load-testing-updates

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/OAuthCallback.tsx (1)

115-115: ⚠️ Potential issue | 🔴 Critical

Add missing updateUser to the useEffect dependency array.

The pipeline is failing because updateUser is used inside the effect but not listed in the dependency array. This violates the react-hooks/exhaustive-deps rule and causes the CI lint check to fail.

🐛 Fix for the ESLint error
-  }, [searchParams, navigate, login]);
+  }, [searchParams, navigate, login, updateUser]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/OAuthCallback.tsx` at line 115, The useEffect in OAuthCallback
references updateUser but the dependency array only lists searchParams,
navigate, and login, causing an exhaustive-deps lint error; fix by adding
updateUser to the dependency array of the useEffect that runs in OAuthCallback
(the same effect referencing searchParams, navigate, and login), and if
updateUser is not stable ensure it is memoized (e.g., defined with useCallback
or moved to a stable context) so adding it to the array does not introduce
unwanted rerenders.
🧹 Nitpick comments (2)
src/components/DashboardLayout.tsx (1)

78-84: Consider guarding against invalid date strings.

If iso is malformed or empty, new Date(iso).getTime() returns NaN, resulting in "NaNm ago" being displayed. This is a minor edge case if the API always returns valid timestamps, but a defensive check would prevent confusing output.

🛡️ Optional defensive fix
 function formatNotifTime(iso: string): string {
+  const time = new Date(iso).getTime();
+  if (Number.isNaN(time)) return '';
-  const mins = Math.floor((Date.now() - new Date(iso).getTime()) / 60000);
+  const mins = Math.floor((Date.now() - time) / 60000);
   if (mins < 60) return `${mins}m ago`;
   const hrs = Math.floor(mins / 60);
   if (hrs < 24) return `${hrs}h ago`;
   return `${Math.floor(hrs / 24)}d ago`;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/DashboardLayout.tsx` around lines 78 - 84, The function
formatNotifTime should guard against invalid or empty ISO strings: inside
formatNotifTime (the function handling the timestamp formatting) validate the
parsed date before using it (e.g., const t = new Date(iso).getTime(); if
(isNaN(t)) return a sensible fallback like 'unknown' or '' or 'just now') and
then compute mins/hrs/days from that validated timestamp; this prevents outputs
like "NaNm ago" when iso is malformed and keeps the rest of the logic
(mins/hrs/days) unchanged.
src/components/FAQSection.tsx (1)

135-137: Extract the booking URL to a shared constant.

This URL is now duplicated across multiple components; centralizing it will avoid future drift and partial updates.

♻️ Example refactor (local start)
+const CONTACT_BOOKING_URL = 'https://cal.com/omsherikar/queries-refactron';

...
-            href="https://cal.com/omsherikar/queries-refactron"
+            href={CONTACT_BOOKING_URL}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/FAQSection.tsx` around lines 135 - 137, The booking URL string
used in JSX (e.g., href="https://cal.com/omsherikar/queries-refactron" inside
FAQSection's anchor) should be extracted into a shared exported constant
(suggest name BOOKING_URL) in a central module (e.g., a new or existing
constants file) and then imported where needed; update FAQSection (and any other
components duplicating the URL) to reference BOOKING_URL instead of the
hardcoded string so all components use the single source of truth.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/EarlyAccessModal.tsx`:
- Around line 58-60: Update the environment template so the documented defaults
for REACT_APP_FROM_EMAIL and REACT_APP_NOTIFICATION_EMAIL match the new
fallbacks used in EarlyAccessModal (om@refactron.dev); open the env example that
documents those two variables and replace the old hello@refactron.dev values
with om@refactron.dev (or note the new defaults) so users who copy the template
won't accidentally route notifications to the old inbox.

---

Outside diff comments:
In `@src/components/OAuthCallback.tsx`:
- Line 115: The useEffect in OAuthCallback references updateUser but the
dependency array only lists searchParams, navigate, and login, causing an
exhaustive-deps lint error; fix by adding updateUser to the dependency array of
the useEffect that runs in OAuthCallback (the same effect referencing
searchParams, navigate, and login), and if updateUser is not stable ensure it is
memoized (e.g., defined with useCallback or moved to a stable context) so adding
it to the array does not introduce unwanted rerenders.

---

Nitpick comments:
In `@src/components/DashboardLayout.tsx`:
- Around line 78-84: The function formatNotifTime should guard against invalid
or empty ISO strings: inside formatNotifTime (the function handling the
timestamp formatting) validate the parsed date before using it (e.g., const t =
new Date(iso).getTime(); if (isNaN(t)) return a sensible fallback like 'unknown'
or '' or 'just now') and then compute mins/hrs/days from that validated
timestamp; this prevents outputs like "NaNm ago" when iso is malformed and keeps
the rest of the logic (mins/hrs/days) unchanged.

In `@src/components/FAQSection.tsx`:
- Around line 135-137: The booking URL string used in JSX (e.g.,
href="https://cal.com/omsherikar/queries-refactron" inside FAQSection's anchor)
should be extracted into a shared exported constant (suggest name BOOKING_URL)
in a central module (e.g., a new or existing constants file) and then imported
where needed; update FAQSection (and any other components duplicating the URL)
to reference BOOKING_URL instead of the hardcoded string so all components use
the single source of truth.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a3e7a540-cdf9-4d62-8e47-151b6003baab

📥 Commits

Reviewing files that changed from the base of the PR and between 8720b5c and 05b7a93.

📒 Files selected for processing (12)
  • src/components/AboutPage.tsx
  • src/components/AccountSettings.tsx
  • src/components/CaseStudiesPage.tsx
  • src/components/DashboardLayout.tsx
  • src/components/EarlyAccessForm.tsx
  • src/components/EarlyAccessModal.tsx
  • src/components/ErrorBoundary.tsx
  • src/components/FAQSection.tsx
  • src/components/Footer.tsx
  • src/components/OAuthCallback.tsx
  • src/components/PricingSection.tsx
  • src/utils/oauth.ts

Comment on lines +58 to +60
process.env.REACT_APP_FROM_EMAIL || 'om@refactron.dev';
const notificationEmail =
process.env.REACT_APP_NOTIFICATION_EMAIL || 'hello@refactron.dev';
process.env.REACT_APP_NOTIFICATION_EMAIL || 'om@refactron.dev';
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Update .env.example to avoid sending notifications to the old inbox.

Lines 58 and 60 changed the fallback, but .env.example Line 8-9 still documents hello@refactron.dev. If those vars are set from the template, they override these new defaults and route emails incorrectly.

🛠️ Suggested follow-up patch (`.env.example`)
-REACT_APP_FROM_EMAIL=hello@refactron.dev
-REACT_APP_NOTIFICATION_EMAIL=hello@refactron.dev
+REACT_APP_FROM_EMAIL=om@refactron.dev
+REACT_APP_NOTIFICATION_EMAIL=om@refactron.dev
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/EarlyAccessModal.tsx` around lines 58 - 60, Update the
environment template so the documented defaults for REACT_APP_FROM_EMAIL and
REACT_APP_NOTIFICATION_EMAIL match the new fallbacks used in EarlyAccessModal
(om@refactron.dev); open the env example that documents those two variables and
replace the old hello@refactron.dev values with om@refactron.dev (or note the
new defaults) so users who copy the template won't accidentally route
notifications to the old inbox.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates the frontend OAuth callback handling to support a dedicated “connect GitHub” flow without replacing the current session, alongside several UI updates (dashboard layout refactor, GitHub disconnect UI, and updated contact links).

Changes:

  • Add a dedicated OAuth “connect” callback path (/api/auth/connect/:provider) and propagate an isConnect flag through the callback handling.
  • Update auth callback UI logic to refresh the user state on connect (instead of calling login).
  • Refactor DashboardLayout sidebar/nav UI and update various contact links/emails across the site; add GitHub disconnect controls in Account Settings.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/utils/oauth.ts Adds connect-flow endpoint handling and isConnect return flag; refactors redirectUri usage.
src/components/OAuthCallback.tsx Uses updateUser for connect flow; keeps login for login/signup flow.
src/components/DashboardLayout.tsx Sidebar refactor (collapse persistence, helper components, nav rendering) and GitHub connect entrypoint.
src/components/AccountSettings.tsx Adds GitHub disconnect UI + request handler.
src/components/PricingSection.tsx Updates contact mailto address.
src/components/Footer.tsx Switches “Contact” to external scheduling link (new tab).
src/components/FAQSection.tsx Switches “Contact Us” to external scheduling link (new tab).
src/components/ErrorBoundary.tsx Updates support mailto address.
src/components/EarlyAccessModal.tsx Updates default from/notification email fallbacks.
src/components/EarlyAccessForm.tsx Updates default from/notification email fallbacks and displayed support email.
src/components/CaseStudiesPage.tsx Switches CTA link to external scheduling link (new tab).
src/components/AboutPage.tsx Switches CTA link to external scheduling link (new tab).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +231 to +242
// Connect flow — use dedicated authenticated endpoint, preserve existing session
if (type === 'connect') {
const token = localStorage.getItem('accessToken');
if (!token) {
return {
success: false,
error: 'You must be logged in to connect a GitHub account.',
};
}

const response = await fetch(
`${apiBaseUrl}/api/auth/connect/${provider}`,
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

PR title mentions “add load testing script”, but the changed files in this PR appear limited to frontend OAuth/UI updates and contact link changes; no load-testing script (e.g. under scripts/ or a new tool config) is included. Please either add the load testing script as described or update the PR title to match the actual scope.

Copilot uses AI. Check for mistakes.
if (!token) {
return {
success: false,
error: 'You must be logged in to connect a GitHub account.',
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

In the connect flow, the error message is hard-coded to “connect a GitHub account”, but this function is provider-agnostic (provider comes from state and the endpoint uses /connect/${provider}). Please make the message generic (e.g., “connect your account”) or interpolate the provider so it stays accurate if additional providers support type === 'connect'.

Suggested change
error: 'You must be logged in to connect a GitHub account.',
error: `You must be logged in to connect your ${provider} account.`,

Copilot uses AI. Check for mistakes.
Comment on lines +231 to +265
// Connect flow — use dedicated authenticated endpoint, preserve existing session
if (type === 'connect') {
const token = localStorage.getItem('accessToken');
if (!token) {
return {
success: false,
error: 'You must be logged in to connect a GitHub account.',
};
}

const response = await fetch(
`${apiBaseUrl}/api/auth/connect/${provider}`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
credentials: 'include',
body: JSON.stringify({ code, redirectUri }),
}
);

const data = await response.json();

if (!response.ok) {
return {
success: false,
error: data.message || `Failed to connect ${provider} account.`,
};
}

// Return isConnect flag so OAuthCallback knows not to replace the session
return { success: true, data, isConnect: true };
}
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

handleOAuthCallback now has a new type === 'connect' branch and new return shape (isConnect). There are existing unit tests for handleOAuthCallback in src/utils/oauth.test.ts, but they don’t cover the connect branch. Please add tests for: (1) missing access token path, (2) successful connect returning isConnect: true, and (3) non-OK response mapping data.message to error.

Copilot uses AI. Check for mistakes.
Comment on lines +69 to +75
if (result.isConnect) {
// Connect flow — keep existing session, just refresh user state
updateUser(result.data.user);
} else {
// Login / signup flow — replace session with new tokens
await login(result.data.accessToken, result.data.user);
}
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

The new result.isConnect branch changes the component’s auth behavior (updating user state without calling login). There are existing component tests (OAuthCallback.test.tsx) but they don’t exercise the connect path; please add a test that asserts updateUser is called (and login is not) when handleOAuthCallback resolves with { success: true, isConnect: true, data: { user: ... } }.

Copilot uses AI. Check for mistakes.
Comment on lines 238 to 242

const handleGitHubConnect = async () => {
try {
const { initiateOAuth } = await import('../utils/oauth');
await initiateOAuth('github', 'connect', {
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

initiateOAuth here uses window.location.origin for redirectUri, but other OAuth entrypoints (e.g. login/signup) use getBaseUrl() and OAuthCallback passes getBaseUrl() as the callback redirect. On non-app.* hosts routed to the same deployment (e.g. docs.*), window.location.origin can differ from getBaseUrl(), which can cause redirect URI mismatches during code exchange. Please align this to use getBaseUrl() (or otherwise ensure the same redirect URI is used for both authorization and token exchange).

Copilot uses AI. Check for mistakes.

return (
<div className="flex h-screen bg-black text-white font-space overflow-hidden">
{/* Sidebar */}
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

The sidebar <motion.aside> now has overflow-hidden. This will clip dropdown popovers and/or their shadows (notifications/profile/org menus) when they extend beyond the sidebar bounds, which is especially noticeable with shadow-2xl. Please remove overflow-hidden or move overflow clipping to a more specific inner container that won’t contain the popovers.

Suggested change
{/* Sidebar */}
className="flex flex-col border-r border-white/[0.08] bg-black z-20"

Copilot uses AI. Check for mistakes.
@omsherikar omsherikar merged commit 55e6775 into main Mar 29, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:feature New feature type:refactor Code refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants