| import { machineIdSync } from 'node-machine-id'; |
| import fs from 'node:fs'; |
| import path from 'node:path'; |
| import crypto from 'node:crypto'; |
| import { DATA_DIR } from '@/lib/dataDir'; |
|
|
| const MACHINE_ID_FILE = path.join(DATA_DIR, 'machine-id'); |
| const AUTH_DIR = path.join(DATA_DIR, 'auth'); |
| const CLI_SECRET_FILE = path.join(AUTH_DIR, 'cli-secret'); |
| const CLI_AUTH_SALT = '9r-cli-auth'; |
| let cachedRawId = null; |
| let cachedCliSecret = null; |
|
|
| |
| |
| function loadRawMachineId() { |
| if (cachedRawId) return cachedRawId; |
| try { |
| cachedRawId = fs.readFileSync(MACHINE_ID_FILE, 'utf8').trim(); |
| if (cachedRawId) return cachedRawId; |
| } catch {} |
| try { |
| cachedRawId = machineIdSync(); |
| } catch { |
| cachedRawId = crypto.randomUUID(); |
| } |
| try { |
| fs.mkdirSync(DATA_DIR, { recursive: true }); |
| fs.writeFileSync(MACHINE_ID_FILE, cachedRawId, { mode: 0o600 }); |
| } catch {} |
| return cachedRawId; |
| } |
|
|
| |
| function loadCliSecret() { |
| if (cachedCliSecret) return cachedCliSecret; |
| try { |
| cachedCliSecret = fs.readFileSync(CLI_SECRET_FILE, 'utf8').trim(); |
| if (cachedCliSecret) return cachedCliSecret; |
| } catch {} |
| cachedCliSecret = crypto.randomBytes(32).toString('hex'); |
| try { |
| fs.mkdirSync(AUTH_DIR, { recursive: true }); |
| fs.writeFileSync(CLI_SECRET_FILE, cachedCliSecret, { mode: 0o600 }); |
| } catch {} |
| return cachedCliSecret; |
| } |
|
|
| export async function getConsistentMachineId(salt = null) { |
| const saltValue = salt || process.env.MACHINE_ID_SALT || 'endpoint-proxy-salt'; |
| const raw = loadRawMachineId(); |
| const extra = saltValue === CLI_AUTH_SALT ? loadCliSecret() : ''; |
| return crypto.createHash('sha256').update(raw + saltValue + extra).digest('hex').substring(0, 16); |
| } |
|
|
| export async function getRawMachineId() { |
| return loadRawMachineId(); |
| } |
|
|
| |
| |
| |
| |
| export function isBrowser() { |
| return typeof window !== 'undefined'; |
| } |
|
|