Admin Dashboard enhancements, OAuth session fixes, and tracking script improvements #37
Reference in New Issue
Block a user
No description provided.
Delete Branch "staging"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Work Item
Summary
Changes
Admin Dashboard (
pulse-frontend):date-fnsdependency to fix build issuesCardcomponent with native equivalents for build compatibilityAuthentication & Session Flow:
Tracking Script:
Test Plan
Greptile Summary
This PR adds a comprehensive admin dashboard for managing organizations and subscription plans, while fixing OAuth session flow issues when opening Pulse from the Ciphera hub. The admin features include organization listing with click-to-copy IDs, detailed organization views, and the ability to manually grant subscription plans.
Key Changes:
/adminwith organization management UICritical Issue:
app/auth/callback/page.tsx) removes CSRF protection by accepting callbacks without astateparameter and provides no origin validation. This allows potential CSRF attacks where malicious actors could craft callback URLs to hijack user sessions.Other Issues:
Confidence Score: 2/5
Important Files Changed
Sequence Diagram
Last reviewed commit:
335cfc17 files reviewed, 3 comments
Edit Code Review Agent Settings | Greptile
@@ -0,0 +196,4 @@/></div><div className="space-y-2">Label says "UTC" but datetime-local input uses the browser's local timezone. User enters "2024-01-01 00:00" in PST thinking it's UTC, but line 95 converts it as PST → UTC (becomes "2024-01-01T08:00:00Z"). Either change label to "Local Time" or use a UTC-aware input component.
Prompt To Fix With AI
@@ -0,0 +23,4 @@onClick={copy}className="font-mono text-xs text-neutral-500 hover:text-brand-orange dark:hover:text-brand-orange cursor-pointer transition-colors text-left"title="Click to copy">Copies only first 8 chars of org ID (
${id.substring(0, 8)}...) butnavigator.clipboard.writeText(id)copies the full ID. The truncated display is inconsistent with what gets copied - consider showing this visually or copy the truncated version if that's the intent.Prompt To Fix With AI
@@ -65,2 +66,4 @@const isFullOAuth = !!storedState && !!codeVerifierif (isFullOAuth && state !== storedState) {logger.error('State mismatch', { received: state, stored: storedState })setError('Invalid state')Accepting OAuth callbacks without
stateparameter creates a CSRF vulnerability. An attacker could craft a malicious callback URL with their own authorization code and trick users into executing it, logging them into the attacker's account.The PR description mentions "trusted origins" but there's no code validating the origin. At minimum, check
document.referrerto ensure it starts with the auth domain whenstateis missing:Prompt To Fix With AI