- Created migration for accounts table with fields: id, username, password, role_id, created_at, updated_at. - Created migration for movies table with fields: id, title, overview, poster_path, backdrop_path, release_date, tmdb_id. refactor: update package.json scripts and dependencies - Changed dev script to use bun instead of tsx. - Added build:migrate script for migration. - Updated devDependencies for bun and oxlint. fix: refactor database connection and migration execution - Updated PgDatabase to use SQL from bun. - Refactored migration execution logic to read SQL files and execute them. feat: implement account creation and validation logic - Updated AccountEntity to use username instead of email. - Added validation for username format and password strength. - Implemented account repository methods for finding by username and inserting accounts. test: add tests for account entity, repository, and service - Created tests for AccountEntity to validate username and password. - Added tests for AccountRepository to ensure correct database interactions. - Implemented tests for AccountService to validate registration and login logic. chore: remove outdated tests and files - Deleted old tests related to email-based account management. - Cleaned up unused imports and files to streamline the codebase.
72 lines
1.8 KiB
TypeScript
72 lines
1.8 KiB
TypeScript
import { Hono } from "hono";
|
|
import { validator } from "hono/validator";
|
|
import type { AccountServiceInterface } from "../service/AccountServiceInterface";
|
|
import { loginSchema, registerSchema } from "../validation/AccountValidation";
|
|
import { BadSchemaError } from "../../../errors";
|
|
import { createRateLimit } from "../../../middleware/rateLimiter";
|
|
|
|
const loginRateLimit = createRateLimit({
|
|
windowMs: 15 * 60 * 1000,
|
|
maxAttempts: 5,
|
|
keyGenerator: (c) => {
|
|
const ip =
|
|
c.req.header("x-forwarded-for") ||
|
|
c.req.header("x-real-ip") ||
|
|
"127.0.0.1";
|
|
return `login:${ip}`;
|
|
},
|
|
});
|
|
|
|
export default function toRoutes(
|
|
accountService: AccountServiceInterface,
|
|
): Hono {
|
|
const app = new Hono();
|
|
|
|
app.post(
|
|
"/login",
|
|
loginRateLimit,
|
|
validator("json", (value) => {
|
|
const parsed = loginSchema.safeParse(value);
|
|
if (!parsed.success) {
|
|
throw new BadSchemaError(parsed.error.message);
|
|
}
|
|
|
|
return parsed.data;
|
|
}),
|
|
async (ctx) => {
|
|
const { username, password } = ctx.req.valid("json");
|
|
const account = await accountService.login(username, password);
|
|
|
|
return ctx.json({
|
|
success: true,
|
|
accountId: account.id,
|
|
username: account.username,
|
|
});
|
|
},
|
|
);
|
|
|
|
app.post(
|
|
"/register",
|
|
validator("json", (value) => {
|
|
const parsed = registerSchema.safeParse(value);
|
|
if (!parsed.success) {
|
|
throw new BadSchemaError(parsed.error.message);
|
|
}
|
|
|
|
return parsed.data;
|
|
}),
|
|
async (ctx) => {
|
|
const { username, password } = ctx.req.valid("json");
|
|
const account = await accountService.register(username, password);
|
|
|
|
return ctx.json({
|
|
success: true,
|
|
accountId: account.id,
|
|
username: account.username,
|
|
});
|
|
},
|
|
);
|
|
|
|
return app;
|
|
}
|