forked from snxraven/peardock
Ship remaining roadmap items: encrypted registry vault, peer invite/revoke, Swarm/plugins behind flags, binary streams, engine create validation, deploy rollback, schema validation, fleet/access UI, metrics, fuzz/load/soak tests, systemd packaging, and release tooling. Mark ROADMAP fully complete.
91 lines
2.7 KiB
JavaScript
91 lines
2.7 KiB
JavaScript
/**
|
|
* Peer invite / revoke / list ACL management (admin).
|
|
*/
|
|
import * as peerPolicy from '../core/peer-policy.js'
|
|
import { peers } from '../core/peer-registry.js'
|
|
import { Roles } from '../../shared/protocol.js'
|
|
import * as validation from '../utils/validation.js'
|
|
|
|
export function registerPeerHandlers(session) {
|
|
session.respond('listPeers', async () => {
|
|
const policy = peerPolicy.listPeers()
|
|
const live = []
|
|
for (const s of peers) {
|
|
live.push({
|
|
peerId: s.id,
|
|
role: s.role,
|
|
connected: !s.closed,
|
|
clientInfo: s.clientInfo || null,
|
|
})
|
|
}
|
|
return {
|
|
success: true,
|
|
type: 'peers',
|
|
...policy,
|
|
live,
|
|
}
|
|
})
|
|
|
|
session.respond('listInvites', async () => {
|
|
return {
|
|
success: true,
|
|
type: 'invites',
|
|
data: peerPolicy.listInvites(),
|
|
}
|
|
})
|
|
|
|
session.respond('invitePeer', async (args) => {
|
|
// Either create redeemable token OR register known peer key
|
|
if (args.peerId) {
|
|
const peerId = validation.sanitizeString(args.peerId, 64).toLowerCase()
|
|
if (!/^[0-9a-f]{64}$/.test(peerId)) throw new Error('peerId must be 64 hex characters')
|
|
const role = args.role || Roles.operator
|
|
const entry = peerPolicy.registerPeer(peerId, {
|
|
role,
|
|
alias: args.alias || null,
|
|
note: args.note || null,
|
|
})
|
|
return { success: true, type: 'peerRegistered', data: entry }
|
|
}
|
|
const invite = peerPolicy.createInvite({
|
|
role: args.role || Roles.operator,
|
|
ttlHours: args.ttlHours,
|
|
maxUses: args.maxUses,
|
|
note: args.note,
|
|
})
|
|
return { success: true, type: 'invite', data: invite }
|
|
})
|
|
|
|
session.respond('revokePeer', async (args) => {
|
|
const peerId = validation.sanitizeString(args.peerId || args.id, 64).toLowerCase()
|
|
if (!peerId) throw new Error('peerId required')
|
|
const result = peerPolicy.revokePeer(peerId)
|
|
// Drop live session if connected
|
|
const live = peers.get(peerId)
|
|
if (live) {
|
|
try {
|
|
live.destroy()
|
|
} catch {
|
|
// ignore
|
|
}
|
|
}
|
|
return { success: true, ...result }
|
|
})
|
|
|
|
session.respond('unrevokePeer', async (args) => {
|
|
const peerId = validation.sanitizeString(args.peerId || args.id, 64).toLowerCase()
|
|
if (!peerId) throw new Error('peerId required')
|
|
return { success: true, ...peerPolicy.unrevokePeer(peerId) }
|
|
})
|
|
|
|
session.respond('setPeerRole', async (args) => {
|
|
const peerId = validation.sanitizeString(args.peerId || args.id, 64).toLowerCase()
|
|
const role = args.role
|
|
if (!peerId || !role) throw new Error('peerId and role required')
|
|
const entry = peerPolicy.setPeerRole(peerId, role)
|
|
const live = peers.get(peerId)
|
|
if (live) live.role = role
|
|
return { success: true, data: entry }
|
|
})
|
|
}
|