feat: port scenario 903 select-pool flow
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -672,6 +672,7 @@ export const appRouter = router({
|
||||
displayName: gameSession.displayName,
|
||||
roles: gameSession.roles,
|
||||
createdAt: gameSession.createdAt,
|
||||
legacyMemberNo: gameSession.legacyMemberNo,
|
||||
},
|
||||
sanctions: gameSession.sanctions,
|
||||
identity: {
|
||||
|
||||
@@ -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({
|
||||
|
||||
Reference in New Issue
Block a user