mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-31 15:45:23 +00:00
feat: add allowlisted host view for plugins
An allowlist rather than a list of fields to strip. A blocklist rots: the moment a new secret-bearing column lands on SSHHost it starts leaking silently. With an allowlist a new field stays invisible to plugins until someone adds it here on purpose.
This commit is contained in:
1 parent
248698f62d
commit
9f4a2d3951
1 file changed
+68
@@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
* The only shape of a host a plugin ever sees.
|
||||||
|
*
|
||||||
|
* This is an ALLOWLIST, deliberately, not a list of fields to strip. A
|
||||||
|
* blocklist rots: the moment someone adds a new secret-bearing column to
|
||||||
|
* SSHHost, a blocklist silently starts leaking it, and nothing fails. With an
|
||||||
|
* allowlist a new field is invisible to plugins until someone consciously adds
|
||||||
|
* it here.
|
||||||
|
*
|
||||||
|
* resolveHostById returns an object carrying password, key, keyPassword,
|
||||||
|
* certPublicKey, sudoPassword and the autostart* secrets in plaintext. None of
|
||||||
|
* them are in this list, and none of them may ever be.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface PluginHostView {
|
||||||
|
id: number;
|
||||||
|
name: string | null;
|
||||||
|
ip: string;
|
||||||
|
port: number;
|
||||||
|
username: string;
|
||||||
|
folder: string | null;
|
||||||
|
tags: string[];
|
||||||
|
authType: string | null;
|
||||||
|
enableTerminal: boolean;
|
||||||
|
enableTunnel: boolean;
|
||||||
|
enableFileManager: boolean;
|
||||||
|
createdAt: string | null;
|
||||||
|
updatedAt: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NUMBER_FIELDS = ["id", "port"] as const;
|
||||||
|
const STRING_FIELDS = [
|
||||||
|
"name",
|
||||||
|
"ip",
|
||||||
|
"username",
|
||||||
|
"folder",
|
||||||
|
"authType",
|
||||||
|
"createdAt",
|
||||||
|
"updatedAt",
|
||||||
|
] as const;
|
||||||
|
const BOOLEAN_FIELDS = [
|
||||||
|
"enableTerminal",
|
||||||
|
"enableTunnel",
|
||||||
|
"enableFileManager",
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export function toPluginHostView(
|
||||||
|
host: Record<string, unknown>,
|
||||||
|
): PluginHostView {
|
||||||
|
const view: Record<string, unknown> = {};
|
||||||
|
|
||||||
|
for (const field of NUMBER_FIELDS) {
|
||||||
|
view[field] = Number(host[field] ?? 0);
|
||||||
|
}
|
||||||
|
for (const field of STRING_FIELDS) {
|
||||||
|
const value = host[field];
|
||||||
|
view[field] = typeof value === "string" ? value : null;
|
||||||
|
}
|
||||||
|
for (const field of BOOLEAN_FIELDS) {
|
||||||
|
view[field] = Boolean(host[field]);
|
||||||
|
}
|
||||||
|
|
||||||
|
view.tags = Array.isArray(host.tags)
|
||||||
|
? host.tags.filter((tag): tag is string => typeof tag === "string")
|
||||||
|
: [];
|
||||||
|
|
||||||
|
return view as unknown as PluginHostView;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user