post-login.ts 2.83 KB
import { canAccessPageByRoles, LOGIN_PATH, normalizePagePath } from '~/utils/permission'
import { isMobileOrTablet } from '~/utils/device'

export const MOBILE_WORKBENCH_PATH = '/m/workbench'
const DEFAULT_DESKTOP_PATH = '/work-orders'
const DESKTOP_FALLBACK_PATHS = [
  '/sn-management',
  '/operations'
]
const MOBILE_FALLBACK_PATHS = [
  MOBILE_WORKBENCH_PATH,
  '/m/production/sn-query'
]
const DESKTOP_ROLE_BASED_FALLBACK_PATHS = [
  DEFAULT_DESKTOP_PATH,
  ...DESKTOP_FALLBACK_PATHS,
  '/'
]

function normalizeRedirectPath(redirect: unknown) {
  if (typeof redirect !== 'string') {
    return null
  }

  if (!redirect.startsWith('/') || redirect.startsWith('//')) {
    return null
  }

  const normalizedRedirect = normalizePagePath(redirect)

  if (normalizedRedirect === LOGIN_PATH) {
    return null
  }

  return normalizedRedirect
}

function normalizeRoles(roles?: string[]) {
  if (!Array.isArray(roles)) {
    return []
  }

  return roles
    .filter(role => typeof role === 'string' && role.trim().length > 0)
    .map(role => role.trim())
}

function isOperatorOnlyRole(roles: string[]) {
  if (!roles.includes('operator')) {
    return false
  }

  const hasDesktopManagementRole = roles.includes('admin') || roles.includes('qa_manager')
  return !hasDesktopManagementRole
}

function isMobilePagePath(path: string) {
  return path === MOBILE_WORKBENCH_PATH || path.startsWith('/m/')
}

function findFirstAccessiblePath(paths: string[], roles: string[]) {
  for (const fallbackPath of paths) {
    if (canAccessPageByRoles(roles, fallbackPath)) {
      return fallbackPath
    }
  }

  return null
}

export function resolvePostLoginPath(redirect: unknown, roles?: string[]) {
  const normalizedRoles = normalizeRoles(roles)
  const normalizedRedirect = normalizeRedirectPath(redirect)
  const canAccessRedirect = Boolean(
    normalizedRedirect && canAccessPageByRoles(normalizedRoles, normalizedRedirect)
  )

  if (isMobileOrTablet()) {
    if (normalizedRedirect && isMobilePagePath(normalizedRedirect) && canAccessRedirect) {
      return normalizedRedirect
    }

    if (isOperatorOnlyRole(normalizedRoles)) {
      return MOBILE_WORKBENCH_PATH
    }

    const mobileFallbackPath = findFirstAccessiblePath(MOBILE_FALLBACK_PATHS, normalizedRoles)
    if (mobileFallbackPath) {
      return mobileFallbackPath
    }
  }

  if (normalizedRedirect && canAccessRedirect) {
    return normalizedRedirect
  }

  if (isOperatorOnlyRole(normalizedRoles)) {
    return MOBILE_WORKBENCH_PATH
  }

  const desktopFallbackPath = findFirstAccessiblePath(DESKTOP_ROLE_BASED_FALLBACK_PATHS, normalizedRoles)
  if (desktopFallbackPath) {
    return desktopFallbackPath
  }

  const mobileFallbackPath = findFirstAccessiblePath(MOBILE_FALLBACK_PATHS, normalizedRoles)
  if (mobileFallbackPath) {
    return mobileFallbackPath
  }

  return normalizedRedirect ?? DEFAULT_DESKTOP_PATH
}