From 26df54a09d7e195d0e33266e0b34f8e11d072277 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sun, 7 Dec 2025 03:24:42 +0900 Subject: feat(client): remove registration page --- src/server/routes/auth.test.ts | 106 ----------------------------------------- src/server/routes/auth.ts | 23 +-------- src/server/scripts/add-user.ts | 48 +++++++++++++++++++ 3 files changed, 49 insertions(+), 128 deletions(-) create mode 100644 src/server/scripts/add-user.ts (limited to 'src/server') diff --git a/src/server/routes/auth.test.ts b/src/server/routes/auth.test.ts index 3ba504e..5bf9f86 100644 --- a/src/server/routes/auth.test.ts +++ b/src/server/routes/auth.test.ts @@ -3,7 +3,6 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; import { errorHandler } from "../middleware/index.js"; import type { RefreshTokenRepository, - UserPublic, UserRepository, } from "../repositories/index.js"; import { createAuthRouter } from "./auth.js"; @@ -32,18 +31,6 @@ function createMockRefreshTokenRepo(): RefreshTokenRepository { }; } -interface RegisterResponse { - user?: { - id: string; - username: string; - createdAt: string; - }; - error?: { - code: string; - message: string; - }; -} - interface LoginResponse { accessToken?: string; refreshToken?: string; @@ -57,99 +44,6 @@ interface LoginResponse { }; } -describe("POST /register", () => { - let app: Hono; - let mockUserRepo: ReturnType; - let mockRefreshTokenRepo: ReturnType; - - beforeEach(() => { - vi.clearAllMocks(); - mockUserRepo = createMockUserRepo(); - mockRefreshTokenRepo = createMockRefreshTokenRepo(); - const auth = createAuthRouter({ - userRepo: mockUserRepo, - refreshTokenRepo: mockRefreshTokenRepo, - }); - app = new Hono(); - app.onError(errorHandler); - app.route("/api/auth", auth); - }); - - it("creates a new user with valid credentials", async () => { - vi.mocked(mockUserRepo.existsByUsername).mockResolvedValue(false); - vi.mocked(mockUserRepo.create).mockResolvedValue({ - id: "test-uuid-123", - username: "testuser", - createdAt: new Date("2024-01-01T00:00:00Z"), - } as UserPublic); - - const res = await app.request("/api/auth/register", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - username: "testuser", - password: "securepassword12345", - }), - }); - - expect(res.status).toBe(201); - const body = (await res.json()) as RegisterResponse; - expect(body.user).toEqual({ - id: "test-uuid-123", - username: "testuser", - createdAt: "2024-01-01T00:00:00.000Z", - }); - expect(mockUserRepo.existsByUsername).toHaveBeenCalledWith("testuser"); - expect(mockUserRepo.create).toHaveBeenCalledWith({ - username: "testuser", - passwordHash: "hashed_securepassword12345", - }); - }); - - it("returns 400 for invalid username", async () => { - const res = await app.request("/api/auth/register", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - username: "", - password: "securepassword12345", - }), - }); - - expect(res.status).toBe(400); - }); - - it("returns 400 for password too short", async () => { - const res = await app.request("/api/auth/register", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - username: "testuser", - password: "tooshort123456", - }), - }); - - expect(res.status).toBe(400); - }); - - it("returns 409 for existing username", async () => { - vi.mocked(mockUserRepo.existsByUsername).mockResolvedValue(true); - - const res = await app.request("/api/auth/register", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - username: "existinguser", - password: "securepassword12345", - }), - }); - - expect(res.status).toBe(409); - const body = (await res.json()) as RegisterResponse; - expect(body.error?.code).toBe("USERNAME_EXISTS"); - }); -}); - describe("POST /login", () => { let app: Hono; let mockUserRepo: ReturnType; diff --git a/src/server/routes/auth.ts b/src/server/routes/auth.ts index 144bbae..06c88a6 100644 --- a/src/server/routes/auth.ts +++ b/src/server/routes/auth.ts @@ -10,11 +10,7 @@ import { type UserRepository, userRepository, } from "../repositories/index.js"; -import { - createUserSchema, - loginSchema, - refreshTokenSchema, -} from "../schemas/index.js"; +import { loginSchema, refreshTokenSchema } from "../schemas/index.js"; function getJwtSecret(): string { const secret = process.env.JWT_SECRET; @@ -43,23 +39,6 @@ export function createAuthRouter(deps: AuthDependencies) { const { userRepo, refreshTokenRepo } = deps; return new Hono() - .post("/register", zValidator("json", createUserSchema), async (c) => { - const { username, password } = c.req.valid("json"); - - // Check if username already exists - const exists = await userRepo.existsByUsername(username); - if (exists) { - throw Errors.conflict("Username already exists", "USERNAME_EXISTS"); - } - - // Hash password with Argon2 - const passwordHash = await argon2.hash(password); - - // Create user - const newUser = await userRepo.create({ username, passwordHash }); - - return c.json({ user: newUser }, 201); - }) .post("/login", zValidator("json", loginSchema), async (c) => { const { username, password } = c.req.valid("json"); diff --git a/src/server/scripts/add-user.ts b/src/server/scripts/add-user.ts new file mode 100644 index 0000000..5fcccac --- /dev/null +++ b/src/server/scripts/add-user.ts @@ -0,0 +1,48 @@ +import * as readline from "node:readline/promises"; +import * as argon2 from "argon2"; +import { userRepository } from "../repositories/index.js"; + +async function main() { + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + const username = await rl.question("Username: "); + const password = await rl.question("Password: "); + rl.close(); + + if (!username || !password) { + console.error("Error: Username and password are required"); + process.exit(1); + } + + if (password.length < 8) { + console.error("Error: Password must be at least 8 characters"); + process.exit(1); + } + + // Check if username already exists + const exists = await userRepository.existsByUsername(username); + if (exists) { + console.error(`Error: Username "${username}" already exists`); + process.exit(1); + } + + // Hash password with Argon2 + const passwordHash = await argon2.hash(password); + + // Create user + const newUser = await userRepository.create({ username, passwordHash }); + + console.log(`User created successfully:`); + console.log(` ID: ${newUser.id}`); + console.log(` Username: ${newUser.username}`); + + process.exit(0); +} + +main().catch((error) => { + console.error("Error:", error.message); + process.exit(1); +}); -- cgit v1.2.3-70-g09d2