Skip to content

[BT-003] Intercept and Validate Dynamic Suffixes #80908

@mjasikowski

Description

@mjasikowski

Description

Current State:

  • getAdaptedStateFromPath.ts handles URL-to-navigation-state conversion
  • The getMatchingFullScreenRoute() function checks for backTo parameters
  • Dynamic suffixes are not recognized; they fall through to standard route matching
  • Any URL can be manually constructed with any suffix (no access control)

Expected State:

  • Modify getMatchingFullScreenRoute() to detect dynamic suffixes BEFORE checking backTo
  • Implement access control that validates the base screen is in the entryScreens allow-list
  • When a dynamic suffix is detected:
    1. Strip the suffix from the path
    2. Get the navigation state for the base path
    3. Validate the base screen is in entryScreens
    4. Build the dynamic route state on top of the base state
  • This enables proper state restoration after page refresh or deep link

Part A: Suffix Interception

Add new logic before the existing isRouteWithBackToParam check:

function getMatchingFullScreenRoute(route) {
    const suffix = getLastSuffixFromPath(route.path);
    
    // NEW: Check for dynamic suffix BEFORE checking backTo
    if (isDynamicRouteSuffix(suffix)) {
        const pathWithoutSuffix = removeSuffix(route.path, suffix);
        const stateUnderneath = getStateFromPath(pathWithoutSuffix, config);
        // ... validate and return appropriate state
    }

    // EXISTING: Check for backTo param
    if (isRouteWithBackToParam(route)) {
        // ... existing logic
    }
}

Part B: Access Control Validation

Extend the suffix interception logic to validate entry screens:

if (isDynamicRouteSuffix(suffix)) {
    const dynamicConfig = getDynamicConfigBySuffix(suffix);
    const baseScreen = findFocusedRoute(baseState);

    if (baseScreen && allowedEntryScreens.includes(baseScreen.name)) {
        // ALLOW: Generate the dynamic route state
        return generateDynamicState(baseState, suffix);
    } else {
        // DENY: Log error and fall through to standard handling
        console.warn(`Access denied: Screen ${baseScreen?.name} is not in entryScreens for ${suffix}`);
    }
}

Scope

Files:

  • App/src/libs/Navigation/helpers/getAdaptedStateFromPath.ts - Main modification point
  • App/src/libs/Navigation/Navigation.ts - Add validation in createDynamicRoute()

Functions to Add/Modify:

  • getMatchingFullScreenRoute() - Add suffix detection and validation
  • getLastSuffixFromPath(), isDynamicRouteSuffix(), removeSuffix() - New helpers
  • getDynamicConfigBySuffix() - New helper to retrieve config by suffix

Dependencies:

Metadata

Metadata

Labels

Awaiting PaymentAuto-added when associated PR is deployed to productionInternalRequires API changes or must be handled by Expensify staffWeeklyKSv2

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions