feat: move snippets backend and tables into a plugin (B2)

This commit is contained in:
LukeGus committed 2026-09-23 08:58:53 -05:00
1 parent fdedca39fd
commit e07221eaf3
51 files changed
+28426 -3553

No files matched your search

@@ -1,79 +0,0 @@
import { describe, expect, it } from "vitest";
import {
createSnippetExecutionResult,
getSnippetExecutionTimeoutMs,
resolveSnippetCommand,
} from "../../../database/routes/snippets-execution.js";
describe("snippet execution", () => {
it("treats stderr as diagnostic output when the command succeeds", () => {
expect(createSnippetExecutionResult(0, "done\n", "warning\n")).toEqual({
success: true,
output: "done\n",
error: "warning\n",
});
});
it("uses the exit code to report command failure", () => {
expect(createSnippetExecutionResult(1, "", "failed\n")).toEqual({
success: false,
output: "",
error: "failed\n",
});
});
it("preserves the previous fallback when no exit code is available", () => {
expect(createSnippetExecutionResult(null, "done\n", "")).toEqual({
success: true,
output: "done\n",
});
expect(createSnippetExecutionResult(null, "", "failed\n").success).toBe(
false,
);
});
it("disables the command timeout by default", () => {
expect(getSnippetExecutionTimeoutMs(undefined)).toBeUndefined();
});
it("converts a configured timeout from seconds to milliseconds", () => {
expect(getSnippetExecutionTimeoutMs("45")).toBe(45_000);
});
it.each(["", "0", "-1", "invalid"])(
"ignores invalid timeout value %j",
(value) => {
expect(getSnippetExecutionTimeoutMs(value)).toBeUndefined();
},
);
});
describe("resolveSnippetCommand", () => {
const host = { ip: "10.0.0.5", username: "root", port: 22, name: "web-01" };
it("substitutes host variables per target host", () => {
expect(
resolveSnippetCommand("ssh $USER@$HOST -p $PORT # $NAME", host),
).toBe("ssh root@10.0.0.5 -p 22 # web-01");
});
it("supports brace syntax for host variables", () => {
expect(resolveSnippetCommand("ping ${HOST}", host)).toBe("ping 10.0.0.5");
});
it("substitutes input placeholders from inputValues", () => {
expect(
resolveSnippetCommand("nc -zv $HOST ${INPUT_1:Port}", host, {
INPUT_1: "8080",
}),
).toBe("nc -zv 10.0.0.5 8080");
});
it("leaves host variables literal when no host context is given", () => {
expect(resolveSnippetCommand("ping $HOST", null)).toBe("ping $HOST");
});
it("leaves input placeholders literal when no value was supplied", () => {
expect(resolveSnippetCommand("echo $INPUT_1", null)).toBe("echo $INPUT_1");
});
});
@@ -1,20 +0,0 @@
import fs from "fs";
import path from "path";
import { describe, expect, it } from "vitest";
describe("snippet execution host access", () => {
it("uses the shared-host-aware resolver", () => {
const source = fs.readFileSync(
path.resolve(__dirname, "../../../database/routes/snippets.ts"),
"utf8",
);
const executeRoute = source.slice(
source.indexOf('router.post(\n "/execute"'),
);
expect(executeRoute).toContain(
"const host = await resolveHostById(parseInt(hostId), userId)",
);
expect(executeRoute).not.toContain("host.userId !== userId");
});
});
@@ -33,8 +33,6 @@ describe("isValidEntityType", () => {
"hosts",
"sshCredentials",
"sshFolders",
"snippets",
"snippetFolders",
"vaultProfiles",
"dashboardServiceLinks",
"homepageItems",
@@ -88,7 +86,7 @@ describe("stripWritePayload", () => {
it("does not mutate the original payload object", () => {
const payload = { id: 1, userId: "user-1", syncId: "abc", name: "x" };
stripWritePayload("snippets", payload);
stripWritePayload("sshFolders", payload);
expect(payload).toEqual({
id: 1,
userId: "user-1",
@@ -6,6 +6,7 @@ const calls = vi.hoisted(() => ({
deletedFor: [] as string[],
rotatedFor: [] as string[],
legacyWrapsDeletedFor: [] as string[],
dataWipedEvents: [] as Array<{ userId: string }>,
}));
function deletingRepo(label: string) {
@@ -29,11 +30,19 @@ vi.mock("../../../database/repositories/factory.js", () => ({
createCurrentFileManagerBookmarkRepository: deletingRepo("bookmarks"),
createCurrentRecentActivityRepository: deletingRepo("activity"),
createCurrentDismissedAlertRepository: deletingRepo("alerts"),
createCurrentSnippetRepository: deletingRepo("snippets"),
createCurrentHostRepository: deletingRepo("hosts"),
createCurrentCredentialRepository: deletingRepo("credentials"),
}));
vi.mock("../../../plugins/events.js", () => ({
pluginEvents: {
emit: (_topic: string, payload: { userId: string }) => {
calls.dataWipedEvents.push(payload);
},
},
TOPICS: { userDataWiped: "user.data_wiped" },
}));
vi.mock("../../../utils/user-keys.js", () => ({
UserKeyManager: {
getInstance: () => ({
@@ -65,6 +74,7 @@ beforeEach(() => {
calls.deletedFor = [];
calls.rotatedFor = [];
calls.legacyWrapsDeletedFor = [];
calls.dataWipedEvents = [];
});
describe("resetUserPassword", () => {
@@ -110,10 +120,10 @@ describe("resetUserPassword", () => {
"bookmarks:user-1",
"activity:user-1",
"alerts:user-1",
"snippets:user-1",
"hosts:user-1",
"credentials:user-1",
]);
expect(calls.dataWipedEvents).toEqual([{ userId: "user-1" }]);
expect(calls.rotatedFor).toEqual(["user-1"]);
expect(calls.legacyWrapsDeletedFor).toEqual(["user-1"]);
expect(