From bda13fde678af1edc27a90cf45cf59bdbad00451 Mon Sep 17 00:00:00 2001 From: Tanya Date: Mon, 23 Mar 2026 14:11:44 -0400 Subject: [PATCH] docs: add appendix for permanent path redirect fixes in cPanel deployment guide - Document long-term solutions for handling path prefixes in PunimTag deployments. - Outline steps to configure viewer base path, align environment variables, and enforce consistent URL patterns. - Include validation checklist and recommended deployment policy to ensure stable setups. --- docs/DEPLOY_CPANEL_STEP_BY_STEP.md | 166 ++++++++++++++++++ .../app/admin/users/ManageUsersContent.tsx | 36 ++-- 2 files changed, 191 insertions(+), 11 deletions(-) diff --git a/docs/DEPLOY_CPANEL_STEP_BY_STEP.md b/docs/DEPLOY_CPANEL_STEP_BY_STEP.md index e365346..78eab79 100644 --- a/docs/DEPLOY_CPANEL_STEP_BY_STEP.md +++ b/docs/DEPLOY_CPANEL_STEP_BY_STEP.md @@ -1150,3 +1150,169 @@ If you encounter issues: **Congratulations!** You've successfully deployed PunimTag to cPanel! 🎉 +--- + +## Appendix: Permanent Fix for Path Redirect Issues (Avoid Per-Feature `.htaccess` Rules) + +This appendix documents the long-term fix for deployments where PunimTag runs under +path prefixes such as: + +- `/punim-admin/` +- `/punim-viewer/` +- `/punim-api/` + +### Why this matters + +If the viewer app is only partially path-aware, some actions may still navigate to +root URLs like `/`, `/search`, or `/api/auth/session`. On WordPress + cPanel hosting, +those root paths are handled by WordPress instead of PunimTag, causing redirects, +404/400/405 errors, and broken flows. + +Temporary `.htaccess` redirect rules can patch specific cases, but they are not +scalable. New features can introduce new root paths that require additional rules. + +### Goal (Target State) + +Use one consistent strategy so the app works without adding route-by-route redirects: + +1. Viewer app is fully aware it runs at `/punim-viewer` +2. Auth routes resolve consistently under the same strategy +3. Reverse proxy behavior matches app expectations +4. `.htaccess` contains only minimal compatibility rules (or none) + +--- + +### Step A - Configure Viewer Base Path (Code-Level, One-Time) + +Edit `viewer-frontend/next.config.ts` and ensure these settings are present: + +```ts +const nextConfig: NextConfig = { + basePath: '/punim-viewer', + assetPrefix: '/punim-viewer', + // ...existing config +}; +``` + +Why: +- `basePath` makes Next.js routes and app navigation prefix-aware +- `assetPrefix` ensures static assets load from `/punim-viewer/_next/...` + +--- + +### Step B - Align Viewer Environment Variables + +In `viewer-frontend/.env` (production), keep auth/app URLs internally consistent. +Use the same canonical public origin and prefix strategy. + +Recommended baseline: + +```bash +NEXT_PUBLIC_APP_URL=https://your-domain.com/punim-viewer +NEXTAUTH_URL=https://your-domain.com/punim-viewer +AUTH_URL=https://your-domain.com/punim-viewer +AUTH_TRUST_HOST=true +NEXT_PUBLIC_API_URL=/punim-api +BACKEND_BASE_URL=/punim-api +``` + +Important: +- If your proxy forwards auth requests to Next.js as `/api/auth/*` (without prefix), + adjust `AUTH_URL`/`NEXTAUTH_URL` to match that behavior. +- Do not mix multiple base URL strategies at the same time. + +--- + +### Step C - Enforce a Single URL Construction Pattern in Viewer + +In viewer frontend code, avoid hardcoding root-absolute app routes for internal +navigation (`'/'`, `'/search'`, `'/upload'`, `'/api/auth/...'`) unless you are sure +Next base path handling applies. + +Use shared helpers/utilities for: +- app route construction +- API route construction +- auth endpoints + +This prevents new features from accidentally introducing root paths that bypass +`/punim-viewer`. + +--- + +### Step D - Proxy Contract with Hosting Provider + +Confirm the reverse proxy contract and keep it stable across deploys: + +- `/punim-admin/*` -> React admin service +- `/punim-viewer/*` -> Next viewer service +- `/punim-api/*` -> FastAPI service root + +For API mapping to FastAPI root: +- Browser endpoints remain `/punim-api/api/v1/...` for versioned routes +- Root routes like `/docs`, `/health`, and `/openapi.json` are under `/punim-api/...` + +For viewer mapping: +- Ensure proxy behavior (path preserved vs stripped) is explicitly documented +- Match viewer env/auth settings to that behavior + +--- + +### Step E - Rebuild and Restart Services + +After changing base path/env/proxy assumptions: + +```bash +cd ~/punimtag/viewer-frontend +rm -rf .next +npm run build +pm2 restart punimtag-viewer +``` + +If admin env/settings changed, rebuild/restart admin too. + +--- + +### Step F - Validation Checklist (Must Pass) + +Run these checks in browser network tab and direct URL tests: + +1. Viewer entry: + - `https://your-domain.com/punim-viewer/` loads correctly +2. Viewer navigation: + - Actions (filters, clear all, login flows) remain under `/punim-viewer/...` +3. Auth session: + - `/punim-viewer/api/auth/session` succeeds (no 400/405) +4. Viewer API: + - Requests resolve under `/punim-viewer/api/...` (or your chosen consistent path) +5. Backend docs: + - `https://your-domain.com/punim-api/docs` loads + - `https://your-domain.com/punim-api/openapi.json` loads +6. Backend API: + - Versioned endpoints reachable at `/punim-api/api/v1/...` + +--- + +### Step G - Decommission Temporary `.htaccess` Workarounds + +Once target state is validated: + +1. Remove route-by-route workaround redirects one by one +2. Retest after each removal +3. Keep only minimal generic rules required by hosting constraints + +This prevents maintenance debt where each new viewer feature needs a new rewrite rule. + +--- + +### Recommended Deployment Policy + +Before every production deployment: + +1. Confirm `next.config.ts` still has `basePath` + `assetPrefix` +2. Confirm viewer `.env` values are consistent with proxy contract +3. Build viewer from clean `.next` +4. Perform the validation checklist above +5. Only use `.htaccess` rewrites as temporary emergency mitigation + +Following this policy gives a stable, permanent setup and avoids per-feature redirect +maintenance. diff --git a/viewer-frontend/app/admin/users/ManageUsersContent.tsx b/viewer-frontend/app/admin/users/ManageUsersContent.tsx index e380749..6254c67 100644 --- a/viewer-frontend/app/admin/users/ManageUsersContent.tsx +++ b/viewer-frontend/app/admin/users/ManageUsersContent.tsx @@ -21,6 +21,11 @@ import { SelectTrigger, SelectValue, } from '@/components/ui/select'; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from '@/components/ui/tooltip'; import { isValidEmail } from '@/lib/utils'; interface User { @@ -387,17 +392,26 @@ export function ManageUsersContent() { > - + {user.isActive !== false && ( + + + + + +

Deactivate User

+
+
+ )}