# ----------------------------------------------------------------------
# SPB Portal .htaccess
# ----------------------------------------------------------------------
# Adapted from the draft in portal_UNFINISHED_HALF_WAY_OF_CONFIGURING...zip.
# One change from that draft, and why:
#
# Added "RewriteCond %{REQUEST_FILENAME} !-f" before the new-page
# pass-through rule below. Without it, this file would have silently
# hijacked the EXISTING, working /portal/index.php (Cognito start) and
# /portal/logout.php (Cognito logout) the moment it was deployed,
# because both names are real files at the portal root today. With the
# guard, a request only gets rewritten into public/ when no real file
# already answers it — so today's index.php and logout.php keep working
# untouched, and the day you remove them in favour of the public/
# versions, the rewrite starts serving those automatically with no
# further .htaccess changes.
#
# Everything else (including the bare "/portal/" rule below) is exactly
# as drafted. See README-REDESIGN.md, section "About that bare /portal/
# rule", before deploying — it explains a real, easy-to-miss interaction
# with the point above.
# ----------------------------------------------------------------------

# Redirect accidental direct /public URL back to clean portal URL
RewriteCond %{THE_REQUEST} \s/+portal/public/? [NC]
RewriteRule ^public/?$ /portal/ [R=302,L]

RewriteCond %{THE_REQUEST} \s/+portal/public/(.*) [NC]
RewriteRule ^public/(.*)$ /portal/$1 [R=302,L]

Options -Indexes

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /portal/

    # ------------------------------------------------------------------
    # Block hidden files and sensitive files
    # ------------------------------------------------------------------

    RewriteRule (^|/)\. - [F,L]

    RewriteRule ^(composer\.json|composer\.lock|package\.json|package-lock\.json|webpack\.config\.js|vite\.config\.js)$ - [F,L,NC]
    RewriteRule ^(.*)\.(bak|backup|old|orig|save|swp|sql|log|ini|env)$ - [F,L,NC]

    # ------------------------------------------------------------------
    # Block direct browser access to backend folders
    # ------------------------------------------------------------------

    RewriteRule ^app(/|$) - [F,L]
    RewriteRule ^storage(/|$) - [F,L]

    # If vendor is not inside portal, this rule will not matter.
    # Keep it for safety if vendor is ever created here.
    RewriteRule ^vendor(/|$) - [F,L]

    # ------------------------------------------------------------------
    # Block direct physical /legacy URL access
    # Example blocked:
    # /portal/legacy/brrpts_erd/welcome.php
    # Reach the same content through the clean aliases below instead:
    # /portal/brrpts_erd/welcome.php
    # ------------------------------------------------------------------

    RewriteCond %{THE_REQUEST} \s/+portal/legacy/ [NC]
    RewriteRule ^legacy(/|$) - [F,L]

    # ------------------------------------------------------------------
    # Main portal entry
    # /portal/  →  public/index.php  (the NEW shell's landing page)
    #
    # NOTE: this does not affect explicit /portal/index.php requests —
    # those keep hitting the real, existing Cognito-starting file below,
    # because of the -f guard on the rule right after this one. See
    # README-REDESIGN.md for what that means in practice.
    # ------------------------------------------------------------------

    RewriteRule ^$ public/index.php [L,QSA]

    # ------------------------------------------------------------------
    # New public PHP entry pages
    # /portal/dashboard.php → /portal/public/dashboard.php
    # ------------------------------------------------------------------

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(index|login|callback|logout|dashboard|unit-select|report|transaction)\.php$ public/$1.php [L,QSA]

    # ------------------------------------------------------------------
    # Public API
    # /portal/api/... → /portal/public/api/index.php
    # ------------------------------------------------------------------

    RewriteRule ^api(/.*)?$ public/api/index.php [L,QSA]

    # ------------------------------------------------------------------
    # Public assets
    # /portal/assets/... → /portal/public/assets/...
    # ------------------------------------------------------------------

    RewriteRule ^assets/(.*)$ public/assets/$1 [L,QSA]

    # ------------------------------------------------------------------
    # Legacy compatibility routes
    # These give the copied legacy/ folders clean URLs:
    #
    # /portal/admin/welcome.php
    # /portal/brrpts_erd/welcome.php
    # /portal/brrpts_tvl/welcome.php
    #
    # The original, untouched files under /portal/otp/... keep working
    # exactly as they do today, completely unaffected by this section.
    # ------------------------------------------------------------------

    RewriteRule ^admin/(.*)$ legacy/admin/$1 [L,QSA]

    RewriteRule ^brrpts/(.*)$ legacy/brrpts/$1 [L,QSA]
    RewriteRule ^brrpts_erd/(.*)$ legacy/brrpts_erd/$1 [L,QSA]
    RewriteRule ^brrpts_tvl/(.*)$ legacy/brrpts_tvl/$1 [L,QSA]

    RewriteRule ^acc/(.*)$ legacy/acc/$1 [L,QSA]
    RewriteRule ^acc_erd/(.*)$ legacy/acc_erd/$1 [L,QSA]
    RewriteRule ^acc_tvl/(.*)$ legacy/acc_tvl/$1 [L,QSA]

    RewriteRule ^indr/(.*)$ legacy/indr/$1 [L,QSA]
    RewriteRule ^indr_erd/(.*)$ legacy/indr_erd/$1 [L,QSA]
    RewriteRule ^indr_tvl/(.*)$ legacy/indr_tvl/$1 [L,QSA]

</IfModule>

# ----------------------------------------------------------------------
# Security Headers
# PHP also sends headers, but Apache-level headers help static files too.
# ----------------------------------------------------------------------

<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set X-XSS-Protection "0"
    Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=()"

    # Keep CSP migration-friendly for now because old pages may use inline JS/CSS.
    Header always set Content-Security-Policy "default-src 'self'; base-uri 'self'; form-action 'self'; frame-ancestors 'self'; object-src 'none'; img-src 'self' data: blob:; font-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; connect-src 'self'"
</IfModule>

# ----------------------------------------------------------------------
# PHP direct access safety
# ----------------------------------------------------------------------

<FilesMatch "(^\.|secrets\.php|database\.php|security\.php|app\.php|modules\.php|units\.php|legacy_routes\.php)$">
    Require all denied
</FilesMatch>
