🪻 distributed transcription service thistle.dunkirk.sh

bug: fix rate limits

dunkirk.sh 0c42bd75 b5be26c7

verified
Changed files
+148 -598
src
+148 -598
src/index.test.ts
···
console.log("✓ Test server stopped and test database cleaned up");
});
+
// Clear database between each test
+
beforeEach(async () => {
+
const db = require("bun:sqlite").Database.open(TEST_DB_PATH);
+
+
// Delete all data from tables (preserve schema)
+
db.run("DELETE FROM rate_limit_attempts");
+
db.run("DELETE FROM email_change_tokens");
+
db.run("DELETE FROM password_reset_tokens");
+
db.run("DELETE FROM email_verification_tokens");
+
db.run("DELETE FROM passkeys");
+
db.run("DELETE FROM sessions");
+
db.run("DELETE FROM subscriptions");
+
db.run("DELETE FROM transcriptions");
+
db.run("DELETE FROM class_members");
+
db.run("DELETE FROM meeting_times");
+
db.run("DELETE FROM classes");
+
db.run("DELETE FROM class_waitlist");
+
db.run("DELETE FROM users WHERE id != 0"); // Keep ghost user
+
+
db.close();
+
});
+
// Test user credentials
const TEST_USER = {
email: "test@example.com",
···
});
}
+
// Helper to register a user, verify email, and get session via login
+
async function registerAndLogin(user: { email: string; password: string; name?: string }): Promise<string> {
+
const hashedPassword = await clientHashPassword(user.email, user.password);
+
+
// Register the user
+
const registerResponse = await fetch(`${BASE_URL}/api/auth/register`, {
+
method: "POST",
+
headers: { "Content-Type": "application/json" },
+
body: JSON.stringify({
+
email: user.email,
+
password: hashedPassword,
+
name: user.name || "Test User",
+
}),
+
});
+
+
if (registerResponse.status !== 200) {
+
const error = await registerResponse.json();
+
throw new Error(`Registration failed: ${JSON.stringify(error)}`);
+
}
+
+
const registerData = await registerResponse.json();
+
const userId = registerData.user.id;
+
+
// Mark email as verified directly in the database (test mode)
+
const db = require("bun:sqlite").Database.open(TEST_DB_PATH);
+
db.run("UPDATE users SET email_verified = 1 WHERE id = ?", [userId]);
+
db.close();
+
+
// Now login to get a session
+
const loginResponse = await fetch(`${BASE_URL}/api/auth/login`, {
+
method: "POST",
+
headers: { "Content-Type": "application/json" },
+
body: JSON.stringify({
+
email: user.email,
+
password: hashedPassword,
+
}),
+
});
+
+
if (loginResponse.status !== 200) {
+
const error = await loginResponse.json();
+
throw new Error(`Login failed: ${JSON.stringify(error)}`);
+
}
+
+
return extractSessionCookie(loginResponse);
+
}
+
+
// Helper to add active subscription to a user
+
function addSubscription(userEmail: string): void {
+
const db = require("bun:sqlite").Database.open(TEST_DB_PATH);
+
const user = db.query("SELECT id FROM users WHERE email = ?").get(userEmail) as { id: number };
+
if (!user) {
+
db.close();
+
throw new Error(`User ${userEmail} not found`);
+
}
+
+
db.run(
+
"INSERT INTO subscriptions (id, user_id, customer_id, status) VALUES (?, ?, ?, ?)",
+
[`test-sub-${user.id}`, user.id, `test-customer-${user.id}`, "active"]
+
);
+
db.close();
+
}
+
// All tests run against a fresh database, no cleanup needed
describe("API Endpoints - Authentication", () => {
···
expect(response.status).toBe(200);
-
// Extract session before consuming response body
-
const sessionCookie = extractSessionCookie(response);
-
const data = await response.json();
expect(data.user).toBeDefined();
expect(data.user.email).toBe(TEST_USER.email);
-
expect(sessionCookie).toBeTruthy();
+
expect(data.email_verification_required).toBe(true);
});
test("should reject registration with missing email", async () => {
···
test("should enforce rate limiting on registration", async () => {
const hashedPassword = await clientHashPassword(
-
"test@example.com",
+
"ratelimit@example.com",
"password",
);
-
// Make registration attempts until rate limit is hit (limit is 5 per hour)
-
let rateLimitHit = false;
-
for (let i = 0; i < 10; i++) {
-
const response = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: `test${i}@example.com`,
-
password: hashedPassword,
-
}),
-
});
-
-
if (response.status === 429) {
-
rateLimitHit = true;
-
break;
-
}
-
}
-
-
// Verify that rate limiting was triggered
-
expect(rateLimitHit).toBe(true);
-
});
-
});
-
-
describe("POST /api/auth/login", () => {
-
test("should login successfully with valid credentials", async () => {
-
// Register user first
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
+
// First registration succeeds
await fetch(`${BASE_URL}/api/auth/register`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
-
email: TEST_USER.email,
+
email: "ratelimit@example.com",
password: hashedPassword,
-
name: TEST_USER.name,
}),
});
-
// Login
-
const response = await fetch(`${BASE_URL}/api/auth/login`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
-
expect(response.status).toBe(200);
-
const data = await response.json();
-
expect(data.user).toBeDefined();
-
expect(data.user.email).toBe(TEST_USER.email);
-
expect(extractSessionCookie(response)).toBeTruthy();
-
});
-
-
test("should reject login with invalid credentials", async () => {
-
// Register user first
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
-
// Login with wrong password
-
const wrongPassword = await clientHashPassword(
-
TEST_USER.email,
-
"WrongPassword123!",
-
);
-
const response = await fetch(`${BASE_URL}/api/auth/login`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: wrongPassword,
-
}),
-
});
-
-
expect(response.status).toBe(401);
-
const data = await response.json();
-
expect(data.error).toBe("Invalid email or password");
-
});
-
-
test("should reject login with missing fields", async () => {
-
const response = await fetch(`${BASE_URL}/api/auth/login`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
}),
-
});
-
-
expect(response.status).toBe(400);
-
const data = await response.json();
-
expect(data.error).toBe("Email and password required");
-
});
-
-
test("should enforce rate limiting on login attempts", async () => {
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
-
// Make 11 login attempts (limit is 10 per 15 minutes per IP)
+
// Try to register same email 10 more times (will fail with 400 but count toward rate limit)
+
// Rate limit is 5 per 30 min from same IP
let rateLimitHit = false;
-
for (let i = 0; i < 11; i++) {
-
const response = await fetch(`${BASE_URL}/api/auth/login`, {
+
for (let i = 0; i < 10; i++) {
+
const response = await fetch(`${BASE_URL}/api/auth/register`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
-
email: TEST_USER.email,
+
email: "ratelimit@example.com",
password: hashedPassword,
}),
});
···
});
});
-
describe("POST /api/auth/logout", () => {
-
test("should logout successfully", async () => {
+
describe("POST /api/auth/login", () => {
+
test("should login successfully with valid credentials", async () => {
// Register and login
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const loginResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
const sessionCookie = extractSessionCookie(loginResponse);
-
-
// Logout
-
const response = await authRequest(
-
`${BASE_URL}/api/auth/logout`,
-
sessionCookie,
-
{
-
method: "POST",
-
},
-
);
-
-
expect(response.status).toBe(200);
-
const data = await response.json();
-
expect(data.success).toBe(true);
-
-
// Verify cookie is cleared
-
const setCookie = response.headers.get("set-cookie");
-
expect(setCookie).toContain("Max-Age=0");
-
});
-
-
test("should logout even without valid session", async () => {
-
const response = await fetch(`${BASE_URL}/api/auth/logout`, {
-
method: "POST",
-
});
-
-
expect(response.status).toBe(200);
-
const data = await response.json();
-
expect(data.success).toBe(true);
-
});
-
});
-
-
describe("GET /api/auth/me", () => {
-
test(
-
"should return current user info when authenticated",
-
async () => {
-
// Register user
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const registerResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
name: TEST_USER.name,
-
}),
-
});
-
const sessionCookie = extractSessionCookie(registerResponse);
-
-
// Get current user
-
const response = await authRequest(
-
`${BASE_URL}/api/auth/me`,
-
sessionCookie,
-
);
-
-
expect(response.status).toBe(200);
-
const data = await response.json();
-
expect(data.email).toBe(TEST_USER.email);
-
expect(data.name).toBe(TEST_USER.name);
-
expect(data.role).toBeDefined();
-
},
-
);
-
-
test("should return 401 when not authenticated", async () => {
-
const response = await fetch(`${BASE_URL}/api/auth/me`);
-
-
expect(response.status).toBe(401);
-
const data = await response.json();
-
expect(data.error).toBe("Not authenticated");
-
});
-
-
test("should return 401 with invalid session", async () => {
-
const response = await authRequest(
-
`${BASE_URL}/api/auth/me`,
-
"invalid-session",
-
);
-
-
expect(response.status).toBe(401);
-
const data = await response.json();
-
expect(data.error).toBe("Invalid session");
-
});
-
});
-
});
-
-
describe("API Endpoints - Session Management", () => {
-
describe("GET /api/sessions", () => {
-
test("should return user sessions", async () => {
-
// Register user
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const registerResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
const sessionCookie = extractSessionCookie(registerResponse);
-
-
// Get sessions
-
const response = await authRequest(
-
`${BASE_URL}/api/sessions`,
-
sessionCookie,
-
);
-
-
expect(response.status).toBe(200);
-
const data = await response.json();
-
expect(data.sessions).toBeDefined();
-
expect(data.sessions.length).toBeGreaterThan(0);
-
expect(data.sessions[0]).toHaveProperty("id");
-
expect(data.sessions[0]).toHaveProperty("ip_address");
-
expect(data.sessions[0]).toHaveProperty("user_agent");
-
});
-
-
test("should require authentication", async () => {
-
const response = await fetch(`${BASE_URL}/api/sessions`);
-
-
expect(response.status).toBe(401);
-
});
-
});
-
-
describe("DELETE /api/sessions", () => {
-
test("should delete specific session", async () => {
-
// Register user and create multiple sessions
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const session1Response = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
const session1Cookie = extractSessionCookie(session1Response);
-
-
const session2Response = await fetch(`${BASE_URL}/api/auth/login`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
const session2Cookie = extractSessionCookie(session2Response);
-
-
// Get sessions list
-
const sessionsResponse = await authRequest(
-
`${BASE_URL}/api/sessions`,
-
session1Cookie,
-
);
-
const sessionsData = await sessionsResponse.json();
-
const targetSessionId = sessionsData.sessions.find(
-
(s: { id: string }) => s.id === session2Cookie,
-
)?.id;
-
-
// Delete session 2
-
const response = await authRequest(
-
`${BASE_URL}/api/sessions`,
-
session1Cookie,
-
{
-
method: "DELETE",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({ sessionId: targetSessionId }),
-
},
-
);
-
-
expect(response.status).toBe(200);
-
const data = await response.json();
-
expect(data.success).toBe(true);
-
-
// Verify session 2 is deleted
-
const verifyResponse = await authRequest(
-
`${BASE_URL}/api/auth/me`,
-
session2Cookie,
-
);
-
expect(verifyResponse.status).toBe(401);
-
});
-
-
test("should not delete another user's session", async () => {
-
// Register two users
-
const hashedPassword1 = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const user1Response = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword1,
-
}),
-
});
-
const user1Cookie = extractSessionCookie(user1Response);
-
-
const hashedPassword2 = await clientHashPassword(
-
TEST_USER_2.email,
-
TEST_USER_2.password,
-
);
-
const user2Response = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER_2.email,
-
password: hashedPassword2,
-
}),
-
});
-
const user2Cookie = extractSessionCookie(user2Response);
-
-
// Try to delete user2's session using user1's credentials
-
const response = await authRequest(
-
`${BASE_URL}/api/sessions`,
-
user1Cookie,
-
{
-
method: "DELETE",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({ sessionId: user2Cookie }),
-
},
-
);
-
-
expect(response.status).toBe(404);
-
});
-
-
test("should not delete current session", async () => {
-
// Register user
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const registerResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
const sessionCookie = extractSessionCookie(registerResponse);
+
const sessionCookie = await registerAndLogin(TEST_USER);
// Try to delete own current session
const response = await authRequest(
···
describe("API Endpoints - User Management", () => {
describe("DELETE /api/user", () => {
test("should delete user account", async () => {
-
// Register user
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const registerResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
const sessionCookie = extractSessionCookie(registerResponse);
+
// Register and login
+
const sessionCookie = await registerAndLogin(TEST_USER);
// Delete account
const response = await authRequest(
···
describe("PUT /api/user/email", () => {
test("should update user email", async () => {
-
// Register user
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const registerResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
const sessionCookie = extractSessionCookie(registerResponse);
+
// Register and login
+
const sessionCookie = await registerAndLogin(TEST_USER);
-
// Update email
+
// Update email - this creates a token but doesn't change email yet
const newEmail = "newemail@example.com";
const response = await authRequest(
`${BASE_URL}/api/user/email`,
···
const data = await response.json();
expect(data.success).toBe(true);
+
// Manually complete the email change in the database (simulating verification)
+
const db = require("bun:sqlite").Database.open(TEST_DB_PATH);
+
const tokenData = db.query("SELECT user_id, new_email FROM email_change_tokens ORDER BY created_at DESC LIMIT 1").get() as { user_id: number, new_email: string };
+
db.run("UPDATE users SET email = ?, email_verified = 1 WHERE id = ?", [tokenData.new_email, tokenData.user_id]);
+
db.run("DELETE FROM email_change_tokens WHERE user_id = ?", [tokenData.user_id]);
+
db.close();
+
// Verify email updated
const meResponse = await authRequest(
`${BASE_URL}/api/auth/me`,
···
test("should reject duplicate email", async () => {
// Register two users
-
const hashedPassword1 = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword1,
-
}),
-
});
-
-
const hashedPassword2 = await clientHashPassword(
-
TEST_USER_2.email,
-
TEST_USER_2.password,
-
);
-
const user2Response = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER_2.email,
-
password: hashedPassword2,
-
}),
-
});
-
const user2Cookie = extractSessionCookie(user2Response);
+
await registerAndLogin(TEST_USER);
+
const user2Cookie = await registerAndLogin(TEST_USER_2);
// Try to update user2's email to user1's email
const response = await authRequest(
···
describe("PUT /api/user/password", () => {
test("should update user password", async () => {
-
// Register user
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const registerResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
const sessionCookie = extractSessionCookie(registerResponse);
+
// Register and login
+
const sessionCookie = await registerAndLogin(TEST_USER);
// Update password
const newPassword = await clientHashPassword(
···
});
test("should reject invalid password format", async () => {
-
// Register user
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const registerResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
const sessionCookie = extractSessionCookie(registerResponse);
+
// Register and login
+
const sessionCookie = await registerAndLogin(TEST_USER);
// Try to update with invalid format
const response = await authRequest(
···
describe("PUT /api/user/name", () => {
test("should update user name", async () => {
-
// Register user
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const registerResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
name: TEST_USER.name,
-
}),
-
});
-
const sessionCookie = extractSessionCookie(registerResponse);
+
// Register and login
+
const sessionCookie = await registerAndLogin(TEST_USER);
// Update name
const newName = "Updated Name";
···
});
test("should reject missing name", async () => {
-
// Register user
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const registerResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
const sessionCookie = extractSessionCookie(registerResponse);
+
// Register and login
+
const sessionCookie = await registerAndLogin(TEST_USER);
const response = await authRequest(
`${BASE_URL}/api/user/name`,
···
describe("PUT /api/user/avatar", () => {
test("should update user avatar", async () => {
-
// Register user
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const registerResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
const sessionCookie = extractSessionCookie(registerResponse);
+
// Register and login
+
const sessionCookie = await registerAndLogin(TEST_USER);
// Update avatar
const newAvatar = "👨‍💻";
···
describe("API Endpoints - Transcriptions", () => {
describe("GET /api/transcriptions", () => {
test("should return user transcriptions", async () => {
-
// Register user
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const registerResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
const sessionCookie = extractSessionCookie(registerResponse);
+
// Register and login
+
const sessionCookie = await registerAndLogin(TEST_USER);
+
+
// Add subscription
+
addSubscription(TEST_USER.email);
// Get transcriptions
const response = await authRequest(
···
describe("POST /api/transcriptions", () => {
test("should upload audio file and start transcription", async () => {
-
// Register user
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const registerResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
const sessionCookie = extractSessionCookie(registerResponse);
+
// Register and login
+
const sessionCookie = await registerAndLogin(TEST_USER);
+
+
// Add subscription
+
addSubscription(TEST_USER.email);
// Create a test audio file
const audioBlob = new Blob(["fake audio data"], { type: "audio/mp3" });
···
});
test("should reject non-audio files", async () => {
-
// Register user
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const registerResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
const sessionCookie = extractSessionCookie(registerResponse);
+
// Register and login
+
const sessionCookie = await registerAndLogin(TEST_USER);
+
+
// Add subscription
+
addSubscription(TEST_USER.email);
// Try to upload non-audio file
const textBlob = new Blob(["text file"], { type: "text/plain" });
···
});
test("should reject files exceeding size limit", async () => {
-
// Register user
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const registerResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
const sessionCookie = extractSessionCookie(registerResponse);
+
// Register and login
+
const sessionCookie = await registerAndLogin(TEST_USER);
+
+
// Add subscription
+
addSubscription(TEST_USER.email);
// Create a file larger than 100MB (the actual limit)
const largeBlob = new Blob([new ArrayBuffer(101 * 1024 * 1024)], {
···
let userId: number;
beforeEach(async () => {
-
// Create admin user
-
const adminHash = await clientHashPassword(
-
TEST_ADMIN.email,
-
TEST_ADMIN.password,
-
);
-
const adminResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_ADMIN.email,
-
password: adminHash,
-
name: TEST_ADMIN.name,
-
}),
-
});
-
adminCookie = extractSessionCookie(adminResponse);
-
+
adminCookie = await registerAndLogin(TEST_ADMIN);
+
// Manually set admin role in database
+
const db = require("bun:sqlite").Database.open(TEST_DB_PATH);
db.run("UPDATE users SET role = 'admin' WHERE email = ?", [
TEST_ADMIN.email,
]);
// Create regular user
-
const userHash = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const userResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: userHash,
-
name: TEST_USER.name,
-
}),
-
});
-
userCookie = extractSessionCookie(userResponse);
+
userCookie = await registerAndLogin(TEST_USER);
// Get user ID
const userIdResult = db
.query<{ id: number }, [string]>("SELECT id FROM users WHERE email = ?")
.get(TEST_USER.email);
userId = userIdResult?.id;
+
+
db.close();
});
describe("GET /api/admin/users", () => {
···
let sessionCookie: string;
beforeEach(async () => {
-
-
// Register user
-
const hashedPassword = await clientHashPassword(
-
TEST_USER.email,
-
TEST_USER.password,
-
);
-
const registerResponse = await fetch(`${BASE_URL}/api/auth/register`, {
-
method: "POST",
-
headers: { "Content-Type": "application/json" },
-
body: JSON.stringify({
-
email: TEST_USER.email,
-
password: hashedPassword,
-
}),
-
});
-
sessionCookie = extractSessionCookie(registerResponse);
+
// Register and login
+
sessionCookie = await registerAndLogin(TEST_USER);
});
describe("GET /api/passkeys", () => {