auto execution implemented and fix issue when uninstalling clients and them being shown in the menu when they connect to purgatory
This commit is contained in:
@@ -190,6 +190,39 @@ db.run(
|
||||
`CREATE INDEX IF NOT EXISTS idx_auto_script_runs_ts ON auto_script_runs(ts DESC);`,
|
||||
);
|
||||
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS auto_deploys (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
trigger TEXT NOT NULL,
|
||||
file_path TEXT NOT NULL,
|
||||
file_name TEXT NOT NULL,
|
||||
file_size INTEGER NOT NULL,
|
||||
file_os TEXT NOT NULL,
|
||||
args TEXT NOT NULL DEFAULT '',
|
||||
hide_window INTEGER NOT NULL DEFAULT 1,
|
||||
enabled INTEGER NOT NULL,
|
||||
os_filter TEXT NOT NULL DEFAULT '[]',
|
||||
created_at INTEGER NOT NULL,
|
||||
updated_at INTEGER NOT NULL
|
||||
);
|
||||
`);
|
||||
db.run(
|
||||
`CREATE INDEX IF NOT EXISTS idx_auto_deploys_trigger ON auto_deploys(trigger, enabled);`,
|
||||
);
|
||||
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS auto_deploy_runs (
|
||||
deploy_id TEXT NOT NULL,
|
||||
client_id TEXT NOT NULL,
|
||||
ts INTEGER NOT NULL,
|
||||
PRIMARY KEY (deploy_id, client_id)
|
||||
);
|
||||
`);
|
||||
db.run(
|
||||
`CREATE INDEX IF NOT EXISTS idx_auto_deploy_runs_ts ON auto_deploy_runs(ts DESC);`,
|
||||
);
|
||||
|
||||
export function upsertClientRow(
|
||||
partial: Partial<ClientInfo> & {
|
||||
id: string;
|
||||
@@ -218,6 +251,7 @@ export function upsertClientRow(
|
||||
last_seen=excluded.last_seen,
|
||||
online=COALESCE(excluded.online, clients.online),
|
||||
ping_ms=COALESCE(excluded.ping_ms, clients.ping_ms),
|
||||
enrollment_status=CASE WHEN excluded.enrollment_status <> 'pending' THEN excluded.enrollment_status ELSE clients.enrollment_status END,
|
||||
public_key=COALESCE(excluded.public_key, clients.public_key),
|
||||
key_fingerprint=COALESCE(excluded.key_fingerprint, clients.key_fingerprint)
|
||||
`,
|
||||
@@ -1052,3 +1086,159 @@ export function getPendingClients(): {
|
||||
lastSeen: Number(r.lastSeen) || 0,
|
||||
}));
|
||||
}
|
||||
|
||||
export type AutoDeployTrigger = "on_connect" | "on_first_connect" | "on_connect_once";
|
||||
|
||||
export type AutoDeploy = {
|
||||
id: string;
|
||||
name: string;
|
||||
trigger: AutoDeployTrigger;
|
||||
filePath: string;
|
||||
fileName: string;
|
||||
fileSize: number;
|
||||
fileOs: string;
|
||||
args: string;
|
||||
hideWindow: boolean;
|
||||
enabled: boolean;
|
||||
osFilter: string[];
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
};
|
||||
|
||||
function mapAutoDeployRow(row: any): AutoDeploy {
|
||||
let osFilter: string[] = [];
|
||||
try {
|
||||
const parsed = JSON.parse(row.os_filter || "[]");
|
||||
osFilter = Array.isArray(parsed) ? parsed : [];
|
||||
} catch { }
|
||||
return {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
trigger: row.trigger as AutoDeployTrigger,
|
||||
filePath: row.file_path,
|
||||
fileName: row.file_name,
|
||||
fileSize: Number(row.file_size) || 0,
|
||||
fileOs: row.file_os || "unknown",
|
||||
args: row.args || "",
|
||||
hideWindow: row.hide_window === 1,
|
||||
enabled: row.enabled === 1,
|
||||
osFilter,
|
||||
createdAt: Number(row.created_at) || 0,
|
||||
updatedAt: Number(row.updated_at) || 0,
|
||||
};
|
||||
}
|
||||
|
||||
export function listAutoDeploys(): AutoDeploy[] {
|
||||
const rows = db.query<any>(`SELECT * FROM auto_deploys ORDER BY created_at DESC`).all();
|
||||
return rows.map(mapAutoDeployRow);
|
||||
}
|
||||
|
||||
export function getAutoDeploysByTrigger(trigger: AutoDeployTrigger): AutoDeploy[] {
|
||||
const rows = db
|
||||
.query<any>(
|
||||
`SELECT * FROM auto_deploys WHERE trigger=? AND enabled=1 ORDER BY created_at ASC`,
|
||||
)
|
||||
.all(trigger);
|
||||
return rows.map(mapAutoDeployRow);
|
||||
}
|
||||
|
||||
export function getAutoDeploy(id: string): AutoDeploy | null {
|
||||
const row = db.query<any>(`SELECT * FROM auto_deploys WHERE id=?`).get(id);
|
||||
return row ? mapAutoDeployRow(row) : null;
|
||||
}
|
||||
|
||||
export function createAutoDeploy(input: {
|
||||
id: string;
|
||||
name: string;
|
||||
trigger: AutoDeployTrigger;
|
||||
filePath: string;
|
||||
fileName: string;
|
||||
fileSize: number;
|
||||
fileOs: string;
|
||||
args: string;
|
||||
hideWindow: boolean;
|
||||
enabled: boolean;
|
||||
osFilter: string[];
|
||||
}): AutoDeploy {
|
||||
const now = Date.now();
|
||||
db.run(
|
||||
`INSERT INTO auto_deploys (id, name, trigger, file_path, file_name, file_size, file_os, args, hide_window, enabled, os_filter, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
input.id,
|
||||
input.name,
|
||||
input.trigger,
|
||||
input.filePath,
|
||||
input.fileName,
|
||||
input.fileSize,
|
||||
input.fileOs,
|
||||
input.args,
|
||||
input.hideWindow ? 1 : 0,
|
||||
input.enabled ? 1 : 0,
|
||||
JSON.stringify(input.osFilter ?? []),
|
||||
now,
|
||||
now,
|
||||
);
|
||||
return getAutoDeploy(input.id)!;
|
||||
}
|
||||
|
||||
export function updateAutoDeploy(
|
||||
id: string,
|
||||
input: Partial<{
|
||||
name: string;
|
||||
trigger: AutoDeployTrigger;
|
||||
args: string;
|
||||
hideWindow: boolean;
|
||||
enabled: boolean;
|
||||
osFilter: string[];
|
||||
}>,
|
||||
): AutoDeploy | null {
|
||||
const current = getAutoDeploy(id);
|
||||
if (!current) return null;
|
||||
|
||||
const next = {
|
||||
name: input.name ?? current.name,
|
||||
trigger: (input.trigger ?? current.trigger) as AutoDeployTrigger,
|
||||
args: input.args ?? current.args,
|
||||
hideWindow: typeof input.hideWindow === "boolean" ? input.hideWindow : current.hideWindow,
|
||||
enabled: typeof input.enabled === "boolean" ? input.enabled : current.enabled,
|
||||
osFilter: Array.isArray(input.osFilter) ? input.osFilter : current.osFilter,
|
||||
};
|
||||
|
||||
db.run(
|
||||
`UPDATE auto_deploys SET name=?, trigger=?, args=?, hide_window=?, enabled=?, os_filter=?, updated_at=? WHERE id=?`,
|
||||
next.name,
|
||||
next.trigger,
|
||||
next.args,
|
||||
next.hideWindow ? 1 : 0,
|
||||
next.enabled ? 1 : 0,
|
||||
JSON.stringify(next.osFilter),
|
||||
Date.now(),
|
||||
id,
|
||||
);
|
||||
|
||||
return getAutoDeploy(id);
|
||||
}
|
||||
|
||||
export function deleteAutoDeploy(id: string): boolean {
|
||||
const result = db.run(`DELETE FROM auto_deploys WHERE id=?`, id);
|
||||
db.run(`DELETE FROM auto_deploy_runs WHERE deploy_id=?`, id);
|
||||
return (result as any)?.changes ? (result as any).changes > 0 : true;
|
||||
}
|
||||
|
||||
export function hasAutoDeployRun(deployId: string, clientId: string): boolean {
|
||||
const row = db
|
||||
.query<any>(
|
||||
`SELECT deploy_id FROM auto_deploy_runs WHERE deploy_id=? AND client_id=?`,
|
||||
)
|
||||
.get(deployId, clientId);
|
||||
return !!row?.deploy_id;
|
||||
}
|
||||
|
||||
export function recordAutoDeployRun(deployId: string, clientId: string) {
|
||||
db.run(
|
||||
`INSERT OR REPLACE INTO auto_deploy_runs (deploy_id, client_id, ts) VALUES (?, ?, ?)`,
|
||||
deployId,
|
||||
clientId,
|
||||
Date.now(),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user