refactor(device-auth): share store types + normalization

This commit is contained in:
Peter Steinberger
2026-02-15 04:22:39 +00:00
parent 9606884ca1
commit f3a474af30
3 changed files with 50 additions and 69 deletions

View File

@@ -1,19 +1,12 @@
import fs from "node:fs";
import path from "node:path";
import { resolveStateDir } from "../config/paths.js";
export type DeviceAuthEntry = {
token: string;
role: string;
scopes: string[];
updatedAtMs: number;
};
type DeviceAuthStore = {
version: 1;
deviceId: string;
tokens: Record<string, DeviceAuthEntry>;
};
import {
type DeviceAuthEntry,
type DeviceAuthStore,
normalizeDeviceAuthRole,
normalizeDeviceAuthScopes,
} from "../shared/device-auth.js";
const DEVICE_AUTH_FILE = "device-auth.json";
@@ -21,24 +14,6 @@ function resolveDeviceAuthPath(env: NodeJS.ProcessEnv = process.env): string {
return path.join(resolveStateDir(env), "identity", DEVICE_AUTH_FILE);
}
function normalizeRole(role: string): string {
return role.trim();
}
function normalizeScopes(scopes: string[] | undefined): string[] {
if (!Array.isArray(scopes)) {
return [];
}
const out = new Set<string>();
for (const scope of scopes) {
const trimmed = scope.trim();
if (trimmed) {
out.add(trimmed);
}
}
return [...out].toSorted();
}
function readStore(filePath: string): DeviceAuthStore | null {
try {
if (!fs.existsSync(filePath)) {
@@ -81,7 +56,7 @@ export function loadDeviceAuthToken(params: {
if (store.deviceId !== params.deviceId) {
return null;
}
const role = normalizeRole(params.role);
const role = normalizeDeviceAuthRole(params.role);
const entry = store.tokens[role];
if (!entry || typeof entry.token !== "string") {
return null;
@@ -98,7 +73,7 @@ export function storeDeviceAuthToken(params: {
}): DeviceAuthEntry {
const filePath = resolveDeviceAuthPath(params.env);
const existing = readStore(filePath);
const role = normalizeRole(params.role);
const role = normalizeDeviceAuthRole(params.role);
const next: DeviceAuthStore = {
version: 1,
deviceId: params.deviceId,
@@ -110,7 +85,7 @@ export function storeDeviceAuthToken(params: {
const entry: DeviceAuthEntry = {
token: params.token,
role,
scopes: normalizeScopes(params.scopes),
scopes: normalizeDeviceAuthScopes(params.scopes),
updatedAtMs: Date.now(),
};
next.tokens[role] = entry;
@@ -128,7 +103,7 @@ export function clearDeviceAuthToken(params: {
if (!store || store.deviceId !== params.deviceId) {
return;
}
const role = normalizeRole(params.role);
const role = normalizeDeviceAuthRole(params.role);
if (!store.tokens[role]) {
return;
}

30
src/shared/device-auth.ts Normal file
View File

@@ -0,0 +1,30 @@
export type DeviceAuthEntry = {
token: string;
role: string;
scopes: string[];
updatedAtMs: number;
};
export type DeviceAuthStore = {
version: 1;
deviceId: string;
tokens: Record<string, DeviceAuthEntry>;
};
export function normalizeDeviceAuthRole(role: string): string {
return role.trim();
}
export function normalizeDeviceAuthScopes(scopes: string[] | undefined): string[] {
if (!Array.isArray(scopes)) {
return [];
}
const out = new Set<string>();
for (const scope of scopes) {
const trimmed = scope.trim();
if (trimmed) {
out.add(trimmed);
}
}
return [...out].toSorted();
}

View File

@@ -1,36 +1,12 @@
export type DeviceAuthEntry = {
token: string;
role: string;
scopes: string[];
updatedAtMs: number;
};
type DeviceAuthStore = {
version: 1;
deviceId: string;
tokens: Record<string, DeviceAuthEntry>;
};
import {
type DeviceAuthEntry,
type DeviceAuthStore,
normalizeDeviceAuthRole,
normalizeDeviceAuthScopes,
} from "../../../src/shared/device-auth.js";
const STORAGE_KEY = "openclaw.device.auth.v1";
function normalizeRole(role: string): string {
return role.trim();
}
function normalizeScopes(scopes: string[] | undefined): string[] {
if (!Array.isArray(scopes)) {
return [];
}
const out = new Set<string>();
for (const scope of scopes) {
const trimmed = scope.trim();
if (trimmed) {
out.add(trimmed);
}
}
return [...out].toSorted();
}
function readStore(): DeviceAuthStore | null {
try {
const raw = window.localStorage.getItem(STORAGE_KEY);
@@ -69,7 +45,7 @@ export function loadDeviceAuthToken(params: {
if (!store || store.deviceId !== params.deviceId) {
return null;
}
const role = normalizeRole(params.role);
const role = normalizeDeviceAuthRole(params.role);
const entry = store.tokens[role];
if (!entry || typeof entry.token !== "string") {
return null;
@@ -83,7 +59,7 @@ export function storeDeviceAuthToken(params: {
token: string;
scopes?: string[];
}): DeviceAuthEntry {
const role = normalizeRole(params.role);
const role = normalizeDeviceAuthRole(params.role);
const next: DeviceAuthStore = {
version: 1,
deviceId: params.deviceId,
@@ -96,7 +72,7 @@ export function storeDeviceAuthToken(params: {
const entry: DeviceAuthEntry = {
token: params.token,
role,
scopes: normalizeScopes(params.scopes),
scopes: normalizeDeviceAuthScopes(params.scopes),
updatedAtMs: Date.now(),
};
next.tokens[role] = entry;
@@ -109,7 +85,7 @@ export function clearDeviceAuthToken(params: { deviceId: string; role: string })
if (!store || store.deviceId !== params.deviceId) {
return;
}
const role = normalizeRole(params.role);
const role = normalizeDeviceAuthRole(params.role);
if (!store.tokens[role]) {
return;
}