feat(auth): enhance authentication system with login attempt tracking and configuration options

- Added a new `LoginAttempt` model to track login attempts, including rate limiting and lockout functionality.
- Introduced environment variables for configuring login rate limits and maximum failures.
- Updated the authentication middleware to handle login attempts and enforce rate limits.
- Enhanced the user model with indexing for username and email for improved lookup performance.
- Modified the `.env.example` file to include new optional authentication settings.
- Updated integration tests to cover new login attempt features and authentication state management.
This commit is contained in:
Adrian Acala
2026-01-20 19:55:32 -08:00
parent 260a898e3e
commit af07a73a07
13 changed files with 433 additions and 29 deletions
+7 -4
View File
@@ -3,8 +3,8 @@ import path from "path";
import os from "os";
// Centralized test environment URLs
const FRONTEND_PORT = 5173;
const BACKEND_PORT = 8000;
const FRONTEND_PORT = Number(process.env.FRONTEND_PORT || 5173);
const BACKEND_PORT = Number(process.env.BACKEND_PORT || 8000);
const FRONTEND_URL = process.env.BASE_URL || `http://localhost:${FRONTEND_PORT}`;
const BACKEND_URL = process.env.API_URL || `http://localhost:${BACKEND_PORT}`;
const API_URL = BACKEND_URL;
@@ -110,7 +110,7 @@ export default defineConfig({
command: "cd ../backend && npx prisma db push && npx ts-node src/index.ts",
url: `${BACKEND_URL}/health`,
reuseExistingServer: false,
timeout: 120000,
timeout: 240000,
stdout: "pipe",
stderr: "pipe",
env: {
@@ -126,18 +126,21 @@ export default defineConfig({
RATE_LIMIT_MAX_REQUESTS: "20000",
NODE_ENV: "e2e",
TS_NODE_TRANSPILE_ONLY: "1",
PORT: String(BACKEND_PORT),
START_SERVER_IN_TEST: "true",
},
},
{
command: "cd ../frontend && npm run dev -- --host",
url: FRONTEND_URL,
reuseExistingServer: false,
timeout: 120000,
timeout: 240000,
stdout: "pipe",
stderr: "pipe",
env: {
VITE_API_URL: "/api",
API_URL,
PORT: String(FRONTEND_PORT),
},
},
],
+1 -1
View File
@@ -64,7 +64,7 @@ elif [ "$CI" = "true" ]; then
CI=true NO_SERVER=true npx playwright test
else
echo " Mode: Headless"
NO_SERVER=${NO_SERVER:-false} npx playwright test
PWDEBUG=${PWDEBUG:-false} NO_SERVER=${NO_SERVER:-false} npx playwright test
fi
echo ""
+4 -2
View File
@@ -86,8 +86,10 @@ test.describe("Dashboard Workflows", () => {
await expect(cardLocator).toHaveCount(0);
const response = await request.get(`${API_URL}/drawings/${createdDrawing.id}`);
expect(response.status()).toBe(404);
await expect.poll(async () => {
const response = await request.get(`${API_URL}/drawings/${createdDrawing.id}`);
return response.status();
}).toBe(404);
createdDrawingIds = createdDrawingIds.filter((id) => id !== createdDrawing.id);
});