refactor: tighten backend and logic boundaries
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user