Files
HiveGrid-Wireframes/03 Quellen und Referenzen/hivegrid-cloud/apps/web/app/utils/integrations/hrPasswordSafeService.archive.test.ts
T

106 lines
4.9 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
const mocks = vi.hoisted(() => ({
tx: {
employeePasswordSafeVault: { findFirst: vi.fn(), findMany: vi.fn(), updateMany: vi.fn() },
employeePasswordSafeAccess: { findFirst: vi.fn() },
employeePasswordSafeEntry: { findMany: vi.fn(), updateMany: vi.fn() },
},
}));
vi.mock("~/utils/db/.server/tenantRls.server", () => ({
withTenantRLS: (_tenantId: string, callback: (tx: typeof mocks.tx) => unknown) => callback(mocks.tx),
}));
vi.mock("@hivegrid/db/audit-events.server", () => ({ createAuditEvent: vi.fn() }));
import { archiveVault, listAccessibleVaults, listEntries, restoreEntry, restoreVault } from "./hrPasswordSafeService.server";
describe("password-safe archive lifecycle", () => {
beforeEach(() => {
vi.clearAllMocks();
mocks.tx.employeePasswordSafeVault.findFirst.mockResolvedValue({ id: "vault-1" });
mocks.tx.employeePasswordSafeAccess.findFirst.mockResolvedValue({ permissionLevel: "write" });
mocks.tx.employeePasswordSafeEntry.findMany.mockResolvedValue([]);
mocks.tx.employeePasswordSafeEntry.updateMany.mockResolvedValue({ count: 1 });
mocks.tx.employeePasswordSafeVault.updateMany.mockResolvedValue({ count: 1 });
mocks.tx.employeePasswordSafeVault.findMany.mockResolvedValue([
{
id: "vault-1",
tenantId: "tenant-1",
name: "Operations",
description: null,
createdByUserId: "user-1",
isDemoData: false,
createdAt: new Date(0),
updatedAt: new Date(0),
archivedAt: null,
access: [{ permissionLevel: "admin" }],
},
]);
});
it("lists active and archived entries through separate metadata-only queries", async () => {
await listEntries({ tenantId: "tenant-1", vaultId: "vault-1", userId: "user-1" });
expect(mocks.tx.employeePasswordSafeEntry.findMany).toHaveBeenLastCalledWith(
expect.objectContaining({ where: { tenantId: "tenant-1", vaultId: "vault-1", archivedAt: null } })
);
await listEntries({ tenantId: "tenant-1", vaultId: "vault-1", userId: "user-1", archived: true });
expect(mocks.tx.employeePasswordSafeEntry.findMany).toHaveBeenLastCalledWith(
expect.objectContaining({ where: { tenantId: "tenant-1", vaultId: "vault-1", archivedAt: { not: null } } })
);
const select = mocks.tx.employeePasswordSafeEntry.findMany.mock.calls.at(-1)?.[0].select;
expect(select).not.toHaveProperty("username");
expect(select).not.toHaveProperty("password");
expect(select).not.toHaveProperty("notes");
});
it("returns the caller's actual access level with each accessible vault", async () => {
await expect(listAccessibleVaults("tenant-1", "user-1")).resolves.toEqual([expect.objectContaining({ id: "vault-1", accessLevel: "admin" })]);
expect(mocks.tx.employeePasswordSafeVault.findMany).toHaveBeenCalledWith(
expect.objectContaining({
where: { tenantId: "tenant-1", archivedAt: null, access: { some: { tenantId: "tenant-1", userId: "user-1" } } },
include: { access: { where: { tenantId: "tenant-1", userId: "user-1" }, select: { permissionLevel: true }, take: 1 } },
})
);
});
it("restores only an archived entry in the caller's tenant and vault", async () => {
await restoreEntry({ tenantId: "tenant-1", vaultId: "vault-1", entryId: "entry-1", userId: "user-1" });
expect(mocks.tx.employeePasswordSafeEntry.updateMany).toHaveBeenCalledWith({
where: {
id: "entry-1",
tenantId: "tenant-1",
vaultId: "vault-1",
archivedAt: { not: null },
},
data: { archivedAt: null },
});
});
it("does not report a missing or already-active entry as restored", async () => {
mocks.tx.employeePasswordSafeEntry.updateMany.mockResolvedValue({ count: 0 });
await expect(restoreEntry({ tenantId: "tenant-1", vaultId: "vault-1", entryId: "missing", userId: "user-1" })).rejects.toThrow();
});
it("archives and restores a vault only through inverse lifecycle filters", async () => {
await archiveVault({ tenantId: "tenant-1", vaultId: "vault-1", userId: "admin-1", isTenantPasswordSafeAdmin: true });
expect(mocks.tx.employeePasswordSafeVault.updateMany).toHaveBeenLastCalledWith({
where: { id: "vault-1", tenantId: "tenant-1", archivedAt: null },
data: { archivedAt: expect.any(Date) },
});
await restoreVault({ tenantId: "tenant-1", vaultId: "vault-1", userId: "admin-1", isTenantPasswordSafeAdmin: true });
expect(mocks.tx.employeePasswordSafeVault.updateMany).toHaveBeenLastCalledWith({
where: { id: "vault-1", tenantId: "tenant-1", archivedAt: { not: null } },
data: { archivedAt: null },
});
});
it("does not restore a vault without the tenant-wide admin capability", async () => {
await expect(restoreVault({ tenantId: "tenant-1", vaultId: "vault-1", userId: "user-1", isTenantPasswordSafeAdmin: false })).rejects.toThrow();
expect(mocks.tx.employeePasswordSafeVault.updateMany).not.toHaveBeenCalled();
});
});