fix: BB admin login no longer bounces to distribute

Problem: /admin/* pages redirect unauthed users to /login or /account,
both of which then hit middleware redirecting to distribute.relevant
mediaproperties.com. Distribute is on a different domain, so its session
cookie doesn't carry to broadcastbeat.com — sign-in there left admins
stranded on distribute's dashboard.

Fix:
  - Remove /login (and /register) from middleware REDIRECT_PATHS. wp-login,
    wp-admin, client-login still bounce to distribute.
  - /login is now a real BB sign-in form (was a redirect to /client-login).
  - Admin pages preserve return path via /login?next=<encoded path>.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ryan Salazar
2026-05-26 14:28:29 +00:00
parent 0e733ca0f8
commit 17e8d9914e
41 changed files with 163 additions and 48 deletions

View File

@@ -39,7 +39,7 @@ export default function ClientsPage() {
const [errors, setErrors] = useState<Record<string, string>>({});
const [successMsg, setSuccessMsg] = useState('');
useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]);
useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]);
const load = useCallback(async () => {
setLoadingData(true);

View File

@@ -16,7 +16,7 @@ export default function CommissionsPage() {
const [filterStaff, setFilterStaff] = useState('');
const [staff, setStaff] = useState<any[]>([]);
useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]);
useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]);
const load = useCallback(async () => {
setLoadingData(true);

View File

@@ -17,7 +17,7 @@ export default function DocumentsPage() {
const [saving, setSaving] = useState(false);
const [form, setForm] = useState({ document_type: 'sales_agreement', title: '', year: String(new Date().getFullYear()), person: '', file_url: '', notes: '' });
useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]);
useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]);
const load = useCallback(async () => {
setLoadingData(true);

View File

@@ -24,7 +24,7 @@ export default function ExpensesPage() {
const [errors, setErrors] = useState<Record<string, string>>({});
const [successMsg, setSuccessMsg] = useState('');
useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]);
useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]);
const load = useCallback(async () => {
setLoadingData(true);

View File

@@ -26,7 +26,7 @@ function InvoicesContent() {
const [payErrors, setPayErrors] = useState<Record<string, string>>({});
const [successMsg, setSuccessMsg] = useState('');
useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]);
useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]);
const load = useCallback(async () => {
setLoadingData(true);

View File

@@ -32,7 +32,7 @@ function OrdersContent() {
invoicing_schedule: 'single', next_invoice_date: '', staff_id: '', po_number: '', notes: '',
});
useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]);
useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]);
const load = useCallback(async () => {
setLoadingData(true);

View File

@@ -26,7 +26,7 @@ export default function AccountingDashboard() {
const [loadingData, setLoadingData] = useState(true);
useEffect(() => {
if (!loading && !user) router.push('/login');
if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
useEffect(() => {

View File

@@ -14,7 +14,7 @@ export default function ReconciliationPage() {
const [uploading, setUploading] = useState(false);
const [summary, setSummary] = useState<{ matched: number; unmatched: number } | null>(null);
useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]);
useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]);
const load = useCallback(async () => {
setLoadingData(true);

View File

@@ -16,7 +16,7 @@ export default function ReportsPage() {
const [startDate, setStartDate] = useState(`${new Date().getFullYear()}-01-01`);
const [endDate, setEndDate] = useState(new Date().toISOString().split('T')[0]);
useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]);
useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]);
async function loadReport() {
setLoadingData(true);

View File

@@ -22,7 +22,7 @@ export default function StaffPage() {
const [errors, setErrors] = useState<Record<string, string>>({});
const [successMsg, setSuccessMsg] = useState('');
useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]);
useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]);
const load = useCallback(async () => {
setLoadingData(true);

View File

@@ -33,7 +33,7 @@ export default function AdOpsIOsPage() {
page_url: '', newsletter_issue_date: '',
});
useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]);
useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]);
const load = useCallback(async () => {
setLoadingData(true);

View File

@@ -10,7 +10,7 @@ export default function AdOpsNotificationsPage() {
const [notifications, setNotifications] = useState<any[]>([]);
const [loadingData, setLoadingData] = useState(true);
useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]);
useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]);
const load = useCallback(async () => {
setLoadingData(true);

View File

@@ -22,7 +22,7 @@ export default function AdOpsDashboardPage() {
const [filterSite, setFilterSite] = useState('');
const [filterStatus, setFilterStatus] = useState('');
useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]);
useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]);
const load = useCallback(async () => {
setLoadingData(true);

View File

@@ -21,7 +21,7 @@ export default function AdOpsProductsPage() {
const [saving, setSaving] = useState(false);
const [form, setForm] = useState({ site: '', product_type: '', name: '', description: '', dimensions: '', duration_days: '', sort_order: '0' });
useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]);
useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]);
const load = useCallback(async () => {
setLoadingData(true);

View File

@@ -138,7 +138,7 @@ export default function AdminAnalyticsPage() {
const [error, setError] = useState<string | null>(null);
useEffect(() => {
if (!loading && !user) router.replace('/account');
if (!loading && !user) router.replace('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
const fetchAnalytics = useCallback(async () => {

View File

@@ -79,7 +79,7 @@ export default function AdminArticlesPage() {
const [newSaving, setNewSaving] = useState(false);
useEffect(() => {
if (!loading && !user) router.replace('/account');
if (!loading && !user) router.replace('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
const showNotification = (type: 'success' | 'error', message: string) => {

View File

@@ -282,7 +282,7 @@ export default function AuditLogPage() {
const PAGE_SIZE = 25;
useEffect(() => {
if (!loading && !user) router.replace('/account');
if (!loading && !user) router.replace('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
const fetchLogs = useCallback(async () => {

View File

@@ -69,7 +69,7 @@ export default function BannedTermsPage() {
}, [searchTerm, filterBanLevel, filterSiteScope, filterActive]);
useEffect(() => {
if (!loading && !user) router.push('/login');
if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
useEffect(() => {

View File

@@ -87,7 +87,7 @@ export default function CompanyCoveragePage() {
}, [activeTab]);
useEffect(() => {
if (!loading && !user) router.push('/login');
if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
useEffect(() => {

View File

@@ -144,7 +144,7 @@ export default function CompanyTrackerPage() {
}, [activeTab, queueStatus, queueSiteFilter]);
useEffect(() => {
if (!loading && !user) router.push('/login');
if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
useEffect(() => {

View File

@@ -261,7 +261,7 @@ export default function ContentStatusPage() {
}, []);
useEffect(() => {
if (!loading && !user) router.push('/login');
if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
useEffect(() => {

View File

@@ -185,7 +185,7 @@ export default function EmailAnalyticsDashboard() {
const [timeRange, setTimeRange] = useState<'3m' | '6m' | '12m'>('6m');
useEffect(() => {
if (!loading && !user) router.replace('/account');
if (!loading && !user) router.replace('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
const fetchData = useCallback(async () => {

View File

@@ -33,7 +33,7 @@ function DomainsContent() {
const [addForm, setAddForm] = useState({ site: '', domain: '', domain_type: 'subdomain', is_primary: false, sort_order: 0 });
const [saving, setSaving] = useState(false);
useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]);
useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]);
const load = useCallback(async () => {
setLoadingData(true);

View File

@@ -21,7 +21,7 @@ export default function EmailDashboard() {
const [stats, setStats] = useState<any>(null);
const [loadingData, setLoadingData] = useState(true);
useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]);
useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]);
const load = useCallback(async () => {
setLoadingData(true);

View File

@@ -14,7 +14,7 @@ export default function SendLogPage() {
const [filterSite, setFilterSite] = useState('');
const [filterStatus, setFilterStatus] = useState('');
useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]);
useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]);
const load = useCallback(async () => {
setLoadingData(true);

View File

@@ -23,7 +23,7 @@ export default function SuppressionsPage() {
const [keywordForm, setKeywordForm] = useState({ keyword: '', keyword_type: 'unsubscribe' });
const [saving, setSaving] = useState(false);
useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]);
useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]);
const load = useCallback(async () => {
setLoadingData(true);

View File

@@ -178,7 +178,7 @@ export default function ForumDashboardPage() {
const [error, setError] = useState<string | null>(null);
useEffect(() => {
if (!loading && !user) router.push('/login');
if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
const fetchStats = useCallback(async () => {

View File

@@ -348,7 +348,7 @@ export default function ForumModerationPage() {
}, [activeTab, threadFilter, replyFilter, page]);
useEffect(() => {
if (!loading && !user) router.push('/login');
if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
useEffect(() => {

View File

@@ -57,7 +57,7 @@ export default function WPImportPage() {
useEffect(() => {
if (!loading && !user) {
router.replace('/account');
router.replace('/login?next=' + encodeURIComponent(window.location.pathname));
}
}, [user, loading, router]);

View File

@@ -178,7 +178,7 @@ export default function NewsletterAnalyticsPage() {
const [sortDir, setSortDir] = useState<'asc' | 'desc'>('desc');
useEffect(() => {
if (!loading && !user) router.replace('/account');
if (!loading && !user) router.replace('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
const fetchData = useCallback(async () => {

View File

@@ -105,7 +105,7 @@ export default function CampaignEditorPage() {
const [previewCharCount, setPreviewCharCount] = useState(0);
useEffect(() => {
if (!loading && !user) router.replace('/account');
if (!loading && !user) router.replace('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
const showNotification = (type: 'success' | 'error', message: string) => {

View File

@@ -101,7 +101,7 @@ export default function AdminNewsletterPage() {
const [appliedTemplate, setAppliedTemplate] = useState<NewsletterTemplate | null>(null);
useEffect(() => {
if (!loading && !user) router.replace('/account');
if (!loading && !user) router.replace('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
// Handle ?template= query param (from templates page "Use" button)

View File

@@ -102,7 +102,7 @@ export default function NewsletterTemplatesPage() {
const [previewTemplate, setPreviewTemplate] = useState<NewsletterTemplate | null>(null);
useEffect(() => {
if (!loading && !user) router.replace('/account');
if (!loading && !user) router.replace('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
const showNotification = (type: 'success' | 'error', message: string) => {

View File

@@ -289,7 +289,7 @@ export default function NotificationsPage() {
// Auth guard
useEffect(() => {
if (user === null) router.push('/login');
if (user === null) router.push('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, router]);
// Build notifications from live DB data

View File

@@ -227,7 +227,7 @@ export default function AdminDashboardPage() {
useEffect(() => {
if (!loading && !user) {
router.push('/login');
router.push('/login?next=' + encodeURIComponent(window.location.pathname));
}
}, [user, loading, router]);

View File

@@ -209,7 +209,7 @@ export default function AdminRolesPage() {
const [notification, setNotification] = useState<{ type: 'success' | 'error'; message: string } | null>(null);
useEffect(() => {
if (!loading && !user) router.replace('/account');
if (!loading && !user) router.replace('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
const showNotification = (type: 'success' | 'error', message: string) => {

View File

@@ -78,7 +78,7 @@ export default function AdminSuspensionsPage() {
const [userSearch, setUserSearch] = useState('');
useEffect(() => {
if (!loading && !user) router.replace('/account');
if (!loading && !user) router.replace('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
const showNotification = (type: 'success' | 'error', message: string) => {

View File

@@ -78,7 +78,7 @@ export default function AdminUsersPage() {
const [editSaving, setEditSaving] = useState(false);
useEffect(() => {
if (!loading && !user) router.replace('/account');
if (!loading && !user) router.replace('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
const showNotification = (type: 'success' | 'error' | 'warning', message: string) => {

View File

@@ -48,7 +48,7 @@ export default function WPUsersAdminPage() {
};
useEffect(() => {
if (!loading && !user) router.push('/login');
if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname));
}, [user, loading, router]);
useEffect(() => {