UNPKG

@acurast/cli

Version:

A cli to interact with the Acurast Cloud.

114 lines 4.29 kB
import { LocalStorage } from './LocalStorage.js'; import { ACURAST_GLOBAL_BASE_PATH } from '../constants.js'; // Kept separate from `keys.json` (which the SDK KeyStore uses for ECDH keys). const AUTH_FILE = 'auth.json'; const AUTH_KEY = 'auth'; // Logins older than this are treated as logged-out and require `acurast login` // again. A remote login only authorises the browser wallet to be prompted, so a // generous window is fine. const SESSION_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1000; // 14 days // auth.json holds identity metadata — keep it readable only by the owner. // The project store uses LocalStorage's default (cwd) base path. const store = (scope) => scope === 'global' ? new LocalStorage(AUTH_FILE, 0o600, ACURAST_GLOBAL_BASE_PATH) : new LocalStorage(AUTH_FILE, 0o600); const isExpired = (record) => { const at = Date.parse(record.loggedInAt); if (Number.isNaN(at)) return false; // tolerate older records without a parseable date return Date.now() - at > SESSION_MAX_AGE_MS; }; /** The stored record as-is, without the expiry check. */ const parse = (scope) => { const raw = store(scope).getItem(AUTH_KEY); if (!raw) return null; try { return JSON.parse(raw); } catch { return null; } }; const read = (scope) => { const record = parse(scope); if (!record || isExpired(record)) return null; return record; }; export const getGlobalAuth = () => read('global'); export const getProjectAuth = () => read('project'); /** * A stored login that exists but has aged out, if any (project pin first, to * match `getActiveAuth`). Lets callers say "your session expired" instead of * the misleading "ACURAST_MNEMONIC is not defined" they would otherwise hit * once an expired session drops the signing mode back to `local`. */ export const getExpiredAuth = () => { for (const scope of ['project', 'global']) { const record = parse(scope); if (record && isExpired(record)) return { scope, record }; } return null; }; /** The account that will actually be used: a project pin wins over the global login. */ export const getActiveAuth = () => getProjectAuth() ?? getGlobalAuth(); export const getLoggedInAddress = () => getActiveAuth()?.address; export const isLoggedIn = () => getLoggedInAddress() !== undefined; export const setAuth = (record, scope = 'global') => { store(scope).setItem(AUTH_KEY, JSON.stringify(record)); }; export const clearAuth = (scope) => { store(scope).removeItem(AUTH_KEY); }; /** Update `lastUsedAt` on whichever scope provided the active account (best-effort). */ export const touchAuth = () => { const now = new Date().toISOString(); const project = getProjectAuth(); if (project) { setAuth({ ...project, lastUsedAt: now }, 'project'); return; } const global = getGlobalAuth(); if (global) { setAuth({ ...global, lastUsedAt: now }, 'global'); } }; /** * Resolve the signing mode, highest priority first: * 1. explicit `ACURAST_SIGNING_MODE=local|remote`; * 2. a project pin (`./.acurast/auth.json`) → `remote`; * 3. `ACURAST_MNEMONIC` present → `local`; * 4. a global login (`~/.acurast/auth.json`) → `remote`; * 5. otherwise `local`. * * An ambient global login never silently changes how an existing mnemonic * project signs (step 3 beats step 4). A deliberate project pin does (step 2). * Expired sessions count as logged-out (see `read`). */ export const getSigningMode = () => { const explicit = process.env.ACURAST_SIGNING_MODE; if (explicit === 'remote' || explicit === 'local') { return explicit; } if (getProjectAuth()) return 'remote'; if (process.env.ACURAST_MNEMONIC) return 'local'; if (getGlobalAuth()) return 'remote'; return 'local'; }; /** Where the account/key that will be used comes from — for `whoami` and deploy output. */ export const getAuthSource = () => { if (getSigningMode() === 'remote') { if (getProjectAuth()) return 'project'; if (getGlobalAuth()) return 'global'; return 'none'; } return process.env.ACURAST_MNEMONIC ? 'mnemonic' : 'none'; }; //# sourceMappingURL=authStore.js.map