refactor: tighten backend and logic boundaries

This commit is contained in:
2026-08-15 06:46:52 +00:00
parent 7b02ff155f
commit 35d8824b95
86 changed files with 820 additions and 1872 deletions
@@ -1,6 +1,6 @@
import { randomUUID } from 'node:crypto';
import { createSimplePasswordHasher, type PasswordHasher } from './passwordHasher.js';
import { createPasswordHasher, type PasswordHasher } from './passwordHasher.js';
import type {
AdminUserListItem,
CreateUserInput,
@@ -24,7 +24,7 @@ const toAdminUserListItem = (user: UserRecord): AdminUserListItem => ({
});
// 유저 데이터 저장소를 메모리로 대체한 임시 구현.
export const createInMemoryUserRepository = (hasher: PasswordHasher = createSimplePasswordHasher()): UserRepository => {
export const createInMemoryUserRepository = (hasher: PasswordHasher = createPasswordHasher()): UserRepository => {
const usersByName = new Map<string, UserRecord>();
const usersByOauthId = new Map<string, UserRecord>();
const usersByEmail = new Map<string, UserRecord>();
@@ -6,10 +6,10 @@ import type { KakaoOAuthClient, KakaoOAuthToken, KakaoUserInfo } from './kakaoCl
import type { OAuthSessionStore } from './oauthSessionStore.js';
import type { UserOAuthInfo, UserRecord, UserRepository } from './userRepository.js';
export const KAKAO_LOGIN_SCOPES = ['account_email', 'talk_message'] as const;
export const KAKAO_OTP_TTL_SECONDS = 180;
export const KAKAO_OTP_ATTEMPTS = 3;
export const KAKAO_TALK_VERIFICATION_DAYS = 10;
const KAKAO_LOGIN_SCOPES = ['account_email', 'talk_message'] as const;
const KAKAO_OTP_TTL_SECONDS = 180;
const KAKAO_OTP_ATTEMPTS = 3;
const KAKAO_TALK_VERIFICATION_DAYS = 10;
export type KakaoVerificationErrorCode =
| 'EMAIL_REQUIRED'
@@ -97,6 +97,3 @@ export const createPasswordHasher = (options: { legacyGlobalSalt?: string } = {}
return { ok: false, needsUpgrade: false };
},
});
// 기존 import 지점을 깨지 않되 새 계정은 Argon2id를 사용한다.
export const createSimplePasswordHasher = createPasswordHasher;
@@ -1,6 +1,6 @@
import { GatewayPrisma, type GatewayPrismaClient } from '@sammo-ts/infra';
import { createSimplePasswordHasher, type PasswordHasher } from './passwordHasher.js';
import { createPasswordHasher, type PasswordHasher } from './passwordHasher.js';
import type {
AdminUserListItem,
CreateUserInput,
@@ -158,7 +158,7 @@ const mapSpecialAccessGrant = (row: {
export const createPostgresUserRepository = (
prisma: GatewayPrismaClient,
hasher: PasswordHasher = createSimplePasswordHasher()
hasher: PasswordHasher = createPasswordHasher()
): UserRepository => {
return {
async findById(id: string): Promise<UserRecord | null> {
@@ -406,7 +406,9 @@ export const createPostgresUserRepository = (
if (result.count !== 1) {
return null;
}
return mapSpecialAccessGrant(await prisma.specialAccountAccessGrant.findUniqueOrThrow({ where: { id: grantId } }));
return mapSpecialAccessGrant(
await prisma.specialAccountAccessGrant.findUniqueOrThrow({ where: { id: grantId } })
);
},
async updateIcon(userId: string, picture: string, imageServer: number, updatedAt: Date): Promise<void> {
await prisma.appUser.update({
@@ -21,7 +21,7 @@ const isWideCodePoint = (codePoint: number): boolean =>
(codePoint >= 0x1f900 && codePoint <= 0x1f9ff) ||
(codePoint >= 0x20000 && codePoint <= 0x3fffd));
export const legacyStringWidth = (value: string): number =>
const legacyStringWidth = (value: string): number =>
Array.from(value).reduce((width, character) => {
const codePoint = character.codePointAt(0) ?? 0;
return width + (isWideCodePoint(codePoint) ? 2 : 1);