sync-network.ts

3.1 KB · raw

1import type { TrustedNetwork } from '../shared/sync-types';2import { getTrustedNetworks, addTrustedNetwork as storageAddTrustedNetwork } from './sync-storage';34export interface NetworkInfo {5  ssid?: string;6  bssid?: string;7  isTailscale: boolean;8  ipAddress?: string;9}1011export function isTailscaleIP(ip: string): boolean {12  const parts = ip.split('.').map(Number);13  if (parts.length !== 4 || parts.some(isNaN)) return false;14  const [a, b] = parts;15  return a === 100 && b >= 64 && b <= 127;16}1718export async function isOnTailscale(): Promise<boolean> {19  try {20    if (typeof chrome === 'undefined' || !(chrome as unknown as { system?: { network?: { getNetworkInterfaces: () => Promise<Array<{ address: string }>> } } }).system?.network) return false;21    const networkApi = (chrome as unknown as { system: { network: { getNetworkInterfaces: () => Promise<Array<{ address: string }>> } } }).system.network;22    const interfaces = await networkApi.getNetworkInterfaces();23    return interfaces.some((iface) => isTailscaleIP(iface.address));24  } catch {25    return false;26  }27}2829export async function getCurrentNetwork(): Promise<NetworkInfo> {30  const info: NetworkInfo = { isTailscale: false };3132  try {33    const chromeTyped = chrome as unknown as { system?: { network?: { getNetworkInterfaces: () => Promise<Array<{ address: string; name?: string }>> } } };34    if (chromeTyped.system?.network) {35      const networkApi = chromeTyped.system.network;36      const interfaces = await networkApi.getNetworkInterfaces();37      const tailscaleIface = interfaces.find((iface) => isTailscaleIP(iface.address));38      if (tailscaleIface) {39        info.isTailscale = true;40        info.ipAddress = tailscaleIface.address;41      } else if (interfaces.length > 0) {42        info.ipAddress = interfaces[0].address;43      }44    }45  } catch {46    // Fallback: network info not available47  }4849  return info;50}5152export async function isCurrentNetworkTrusted(): Promise<boolean> {53  try {54    const networks = await getTrustedNetworks();55    if (networks.length === 0) return false;5657    if (typeof chrome !== 'undefined') {58      const chromeTyped = chrome as unknown as { system?: { network?: { getNetworkInterfaces: () => Promise<Array<{ address: string }>> } } };59      if (chromeTyped.system?.network) {60        const interfaces = await chromeTyped.system.network.getNetworkInterfaces();61        const hasTailscaleIp = interfaces.some((iface) => isTailscaleIP(iface.address));6263        for (const network of networks) {64          if (network.isTailscale && hasTailscaleIp) return true;65        }66      }67    }6869    return false;70  } catch {71    return false;72  }73}7475export async function trustCurrentNetwork(): Promise<void> {76  const network = await getCurrentNetwork();77  const trusted: TrustedNetwork = {78    isTailscale: network.isTailscale,79    addedAt: Date.now(),80  };8182  if (network.ssid) trusted.ssid = network.ssid;83  if (network.bssid) trusted.bssid = network.bssid;84  if (network.ipAddress) {85    trusted.isTailscale = isTailscaleIP(network.ipAddress) || network.isTailscale;86  }8788  await storageAddTrustedNetwork(trusted);89}