feat: made e2ee api test indepdent or stateless

This commit is contained in:
Akhil Mohan
2024-02-19 20:56:29 +05:30
parent 678306b350
commit 7070a69711
6 changed files with 601 additions and 294 deletions
+213 -86
View File
@@ -2,6 +2,54 @@ import { SecretType, TSecrets } from "@app/db/schemas";
import { decryptSecret, encryptSecret, getUserPrivateKey, seedData1 } from "@app/db/seed-data";
import { decryptAsymmetric, encryptAsymmetric } from "@app/lib/crypto";
const createSecret = async (dto: {
projectKey: string;
path: string;
key: string;
value: string;
comment: string;
type?: SecretType;
}) => {
const createSecretReqBody = {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
type: dto.type || SecretType.Shared,
secretPath: dto.path,
...encryptSecret(dto.projectKey, dto.key, dto.value, dto.comment)
};
const createSecRes = await testServer.inject({
method: "POST",
url: `/api/v3/secrets/${dto.key}`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
},
body: createSecretReqBody
});
expect(createSecRes.statusCode).toBe(200);
const createdSecretPayload = JSON.parse(createSecRes.payload);
expect(createdSecretPayload).toHaveProperty("secret");
return createdSecretPayload.secret;
};
const deleteSecret = async (dto: { path: string; key: string }) => {
const deleteSecRes = await testServer.inject({
method: "DELETE",
url: `/api/v3/secrets/${dto.key}`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
},
body: {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
secretPath: dto.path
}
});
expect(deleteSecRes.statusCode).toBe(200);
const updatedSecretPayload = JSON.parse(deleteSecRes.payload);
expect(updatedSecretPayload).toHaveProperty("secret");
return updatedSecretPayload.secret;
};
describe("Secret V3 Router", async () => {
const testSecrets = [
{
@@ -23,6 +71,7 @@ describe("Secret V3 Router", async () => {
];
let projectKey = "";
let folderId = "";
beforeAll(async () => {
const projectKeyRes = await testServer.inject({
method: "GET",
@@ -64,6 +113,23 @@ describe("Secret V3 Router", async () => {
}
});
expect(folderCreate.statusCode).toBe(200);
folderId = folderCreate.json().folder.id;
});
afterAll(async () => {
const deleteFolder = await testServer.inject({
method: "DELETE",
url: `/api/v1/folders/${folderId}`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
},
body: {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
path: "/nested1/nested2"
}
});
expect(deleteFolder.statusCode).toBe(200);
});
const getSecrets = async (environment: string, secretPath = "/") => {
@@ -84,25 +150,8 @@ describe("Secret V3 Router", async () => {
};
test.each(testSecrets)("Create secret in path $path", async ({ secret, path }) => {
const createSecretReqBody = {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
type: SecretType.Shared,
secretPath: path,
...encryptSecret(projectKey, secret.key, secret.value, secret.comment)
};
const createSecRes = await testServer.inject({
method: "POST",
url: `/api/v3/secrets/${secret.key}`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
},
body: createSecretReqBody
});
expect(createSecRes.statusCode).toBe(200);
const createdSecretPayload = JSON.parse(createSecRes.payload);
expect(createdSecretPayload).toHaveProperty("secret");
const decryptedSecret = decryptSecret(projectKey, createdSecretPayload.secret);
const createdSecret = await createSecret({ projectKey, path, ...secret });
const decryptedSecret = decryptSecret(projectKey, createdSecret);
expect(decryptedSecret.key).toEqual(secret.key);
expect(decryptedSecret.value).toEqual(secret.value);
expect(decryptedSecret.comment).toEqual(secret.comment);
@@ -118,9 +167,12 @@ describe("Secret V3 Router", async () => {
})
])
);
await deleteSecret({ path, key: secret.key });
});
test.each(testSecrets)("Get secret by name in path $path", async ({ secret, path }) => {
await createSecret({ projectKey, path, ...secret });
const getSecByNameRes = await testServer.inject({
method: "GET",
url: `/api/v3/secrets/${secret.key}`,
@@ -140,6 +192,8 @@ describe("Secret V3 Router", async () => {
expect(decryptedSecret.key).toEqual(secret.key);
expect(decryptedSecret.value).toEqual(secret.value);
expect(decryptedSecret.comment).toEqual(secret.comment);
await deleteSecret({ path, key: secret.key });
});
test.each(testSecrets)("Creating personal secret without shared throw error in path $path", async ({ secret }) => {
@@ -164,6 +218,8 @@ describe("Secret V3 Router", async () => {
});
test.each(testSecrets)("Creating personal secret in path $path", async ({ secret, path }) => {
await createSecret({ projectKey, path, ...secret });
const createSecretReqBody = {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
@@ -197,9 +253,12 @@ describe("Secret V3 Router", async () => {
})
])
);
await deleteSecret({ path, key: secret.key });
});
test.each(testSecrets)("Update secret in path $path", async ({ path, secret }) => {
await createSecret({ projectKey, path, ...secret });
const updateSecretReqBody = {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
@@ -234,25 +293,14 @@ describe("Secret V3 Router", async () => {
})
])
);
await deleteSecret({ path, key: secret.key });
});
test.each(testSecrets)("Delete secret in path $path", async ({ secret, path }) => {
const deleteSecRes = await testServer.inject({
method: "DELETE",
url: `/api/v3/secrets/${secret.key}`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
},
body: {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
secretPath: path
}
});
expect(deleteSecRes.statusCode).toBe(200);
const updatedSecretPayload = JSON.parse(deleteSecRes.payload);
expect(updatedSecretPayload).toHaveProperty("secret");
const decryptedSecret = decryptSecret(projectKey, updatedSecretPayload.secret);
await createSecret({ projectKey, path, ...secret });
const deletedSecret = await deleteSecret({ path, key: secret.key });
const decryptedSecret = decryptSecret(projectKey, deletedSecret);
expect(decryptedSecret.key).toEqual(secret.key);
// shared secret deletion should delete personal ones also
@@ -274,37 +322,8 @@ describe("Secret V3 Router", async () => {
test.each(testSecrets)(
"Deleting personal one should not delete shared secret in path $path",
async ({ secret, path }) => {
const createSharedSecRes = await testServer.inject({
method: "POST",
url: `/api/v3/secrets/${secret.key}`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
},
body: {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
type: SecretType.Shared,
secretPath: path,
...encryptSecret(projectKey, secret.key, secret.value, secret.comment)
}
});
expect(createSharedSecRes.statusCode).toBe(200);
const createPersonalSecRes = await testServer.inject({
method: "POST",
url: `/api/v3/secrets/${secret.key}`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
},
body: {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
secretPath: path,
type: SecretType.Personal,
...encryptSecret(projectKey, secret.key, secret.value, secret.comment)
}
});
expect(createPersonalSecRes.statusCode).toBe(200);
await createSecret({ projectKey, path, ...secret }); // shared one
await createSecret({ projectKey, path, ...secret, type: SecretType.Personal });
// shared secret deletion should delete personal ones also
const secrets = await getSecrets(seedData1.environment.slug, path);
@@ -320,6 +339,7 @@ describe("Secret V3 Router", async () => {
})
])
);
await deleteSecret({ path, key: secret.key });
}
);
@@ -334,7 +354,7 @@ describe("Secret V3 Router", async () => {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
secretPath: path,
secrets: Array.from(Array(10)).map((_e, i) => ({
secrets: Array.from(Array(5)).map((_e, i) => ({
secretName: `BULK-${secret.key}-${i + 1}`,
...encryptSecret(projectKey, `BULK-${secret.key}-${i + 1}`, secret.value, secret.comment)
}))
@@ -348,7 +368,7 @@ describe("Secret V3 Router", async () => {
const secrets = await getSecrets(seedData1.environment.slug, path);
expect(secrets).toEqual(
expect.arrayContaining(
Array.from(Array(10)).map((_e, i) =>
Array.from(Array(5)).map((_e, i) =>
expect.objectContaining({
key: `BULK-${secret.key}-${i + 1}`,
type: SecretType.Shared
@@ -356,9 +376,13 @@ describe("Secret V3 Router", async () => {
)
)
);
await Promise.all(Array.from(Array(5)).map((_e, i) => deleteSecret({ path, key: `BULK-${secret.key}-${i + 1}` })));
});
test.each(testSecrets)("Bulk create fail on existing secret in path $path", async ({ secret, path }) => {
await createSecret({ projectKey, ...secret, key: `BULK-${secret.key}-1`, path });
const createSharedSecRes = await testServer.inject({
method: "POST",
url: `/api/v3/secrets/batch`,
@@ -369,16 +393,24 @@ describe("Secret V3 Router", async () => {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
secretPath: path,
secrets: Array.from(Array(10)).map((_e, i) => ({
secrets: Array.from(Array(5)).map((_e, i) => ({
secretName: `BULK-${secret.key}-${i + 1}`,
...encryptSecret(projectKey, `BULK-${secret.key}-${i + 1}`, secret.value, secret.comment)
}))
}
});
expect(createSharedSecRes.statusCode).toBe(400);
await deleteSecret({ path, key: `BULK-${secret.key}-1` });
});
test.each(testSecrets)("Bulk update secrets in path $path", async ({ secret, path }) => {
await Promise.all(
Array.from(Array(5)).map((_e, i) =>
createSecret({ projectKey, ...secret, key: `BULK-${secret.key}-${i + 1}`, path })
)
);
const updateSharedSecRes = await testServer.inject({
method: "PATCH",
url: `/api/v3/secrets/batch`,
@@ -389,7 +421,7 @@ describe("Secret V3 Router", async () => {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
secretPath: path,
secrets: Array.from(Array(10)).map((_e, i) => ({
secrets: Array.from(Array(5)).map((_e, i) => ({
secretName: `BULK-${secret.key}-${i + 1}`,
...encryptSecret(projectKey, `BULK-${secret.key}-${i + 1}`, "update-value", secret.comment)
}))
@@ -403,7 +435,7 @@ describe("Secret V3 Router", async () => {
const secrets = await getSecrets(seedData1.environment.slug, path);
expect(secrets).toEqual(
expect.arrayContaining(
Array.from(Array(10)).map((_e, i) =>
Array.from(Array(5)).map((_e, i) =>
expect.objectContaining({
key: `BULK-${secret.key}-${i + 1}`,
value: "update-value",
@@ -412,10 +444,17 @@ describe("Secret V3 Router", async () => {
)
)
);
await Promise.all(Array.from(Array(5)).map((_e, i) => deleteSecret({ path, key: `BULK-${secret.key}-${i + 1}` })));
});
test.each(testSecrets)("Bulk delete secrets in path $path", async ({ secret, path }) => {
const updateSharedSecRes = await testServer.inject({
await Promise.all(
Array.from(Array(5)).map((_e, i) =>
createSecret({ projectKey, ...secret, key: `BULK-${secret.key}-${i + 1}`, path })
)
);
const deletedSharedSecRes = await testServer.inject({
method: "DELETE",
url: `/api/v3/secrets/batch`,
headers: {
@@ -425,20 +464,21 @@ describe("Secret V3 Router", async () => {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
secretPath: path,
secrets: Array.from(Array(10)).map((_e, i) => ({
secrets: Array.from(Array(5)).map((_e, i) => ({
secretName: `BULK-${secret.key}-${i + 1}`
}))
}
});
expect(updateSharedSecRes.statusCode).toBe(200);
const updateSharedSecPayload = JSON.parse(updateSharedSecRes.payload);
expect(updateSharedSecPayload).toHaveProperty("secrets");
expect(deletedSharedSecRes.statusCode).toBe(200);
const deletedSecretPayload = JSON.parse(deletedSharedSecRes.payload);
expect(deletedSecretPayload).toHaveProperty("secrets");
// bulk ones should exist
const secrets = await getSecrets(seedData1.environment.slug, path);
expect(secrets).toEqual(
expect.not.arrayContaining(
Array.from(Array(10)).map((_e, i) =>
Array.from(Array(5)).map((_e, i) =>
expect.objectContaining({
key: `BULK-${secret.value}-${i + 1}`,
type: SecretType.Shared
@@ -449,8 +489,57 @@ describe("Secret V3 Router", async () => {
});
});
const createRawSecret = async (dto: {
path: string;
key: string;
value: string;
comment: string;
type?: SecretType;
}) => {
const createSecretReqBody = {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
type: dto.type || SecretType.Shared,
secretValue: dto.value,
secretComment: dto.comment,
secretPath: dto.path
};
const createSecRes = await testServer.inject({
method: "POST",
url: `/api/v3/secrets/raw/${dto.key}`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
},
body: createSecretReqBody
});
expect(createSecRes.statusCode).toBe(200);
const createdSecretPayload = JSON.parse(createSecRes.payload);
expect(createdSecretPayload).toHaveProperty("secret");
return createdSecretPayload.secret;
};
const deleteRawSecret = async (dto: { path: string; key: string }) => {
const deleteSecRes = await testServer.inject({
method: "DELETE",
url: `/api/v3/secrets/raw/${dto.key}`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
},
body: {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
secretPath: dto.path
}
});
expect(deleteSecRes.statusCode).toBe(200);
const updatedSecretPayload = JSON.parse(deleteSecRes.payload);
expect(updatedSecretPayload).toHaveProperty("secret");
return updatedSecretPayload.secret;
};
// raw secret endpoints
describe("Secret V3 Raw Router", async () => {
let folderId = "";
const testRawSecrets = [
{
path: "/",
@@ -543,6 +632,7 @@ describe("Secret V3 Raw Router", async () => {
}
});
expect(folderCreate.statusCode).toBe(200);
folderId = folderCreate.json().folder.id;
});
afterAll(async () => {
@@ -569,6 +659,19 @@ describe("Secret V3 Raw Router", async () => {
}
});
expect(setBotInActive.statusCode).toEqual(200);
const deleteFolder = await testServer.inject({
method: "DELETE",
url: `/api/v1/folders/${folderId}`,
headers: {
authorization: `Bearer ${jwtAuthToken}`
},
body: {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
path: "/nested1/nested2"
}
});
expect(deleteFolder.statusCode).toBe(200);
});
const getSecrets = async (environment: string, secretPath = "/") => {
@@ -621,9 +724,13 @@ describe("Secret V3 Raw Router", async () => {
})
])
);
await deleteRawSecret({ path, key: secret.key });
});
test.each(testRawSecrets)("Get secret by name raw in path $path", async ({ secret, path }) => {
await createRawSecret({ path, ...secret });
const getSecByNameRes = await testServer.inject({
method: "GET",
url: `/api/v3/secrets/raw/${secret.key}`,
@@ -645,9 +752,33 @@ describe("Secret V3 Raw Router", async () => {
secretValue: secret.value
})
);
await deleteRawSecret({ path, key: secret.key });
});
test.each(testRawSecrets)("List secret raw in path $path", async ({ secret, path }) => {
await Promise.all(
Array.from(Array(5)).map((_e, i) => createRawSecret({ path, ...secret, key: `BULK-${secret.key}-${i + 1}` }))
);
const secrets = await getSecrets(seedData1.environment.slug, path);
expect(secrets.length).toEqual(5);
expect(secrets).toEqual(
expect.arrayContaining(
Array.from(Array(5)).map((_e, i) =>
expect.objectContaining({ value: expect.any(String), key: `BULK-${secret.key}-${i + 1}` })
)
)
);
await Promise.all(
Array.from(Array(5)).map((_e, i) => deleteRawSecret({ path, key: `BULK-${secret.key}-${i + 1}` }))
);
});
test.each(testRawSecrets)("Update secret raw in path $path", async ({ secret, path }) => {
await createRawSecret({ path, ...secret });
const updateSecretReqBody = {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
@@ -655,7 +786,6 @@ describe("Secret V3 Raw Router", async () => {
secretValue: "new-value",
secretPath: path
};
const updateSecRes = await testServer.inject({
method: "PATCH",
url: `/api/v3/secrets/raw/${secret.key}`,
@@ -680,9 +810,13 @@ describe("Secret V3 Raw Router", async () => {
})
])
);
await deleteRawSecret({ path, key: secret.key });
});
test.each(testRawSecrets)("Delete secret raw in path $path", async ({ path, secret }) => {
await createRawSecret({ path, ...secret });
const deletedSecretReqBody = {
workspaceId: seedData1.project.id,
environment: seedData1.environment.slug,
@@ -703,14 +837,7 @@ describe("Secret V3 Raw Router", async () => {
// fetch secrets
const secrets = await getSecrets(seedData1.environment.slug, path);
expect(secrets).toEqual(
expect.arrayContaining([
expect.not.objectContaining({
key: secret.key,
type: SecretType.Shared
})
])
);
expect(secrets).toEqual([]);
});
});