{"version":3,"file":"ad-attributes.mjs","sources":["../../../../src/lib/auth/active-directory/ad-attributes.ts"],"sourcesContent":["/**\n * Active Directory User Attribute Mapping\n *\n * Maps AD/Graph API user attributes to application user properties.\n * Supports custom attribute mapping, transformation, and validation.\n *\n * @module auth/active-directory/ad-attributes\n */\n\nimport type { ADUserAttributes, ADUser } from './types';\nimport type { User } from '@/lib';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Attribute transformation function type.\n */\nexport type AttributeTransformer<TIn = unknown, TOut = unknown> = (\n  value: TIn,\n  source: ADUserAttributes\n) => TOut;\n\n/**\n * Attribute validation function type.\n */\nexport type AttributeValidator<T = unknown> = (\n  value: T,\n  attributeName: string\n) => { valid: boolean; error?: string };\n\n/**\n * Single attribute mapping configuration.\n */\nexport interface AttributeMapping<TIn = unknown, TOut = unknown> {\n  /** Source attribute name in AD */\n  source: keyof ADUserAttributes | string;\n  /** Target attribute name in application user */\n  target: string;\n  /** Optional transformation function */\n  transform?: AttributeTransformer<TIn, TOut>;\n  /** Optional validation function */\n  validate?: AttributeValidator<TIn>;\n  /** Default value if source is undefined */\n  defaultValue?: TOut;\n  /** Whether this attribute is required */\n  required?: boolean;\n  /** Custom extraction function for complex mappings */\n  extract?: (source: ADUserAttributes) => TIn;\n}\n\n/**\n * Complete attribute mapping configuration.\n */\nexport interface AttributeMappingConfig {\n  /** Individual attribute mappings */\n  mappings: AttributeMapping[];\n  /** Whether to include unmapped attributes in metadata */\n  includeUnmapped?: boolean;\n  /** Prefix for unmapped attributes in metadata */\n  unmappedPrefix?: string;\n  /** Custom extension attribute mappings */\n  extensionMappings?: Record<string, string>;\n  /** Attributes to explicitly exclude */\n  excludeAttributes?: string[];\n}\n\n/**\n * Result of attribute mapping operation.\n */\nexport interface AttributeMappingResult {\n  /** Mapped attributes */\n  attributes: Record<string, unknown>;\n  /** Validation errors encountered */\n  errors: Array<{ attribute: string; error: string }>;\n  /** Unmapped attributes (if includeUnmapped is true) */\n  unmapped?: Record<string, unknown>;\n  /** Whether mapping was successful (no required attribute errors) */\n  success: boolean;\n}\n\n// =============================================================================\n// Default Mappings\n// =============================================================================\n\n/**\n * Default attribute mappings from AD to application User.\n */\nexport const DEFAULT_ATTRIBUTE_MAPPINGS: AttributeMapping[] = [\n  {\n    source: 'objectId',\n    target: 'id',\n    required: true,\n  },\n  {\n    source: 'email',\n    target: 'email',\n    required: true,\n    extract: (source) =>\n      source.email != null && source.email !== '' ? source.email : (source.upn ?? undefined),\n  },\n  {\n    source: 'givenName',\n    target: 'firstName',\n    defaultValue: '',\n  },\n  {\n    source: 'surname',\n    target: 'lastName',\n    defaultValue: '',\n  },\n  {\n    source: 'displayName',\n    target: 'displayName',\n    required: true,\n  },\n  {\n    source: 'createdDateTime',\n    target: 'createdAt',\n    transform: (value) => (value != null && value !== '' ? value : new Date().toISOString()),\n  },\n];\n\n/**\n * Extended attribute mappings for additional user properties.\n */\nexport const EXTENDED_ATTRIBUTE_MAPPINGS: AttributeMapping[] = [\n  {\n    source: 'jobTitle',\n    target: 'jobTitle',\n  },\n  {\n    source: 'department',\n    target: 'department',\n  },\n  {\n    source: 'officeLocation',\n    target: 'officeLocation',\n  },\n  {\n    source: 'mobilePhone',\n    target: 'phone',\n  },\n  {\n    source: 'employeeId',\n    target: 'employeeId',\n  },\n  {\n    source: 'companyName',\n    target: 'company',\n  },\n  {\n    source: 'manager',\n    target: 'manager',\n  },\n];\n\n/**\n * Healthcare-specific attribute mappings for HIPAA compliance.\n */\nexport const HEALTHCARE_ATTRIBUTE_MAPPINGS: AttributeMapping[] = [\n  {\n    source: 'employeeId',\n    target: 'providerId',\n    required: false,\n  },\n  {\n    source: 'department',\n    target: 'medicalDepartment',\n  },\n  {\n    source: 'jobTitle',\n    target: 'clinicalRole',\n  },\n  // Custom extension attribute for NPI (National Provider Identifier)\n  {\n    source: 'extensionAttributes',\n    target: 'npi',\n    extract: (source) => source.extensionAttributes?.['extension_npi'],\n    validate: (value) => ({\n      valid:\n        value == null || /^\\d{10}$/.test(typeof value === 'string' ? value : JSON.stringify(value)),\n      error: 'NPI must be a 10-digit number',\n    }),\n  },\n  // DEA number for prescribing authority\n  {\n    source: 'extensionAttributes',\n    target: 'deaNumber',\n    extract: (source) => source.extensionAttributes?.['extension_deaNumber'],\n    validate: (value) => ({\n      valid:\n        value == null ||\n        /^[A-Z]{2}\\d{7}$/.test(typeof value === 'string' ? value : JSON.stringify(value)),\n      error: 'DEA number must be 2 letters followed by 7 digits',\n    }),\n  },\n];\n\n// =============================================================================\n// Attribute Mapper Class\n// =============================================================================\n\n/**\n * AD Attribute Mapper for user property transformation.\n *\n * Maps AD user attributes to application user properties using\n * configurable mapping rules with support for transformation,\n * validation, and custom extraction logic.\n *\n * @example\n * ```typescript\n * const mapper = new ADAttributeMapper({\n *   mappings: DEFAULT_ATTRIBUTE_MAPPINGS,\n *   includeUnmapped: true,\n *   unmappedPrefix: 'ad_',\n * });\n *\n * const result = mapper.mapAttributes(adUserAttributes);\n * if (result.success) {\n *   console.log('Mapped attributes:', result.attributes);\n * } else {\n *   console.error('Mapping errors:', result.errors);\n * }\n * ```\n */\nexport class ADAttributeMapper {\n  private readonly config: AttributeMappingConfig;\n\n  /**\n   * Create a new attribute mapper.\n   *\n   * @param config - Attribute mapping configuration\n   */\n  constructor(config: Partial<AttributeMappingConfig> = {}) {\n    this.config = {\n      mappings: config.mappings ?? DEFAULT_ATTRIBUTE_MAPPINGS,\n      includeUnmapped: config.includeUnmapped ?? false,\n      unmappedPrefix: config.unmappedPrefix ?? 'ad_',\n      extensionMappings: config.extensionMappings ?? {},\n      excludeAttributes: config.excludeAttributes ?? [],\n    };\n  }\n\n  /**\n   * Map AD user attributes to application user properties.\n   *\n   * @param source - Source AD user attributes\n   * @returns Mapping result with attributes and any errors\n   */\n  mapAttributes(source: ADUserAttributes): AttributeMappingResult {\n    const attributes: Record<string, unknown> = {};\n    const errors: Array<{ attribute: string; error: string }> = [];\n    const processedKeys = new Set<string>();\n\n    // Process each mapping\n    for (const mapping of this.config.mappings) {\n      const sourceKey = mapping.source;\n      processedKeys.add(sourceKey);\n\n      try {\n        // Extract value using custom extractor or direct access\n        let value: unknown;\n        if (mapping.extract) {\n          value = mapping.extract(source);\n        } else {\n          value = this.getNestedValue(source as unknown as Record<string, unknown>, sourceKey);\n        }\n\n        // Apply validation if present\n        if (\n          mapping.validate !== undefined &&\n          mapping.validate !== null &&\n          value !== undefined &&\n          value !== null\n        ) {\n          const validation = mapping.validate(value, sourceKey);\n          if (!validation.valid) {\n            errors.push({\n              attribute: sourceKey,\n              error: validation.error ?? `Validation failed for ${sourceKey}`,\n            });\n\n            if (mapping.required === true) {\n              continue; // Skip required attributes that fail validation\n            }\n          }\n        }\n\n        // Check for required attributes\n        if (mapping.required === true && (value === undefined || value === null)) {\n          errors.push({\n            attribute: sourceKey,\n            error: `Required attribute '${sourceKey}' is missing`,\n          });\n          continue;\n        }\n\n        // Apply transformation if present\n        if (mapping.transform !== undefined && mapping.transform !== null && value !== undefined) {\n          value = mapping.transform(value, source);\n        }\n\n        // Use default value if needed\n        if (\n          (value === undefined || value === null) &&\n          mapping.defaultValue !== undefined &&\n          mapping.defaultValue !== null\n        ) {\n          value = mapping.defaultValue;\n        }\n\n        // Set the target attribute\n        if (value !== undefined && value !== null) {\n          attributes[mapping.target] = value;\n        }\n      } catch (error) {\n        errors.push({\n          attribute: sourceKey,\n          error: `Error mapping '${sourceKey}': ${(error as Error).message}`,\n        });\n      }\n    }\n\n    // Process extension attribute mappings\n    if (\n      this.config.extensionMappings !== undefined &&\n      this.config.extensionMappings !== null &&\n      source.extensionAttributes !== undefined &&\n      source.extensionAttributes !== null\n    ) {\n      for (const [extAttr, targetAttr] of Object.entries(this.config.extensionMappings)) {\n        const value = source.extensionAttributes[extAttr];\n        if (value !== undefined && value !== null) {\n          attributes[targetAttr] = value;\n        }\n      }\n    }\n\n    // Collect unmapped attributes if requested\n    let unmapped: Record<string, unknown> | undefined;\n    if (this.config.includeUnmapped === true) {\n      unmapped = {};\n      const excludeSet = new Set(this.config.excludeAttributes);\n\n      for (const [key, value] of Object.entries(source)) {\n        if (\n          !processedKeys.has(key) &&\n          !excludeSet.has(key) &&\n          value !== undefined &&\n          value !== null\n        ) {\n          unmapped[`${this.config.unmappedPrefix}${key}`] = value;\n        }\n      }\n    }\n\n    // Determine success based on required attribute errors\n    const hasRequiredErrors = errors.some((error) =>\n      this.config.mappings.some((m) => m.source === error.attribute && m.required === true)\n    );\n\n    return {\n      attributes,\n      errors,\n      unmapped,\n      success: !hasRequiredErrors,\n    };\n  }\n\n  /**\n   * Map AD user to application User type.\n   *\n   * @param adUser - Source AD user\n   * @returns Mapped application User\n   */\n  mapToUser(adUser: ADUser): User {\n    const result = this.mapAttributes(adUser.adAttributes);\n\n    return {\n      id: (result.attributes['id'] as string) || adUser.adAttributes.objectId,\n      email: (result.attributes['email'] as string) || adUser.email,\n      firstName: (result.attributes['firstName'] as string) || adUser.firstName,\n      lastName: (result.attributes['lastName'] as string) || adUser.lastName,\n      displayName: (result.attributes['displayName'] as string) || adUser.displayName,\n      avatarUrl: adUser.avatarUrl,\n      roles: adUser.roles,\n      permissions: adUser.permissions,\n      metadata: {\n        ...result.unmapped,\n        ...adUser.metadata,\n        adObjectId: adUser.adAttributes.objectId,\n        adProvider: adUser.adProvider,\n      },\n      createdAt: (result.attributes['createdAt'] as string) || adUser.createdAt,\n      updatedAt: adUser.updatedAt,\n    };\n  }\n\n  /**\n   * Add a mapping at runtime.\n   *\n   * @param mapping - Mapping to add\n   */\n  addMapping(mapping: AttributeMapping): void {\n    this.config.mappings.push(mapping);\n  }\n\n  /**\n   * Remove a mapping by source attribute.\n   *\n   * @param source - Source attribute name to remove\n   */\n  removeMapping(source: string): void {\n    this.config.mappings = this.config.mappings.filter((m) => m.source !== source);\n  }\n\n  /**\n   * Get the current configuration.\n   */\n  getConfig(): AttributeMappingConfig {\n    return { ...this.config };\n  }\n\n  // ===========================================================================\n  // Private Methods\n  // ===========================================================================\n\n  /**\n   * Get a nested value from an object using dot notation.\n   */\n  private getNestedValue(obj: Record<string, unknown>, path: string): unknown {\n    const keys = path.split('.');\n    let current: unknown = obj;\n\n    for (const key of keys) {\n      if (current === null || current === undefined) {\n        return undefined;\n      }\n      current = (current as Record<string, unknown>)[key];\n    }\n\n    return current;\n  }\n}\n\n// =============================================================================\n// Common Transformers\n// =============================================================================\n\n/**\n * Pre-built attribute transformers for common use cases.\n */\nexport const attributeTransformers = {\n  /**\n   * Normalize email to lowercase.\n   */\n  normalizeEmail: (value: string | undefined): string | undefined => value?.toLowerCase().trim(),\n\n  /**\n   * Format display name (proper case).\n   */\n  formatDisplayName: (value: string | undefined): string | undefined => {\n    if (value === undefined || value === null || value === '') return value;\n    return value\n      .split(' ')\n      .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n      .join(' ');\n  },\n\n  /**\n   * Parse phone number to E.164 format.\n   */\n  normalizePhone: (value: string | undefined): string | undefined => {\n    if (value === undefined || value === null || value === '') return value;\n    // Remove all non-numeric characters except leading +\n    const cleaned = value.replace(/[^\\d+]/g, '');\n    // Ensure US numbers start with +1\n    if (cleaned.length === 10) {\n      return `+1${cleaned}`;\n    }\n    return cleaned.startsWith('+') ? cleaned : `+${cleaned}`;\n  },\n\n  /**\n   * Convert ISO date string to timestamp.\n   */\n  dateToTimestamp: (value: string | undefined): number | undefined => {\n    if (value === undefined || value === null || value === '') return undefined;\n    const date = new Date(value);\n    return isNaN(date.getTime()) ? undefined : date.getTime();\n  },\n\n  /**\n   * Parse boolean from string.\n   */\n  parseBoolean: (value: unknown): boolean => {\n    if (typeof value === 'boolean') return value;\n    if (typeof value === 'string') {\n      return value.toLowerCase() === 'true' || value === '1';\n    }\n    return Boolean(value);\n  },\n\n  /**\n   * Parse array from comma-separated string.\n   */\n  parseArray: (value: string | string[] | undefined): string[] => {\n    if (value === undefined || value === null) return [];\n    if (Array.isArray(value)) return value;\n    return value\n      .split(',')\n      .map((item) => item.trim())\n      .filter(Boolean);\n  },\n\n  /**\n   * Mask sensitive data (show last 4 characters).\n   */\n  maskSensitive: (value: string | undefined): string | undefined => {\n    if (value === undefined || value === null) return value;\n    if (value === '' || value.length <= 4) return '****';\n    return '*'.repeat(value.length - 4) + value.slice(-4);\n  },\n} as const;\n\n// =============================================================================\n// Common Validators\n// =============================================================================\n\n/**\n * Pre-built attribute validators for common use cases.\n */\nexport const attributeValidators = {\n  /**\n   * Validate email format.\n   */\n  email: (value: string | undefined, attr: string): { valid: boolean; error?: string } => {\n    if (value === undefined || value === null || value === '') return { valid: true };\n    const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n    return {\n      valid: emailRegex.test(value),\n      error: `${attr} must be a valid email address`,\n    };\n  },\n\n  /**\n   * Validate UPN format.\n   */\n  upn: (value: string | undefined, attr: string): { valid: boolean; error?: string } => {\n    if (value === undefined || value === null || value === '') return { valid: true };\n    const upnRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+$/;\n    return {\n      valid: upnRegex.test(value),\n      error: `${attr} must be a valid User Principal Name`,\n    };\n  },\n\n  /**\n   * Validate GUID format.\n   */\n  guid: (value: string | undefined, attr: string): { valid: boolean; error?: string } => {\n    if (value === undefined || value === null || value === '') return { valid: true };\n    const guidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n    return {\n      valid: guidRegex.test(value),\n      error: `${attr} must be a valid GUID`,\n    };\n  },\n\n  /**\n   * Validate string length.\n   */\n  maxLength:\n    (max: number) =>\n    (value: string | undefined, attr: string): { valid: boolean; error?: string } => {\n      if (value === undefined || value === null || value === '') return { valid: true };\n      return {\n        valid: value.length <= max,\n        error: `${attr} must be at most ${max} characters`,\n      };\n    },\n\n  /**\n   * Validate required field.\n   */\n  required: (value: unknown, attr: string): { valid: boolean; error?: string } => ({\n    valid: value !== undefined && value !== null && value !== '',\n    error: `${attr} is required`,\n  }),\n\n  /**\n   * Validate against regex pattern.\n   */\n  pattern:\n    (regex: RegExp, message: string) =>\n    (value: string | undefined, attr: string): { valid: boolean; error?: string } => {\n      if (value === undefined || value === null || value === '') return { valid: true };\n      return {\n        valid: regex.test(value),\n        error:\n          message !== undefined && message !== null && message !== ''\n            ? message\n            : `${attr} does not match required pattern`,\n      };\n    },\n} as const;\n\n// =============================================================================\n// Factory Functions\n// =============================================================================\n\n/**\n * Create an attribute mapper with default configuration.\n *\n * @param options - Configuration options\n * @returns Configured ADAttributeMapper\n */\nexport function createAttributeMapper(\n  options: {\n    includeExtended?: boolean;\n    includeHealthcare?: boolean;\n    customMappings?: AttributeMapping[];\n    includeUnmapped?: boolean;\n    extensionMappings?: Record<string, string>;\n  } = {}\n): ADAttributeMapper {\n  const mappings = [...DEFAULT_ATTRIBUTE_MAPPINGS];\n\n  if (options.includeExtended === true) {\n    mappings.push(...EXTENDED_ATTRIBUTE_MAPPINGS);\n  }\n\n  if (options.includeHealthcare === true) {\n    mappings.push(...HEALTHCARE_ATTRIBUTE_MAPPINGS);\n  }\n\n  if (options.customMappings) {\n    mappings.push(...options.customMappings);\n  }\n\n  return new ADAttributeMapper({\n    mappings,\n    includeUnmapped: options.includeUnmapped ?? false,\n    extensionMappings: options.extensionMappings,\n  });\n}\n\n/**\n * Create a mapping for a custom extension attribute.\n *\n * @param extensionName - Name of the extension attribute\n * @param targetName - Target property name\n * @param options - Additional mapping options\n * @returns AttributeMapping for the extension\n */\nexport function createExtensionMapping<T>(\n  extensionName: string,\n  targetName: string,\n  options?: {\n    transform?: AttributeTransformer<T>;\n    validate?: AttributeValidator<T>;\n    required?: boolean;\n    defaultValue?: T;\n  }\n): AttributeMapping<T> {\n  return {\n    source: 'extensionAttributes',\n    target: targetName,\n    extract: (source) => source.extensionAttributes?.[extensionName] as T,\n    transform: options?.transform,\n    validate: options?.validate,\n    required: options?.required,\n    defaultValue: options?.defaultValue,\n  };\n}\n"],"names":["DEFAULT_ATTRIBUTE_MAPPINGS","source","value","EXTENDED_ATTRIBUTE_MAPPINGS","HEALTHCARE_ATTRIBUTE_MAPPINGS","ADAttributeMapper","config","attributes","errors","processedKeys","mapping","sourceKey","validation","error","extAttr","targetAttr","unmapped","excludeSet","key","hasRequiredErrors","m","adUser","result","obj","path","keys","current","attributeTransformers","word","cleaned","date","item","attributeValidators","attr","max","regex","message","createAttributeMapper","options","mappings","createExtensionMapping","extensionName","targetName"],"mappings":"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"}