feat: added logged in based testing by injecting jwt token logic

This commit is contained in:
Akhil Mohan
2024-01-27 12:38:23 +05:30
parent dd7c449483
commit 0506389ada
10 changed files with 125 additions and 28 deletions
+3 -3
View File
@@ -1,11 +1,11 @@
import { testUser } from "@app/db/seeds/1-user"; import { seedData1 } from "@app/db/seed-data";
import jsrp from "jsrp"; import jsrp from "jsrp";
describe("Login V1 Router", async () => { describe("Login V1 Router", async () => {
// eslint-disable-next-line // eslint-disable-next-line
const client = new jsrp.client(); const client = new jsrp.client();
await new Promise((resolve) => { await new Promise((resolve) => {
client.init({ username: testUser.email, password: testUser.password }, () => resolve(null)); client.init({ username: seedData1.email, password: seedData1.password }, () => resolve(null));
}); });
let clientProof: string; let clientProof: string;
@@ -32,7 +32,7 @@ describe("Login V1 Router", async () => {
method: "POST", method: "POST",
url: "/api/v3/auth/login2", url: "/api/v3/auth/login2",
body: { body: {
email: testUser.email, email: seedData1.email,
clientProof clientProof
} }
}); });
+19
View File
@@ -0,0 +1,19 @@
import { seedData1 } from "@app/db/seed-data";
describe("Org V1 Router", async () => {
test("GET Org list", async () => {
const res = await testServer.inject({
method: "GET",
url: "/api/v1/organization",
headers: {
authorization: `Bearer ${jwtAuthToken}`
}
});
expect(res.statusCode).toBe(200);
const payload = JSON.parse(res.payload);
expect(payload).toHaveProperty("organizations");
expect(payload).toEqual({
organizations: [expect.objectContaining({ name: seedData1.organization.name })]
});
});
});
@@ -1,9 +0,0 @@
describe("Status V1 Router", async () => {
test("Simple check", async () => {
const res = await testServer.inject({
method: "GET",
url: "/api/status"
});
expect(res.statusCode).toBe(200);
});
});
+17 -1
View File
@@ -5,10 +5,13 @@ import knex from "knex";
import path from "path"; import path from "path";
import { mockSmtpServer } from "./mocks/smtp"; import { mockSmtpServer } from "./mocks/smtp";
import { initLogger } from "@app/lib/logger"; import { initLogger } from "@app/lib/logger";
import jwt from "jsonwebtoken";
import "ts-node/register"; import "ts-node/register";
import { main } from "@app/server/app"; import { main } from "@app/server/app";
import { mockQueue } from "./mocks/queue"; import { mockQueue } from "./mocks/queue";
import { AuthTokenType } from "@app/services/auth/auth-type";
import { seedData1 } from "@app/db/seed-data";
dotenv.config({ path: path.join(__dirname, "../.env.test") }); dotenv.config({ path: path.join(__dirname, "../.env.test") });
export default { export default {
@@ -35,10 +38,21 @@ export default {
const smtp = mockSmtpServer(); const smtp = mockSmtpServer();
const queue = mockQueue(); const queue = mockQueue();
const logger = await initLogger(); const logger = await initLogger();
initEnvConfig(logger); const cfg = initEnvConfig(logger);
const server = await main({ db, smtp, logger, queue }); const server = await main({ db, smtp, logger, queue });
// @ts-expect-error type // @ts-expect-error type
globalThis.testServer = server; globalThis.testServer = server;
// @ts-expect-error type
globalThis.jwtAuthToken = jwt.sign(
{
authTokenType: AuthTokenType.ACCESS_TOKEN,
userId: seedData1.id,
tokenVersionId: seedData1.token.id,
accessVersion: 1
},
cfg.JWT_AUTH_SECRET,
{ expiresIn: cfg.JWT_AUTH_LIFETIME }
);
} catch (error) { } catch (error) {
await db.destroy(); await db.destroy();
throw error; throw error;
@@ -50,6 +64,8 @@ export default {
await globalThis.testServer.close(); await globalThis.testServer.close();
// @ts-expect-error type // @ts-expect-error type
delete globalThis.testServer; delete globalThis.testServer;
// @ts-expect-error type
delete globalThis.jwtToken;
// called after all tests with this env have been run // called after all tests with this env have been run
await db.migrate.rollback({}, true); await db.migrate.rollback({}, true);
await db.destroy(); await db.destroy();
+1
View File
@@ -19,4 +19,5 @@ declare global {
// used only for testing // used only for testing
const testServer: FastifyZodProvider; const testServer: FastifyZodProvider;
const jwtAuthToken: string;
} }
+16
View File
@@ -0,0 +1,16 @@
export const seedData1 = {
id: "3dafd81d-4388-432b-a4c5-f735616868c1",
email: "[email protected]",
password: process.env.TEST_USER_PASSWORD || "testInfisical@1",
organization: {
id: "180870b7-f464-4740-8ffe-9d11c9245ea7",
name: "infisical"
},
project: {
id: "77fa7aed-9288-401e-a4c9-3a9430be62a0",
name: "first project"
},
token: {
id: "a9dfafba-a3b7-42e3-8618-91abb702fd36"
}
};
+25 -12
View File
@@ -1,17 +1,16 @@
import { Knex } from "knex"; import crypto from "node:crypto";
import argon2, { argon2id } from "argon2";
import jsrp from "jsrp"; import jsrp from "jsrp";
import { Knex } from "knex";
import nacl from "tweetnacl"; import nacl from "tweetnacl";
import { encodeBase64 } from "tweetnacl-util"; import { encodeBase64 } from "tweetnacl-util";
import argon2, { argon2id } from "argon2";
import { AuthMethod } from "../../services/auth/auth-type";
import { TableName } from "../schemas";
import crypto from "node:crypto";
import { encryptSymmetric } from "@app/lib/crypto"; import { encryptSymmetric } from "@app/lib/crypto";
export const testUser = { import { AuthMethod } from "../../services/auth/auth-type";
email: "[email protected]", import { TableName } from "../schemas";
password: process.env.TEST_USER_PASSWORD || "testInfisical@1" import { seedData1 } from "../seed-data";
};
export const generateUserSrpKeys = async (password: string) => { export const generateUserSrpKeys = async (password: string) => {
const pair = nacl.box.keyPair(); const pair = nacl.box.keyPair();
@@ -23,7 +22,7 @@ export const generateUserSrpKeys = async (password: string) => {
// eslint-disable-next-line // eslint-disable-next-line
const client = new jsrp.client(); const client = new jsrp.client();
await new Promise((resolve) => { await new Promise((resolve) => {
client.init({ username: testUser.email, password: testUser.password }, () => resolve(null)); client.init({ username: seedData1.email, password: seedData1.password }, () => resolve(null));
}); });
const { salt, verifier } = await new Promise<{ salt: string; verifier: string }>( const { salt, verifier } = await new Promise<{ salt: string; verifier: string }>(
(resolve, reject) => { (resolve, reject) => {
@@ -85,7 +84,9 @@ export async function seed(knex: Knex): Promise<void> {
const [user] = await knex(TableName.Users) const [user] = await knex(TableName.Users)
.insert([ .insert([
{ {
email: testUser.email, // @ts-ignore to calculate predefined
id: seedData1.id,
email: seedData1.email,
superAdmin: true, superAdmin: true,
firstName: "test", firstName: "test",
lastName: "", lastName: "",
@@ -98,7 +99,7 @@ export async function seed(knex: Knex): Promise<void> {
]) ])
.returning("*"); .returning("*");
const encKeys = await generateUserSrpKeys(testUser.password); const encKeys = await generateUserSrpKeys(seedData1.password);
// password: testInfisical@1 // password: testInfisical@1
await knex(TableName.UserEncryptionKey).insert([ await knex(TableName.UserEncryptionKey).insert([
{ {
@@ -115,4 +116,16 @@ export async function seed(knex: Knex): Promise<void> {
userId: user.id userId: user.id
} }
]); ]);
await knex(TableName.AuthTokenSession).insert({
// @ts-ignore
id: seedData1.token.id,
userId: seedData1.id,
ip: "151.196.220.213",
userAgent:
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36 RuxitSynthetic/1.0 v3690753611340580436 t8052286838287810618",
accessVersion: 1,
refreshVersion: 1,
lastUsed: new Date()
});
} }
+4 -2
View File
@@ -1,19 +1,21 @@
import { Knex } from "knex"; import { Knex } from "knex";
import { OrgMembershipRole, OrgMembershipStatus, TableName } from "../schemas"; import { OrgMembershipRole, OrgMembershipStatus, TableName } from "../schemas";
import { testUser } from "./1-user"; import { seedData1 } from "../seed-data";
export async function seed(knex: Knex): Promise<void> { export async function seed(knex: Knex): Promise<void> {
// Deletes ALL existing entries // Deletes ALL existing entries
await knex(TableName.Organization).del(); await knex(TableName.Organization).del();
await knex(TableName.OrgMembership).del(); await knex(TableName.OrgMembership).del();
const user = await knex(TableName.Users).where({ email: testUser.email }).first(); const user = await knex(TableName.Users).where({ email: seedData1.email }).first();
if (!user) throw new Error("User not found"); if (!user) throw new Error("User not found");
// Inserts seed entries // Inserts seed entries
const [org] = await knex(TableName.Organization) const [org] = await knex(TableName.Organization)
.insert([ .insert([
{ {
// @ts-ignore because we need that id for api calls
id: seedData1.organization.id,
name: "infisical", name: "infisical",
customerId: null customerId: null
} }
+39
View File
@@ -0,0 +1,39 @@
import { Knex } from "knex";
import { TableName } from "../schemas";
import { seedData1 } from "../seed-data";
export const DEFAULT_PROJECT_ENVS = [
{ name: "Development", slug: "dev" },
{ name: "Staging", slug: "staging" },
{ name: "Production", slug: "prod" }
];
export async function seed(knex: Knex): Promise<void> {
// Deletes ALL existing entries
await knex(TableName.Project).del();
await knex(TableName.Environment).del();
await knex(TableName.SecretFolder).del();
const [project] = await knex(TableName.Project)
.insert({
name: seedData1.project.name,
orgId: seedData1.organization.id,
// @ts-ignore pre calc id
id: seedData1.project.id
})
.returning("*");
const envs = await knex(TableName.Environment)
.insert(
DEFAULT_PROJECT_ENVS.map(({ name, slug }, index) => ({
name,
slug,
projectId: project.id,
position: index + 1
}))
)
.returning("*");
await knex(TableName.SecretFolder).insert(
envs.map(({ id }) => ({ name: "root", envId: id, parentId: null }))
);
}
@@ -22,7 +22,7 @@ import { ROOT_FOLDER_NAME, TSecretFolderDalFactory } from "../secret-folder/secr
import { TProjectDalFactory } from "./project-dal"; import { TProjectDalFactory } from "./project-dal";
import { TCreateProjectDTO, TDeleteProjectDTO, TGetProjectDTO } from "./project-types"; import { TCreateProjectDTO, TDeleteProjectDTO, TGetProjectDTO } from "./project-types";
const DEFAULT_PROJECT_ENVS = [ export const DEFAULT_PROJECT_ENVS = [
{ name: "Development", slug: "dev" }, { name: "Development", slug: "dev" },
{ name: "Staging", slug: "staging" }, { name: "Staging", slug: "staging" },
{ name: "Production", slug: "prod" } { name: "Production", slug: "prod" }