feat: port scenario 903 select-pool flow

This commit is contained in:
2026-07-30 23:27:59 +00:00
parent 9bd057456b
commit 115218ded8
80 changed files with 6859 additions and 48 deletions
@@ -45,6 +45,7 @@ export class InMemoryGatewaySessionService implements GatewaySessionService {
sanctions: user.sanctions,
createdAt: user.createdAt,
issuedAt: new Date().toISOString(),
legacyMemberNo: user.legacyMemberNo,
};
this.sessions.set(sessionToken, {
info,
@@ -99,6 +100,7 @@ export class InMemoryGatewaySessionService implements GatewaySessionService {
sanctions: session.sanctions,
createdAt: session.createdAt,
issuedAt: new Date().toISOString(),
legacyMemberNo: session.legacyMemberNo,
};
const key = buildGameKey(profile, gameToken);
this.gameSessions.set(key, {
@@ -17,6 +17,14 @@ const readObject = <T extends object>(value: unknown, fallback: T): T => {
return value as T;
};
const readLegacyMemberNo = (value: unknown): number | undefined => {
const legacyData = readObject<Record<string, unknown>>(value, {});
const memberNo = legacyData.memberNo;
return typeof memberNo === 'number' && Number.isSafeInteger(memberNo) && memberNo > 0
? memberNo
: undefined;
};
const mapUser = (row: {
id: string;
loginId: string;
@@ -39,6 +47,7 @@ const mapUser = (row: {
kakaoGraceStartedAt: Date;
deleteAfter: Date | null;
createdAt: Date;
legacyData: GatewayPrisma.JsonValue;
}): UserRecord => ({
id: row.id,
username: row.loginId,
@@ -61,6 +70,7 @@ const mapUser = (row: {
passwordHash: row.passwordHash,
passwordSalt: row.passwordSalt,
createdAt: row.createdAt.toISOString(),
legacyMemberNo: readLegacyMemberNo(row.legacyData),
});
export const createPostgresUserRepository = (
@@ -56,6 +56,7 @@ export class RedisGatewaySessionService implements GatewaySessionService {
sanctions: user.sanctions,
createdAt: user.createdAt,
issuedAt: new Date().toISOString(),
legacyMemberNo: user.legacyMemberNo,
};
await this.client.set(this.keys.sessionKey(sessionToken), JSON.stringify(info), {
EX: this.sessionTtlSeconds,
@@ -108,6 +109,7 @@ export class RedisGatewaySessionService implements GatewaySessionService {
sanctions: session.sanctions,
createdAt: session.createdAt,
issuedAt: new Date().toISOString(),
legacyMemberNo: session.legacyMemberNo,
};
const gameKey = this.keys.gameSessionKey(profile, gameToken);
const gameSetKey = this.keys.sessionGameSetKey(sessionToken);
@@ -9,6 +9,7 @@ export interface GatewaySessionInfo {
sanctions: UserSanctions;
createdAt: string;
issuedAt: string;
legacyMemberNo?: number;
}
export interface GameSessionInfo {
@@ -22,6 +23,7 @@ export interface GameSessionInfo {
sanctions: UserSanctions;
createdAt: string;
issuedAt: string;
legacyMemberNo?: number;
}
export interface GatewaySessionConfig {
@@ -20,6 +20,7 @@ export interface UserRecord {
passwordHash: string;
passwordSalt: string;
createdAt: string;
legacyMemberNo?: number;
}
export interface PublicUser {
+1
View File
@@ -672,6 +672,7 @@ export const appRouter = router({
displayName: gameSession.displayName,
roles: gameSession.roles,
createdAt: gameSession.createdAt,
legacyMemberNo: gameSession.legacyMemberNo,
},
sanctions: gameSession.sanctions,
identity: {
+28
View File
@@ -516,6 +516,34 @@ describe('gateway auth flow', () => {
expect(validated?.user.username).toBe('tester');
});
it('keeps the migrated member number inside the encrypted game identity', async () => {
const { caller, users, sessions } = buildCaller();
const user = await users.createUser({
username: 'legacy-seed-user',
password: 'secretpass',
});
user.legacyMemberNo = 42;
const session = await sessions.createSession(user);
const issued = await caller.auth.issueGameSession({
sessionToken: session.sessionToken,
profile: 'che:default',
});
const payload = decryptGameSessionToken(issued.gameToken, 'test-secret');
expect(payload?.user.legacyMemberNo).toBe(42);
const validated = await caller.auth.validateGameSession({
profile: 'che:default',
gameToken: issued.gameToken,
});
expect(validated).toMatchObject({
user: {
id: user.id,
},
});
expect(validated?.user).not.toHaveProperty('legacyMemberNo');
});
it('revokes the gateway session and every linked game session on logout', async () => {
const { caller, users, sessions } = buildCaller();
const user = await users.createUser({