operation-cycle / api-server\scripts\test-user-creation.ts
o134's picture
Upload api-server\scripts\test-user-creation.ts with huggingface_hub
e166039 verified
Raw
History Blame Contribute Delete
5.44 kB
import { db, usersTable, auditLogsTable } from "@workspace/db";
import { eq, desc } from "drizzle-orm";
import jwt from "jsonwebtoken";
import app from "../src/app.js";
import http from "http";
async function runTest() {
console.log("πŸš€ Starting E2E User Creation & Audit Log Verification Test...\n");
let server: http.Server | null = null;
try {
// 1. Find or create an admin user in the database
let [admin] = await db.select().from(usersTable).where(eq(usersTable.role, "admin")).limit(1);
if (!admin) {
console.log("ℹ️ No admin user found. Creating a temporary admin user...");
[admin] = await db.insert(usersTable).values({
email: "admin_" + Date.now() + "@example.com",
name: "System Admin",
role: "admin",
team: "Executive",
passwordHash: "dummy_hash",
}).returning();
}
console.log(`βœ… Using Admin User: ${admin.name} (ID: ${admin.id}, Email: ${admin.email})`);
// 2. Generate JWT Token for Admin
const token = jwt.sign(
{ id: admin.id, email: admin.email, role: admin.role, team: admin.team },
process.env.JWT_SECRET || "",
{ expiresIn: "1h" }
);
// 3. Start Express Server on port 5005
server = app.listen(5005);
console.log("βœ… Express Test Server listening on port 5005");
// 4. Prepare Test User Payload
const newUserData = {
name: "E2E Test User",
email: "e2e_test_" + Date.now() + "@example.com",
password: "SecurePassword123!",
role: "member",
team: "Engineering",
avatarColor: "#336699",
// Attempting mass assignment injection
id: 99999,
passwordHash: "injected_hash",
createdAt: "2020-01-01T00:00:00.000Z",
};
console.log("\nπŸ“¦ Sending POST /api/users request with payload (including mass-assignment attempts)...");
// 5. Send Request
const res = await fetch("http://localhost:5005/api/users", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
},
body: JSON.stringify(newUserData),
});
const responseBody = await res.json();
console.log(`HTTP Response Status: ${res.status}`);
if (res.status !== 201) {
throw new Error(`Expected status 201, got ${res.status}. Response: ${JSON.stringify(responseBody)}`);
}
console.log("βœ… API Response received successfully. Verifying response payload...");
// Verify response does not expose passwordHash or injected fields
if (responseBody.passwordHash || responseBody.password || responseBody.id === 99999) {
throw new Error("❌ API Response exposed sensitive fields or allowed mass assignment!");
}
console.log("βœ… API Response is perfectly sanitized (password/passwordHash excluded, mass-assignment ignored).");
const createdUserId = responseBody.id;
// 6. Query Supabase directly to verify record in users table
console.log(`\nπŸ” Querying Supabase for created user (ID: ${createdUserId})...`);
const [dbUser] = await db.select().from(usersTable).where(eq(usersTable.id, createdUserId));
if (!dbUser) {
throw new Error("❌ User record not found in Supabase database!");
}
console.log("βœ… User record found in database:");
console.log({
id: dbUser.id,
name: dbUser.name,
email: dbUser.email,
role: dbUser.role,
team: dbUser.team,
createdAt: dbUser.createdAt,
passwordHashIsSet: !!dbUser.passwordHash && dbUser.passwordHash !== "injected_hash" && dbUser.passwordHash !== "SecurePassword123!",
});
if (!dbUser.passwordHash || dbUser.passwordHash === "SecurePassword123!" || dbUser.passwordHash === "injected_hash") {
throw new Error("❌ Password was not hashed correctly or mass assignment succeeded!");
}
console.log("βœ… Password is securely hashed in the database using bcrypt.");
// 7. Query Supabase directly for the audit log entry
// Wait briefly for async audit log insertion
await new Promise(resolve => setTimeout(resolve, 500));
console.log(`\nπŸ” Querying Supabase for audit log entry...`);
const [auditLog] = await db.select().from(auditLogsTable)
.where(eq(auditLogsTable.event, "role_change"))
.orderBy(desc(auditLogsTable.createdAt))
.limit(1);
if (!auditLog) {
throw new Error("❌ Audit log entry for 'role_change' not found!");
}
console.log("βœ… Audit log entry found in database:");
console.log({
id: auditLog.id,
event: auditLog.event,
performedById: auditLog.performedById,
entityId: auditLog.entityId,
entityType: auditLog.entityType,
details: auditLog.details,
createdAt: auditLog.createdAt,
});
if (auditLog.performedById !== admin.id.toString()) {
throw new Error(`❌ Audit log performedById (${auditLog.performedById}) does not match admin ID (${admin.id})!`);
}
const details: any = auditLog.details;
if (details.password || details.passwordHash) {
throw new Error("❌ Audit log details leaked sensitive password information!");
}
console.log("\nπŸŽ‰ ALL E2E VERIFICATION CHECKS PASSED SUCCESSFULLY!");
} catch (err) {
console.error("\n❌ Test Failed:", err);
} finally {
if (server) {
server.close();
console.log("\nβœ… Express server closed.");
}
}
}
runTest();