diff --git a/dictation_server/src/common/log/context.ts b/dictation_server/src/common/log/context.ts index 229cca8..2c8bbe3 100644 --- a/dictation_server/src/common/log/context.ts +++ b/dictation_server/src/common/log/context.ts @@ -4,8 +4,5 @@ export const makeContext = ( externalId: string, delegationId?: string, ): Context => { - return { - trackingId: externalId, - delegationId: delegationId, - }; + return new Context(externalId, delegationId); }; diff --git a/dictation_server/src/common/log/types.ts b/dictation_server/src/common/log/types.ts index 5c843db..7ed3855 100644 --- a/dictation_server/src/common/log/types.ts +++ b/dictation_server/src/common/log/types.ts @@ -7,4 +7,19 @@ export class Context { * APIの代行操作ユーザーを追跡するためのID */ delegationId?: string | undefined; + + constructor(externalId: string, delegationId?: string) { + this.trackingId = externalId; + this.delegationId = delegationId; + } + /** + * ログにユーザーを特定する情報を出力する + */ + getTrackingId(): string { + if (this.delegationId) { + return `${this.trackingId} by ${this.delegationId}`; + } else { + return this.trackingId; + } + } } diff --git a/dictation_server/src/features/accounts/accounts.controller.ts b/dictation_server/src/features/accounts/accounts.controller.ts index 70319e3..571f4ae 100644 --- a/dictation_server/src/features/accounts/accounts.controller.ts +++ b/dictation_server/src/features/accounts/accounts.controller.ts @@ -76,9 +76,9 @@ import { retrieveAuthorizationToken } from '../../common/http/helper'; import { AccessToken } from '../../common/token'; import jwt from 'jsonwebtoken'; import { makeContext } from '../../common/log'; -import { v4 as uuidv4 } from 'uuid'; import { AuthService } from '../auth/auth.service'; import { makeErrorResponse } from '../../common/error/makeErrorResponse'; +import { v4 as uuidv4 } from 'uuid'; @ApiTags('accounts') @Controller('accounts') @@ -167,7 +167,24 @@ export class AccountsController { @Req() req: Request, @Body() body: GetLicenseSummaryRequest, ): Promise { + const accessToken = retrieveAuthorizationToken(req); + if (!accessToken) { + throw new HttpException( + makeErrorResponse('E000107'), + HttpStatus.UNAUTHORIZED, + ); + } + const decodedAccessToken = jwt.decode(accessToken, { json: true }); + if (!decodedAccessToken) { + throw new HttpException( + makeErrorResponse('E000101'), + HttpStatus.UNAUTHORIZED, + ); + } + const { userId } = decodedAccessToken as AccessToken; + const context = makeContext(userId); const response = await this.accountService.getLicenseSummary( + context, body.accountId, ); return response; @@ -317,8 +334,9 @@ export class AccountsController { ); } const { userId } = decodedAccessToken as AccessToken; + const context = makeContext(userId); - const typists = await this.accountService.getTypists(userId); + const typists = await this.accountService.getTypists(context, userId); return { typists }; } @@ -363,8 +381,12 @@ export class AccountsController { ); } const { userId } = decodedAccessToken as AccessToken; + const context = makeContext(userId); - const typistGroups = await this.accountService.getTypistGroups(userId); + const typistGroups = await this.accountService.getTypistGroups( + context, + userId, + ); return { typistGroups }; } @@ -666,8 +688,31 @@ export class AccountsController { ): Promise { const { limit, offset, accountId } = body; + const accessToken = retrieveAuthorizationToken(req); + if (!accessToken) { + throw new HttpException( + makeErrorResponse('E000107'), + HttpStatus.UNAUTHORIZED, + ); + } + const decodedAccessToken = jwt.decode(accessToken, { json: true }); + if (!decodedAccessToken) { + throw new HttpException( + makeErrorResponse('E000101'), + HttpStatus.UNAUTHORIZED, + ); + } + const { userId } = decodedAccessToken as AccessToken; + + const context = makeContext(userId); + const getPartnerLicensesResponse = - await this.accountService.getPartnerLicenses(limit, offset, accountId); + await this.accountService.getPartnerLicenses( + context, + limit, + offset, + accountId, + ); return getPartnerLicensesResponse; } @@ -703,8 +748,31 @@ export class AccountsController { ): Promise { const { limit, offset, accountId } = body; + const accessToken = retrieveAuthorizationToken(req); + if (!accessToken) { + throw new HttpException( + makeErrorResponse('E000107'), + HttpStatus.UNAUTHORIZED, + ); + } + const decodedAccessToken = jwt.decode(accessToken, { json: true }); + if (!decodedAccessToken) { + throw new HttpException( + makeErrorResponse('E000101'), + HttpStatus.UNAUTHORIZED, + ); + } + const { userId } = decodedAccessToken as AccessToken; + + const context = makeContext(userId); + const getOrderHistoriesResponse = - await this.accountService.getOrderHistories(limit, offset, accountId); + await this.accountService.getOrderHistories( + context, + limit, + offset, + accountId, + ); return getOrderHistoriesResponse; } @@ -786,7 +854,8 @@ export class AccountsController { }) @ApiOperation({ operationId: 'getDealers' }) async getDealers(): Promise { - return await this.accountService.getDealers(); + const context = makeContext(uuidv4()); + return await this.accountService.getDealers(context); } @Post('/issue/cancel') @@ -1460,9 +1529,14 @@ export class AccountsController { async getAccountInfoMinimalAccess( @Body() body: GetAccountInfoMinimalAccessRequest, ): Promise { + const context = makeContext(uuidv4()); + // IDトークンの検証 - const idToken = await this.authService.getVerifiedIdToken(body.idToken); - const isVerified = await this.authService.isVerifiedUser(idToken); + const idToken = await this.authService.getVerifiedIdToken( + context, + body.idToken, + ); + const isVerified = await this.authService.isVerifiedUser(context, idToken); if (!isVerified) { throw new HttpException( makeErrorResponse('E010201'), @@ -1470,8 +1544,6 @@ export class AccountsController { ); } - const context = makeContext(idToken.sub); - const tier = await this.accountService.getAccountInfoMinimalAccess( context, idToken.sub, diff --git a/dictation_server/src/features/accounts/accounts.service.spec.ts b/dictation_server/src/features/accounts/accounts.service.spec.ts index abe01f2..b0c2b47 100644 --- a/dictation_server/src/features/accounts/accounts.service.spec.ts +++ b/dictation_server/src/features/accounts/accounts.service.spec.ts @@ -1587,7 +1587,8 @@ describe('AccountsService', () => { licensesRepositoryMockValue, worktypesRepositoryMockValue, ); - expect(await service.getLicenseSummary(accountId)).toEqual( + const context = makeContext(`uuidv4`); + expect(await service.getLicenseSummary(context, accountId)).toEqual( expectedAccountLisenceCounts, ); }); @@ -1619,7 +1620,8 @@ describe('AccountsService', () => { licensesRepositoryMockValue, worktypesRepositoryMockValue, ); - await expect(service.getLicenseSummary(accountId)).rejects.toEqual( + const context = makeContext(`uuidv4`); + await expect(service.getLicenseSummary(context, accountId)).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -1653,7 +1655,8 @@ describe('AccountsService', () => { licensesRepositoryMockValue, worktypesRepositoryMockValue, ); - expect(await service.getTypists(externalId)).toEqual([ + const context = makeContext(`uuidv4`); + expect(await service.getTypists(context, externalId)).toEqual([ { id: 1, name: 'Typist1' }, { id: 2, name: 'Typist2' }, { id: 3, name: 'Typist3' }, @@ -1686,7 +1689,8 @@ describe('AccountsService', () => { licensesRepositoryMockValue, worktypesRepositoryMockValue, ); - await expect(service.getTypists(externalId)).rejects.toEqual( + const context = makeContext(`uuidv4`); + await expect(service.getTypists(context, externalId)).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -1720,7 +1724,8 @@ describe('AccountsService', () => { licensesRepositoryMockValue, worktypesRepositoryMockValue, ); - await expect(service.getTypists(externalId)).rejects.toEqual( + const context = makeContext(`uuidv4`); + await expect(service.getTypists(context, externalId)).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -1755,7 +1760,8 @@ describe('AccountsService', () => { worktypesRepositoryMockValue, ); - expect(await service.getTypistGroups(externalId)).toEqual([ + const context = makeContext(`uuidv4`); + expect(await service.getTypistGroups(context, externalId)).toEqual([ { id: 1, name: 'GroupA' }, { id: 2, name: 'GroupB' }, ]); @@ -1788,7 +1794,8 @@ describe('AccountsService', () => { worktypesRepositoryMockValue, ); - await expect(service.getTypistGroups(externalId)).rejects.toEqual( + const context = makeContext(`uuidv4`); + await expect(service.getTypistGroups(context, externalId)).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -1823,7 +1830,8 @@ describe('AccountsService', () => { worktypesRepositoryMockValue, ); - await expect(service.getTypistGroups(externalId)).rejects.toEqual( + const context = makeContext(`uuidv4`); + await expect(service.getTypistGroups(context, externalId)).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -2005,7 +2013,13 @@ describe('getPartnerAccount', () => { const offset = 0; const limit = 20; - const response = await service.getPartnerLicenses(limit, offset, accountId); + const context = makeContext(`uuidv4`); + const response = await service.getPartnerLicenses( + context, + limit, + offset, + accountId, + ); expect(response.total).toBe(2); @@ -2146,7 +2160,13 @@ describe('getPartnerAccount', () => { const offset = 0; const limit = 20; - const response = await service.getPartnerLicenses(limit, offset, accountId); + const context = makeContext(`uuidv4`); + const response = await service.getPartnerLicenses( + context, + limit, + offset, + accountId, + ); // 有効期限間近(5件)+ 有効期限間近でない(3件)'Unallocated', 'Allocated', 'Reusable'+ 有効期限未設定(1件) → 9件 expect(response.childrenPartnerLicenses[0].stockLicense).toBe(9); @@ -2239,7 +2259,13 @@ describe('getOrderHistories', () => { const offset = 1; const limit = 2; - const response = await service.getOrderHistories(limit, offset, accountId); + const context = makeContext(`uuidv4`); + const response = await service.getOrderHistories( + context, + limit, + offset, + accountId, + ); expect(response.total).toBe(5); @@ -2278,8 +2304,9 @@ describe('getOrderHistories', () => { licensesRepositoryMockValue, worktypesRepositoryMockValue, ); + const context = makeContext(`uuidv4`); await expect( - service.getOrderHistories(limit, offset, accountId), + service.getOrderHistories(context, limit, offset, accountId), ).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), @@ -2640,8 +2667,9 @@ describe('getDealers', () => { }) ).account; const service = module.get(AccountsService); + const context = makeContext(`uuidv4`); - expect(await service.getDealers()).toEqual({ + expect(await service.getDealers(context)).toEqual({ dealers: [ { country: 'JP', @@ -2668,7 +2696,8 @@ describe('getDealers', () => { const service = module.get(AccountsService); - expect(await service.getDealers()).toEqual({ + const context = makeContext(`uuidv4`); + expect(await service.getDealers(context)).toEqual({ dealers: [], }); }); @@ -6019,7 +6048,8 @@ describe('getTypists', () => { ], }); - const typists = await service.getTypists(admin.external_id); + const context = makeContext(`uuidv4`); + const typists = await service.getTypists(context, admin.external_id); //実行結果を確認 { @@ -6046,7 +6076,8 @@ describe('getTypists', () => { overrideAdB2cService(service, { getUsers: async () => [{ id: admin.external_id, displayName: '' }], }); - const typists = await service.getTypists(admin.external_id); + const context = makeContext(`uuidv4`); + const typists = await service.getTypists(context, admin.external_id); //実行結果を確認 { @@ -6094,7 +6125,8 @@ describe('getTypists', () => { ], }); - const typists = await service.getTypists(admin.external_id); + const context = makeContext(`uuidv4`); + const typists = await service.getTypists(context, admin.external_id); //実行結果を確認 { @@ -6120,10 +6152,11 @@ describe('getTypists', () => { UsersRepositoryService, ); usersService.findTypistUsers = jest.fn().mockRejectedValue('DB failed'); + const context = makeContext(`uuidv4`); //実行結果を確認 try { - await service.getTypists(admin.external_id); + await service.getTypists(context, admin.external_id); fail(); } catch (e) { if (e instanceof HttpException) { diff --git a/dictation_server/src/features/accounts/accounts.service.ts b/dictation_server/src/features/accounts/accounts.service.ts index 985b764..0b59167 100644 --- a/dictation_server/src/features/accounts/accounts.service.ts +++ b/dictation_server/src/features/accounts/accounts.service.ts @@ -93,9 +93,14 @@ export class AccountsService { * @returns LicenseSummary */ async getLicenseSummary( + context: Context, accountId: number, ): Promise { - this.logger.log(`[IN] ${this.getLicenseSummary.name}`); + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.getLicenseSummary.name + } | params: { ` + `accountId: ${accountId}, };`, + ); try { const currentDate = new DateWithZeroTime(); @@ -139,8 +144,10 @@ export class AccountsService { }; return licenseSummaryResponse; } catch (e) { - this.logger.error(`error=${e}`); - this.logger.error('get licenseSummary failed'); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + this.logger.error( + `[${context.getTrackingId()}] get licenseSummary failed`, + ); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -167,8 +174,9 @@ export class AccountsService { acceptedDpaVersion: string, ): Promise<{ accountId: number; userId: number; externalUserId: string }> { this.logger.log( - `[IN] [${context.trackingId}] ${this.createAccount.name} | params: { ` + - `country: ${country}, ` + + `[IN] [${context.getTrackingId()}] ${ + this.createAccount.name + } | params: { ` + `dealerAccountId: ${dealerAccountId}, ` + `role: ${role}, ` + `acceptedEulaVersion: ${acceptedEulaVersion} }, ` + @@ -185,8 +193,10 @@ export class AccountsService { username, ); } catch (e) { - this.logger.error(`error=${e}`); - this.logger.error('create externalUser failed'); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + this.logger.error( + `[${context.getTrackingId()}] create externalUser failed`, + ); throw new HttpException( makeErrorResponse('E009999'), @@ -196,7 +206,9 @@ export class AccountsService { // メールアドレス重複エラー if (isConflictError(externalUser)) { - this.logger.error(`email conflict. externalUser: ${externalUser}`); + this.logger.error( + `[${context.getTrackingId()}] email conflict. externalUser: ${externalUser}`, + ); throw new HttpException( makeErrorResponse('E010301'), HttpStatus.BAD_REQUEST, @@ -221,11 +233,13 @@ export class AccountsService { account = newAccount; user = adminUser; this.logger.log( - `[${context.trackingId}] adminUser.external_id: ${user.external_id}`, + `[${context.getTrackingId()}] adminUser.external_id: ${ + user.external_id + }`, ); } catch (e) { - this.logger.error(`error=${e}`); - this.logger.error('create account failed'); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + this.logger.error(`[${context.getTrackingId()}] create account failed`); //リカバリ処理 // idpのユーザーを削除 await this.deleteAdB2cUser(externalUser.sub, context); @@ -244,8 +258,10 @@ export class AccountsService { country, ); } catch (e) { - this.logger.error(`error=${e}`); - this.logger.error('create container failed'); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + this.logger.error( + `[${context.getTrackingId()}] create container failed`, + ); //リカバリ処理 // idpのユーザーを削除 await this.deleteAdB2cUser(externalUser.sub, context); @@ -279,8 +295,8 @@ export class AccountsService { html, ); } catch (e) { - this.logger.error(`error=${e}`); - this.logger.error('send E-mail failed'); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + this.logger.error(`[${context.getTrackingId()}] send E-mail failed`); //リカバリ処理 // idpのユーザーを削除 await this.deleteAdB2cUser(externalUser.sub, context); @@ -306,7 +322,7 @@ export class AccountsService { throw e; } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.createAccount.name}`, + `[OUT] [${context.getTrackingId()}] ${this.createAccount.name}`, ); } } @@ -320,12 +336,13 @@ export class AccountsService { try { await this.adB2cService.deleteUser(externalUserId, context); this.logger.log( - `[${context.trackingId}] delete externalUser: ${externalUserId}`, + `[${context.getTrackingId()}] delete externalUser: ${externalUserId} | params: { ` + + `externalUserId: ${externalUserId}, };`, ); } catch (error) { - this.logger.error(`error=${error}`); + this.logger.error(`[${context.getTrackingId()}] error=${error}`); this.logger.error( - `${MANUAL_RECOVERY_REQUIRED} [${context.trackingId}] Failed to delete externalUser: ${externalUserId}`, + `${MANUAL_RECOVERY_REQUIRED} [${context.getTrackingId()}] Failed to delete externalUser: ${externalUserId}`, ); } } @@ -336,15 +353,20 @@ export class AccountsService { userId: number, context: Context, ): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.deleteAccount.name + } | params: { accountId: ${accountId}, userId: ${userId} };`, + ); try { await this.accountRepository.deleteAccount(accountId, userId); this.logger.log( - `[${context.trackingId}] delete account: ${accountId}, user: ${userId}`, + `[${context.getTrackingId()}] delete account: ${accountId}, user: ${userId}`, ); } catch (error) { - this.logger.error(`error=${error}`); + this.logger.error(`[${context.getTrackingId()}] error=${error}`); this.logger.error( - `${MANUAL_RECOVERY_REQUIRED} [${context.trackingId}] Failed to delete account: ${accountId}, user: ${userId}`, + `${MANUAL_RECOVERY_REQUIRED} [${context.getTrackingId()}] Failed to delete account: ${accountId}, user: ${userId}`, ); } } @@ -356,6 +378,11 @@ export class AccountsService { country: string, context: Context, ): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.deleteBlobContainer.name + } | params: { accountId: ${accountId} };`, + ); try { await this.blobStorageService.deleteContainer( context, @@ -363,11 +390,11 @@ export class AccountsService { country, ); this.logger.log( - `[${context.trackingId}] delete container: ${accountId}, country: ${country}`, + `[${context.getTrackingId()}] delete container: ${accountId}, country: ${country}`, ); } catch (error) { this.logger.error( - `${MANUAL_RECOVERY_REQUIRED} [${context.trackingId}] Failed to delete container: ${accountId}, country: ${country}`, + `${MANUAL_RECOVERY_REQUIRED} [${context.getTrackingId()}] Failed to delete container: ${accountId}, country: ${country}`, ); } } @@ -382,8 +409,9 @@ export class AccountsService { externalId: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.getAccountInfo.name} | params: { ` + - `name: ${externalId}, };`, + `[IN] [${context.getTrackingId()}] ${ + this.getAccountInfo.name + } | params: { ` + `externalId: ${externalId}, };`, ); try { let userInfo: User; @@ -415,7 +443,7 @@ export class AccountsService { }, }; } catch (e) { - this.logger.error(`[${context.trackingId}] error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); switch (e.constructor) { case UserNotFoundError: throw new HttpException( @@ -435,13 +463,20 @@ export class AccountsService { } } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.getAccountInfo.name}`, + `[OUT] [${context.getTrackingId()}] ${this.getAccountInfo.name}`, ); } } - async getTypistGroups(externalId: string): Promise { - this.logger.log(`[IN] ${this.getTypistGroups.name}`); + async getTypistGroups( + context: Context, + externalId: string, + ): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.getTypistGroups.name + } | params: { externalId: ${externalId} };`, + ); // TypistGroup取得 try { @@ -452,13 +487,15 @@ export class AccountsService { return userGroups.map((x) => ({ id: x.id, name: x.name })); } catch (e) { - this.logger.error(e); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] ${this.getTypistGroups.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getTypistGroups.name}`, + ); } } /** @@ -474,7 +511,9 @@ export class AccountsService { typistGroupId: number, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.getTypistGroup.name} | params: { externalId: ${externalId}, typistGroupId: ${typistGroupId} };`, + `[IN] [${context.getTrackingId()}] ${ + this.getTypistGroup.name + } | params: { externalId: ${externalId}, typistGroupId: ${typistGroupId} };`, ); try { @@ -497,7 +536,7 @@ export class AccountsService { typistIds: userGroupMembers.map((x) => x.user_id), }; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case TypistGroupNotExistError: @@ -518,7 +557,7 @@ export class AccountsService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.getTypistGroup.name}`, + `[OUT] [${context.getTrackingId()}] ${this.getTypistGroup.name}`, ); } } @@ -528,8 +567,12 @@ export class AccountsService { * @param externalId * @returns typists */ - async getTypists(externalId: string): Promise { - this.logger.log(`[IN] ${this.getTypists.name}`); + async getTypists(context: Context, externalId: string): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.getTypists.name + } | params: { externalId: ${externalId} };`, + ); // Typist取得 try { @@ -539,9 +582,9 @@ export class AccountsService { const externalIds = typistUsers.map((x) => x.external_id); // B2Cからユーザー名を取得する + const trackingId = new Context(context.trackingId); const adb2cUsers = await this.adB2cService.getUsers( - // TODO: 外部連携以外のログ強化時に、ContollerからContextを取得するように修正する - { trackingId: 'dummy' }, + trackingId, externalIds, ); @@ -560,13 +603,15 @@ export class AccountsService { return typists; } catch (e) { - this.logger.error(e); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] ${this.getTypists.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getTypists.name}`, + ); } } @@ -578,7 +623,9 @@ export class AccountsService { */ async getAuthors(context: Context, externalId: string): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.getAuthors.name} | params: { externalId: ${externalId} };`, + `[IN] [${context.getTrackingId()}] ${ + this.getAuthors.name + } | params: { externalId: ${externalId} };`, ); try { @@ -609,7 +656,7 @@ export class AccountsService { }); return authors; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case AccountNotFoundError: @@ -629,7 +676,9 @@ export class AccountsService { HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.getAuthors.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getAuthors.name}`, + ); } } @@ -652,7 +701,9 @@ export class AccountsService { creatorAccountTier: number, ): Promise<{ accountId: number }> { this.logger.log( - `[IN] [${context.trackingId}] ${this.createPartnerAccount.name} | params: { creatorUserId: ${creatorUserId}, creatorAccountTier: ${creatorAccountTier} };`, + `[IN] [${context.getTrackingId()}] ${ + this.createPartnerAccount.name + } | params: { creatorUserId: ${creatorUserId}, creatorAccountTier: ${creatorAccountTier} };`, ); try { @@ -664,7 +715,7 @@ export class AccountsService { await this.usersRepository.findUserByExternalId(creatorUserId) ).account_id; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof UserNotFoundError) { throw new HttpException( makeErrorResponse('E010204'), @@ -691,7 +742,7 @@ export class AccountsService { adminName, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -723,8 +774,10 @@ export class AccountsService { account = newAccount; user = adminUser; } catch (e) { - this.logger.error(`error=${e}`); - this.logger.error('create partner account failed'); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + this.logger.error( + `[${context.getTrackingId()}] create partner account failed`, + ); //リカバリ処理 // idpのユーザーを削除 await this.deleteAdB2cUser(externalUser.sub, context); @@ -743,8 +796,10 @@ export class AccountsService { country, ); } catch (e) { - this.logger.error(`error=${e}`); - this.logger.error('create partner container failed'); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + this.logger.error( + `[${context.getTrackingId()}] create partner container failed`, + ); //リカバリ処理 // idpのユーザーを削除 await this.deleteAdB2cUser(externalUser.sub, context); @@ -761,6 +816,7 @@ export class AccountsService { try { const { subject, text, html } = await this.sendgridService.createMailContentFromEmailConfirmForNormalUser( + context, account.id, user.id, email, @@ -775,8 +831,10 @@ export class AccountsService { ); return { accountId: account.id }; } catch (e) { - this.logger.error(`error=${e}`); - this.logger.error('create partner account send mail failed'); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + this.logger.error( + `[${context.getTrackingId()}] create partner account send mail failed`, + ); //リカバリ処理 // idpのユーザーを削除 await this.deleteAdB2cUser(externalUser.sub, context); @@ -796,7 +854,7 @@ export class AccountsService { throw e; } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.createPartnerAccount.name}`, + `[OUT] [${context.getTrackingId()}] ${this.createPartnerAccount.name}`, ); } } @@ -809,11 +867,16 @@ export class AccountsService { * @returns getPartnerLicensesResponse */ async getPartnerLicenses( + context: Context, limit: number, offset: number, accountId: number, ): Promise { - this.logger.log(`[IN] ${this.getPartnerLicenses.name}`); + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.getPartnerLicenses.name + } | params: { limit: ${limit}, offset: ${offset}, accountId: ${accountId} };`, + ); try { const currentDate = new DateWithZeroTime(); @@ -891,13 +954,15 @@ export class AccountsService { return getPartnerLicensesResponse; } catch (e) { - this.logger.error(e); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] ${this.getPartnerLicenses.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getPartnerLicenses.name}`, + ); } } /** @@ -908,11 +973,16 @@ export class AccountsService { * @returns getOrderHistoriesResponse */ async getOrderHistories( + context: Context, limit: number, offset: number, accountId: number, ): Promise { - this.logger.log(`[IN] ${this.getOrderHistories.name}`); + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.getOrderHistories.name + } | params: { limit: ${limit}, offset: ${offset}, accountId: ${accountId} };`, + ); try { const licenseHistoryInfo = @@ -949,13 +1019,15 @@ export class AccountsService { }; return getOrderHistoriesResponse; } catch (e) { - this.logger.error(e); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] ${this.getOrderHistories.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getOrderHistories.name}`, + ); } } @@ -975,7 +1047,9 @@ export class AccountsService { poNumber: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.issueLicense.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.issueLicense.name + } | params: { ` + `orderedAccountId: ${orderedAccountId}, ` + `userId: ${userId}, ` + `tier: ${tier}, ` + @@ -993,7 +1067,7 @@ export class AccountsService { poNumber, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case OrderNotFoundError: @@ -1020,14 +1094,16 @@ export class AccountsService { } } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.issueLicense.name}`, + `[OUT] [${context.getTrackingId()}] ${this.issueLicense.name}`, ); } } // dealersのアカウント情報を取得する - async getDealers(): Promise { - this.logger.log(`[IN] ${this.getDealers.name}`); + async getDealers(context: Context): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.getDealers.name}`, + ); try { const dealerAccounts = await this.accountRepository.findDealerAccounts(); @@ -1044,13 +1120,15 @@ export class AccountsService { return dealers; } catch (e) { - this.logger.error(e); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] ${this.getDealers.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getDealers.name}`, + ); } } /** @@ -1068,7 +1146,9 @@ export class AccountsService { typistIds: number[], ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.createTypistGroup.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.createTypistGroup.name + } | params: { ` + `externalId: ${externalId}, ` + `typistGroupName: ${typistGroupName}, ` + `typistIds: ${typistIds} };`, @@ -1085,7 +1165,7 @@ export class AccountsService { account_id, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case TypistIdInvalidError: @@ -1124,7 +1204,13 @@ export class AccountsService { typistIds: number[], ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.updateTypistGroup.name} | params: { typistGroupId: ${typistGroupId}, typistGroupName: ${typistGroupName}, typistIds: ${typistIds} };`, + `[IN] [${context.getTrackingId()}] ${ + this.updateTypistGroup.name + } | params: { ` + + `externalId: ${externalId}, ` + + `typistGroupId: ${typistGroupId}, ` + + `typistGroupName: ${typistGroupName}, ` + + `typistIds: ${typistIds} };`, ); try { // 外部IDをもとにユーザー情報を取得する @@ -1140,7 +1226,7 @@ export class AccountsService { typistIds, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { // タイピストIDが存在しない場合は400エラーを返す @@ -1168,7 +1254,7 @@ export class AccountsService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.updateTypistGroup.name}`, + `[OUT] [${context.getTrackingId()}] ${this.updateTypistGroup.name}`, ); } } @@ -1187,7 +1273,9 @@ export class AccountsService { orderedAccountId: number, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.cancelIssue.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.cancelIssue.name + } | params: { ` + `extarnalId: ${extarnalId}, ` + `poNumber: ${poNumber}, ` + `orderedAccountId: ${orderedAccountId}, };`, @@ -1200,7 +1288,7 @@ export class AccountsService { await this.usersRepository.findUserByExternalId(extarnalId) ).account_id; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); switch (e.constructor) { default: throw new HttpException( @@ -1209,7 +1297,9 @@ export class AccountsService { ); } } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.cancelIssue.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.cancelIssue.name}`, + ); } // 注文元アカウントIDの親世代を取得 @@ -1218,7 +1308,9 @@ export class AccountsService { ); // 自身が存在しない場合、エラー if (!parentAccountIds.includes(myAccountId)) { - this.logger.log(`[OUT] [${context.trackingId}] ${this.cancelIssue.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.cancelIssue.name}`, + ); throw new HttpException( makeErrorResponse('E000108'), HttpStatus.UNAUTHORIZED, @@ -1229,7 +1321,7 @@ export class AccountsService { // 発行キャンセル処理 await this.accountRepository.cancelIssue(orderedAccountId, poNumber); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); switch (e.constructor) { case AlreadyLicenseStatusChangedError: throw new HttpException( @@ -1253,7 +1345,9 @@ export class AccountsService { ); } } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.cancelIssue.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.cancelIssue.name}`, + ); } } @@ -1267,7 +1361,11 @@ export class AccountsService { context: Context, externalId: string, ): Promise { - this.logger.log(`[IN] [${context.trackingId}] ${this.getWorktypes.name}`); + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.getWorktypes.name + } | params: { externalId: ${externalId} };`, + ); try { // 外部IDをもとにユーザー情報を取得する const { account_id: accountId } = @@ -1286,7 +1384,7 @@ export class AccountsService { active: active_worktype_id, }; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case AccountNotFoundError: @@ -1307,7 +1405,7 @@ export class AccountsService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.getWorktypes.name}`, + `[OUT] [${context.getTrackingId()}] ${this.getWorktypes.name}`, ); } } @@ -1325,7 +1423,11 @@ export class AccountsService { worktypeId: string, description?: string, ): Promise { - this.logger.log(`[IN] [${context.trackingId}] ${this.createWorktype.name}`); + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.createWorktype.name + } | params: { externalId: ${externalId}, worktypeId: ${worktypeId}, description: ${description} };`, + ); try { // 外部IDをもとにユーザー情報を取得する @@ -1338,7 +1440,7 @@ export class AccountsService { description, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { // WorktypeIDが既に存在する場合は400エラーを返す @@ -1366,7 +1468,7 @@ export class AccountsService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.createWorktype.name}`, + `[OUT] [${context.getTrackingId()}] ${this.createWorktype.name}`, ); } } @@ -1388,7 +1490,9 @@ export class AccountsService { description?: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.updateWorktype.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.updateWorktype.name + } | params: { ` + `externalId: ${externalId}, ` + `id: ${id}, ` + `worktypeId: ${worktypeId}, ` + @@ -1408,7 +1512,7 @@ export class AccountsService { description, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { // ユーザーが設定したWorktypeIDが既存WorktypeのWorktypeIDと重複する場合は400エラーを返す @@ -1436,7 +1540,7 @@ export class AccountsService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.updateWorktype.name}`, + `[OUT] [${context.getTrackingId()}] ${this.updateWorktype.name}`, ); } } @@ -1454,7 +1558,9 @@ export class AccountsService { id: number, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.deleteWorktype.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.deleteWorktype.name + } | params: { ` + `externalId: ${externalId}, ` + `id: ${id} };`, ); @@ -1473,7 +1579,7 @@ export class AccountsService { // ワークタイプを削除する await this.worktypesRepository.deleteWorktype(accountId, id); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case UserNotFoundError: @@ -1511,7 +1617,7 @@ export class AccountsService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.deleteWorktype.name}`, + `[OUT] [${context.getTrackingId()}] ${this.deleteWorktype.name}`, ); } } @@ -1529,7 +1635,9 @@ export class AccountsService { id: number, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.getOptionItems.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.getOptionItems.name + } | params: { ` + `externalId: ${externalId}, ` + `id: ${id} };`, ); @@ -1553,7 +1661,7 @@ export class AccountsService { })), }; } catch (e) { - this.logger.error(e); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { // 内部IDで指定されたWorktypeが存在しない場合は400エラーを返す @@ -1575,7 +1683,7 @@ export class AccountsService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.getOptionItems.name}`, + `[OUT] [${context.getTrackingId()}] ${this.getOptionItems.name}`, ); } } @@ -1595,7 +1703,9 @@ export class AccountsService { optionItems: PostWorktypeOptionItem[], ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.updateOptionItems.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.updateOptionItems.name + } | params: { ` + `externalId: ${externalId}, ` + `id: ${id}, ` + `optionItems: ${JSON.stringify(optionItems)} };`, @@ -1620,7 +1730,7 @@ export class AccountsService { })), ); } catch (e) { - this.logger.error(e); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { // 内部IDで指定されたWorktypeが存在しない場合は400エラーを返す @@ -1642,7 +1752,7 @@ export class AccountsService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.updateOptionItems.name}`, + `[OUT] [${context.getTrackingId()}] ${this.updateOptionItems.name}`, ); } } @@ -1660,7 +1770,9 @@ export class AccountsService { id: number | undefined, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.updateActiveWorktype.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.updateActiveWorktype.name + } | params: { ` + `externalId: ${externalId}, ` + `id: ${id} };`, ); @@ -1672,7 +1784,7 @@ export class AccountsService { // ActiveWorktypeを更新する await this.accountRepository.updateActiveWorktypeId(accountId, id); } catch (e) { - this.logger.error(e); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { // 内部IDで指定されたWorktypeが存在しない場合は400エラーを返す @@ -1694,7 +1806,7 @@ export class AccountsService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.updateActiveWorktype.name}`, + `[OUT] [${context.getTrackingId()}] ${this.updateActiveWorktype.name}`, ); } } @@ -1714,7 +1826,9 @@ export class AccountsService { offset: number, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.getPartners.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.getPartners.name + } | params: { ` + `externalId: ${externalId}, ` + `limit: ${limit}, ` + `offset: ${offset}, };`, @@ -1774,13 +1888,15 @@ export class AccountsService { partners: partners, }; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.getPartners.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getPartners.name}`, + ); } } @@ -1805,8 +1921,11 @@ export class AccountsService { secondryAdminUserId?: number, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.updateAccountInfo.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.updateAccountInfo.name + } | params: { ` + `externalId: ${externalId}, ` + + `tier: ${tier}, ` + `delegationPermission: ${delegationPermission}, ` + `primaryAdminUserId: ${primaryAdminUserId}, ` + `parentAccountId: ${parentAccountId}, ` + @@ -1825,7 +1944,7 @@ export class AccountsService { secondryAdminUserId, ); } catch (e) { - this.logger.error(`[${context.trackingId}] error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case DealerAccountNotFoundError: @@ -1847,7 +1966,7 @@ export class AccountsService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.updateAccountInfo.name}`, + `[OUT] [${context.getTrackingId()}] ${this.updateAccountInfo.name}`, ); } } @@ -1864,7 +1983,9 @@ export class AccountsService { accountId: number, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.deleteAccountAndData.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.deleteAccountAndData.name + } | params: { ` + `externalId: ${externalId}, ` + `accountId: ${accountId}, };`, ); @@ -1889,13 +2010,15 @@ export class AccountsService { dbUsers = await this.accountRepository.deleteAccountAndInsertArchives( accountId, ); - this.logger.log(`[${context.trackingId}] delete account: ${accountId}`); + this.logger.log( + `[${context.getTrackingId()}] delete account: ${accountId}`, + ); country = targetAccount.country; } catch (e) { // アカウントの削除に失敗した場合はエラーを返す - this.logger.log(`[${context.trackingId}] ${e}`); + this.logger.log(`[${context.getTrackingId()}] ${e}`); this.logger.log( - `[OUT] [${context.trackingId}] ${this.deleteAccountAndData.name}`, + `[OUT] [${context.getTrackingId()}] ${this.deleteAccountAndData.name}`, ); throw new HttpException( makeErrorResponse('E009999'), @@ -1910,19 +2033,15 @@ export class AccountsService { context, ); this.logger.log( - `[${ - context.trackingId - }] delete ADB2C users: ${accountId}, users_id: ${dbUsers.map( + `[${context.getTrackingId()}] delete ADB2C users: ${accountId}, users_id: ${dbUsers.map( (x) => x.external_id, )}`, ); } catch (e) { // ADB2Cユーザーの削除失敗時は、MANUAL_RECOVERY_REQUIREDを出して処理続行 - this.logger.log(`[${context.trackingId}] ${e}`); + this.logger.log(`[${context.getTrackingId()}] ${e}`); this.logger.log( - `${MANUAL_RECOVERY_REQUIRED} [${ - context.trackingId - }] Failed to delete ADB2C users: ${accountId}, users_id: ${dbUsers.map( + `${MANUAL_RECOVERY_REQUIRED} [${context.getTrackingId()}] Failed to delete ADB2C users: ${accountId}, users_id: ${dbUsers.map( (x) => x.external_id, )}`, ); @@ -1932,18 +2051,18 @@ export class AccountsService { // blobstorageコンテナを削除する await this.deleteBlobContainer(accountId, country, context); this.logger.log( - `[${context.trackingId}] delete blob container: ${accountId}-${country}`, + `[${context.getTrackingId()}] delete blob container: ${accountId}-${country}`, ); } catch (e) { // blobstorageコンテナを削除で失敗した場合は、MANUAL_RECOVERY_REQUIRED出して正常終了 - this.logger.log(`[${context.trackingId}] ${e}`); + this.logger.log(`[${context.getTrackingId()}] ${e}`); this.logger.log( - `${MANUAL_RECOVERY_REQUIRED}[${context.trackingId}] Failed to delete blob container: ${accountId}, country: ${country}`, + `${MANUAL_RECOVERY_REQUIRED}[${context.getTrackingId()}] Failed to delete blob container: ${accountId}, country: ${country}`, ); } this.logger.log( - `[OUT] [${context.trackingId}] ${this.deleteAccountAndData.name}`, + `[OUT] [${context.getTrackingId()}] ${this.deleteAccountAndData.name}`, ); } @@ -1958,7 +2077,9 @@ export class AccountsService { externalId: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.getAccountInfoMinimalAccess.name} | params: { externalId: ${externalId} };`, + `[IN] [${context.getTrackingId()}] ${ + this.getAccountInfoMinimalAccess.name + } | params: { externalId: ${externalId} };`, ); try { @@ -1973,7 +2094,7 @@ export class AccountsService { return account.tier; } catch (e) { - this.logger.error(`[${context.trackingId}] error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case UserNotFoundError: @@ -1999,7 +2120,9 @@ export class AccountsService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.getAccountInfoMinimalAccess.name}`, + `[OUT] [${context.getTrackingId()}] ${ + this.getAccountInfoMinimalAccess.name + }`, ); } } diff --git a/dictation_server/src/features/auth/auth.controller.ts b/dictation_server/src/features/auth/auth.controller.ts index d756f8d..dbec612 100644 --- a/dictation_server/src/features/auth/auth.controller.ts +++ b/dictation_server/src/features/auth/auth.controller.ts @@ -66,9 +66,13 @@ export class AuthController { operationId: 'token', }) async token(@Body() body: TokenRequest): Promise { - const idToken = await this.authService.getVerifiedIdToken(body.idToken); + const context = makeContext(uuidv4()); + const idToken = await this.authService.getVerifiedIdToken( + context, + body.idToken, + ); - const isVerified = await this.authService.isVerifiedUser(idToken); + const isVerified = await this.authService.isVerifiedUser(context, idToken); if (!isVerified) { throw new HttpException( makeErrorResponse('E010201'), @@ -76,10 +80,8 @@ export class AuthController { ); } - const context = makeContext(idToken.sub); - const key = makeIDTokenKey(body.idToken); - const isTokenExists = await this.redisService.get(key); + const isTokenExists = await this.redisService.get(context, key); if (isTokenExists) { // IDトークンがキャッシュに存在する場合エラー throw new HttpException( @@ -101,7 +103,7 @@ export class AuthController { } // IDトークンをキャッシュに保存(idTokenの有効期限をADB2Cの有効期限と合わせる(300秒)) - await this.redisService.set(key, true, 300); + await this.redisService.set(context, key, true, 300); const refreshToken = await this.authService.generateRefreshToken( context, diff --git a/dictation_server/src/features/auth/auth.service.spec.ts b/dictation_server/src/features/auth/auth.service.spec.ts index 1be5e40..4451cb0 100644 --- a/dictation_server/src/features/auth/auth.service.spec.ts +++ b/dictation_server/src/features/auth/auth.service.spec.ts @@ -31,7 +31,10 @@ describe('AuthService', () => { const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtpZCJ9.eyJleHAiOjkwMDAwMDAwMDAsIm5iZiI6MTAwMDAwMDAwMCwidmVyIjoiMS4wIiwiaXNzIjoiaXNzdWVyIiwic3ViIjoic3ViIiwiYXVkIjoiYXVkIiwibm9uY2UiOiJkZWZhdWx0Tm9uY2UiLCJpYXQiOjEwMDAwMDAwMDAsImF1dGhfdGltZSI6MTAwMDAwMDAwMCwiZW1haWxzIjpbInh4eEB4eC5jb20iXSwidGZwIjoic2lnbmluX3VzZXJmbG93In0.RyieW-VHsHPQOjXbbhRc307AYJOc1sq2hrcu4SW1-K0pvLlkplepxvx02a3vCwQrnBYrIP5w6HExG-S_JgW5nYyWr6DeY11mA484n9KA8GeAcAXV37StH1gfWUJvfGb4C8BaMbMM9Ix4Z9NGwKA9vjNwevfmBZnz9lQUePgv6BJNmyvCt8ElJ01O-1WODbZuojJ4xXymA1OqluzfbphPOsqWTSNmTn0emkLjjnlMQf1iwM4C_kvvr8dUCFg0_UGDfQVJnzPEKB38UqnhLnC5WacrddDwQ0kBuGKZgZ_63Q_7fOvqAZivqLK7BPmbPxi6mx3R1S9Eq2ugzpY1LfJOjA'; - expect(await service.getVerifiedIdToken(token)).toEqual(idTokenPayload); + const context = makeContext(`uuidv4`); + expect(await service.getVerifiedIdToken(context, token)).toEqual( + idTokenPayload, + ); }); it('IDトークンの形式が不正な場合、形式不正エラーとなる。', async () => { @@ -40,7 +43,8 @@ describe('AuthService', () => { const service = await makeAuthServiceMock(adb2cParam, configMockValue); const token = 'invalid.id.token'; - await expect(service.getVerifiedIdToken(token)).rejects.toEqual( + const context = makeContext(`uuidv4`); + await expect(service.getVerifiedIdToken(context, token)).rejects.toEqual( new HttpException(makeErrorResponse('E000101'), HttpStatus.UNAUTHORIZED), ); }); @@ -54,7 +58,8 @@ describe('AuthService', () => { const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtpZCJ9.eyJleHAiOjEwMDAwMDAwMDAsIm5iZiI6MTAwMDAwMDAwMCwidmVyIjoiMS4wIiwiaXNzIjoiaXNzdWVyIiwic3ViIjoic3ViIiwiYXVkIjoiYXVkIiwibm9uY2UiOiJkZWZhdWx0Tm9uY2UiLCJpYXQiOjEwMDAwMDAwMDAsImF1dGhfdGltZSI6MTAwMDAwMDAwMCwiZW1haWxzIjpbInh4eEB4eC5jb20iXSwidGZwIjoic2lnbmluX3VzZXJmbG93In0.r9x61Mf1S2qFgU_QDKB6tRFBmTQXyOEtpoacOlL_bQzFz1t3GsxMy6SJIvQQ-LtDgylQ1UCdMFiRuy4V8nyLuME0fR-9IkKsboGvwllHB_Isai3XFoja0jpDHMVby1m0B3Z9xOTb7YsaQGyEH-qs1TtnRm6Ny98h4Po80nK8HGefQZHBOlfQN_B1LiHwI3nLXV18NL-4olKXj2NloNRYtnWM0PaqDQcGvZFaSNvtrSYpo9ddD906QWDGVOQ7WvGSUgdNCoxX8Lb3r2-VSj6n84jpb-Y1Fz-GhLluNglAsBhasnJfUIvCIO3iG5pRyTYjHFAVHmzjr8xMOmhS3s41Jw'; - await expect(service.getVerifiedIdToken(token)).rejects.toEqual( + const context = makeContext(`uuidv4`); + await expect(service.getVerifiedIdToken(context, token)).rejects.toEqual( new HttpException(makeErrorResponse('E000102'), HttpStatus.UNAUTHORIZED), ); }); @@ -68,7 +73,8 @@ describe('AuthService', () => { const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtpZCJ9.eyJleHAiOjkwMDAwMDAwMDAsIm5iZiI6OTAwMDAwMDAwMCwidmVyIjoiMS4wIiwiaXNzIjoiaXNzdWVyIiwic3ViIjoic3ViIiwiYXVkIjoiYXVkIiwibm9uY2UiOiJkZWZhdWx0Tm9uY2UiLCJpYXQiOjEwMDAwMDAwMDAsImF1dGhfdGltZSI6MTAwMDAwMDAwMCwiZW1haWxzIjpbInh4eEB4eC5jb20iXSwidGZwIjoic2lnbmluX3VzZXJmbG93In0.fX2Gbd7fDPNE3Lw-xbum_5CVqQYqEmMhv_v5u8A-U81pmPD2P5rsJEJx66ns1taFLVaE3j9_OzotxrqjqqQqbACkagGcN5wvA3_ZIxyqmhrKYFJc53ZcO7d0pFWiQlluNBI_pnFNDlSMB2Ut8Th5aiPy2uamBM9wC99bcjo7HkHvTKBf6ljU6rPKoD51qGDWqNxjoH-hdSJ29wprvyxyk_yX6dp-cxXUj5DIgXYQuIZF71rdiPtGlAiyTBns8rS2QlEEXapZVlvYrK4mkpUXVDA7ifD8q6gAC2BStqHeys7CGp2MbV4ZwKCVbAUbMs6Tboh8rADZvQhuTEq7qlhZ-w'; - await expect(service.getVerifiedIdToken(token)).rejects.toEqual( + const context = makeContext(`uuidv4`); + await expect(service.getVerifiedIdToken(context, token)).rejects.toEqual( new HttpException(makeErrorResponse('E000103'), HttpStatus.UNAUTHORIZED), ); }); @@ -80,7 +86,8 @@ describe('AuthService', () => { const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtpZCJ9.eyJleHAiOjkwMDAwMDAwMDAsIm5iZiI6MTAwMDAwMDAwMCwidmVyIjoiMS4wIiwiaXNzIjoiaXNzdXNlciIsInN1YiI6InN1YiIsImF1ZCI6ImF1ZCIsIm5vbmNlIjoiZGVmYXVsdE5vbmNlIiwiaWF0IjoxMDAwMDAwMDAwLCJhdXRoX3RpbWUiOjEwMDAwMDAwMDAsImVtYWlscyI6WyJ4eHhAeHguY29tIl0sInRmcCI6InNpZ25pbl91c2VyZmxvdyJ9.sign'; - await expect(service.getVerifiedIdToken(token)).rejects.toEqual( + const context = makeContext(`uuidv4`); + await expect(service.getVerifiedIdToken(context, token)).rejects.toEqual( new HttpException(makeErrorResponse('E000104'), HttpStatus.UNAUTHORIZED), ); }); @@ -94,7 +101,8 @@ describe('AuthService', () => { const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtpZCJ9.eyJleHAiOjkwMDAwMDAwMDAsIm5iZiI6MTAwMDAwMDAwMCwidmVyIjoiMS4wIiwiaXNzIjoiaW52bGlkX2lzc3VlciIsInN1YiI6InN1YiIsImF1ZCI6ImF1ZCIsIm5vbmNlIjoiZGVmYXVsdE5vbmNlIiwiaWF0IjoxMDAwMDAwMDAwLCJhdXRoX3RpbWUiOjEwMDAwMDAwMDAsImVtYWlscyI6WyJ4eHhAeHguY29tIl0sInRmcCI6InNpZ25pbl91c2VyZmxvdyJ9.0bp3e1mDG78PX3lo8zgOLXGenIqG_Vi6kw7CbwauAQM-cnUZ_aVCoJ_dAv_QmPElOQKcCkRrAvAZ91FwuHDlBGuuDqx8OwqN0VaD-4NPouoAswj-9HNvBm8gUn-pGaXkvWt_72UdCJavZJjDj_RHur8y8kFt5Qeab3mUP2x-uNcV2Q2x3M_IIfcRiIZkRZm_azKfiVIy7tzoUFLDss97y938aR8imMVxazoSQvj7RWIWylgeRr9yVt7qYl18cnEVL0IGtslFbqhfNsiEmRCMsttm5kXs7E9B0bhhUe_xbJW9VumQ6G7dgMrswevp_jRgbpWJoZsgErtqIRl9Tc9ikA'; - await expect(service.getVerifiedIdToken(token)).rejects.toEqual( + const context = makeContext(`uuidv4`); + await expect(service.getVerifiedIdToken(context, token)).rejects.toEqual( new HttpException(makeErrorResponse('E000105'), HttpStatus.UNAUTHORIZED), ); }); @@ -107,7 +115,8 @@ describe('AuthService', () => { const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtpZCJ9.eyJleHAiOjkwMDAwMDAwMDAsIm5iZiI6MTAwMDAwMDAwMCwidmVyIjoiMS4wIiwiaXNzIjoiaXNzdWVyIiwic3ViIjoic3ViIiwiYXVkIjoiYXVkIiwibm9uY2UiOiJkZWZhdWx0Tm9uY2UiLCJpYXQiOjEwMDAwMDAwMDAsImF1dGhfdGltZSI6MTAwMDAwMDAwMCwiZW1haWxzIjpbInh4eEB4eC5jb20iXSwidGZwIjoic2lnbmluX3VzZXJmbG93In0.RyieW-VHsHPQOjXbbhRc307AYJOc1sq2hrcu4SW1-K0pvLlkplepxvx02a3vCwQrnBYrIP5w6HExG-S_JgW5nYyWr6DeY11mA484n9KA8GeAcAXV37StH1gfWUJvfGb4C8BaMbMM9Ix4Z9NGwKA9vjNwevfmBZnz9lQUePgv6BJNmyvCt8ElJ01O-1WODbZuojJ4xXymA1OqluzfbphPOsqWTSNmTn0emkLjjnlMQf1iwM4C_kvvr8dUCFg0_UGDfQVJnzPEKB38UqnhLnC5WacrddDwQ0kBuGKZgZ_63Q_7fOvqAZivqLK7BPmbPxi6mx3R1S9Eq2ugzpY1LfJOjA'; - await expect(service.getVerifiedIdToken(token)).rejects.toEqual( + const context = makeContext(`uuidv4`); + await expect(service.getVerifiedIdToken(context, token)).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -122,7 +131,8 @@ describe('AuthService', () => { const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtpZCJ9.eyJleHAiOjkwMDAwMDAwMDAsIm5iZiI6MTAwMDAwMDAwMCwidmVyIjoiMS4wIiwiaXNzIjoiaXNzdWVyIiwic3ViIjoic3ViIiwiYXVkIjoiYXVkIiwibm9uY2UiOiJkZWZhdWx0Tm9uY2UiLCJpYXQiOjEwMDAwMDAwMDAsImF1dGhfdGltZSI6MTAwMDAwMDAwMCwiZW1haWxzIjpbInh4eEB4eC5jb20iXSwidGZwIjoic2lnbmluX3VzZXJmbG93In0.RyieW-VHsHPQOjXbbhRc307AYJOc1sq2hrcu4SW1-K0pvLlkplepxvx02a3vCwQrnBYrIP5w6HExG-S_JgW5nYyWr6DeY11mA484n9KA8GeAcAXV37StH1gfWUJvfGb4C8BaMbMM9Ix4Z9NGwKA9vjNwevfmBZnz9lQUePgv6BJNmyvCt8ElJ01O-1WODbZuojJ4xXymA1OqluzfbphPOsqWTSNmTn0emkLjjnlMQf1iwM4C_kvvr8dUCFg0_UGDfQVJnzPEKB38UqnhLnC5WacrddDwQ0kBuGKZgZ_63Q_7fOvqAZivqLK7BPmbPxi6mx3R1S9Eq2ugzpY1LfJOjA'; - await expect(service.getVerifiedIdToken(token)).rejects.toEqual( + const context = makeContext(`uuidv4`); + await expect(service.getVerifiedIdToken(context, token)).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -140,7 +150,8 @@ describe('AuthService', () => { const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtpZCJ9.eyJleHAiOjkwMDAwMDAwMDAsIm5iZiI6MTAwMDAwMDAwMCwidmVyIjoiMS4wIiwiaXNzIjoiaXNzdWVyIiwic3ViIjoic3ViIiwiYXVkIjoiYXVkIiwibm9uY2UiOiJkZWZhdWx0Tm9uY2UiLCJpYXQiOjEwMDAwMDAwMDAsImF1dGhfdGltZSI6MTAwMDAwMDAwMCwiZW1haWxzIjpbInh4eEB4eC5jb20iXSwidGZwIjoic2lnbmluX3VzZXJmbG93In0.RyieW-VHsHPQOjXbbhRc307AYJOc1sq2hrcu4SW1-K0pvLlkplepxvx02a3vCwQrnBYrIP5w6HExG-S_JgW5nYyWr6DeY11mA484n9KA8GeAcAXV37StH1gfWUJvfGb4C8BaMbMM9Ix4Z9NGwKA9vjNwevfmBZnz9lQUePgv6BJNmyvCt8ElJ01O-1WODbZuojJ4xXymA1OqluzfbphPOsqWTSNmTn0emkLjjnlMQf1iwM4C_kvvr8dUCFg0_UGDfQVJnzPEKB38UqnhLnC5WacrddDwQ0kBuGKZgZ_63Q_7fOvqAZivqLK7BPmbPxi6mx3R1S9Eq2ugzpY1LfJOjA'; - await expect(service.getVerifiedIdToken(token)).rejects.toEqual( + const context = makeContext(`uuidv4`); + await expect(service.getVerifiedIdToken(context, token)).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, diff --git a/dictation_server/src/features/auth/auth.service.ts b/dictation_server/src/features/auth/auth.service.ts index 23ba89b..06404c7 100644 --- a/dictation_server/src/features/auth/auth.service.ts +++ b/dictation_server/src/features/auth/auth.service.ts @@ -55,21 +55,25 @@ export class AuthService { * @param idToken AzureAD B2Cにより発行されたIDトークン * @returns verified user */ - async isVerifiedUser(idToken: IDToken): Promise { - this.logger.log(`[IN] ${this.isVerifiedUser.name}`); + async isVerifiedUser(context: Context, idToken: IDToken): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.isVerifiedUser.name}`, + ); try { // IDトークンのユーザーがDBに登録されていてメール認証が完了しているユーザーか検証 const user = await this.usersRepository.findVerifiedUser(idToken.sub); return user !== undefined; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] ${this.isVerifiedUser.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.isVerifiedUser.name}`, + ); } } @@ -85,7 +89,9 @@ export class AuthService { type: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.generateRefreshToken.name}`, + `[IN] [${context.getTrackingId()}] ${ + this.generateRefreshToken.name + } | params: { type: ${type} };`, ); // ユーザー情報とユーザーが属しているアカウント情報を取得 @@ -133,7 +139,7 @@ export class AuthService { return token; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case TierUnexpectedError: @@ -156,7 +162,7 @@ export class AuthService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.generateRefreshToken.name}`, + `[OUT] [${context.getTrackingId()}] ${this.generateRefreshToken.name}`, ); } } @@ -171,7 +177,7 @@ export class AuthService { refreshToken: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.generateAccessToken.name}`, + `[IN] [${context.getTrackingId()}] ${this.generateAccessToken.name}`, ); const privateKey = getPrivateKey(this.configService); @@ -179,9 +185,11 @@ export class AuthService { const token = verify(refreshToken, pubkey); if (isVerifyError(token)) { - this.logger.error(`${token.reason} | ${token.message}`); + this.logger.error( + `[${context.getTrackingId()}] ${token.reason} | ${token.message}`, + ); this.logger.log( - `[OUT] [${context.trackingId}] ${this.generateAccessToken.name}`, + `[OUT] [${context.getTrackingId()}] ${this.generateAccessToken.name}`, ); throw new HttpException( makeErrorResponse('E000101'), @@ -200,7 +208,7 @@ export class AuthService { ); this.logger.log( - `[OUT] [${context.trackingId}] ${this.generateAccessToken.name}`, + `[OUT] [${context.getTrackingId()}] ${this.generateAccessToken.name}`, ); return accessToken; } @@ -218,7 +226,9 @@ export class AuthService { originAccountId: number, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.generateDelegationRefreshToken.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.generateDelegationRefreshToken.name + } | params: { ` + `delegateUserExternalId: ${delegateUserExternalId}, ` + `originAccountId: ${originAccountId}, };`, ); @@ -255,7 +265,7 @@ export class AuthService { return token; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case AccountNotFoundError: @@ -284,7 +294,9 @@ export class AuthService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.generateDelegationRefreshToken.name}`, + `[OUT] [${context.getTrackingId()}] ${ + this.generateDelegationRefreshToken.name + }`, ); } } @@ -300,7 +312,9 @@ export class AuthService { refreshToken: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.generateDelegationAccessToken.name}`, + `[IN] [${context.getTrackingId()}] ${ + this.generateDelegationAccessToken.name + }`, ); const privateKey = getPrivateKey(this.configService); @@ -308,9 +322,13 @@ export class AuthService { const token = verify(refreshToken, pubkey); if (isVerifyError(token)) { - this.logger.error(`${token.reason} | ${token.message}`); + this.logger.error( + `[${context.getTrackingId()}] ${token.reason} | ${token.message}`, + ); this.logger.log( - `[OUT] [${context.trackingId}] ${this.generateDelegationAccessToken.name}`, + `[OUT] [${context.getTrackingId()}] ${ + this.generateDelegationAccessToken.name + }`, ); throw new HttpException( makeErrorResponse('E000101'), @@ -330,7 +348,9 @@ export class AuthService { ); this.logger.log( - `[OUT] [${context.trackingId}] ${this.generateDelegationAccessToken.name}`, + `[OUT] [${context.getTrackingId()}] ${ + this.generateDelegationAccessToken.name + }`, ); return accessToken; } @@ -350,7 +370,9 @@ export class AuthService { refreshToken: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.updateDelegationAccessToken.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.updateDelegationAccessToken.name + } | params: { ` + `delegateUserExternalId: ${delegateUserExternalId}, ` + `originUserExternalId: ${originUserExternalId}, };`, ); @@ -407,7 +429,7 @@ export class AuthService { return accessToken; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof HttpException) { throw e; } @@ -440,7 +462,9 @@ export class AuthService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.updateDelegationAccessToken.name}`, + `[OUT] [${context.getTrackingId()}] ${ + this.updateDelegationAccessToken.name + }`, ); } } @@ -450,8 +474,10 @@ export class AuthService { * @param token * @returns id token */ - async getVerifiedIdToken(token: string): Promise { - this.logger.log(`[IN] ${this.getVerifiedIdToken.name}`); + async getVerifiedIdToken(context: Context, token: string): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.getVerifiedIdToken.name}`, + ); let kid: string | undefined = ''; try { @@ -462,7 +488,7 @@ export class AuthService { throw new Error('kid not found'); } } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E000101'), HttpStatus.UNAUTHORIZED, @@ -471,8 +497,8 @@ export class AuthService { let issuer = ''; try { - const metadata = await this.adB2cService.getMetaData(); - const keySets = await this.adB2cService.getSignKeySets(); + const metadata = await this.adB2cService.getMetaData(context); + const keySets = await this.adB2cService.getSignKeySets(context); issuer = metadata.issuer; @@ -482,7 +508,7 @@ export class AuthService { throw new Error('Public Key Not Found.'); } - const publicKey = this.getPublicKeyFromJwk(jwkKey); + const publicKey = this.getPublicKeyFromJwk(context, jwkKey); const verifiedToken = jwt.verify(token, publicKey, { algorithms: ['RS256'], @@ -496,7 +522,9 @@ export class AuthService { } catch (e) { if (e instanceof Error) { const { name, message } = e; - this.logger.error(`error=${name}: ${message}`); + this.logger.error( + `[${context.getTrackingId()}] error=${name}: ${message}`, + ); switch (e.constructor) { case jwt.TokenExpiredError: @@ -519,18 +547,20 @@ export class AuthService { break; } } else { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); } throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] ${this.getVerifiedIdToken.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getVerifiedIdToken.name}`, + ); } } - getPublicKeyFromJwk(jwkKey: JwkSignKey): string { + getPublicKeyFromJwk(context: Context, jwkKey: JwkSignKey): string { try { // JWK形式のJSONなのでJWTの公開鍵として使えるようにPEM形式に変換 const publicKey = jwkToPem({ @@ -541,10 +571,12 @@ export class AuthService { return publicKey; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw e; } finally { - this.logger.log(`[OUT] ${this.getPublicKeyFromJwk.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getPublicKeyFromJwk.name}`, + ); } } @@ -613,8 +645,9 @@ export class AuthService { idToken: IDToken, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.isAcceptedLatestVersion.name} | params: { ` + - `idToken.sub: ${idToken.sub}, };`, + `[IN] [${context.getTrackingId()}] ${ + this.isAcceptedLatestVersion.name + } | params: { ` + `idToken.sub: ${idToken.sub}, };`, ); try { @@ -646,14 +679,16 @@ export class AuthService { return eulaAccepted && dpaAccepted; } } catch (e) { - this.logger.error(`[${context.trackingId}] error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.isAcceptedLatestVersion.name}`, + `[OUT] [${context.getTrackingId()}] ${ + this.isAcceptedLatestVersion.name + }`, ); } } diff --git a/dictation_server/src/features/auth/test/auth.service.mock.ts b/dictation_server/src/features/auth/test/auth.service.mock.ts index 5f8c9f8..fb7f6c9 100644 --- a/dictation_server/src/features/auth/test/auth.service.mock.ts +++ b/dictation_server/src/features/auth/test/auth.service.mock.ts @@ -4,6 +4,7 @@ import { JwkSignKey, B2cMetadata } from '../../../common/token'; import { AuthService } from '../auth.service'; import { ConfigService } from '@nestjs/config'; import { UsersRepositoryService } from '../../../repositories/users/users.repository.service'; +import { Context } from '../../../common/log'; export type AdB2cMockValue = { getMetaData: B2cMetadata | Error; @@ -71,7 +72,10 @@ export const makeAdB2cServiceMock = (value: AdB2cMockValue) => { }; // eslint-disable-next-line @typescript-eslint/no-unused-vars -export const makeDefaultGetPublicKeyFromJwk = (jwkKey: JwkSignKey): string => { +export const makeDefaultGetPublicKeyFromJwk = ( + context: Context, + jwkKey: JwkSignKey, +): string => { return [ '-----BEGIN PUBLIC KEY-----', 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5IZZNgDew9eGmuFTezwd', diff --git a/dictation_server/src/features/files/files.service.ts b/dictation_server/src/features/files/files.service.ts index 6e81ab1..ae441af 100644 --- a/dictation_server/src/features/files/files.service.ts +++ b/dictation_server/src/features/files/files.service.ts @@ -87,7 +87,10 @@ export class FilesService { isEncrypted: boolean, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.uploadFinished.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.uploadFinished.name + } | params: { ` + + `userId: ${userId}, ` + `url: ${url}, ` + `authorId: ${authorId}, ` + `fileName: ${fileName}, ` + @@ -120,21 +123,21 @@ export class FilesService { ) { if (isInvalidCreatedDate) { this.logger.error( - `param createdDate is invalid format:[createdDate=${createdDate}]`, + `[${context.getTrackingId()}] param createdDate is invalid format:[createdDate=${createdDate}]`, ); } if (isInvalidFinishedDate) { this.logger.error( - `param finishedDate is invalid format:[finishedDate=${finishedDate}]`, + `[${context.getTrackingId()}] param finishedDate is invalid format:[finishedDate=${finishedDate}]`, ); } if (isInvalidUploadedDate) { this.logger.error( - `param uploadedDate is invalid format:[uploadedDate=${uploadedDate}]`, + `[${context.getTrackingId()}] param uploadedDate is invalid format:[uploadedDate=${uploadedDate}]`, ); } this.logger.log( - `[OUT] [${context.trackingId}] ${this.uploadFinished.name}`, + `[OUT] [${context.getTrackingId()}] ${this.uploadFinished.name}`, ); throw new HttpException( @@ -146,10 +149,12 @@ export class FilesService { // オプションアイテムが10個ない場合はパラメータ不正 if (optionItemList.length !== OPTION_ITEM_NUM) { this.logger.error( - `param optionItemList expects ${OPTION_ITEM_NUM} items, but has ${optionItemList.length} items`, + `[${context.getTrackingId()}] param optionItemList expects ${OPTION_ITEM_NUM} items, but has ${ + optionItemList.length + } items`, ); this.logger.log( - `[OUT] [${context.trackingId}] ${this.uploadFinished.name}`, + `[OUT] [${context.getTrackingId()}] ${this.uploadFinished.name}`, ); throw new HttpException( makeErrorResponse('E010001'), @@ -162,9 +167,9 @@ export class FilesService { // ユーザー取得 user = await this.usersRepository.findUserByExternalId(userId); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); this.logger.log( - `[OUT] [${context.trackingId}] ${this.uploadFinished.name}`, + `[OUT] [${context.getTrackingId()}] ${this.uploadFinished.name}`, ); throw new HttpException( makeErrorResponse('E009999'), @@ -177,7 +182,9 @@ export class FilesService { const urlObj = new URL(url); urlObj.search = ''; const fileUrl = urlObj.toString(); - this.logger.log(`Request URL: ${url}, Without param URL${fileUrl}`); + this.logger.log( + `[${context.getTrackingId()}] Request URL: ${url}, Without param URL${fileUrl}`, + ); // 文字起こしタスク追加(音声ファイルとオプションアイテムも同時に追加) // 追加時に末尾のJOBナンバーにインクリメントする @@ -200,7 +207,7 @@ export class FilesService { optionItemList, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -227,13 +234,13 @@ export class FilesService { // 割り当てられたユーザーがいない場合は通知不要 if (distinctUserIds.length === 0) { - this.logger.log('No user assigned.'); + this.logger.log(`[${context.getTrackingId()}] No user assigned.`); return { jobNumber: task.job_number }; } // タグを生成 const tags = distinctUserIds.map((x) => `user_${x}`); - this.logger.log(`tags: ${tags}`); + this.logger.log(`[${context.getTrackingId()}] tags: ${tags}`); // タグ対象に通知送信 await this.notificationhubService.notify(context, tags, { @@ -247,12 +254,14 @@ export class FilesService { return { jobNumber: task.job_number }; } catch (error) { // 処理の本筋はタスク生成のため自動ルーティングに失敗してもエラーにしない - this.logger.error(`Automatic routing or notification failed.`); - this.logger.error(`error=${error}`); + this.logger.error( + `[${context.getTrackingId()}] Automatic routing or notification failed.`, + ); + this.logger.error(`[${context.getTrackingId()}] error=${error}`); return { jobNumber: task.job_number }; } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.uploadFinished.name}`, + `[OUT] [${context.getTrackingId()}] ${this.uploadFinished.name}`, ); } } @@ -267,7 +276,9 @@ export class FilesService { externalId: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.publishUploadSas.name} | params: { externalId: ${externalId} };`, + `[IN] [${context.getTrackingId()}] ${ + this.publishUploadSas.name + } | params: { externalId: ${externalId} };`, ); //DBから国情報とアカウントIDを取得する @@ -286,6 +297,7 @@ export class FilesService { } // ライセンスの有効性をチェック const { licenseError } = await this.checkLicenseValidityByUserId( + context, user.id, ); if (licenseError) { @@ -307,7 +319,7 @@ export class FilesService { ); return url; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); switch (e.constructor) { case AccountLockedError: throw new HttpException( @@ -332,7 +344,7 @@ export class FilesService { } } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.publishUploadSas.name}`, + `[OUT] [${context.getTrackingId()}] ${this.publishUploadSas.name}`, ); } } @@ -349,7 +361,9 @@ export class FilesService { audioFileId: number, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.publishAudioFileDownloadSas.name} | params: { externalId: ${externalId}, audioFileId: ${audioFileId} };`, + `[IN] [${context.getTrackingId()}] ${ + this.publishAudioFileDownloadSas.name + } | params: { externalId: ${externalId}, audioFileId: ${audioFileId} };`, ); //DBから国情報とアカウントID,ユーザーIDを取得する @@ -367,6 +381,7 @@ export class FilesService { if (user.account.tier === TIERS.TIER5) { // ライセンスの有効性をチェック const { licenseError } = await this.checkLicenseValidityByUserId( + context, user.id, ); if (licenseError) { @@ -379,9 +394,11 @@ export class FilesService { isTypist = user.role === USER_ROLES.TYPIST; authorId = user.author_id ?? undefined; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); this.logger.log( - `[OUT] [${context.trackingId}] ${this.publishAudioFileDownloadSas.name}`, + `[OUT] [${context.getTrackingId()}] ${ + this.publishAudioFileDownloadSas.name + }`, ); switch (e.constructor) { case LicenseExpiredError: @@ -446,7 +463,7 @@ export class FilesService { ); if (!isFileExist) { - this.logger.log(`filePath:${filePath}`); + this.logger.log(`[${context.getTrackingId()}] filePath:${filePath}`); throw new AudioFileNotFoundError( `Audio file is not exists in blob storage. audio_file_id:${audioFileId}, url:${file.url}, fileName:${file.file_name}`, ); @@ -461,7 +478,7 @@ export class FilesService { ); return url; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case TasksNotFoundError: @@ -491,7 +508,9 @@ export class FilesService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.publishAudioFileDownloadSas.name}`, + `[OUT] [${context.getTrackingId()}] ${ + this.publishAudioFileDownloadSas.name + }`, ); } } @@ -508,7 +527,9 @@ export class FilesService { audioFileId: number, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.publishTemplateFileDownloadSas.name} | params: { externalId: ${externalId}, audioFileId: ${audioFileId} };`, + `[IN] [${context.getTrackingId()}] ${ + this.publishTemplateFileDownloadSas.name + } | params: { externalId: ${externalId}, audioFileId: ${audioFileId} };`, ); //DBから国情報とアカウントID,ユーザーIDを取得する @@ -526,6 +547,7 @@ export class FilesService { if (user.account.tier === TIERS.TIER5) { // ライセンスの有効性をチェック const { licenseError } = await this.checkLicenseValidityByUserId( + context, user.id, ); if (licenseError) { @@ -538,9 +560,11 @@ export class FilesService { isTypist = user.role === USER_ROLES.TYPIST; authorId = user.author_id ?? undefined; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); this.logger.log( - `[OUT] [${context.trackingId}] ${this.publishTemplateFileDownloadSas.name}`, + `[OUT] [${context.getTrackingId()}] ${ + this.publishTemplateFileDownloadSas.name + }`, ); switch (e.constructor) { case LicenseExpiredError: @@ -629,7 +653,7 @@ export class FilesService { ); return url; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case TasksNotFoundError: @@ -661,7 +685,9 @@ export class FilesService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.publishTemplateFileDownloadSas.name}`, + `[OUT] [${context.getTrackingId()}] ${ + this.publishTemplateFileDownloadSas.name + }`, ); } } @@ -677,7 +703,9 @@ export class FilesService { externalId: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.publishTemplateFileUploadSas.name} | params: { externalId: ${externalId} };`, + `[IN] [${context.getTrackingId()}] ${ + this.publishTemplateFileUploadSas.name + } | params: { externalId: ${externalId} };`, ); try { const { account } = await this.usersRepository.findUserByExternalId( @@ -706,14 +734,16 @@ export class FilesService { return url; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.publishTemplateFileUploadSas.name}`, + `[OUT] [${context.getTrackingId()}] ${ + this.publishTemplateFileUploadSas.name + }`, ); } } @@ -733,7 +763,9 @@ export class FilesService { fileName: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.templateUploadFinished.name} | params: { externalId: ${externalId}, url: ${url}, fileName: ${fileName} };`, + `[IN] [${context.getTrackingId()}] ${ + this.templateUploadFinished.name + } | params: { externalId: ${externalId}, url: ${url}, fileName: ${fileName} };`, ); try { @@ -745,7 +777,9 @@ export class FilesService { const urlObj = new URL(url); urlObj.search = ''; const fileUrl = urlObj.toString(); - this.logger.log(`Request URL: ${url}, Without param URL${fileUrl}`); + this.logger.log( + `[${context.getTrackingId()}] Request URL: ${url}, Without param URL${fileUrl}`, + ); // テンプレートファイル情報をDBに登録 await this.templateFilesRepository.upsertTemplateFile( @@ -754,14 +788,16 @@ export class FilesService { fileUrl, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.templateUploadFinished.name}`, + `[OUT] [${context.getTrackingId()}] ${ + this.templateUploadFinished.name + }`, ); } } @@ -774,8 +810,14 @@ export class FilesService { */ // TODO: TASK3084で共通部品化する private async checkLicenseValidityByUserId( + context: Context, userId: number, ): Promise<{ licenseError?: Error }> { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.checkLicenseValidityByUserId.name + } | params: { userId: ${userId} };`, + ); try { const allocatedLicense = await this.usersRepository.findLicenseByUserId( userId, diff --git a/dictation_server/src/features/licenses/licenses.controller.ts b/dictation_server/src/features/licenses/licenses.controller.ts index eb702b9..33fd5e0 100644 --- a/dictation_server/src/features/licenses/licenses.controller.ts +++ b/dictation_server/src/features/licenses/licenses.controller.ts @@ -91,9 +91,11 @@ export class LicensesController { ); } const { userId } = decodedAccessToken as AccessToken; + const context = makeContext(userId); // ライセンス注文処理 await this.licensesService.licenseOrders( + context, userId, body.poNumber, body.orderCount, @@ -142,8 +144,10 @@ export class LicensesController { ); } const { userId } = decodedAccessToken as AccessToken; + const context = makeContext(userId); const cardLicenseKeys = await this.licensesService.issueCardLicenseKeys( + context, userId, body.createCount, ); @@ -202,8 +206,10 @@ export class LicensesController { ); } const { userId } = decodedAccessToken as AccessToken; + const context = makeContext(userId); await this.licensesService.activateCardLicenseKey( + context, userId, body.cardLicenseKey, ); diff --git a/dictation_server/src/features/licenses/licenses.service.spec.ts b/dictation_server/src/features/licenses/licenses.service.spec.ts index 56d1ef2..27a2458 100644 --- a/dictation_server/src/features/licenses/licenses.service.spec.ts +++ b/dictation_server/src/features/licenses/licenses.service.spec.ts @@ -59,8 +59,14 @@ describe('LicensesService', () => { const userId = '0001'; body.orderCount = 1000; body.poNumber = '1'; + const context = makeContext(`uuidv4`); expect( - await service.licenseOrders(userId, body.poNumber, body.orderCount), + await service.licenseOrders( + context, + userId, + body.poNumber, + body.orderCount, + ), ).toEqual(undefined); }); it('ユーザID取得できなかった場合、エラーとなる', async () => { @@ -81,8 +87,9 @@ describe('LicensesService', () => { const userId = ''; body.orderCount = 1000; body.poNumber = '1'; + const context = makeContext(`uuidv4`); await expect( - service.licenseOrders(userId, body.poNumber, body.orderCount), + service.licenseOrders(context, userId, body.poNumber, body.orderCount), ).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), @@ -108,8 +115,9 @@ describe('LicensesService', () => { const userId = '0001'; body.orderCount = 1000; body.poNumber = '1'; + const context = makeContext(`uuidv4`); await expect( - service.licenseOrders(userId, body.poNumber, body.orderCount), + service.licenseOrders(context, userId, body.poNumber, body.orderCount), ).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), @@ -133,8 +141,9 @@ describe('LicensesService', () => { const userId = '0001'; body.orderCount = 1000; body.poNumber = '1'; + const context = makeContext(`uuidv4`); await expect( - service.licenseOrders(userId, body.poNumber, body.orderCount), + service.licenseOrders(context, userId, body.poNumber, body.orderCount), ).rejects.toEqual( new HttpException( makeErrorResponse('E010401'), @@ -170,8 +179,9 @@ describe('LicensesService', () => { 'AEJWRFFSWRQYQQJ6WVLV', ], }; + const context = makeContext(`uuidv4`); expect( - await service.issueCardLicenseKeys(userId, body.createCount), + await service.issueCardLicenseKeys(context, userId, body.createCount), ).toEqual(issueCardLicensesResponse); }); it('カードライセンス発行に失敗した場合、エラーになる', async () => { @@ -189,8 +199,9 @@ describe('LicensesService', () => { const body = new IssueCardLicensesRequest(); const userId = '0001'; body.createCount = 1000; + const context = makeContext(`uuidv4`); await expect( - service.issueCardLicenseKeys(userId, body.createCount), + service.issueCardLicenseKeys(context, userId, body.createCount), ).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), @@ -212,8 +223,13 @@ describe('LicensesService', () => { const body = new ActivateCardLicensesRequest(); const userId = '0001'; body.cardLicenseKey = 'WZCETXC0Z9PQZ9GKRGGY'; + const context = makeContext(`uuidv4`); expect( - await service.activateCardLicenseKey(userId, body.cardLicenseKey), + await service.activateCardLicenseKey( + context, + userId, + body.cardLicenseKey, + ), ).toEqual(undefined); }); it('カードライセンス取り込みに失敗した場合、エラーになる(DBエラー)', async () => { @@ -231,8 +247,9 @@ describe('LicensesService', () => { const body = new ActivateCardLicensesRequest(); const userId = '0001'; body.cardLicenseKey = 'WZCETXC0Z9PQZ9GKRGGY'; + const context = makeContext(`uuidv4`); await expect( - service.activateCardLicenseKey(userId, body.cardLicenseKey), + service.activateCardLicenseKey(context, userId, body.cardLicenseKey), ).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), @@ -256,8 +273,9 @@ describe('LicensesService', () => { const body = new ActivateCardLicensesRequest(); const userId = '0001'; body.cardLicenseKey = 'WZCETXC0Z9PQZ9GKRGGY'; + const context = makeContext(`uuidv4`); await expect( - service.activateCardLicenseKey(userId, body.cardLicenseKey), + service.activateCardLicenseKey(context, userId, body.cardLicenseKey), ).rejects.toEqual( new HttpException(makeErrorResponse('E010801'), HttpStatus.BAD_REQUEST), ); @@ -278,8 +296,9 @@ describe('LicensesService', () => { const body = new ActivateCardLicensesRequest(); const userId = '0001'; body.cardLicenseKey = 'WZCETXC0Z9PQZ9GKRGGY'; + const context = makeContext(`uuidv4`); await expect( - service.activateCardLicenseKey(userId, body.cardLicenseKey), + service.activateCardLicenseKey(context, userId, body.cardLicenseKey), ).rejects.toEqual( new HttpException(makeErrorResponse('E010802'), HttpStatus.BAD_REQUEST), ); @@ -320,7 +339,8 @@ describe('DBテスト', () => { const service = module.get(LicensesService); const issueCount = 500; - await service.issueCardLicenseKeys(externalId, issueCount); + const context = makeContext(`uuidv4`); + await service.issueCardLicenseKeys(context, externalId, issueCount); const dbSelectResult = await selectCardLicensesCount(source); expect(dbSelectResult.count).toEqual(issueCount); }); @@ -359,8 +379,9 @@ describe('DBテスト', () => { await createCardLicenseIssue(source, issueId); const service = module.get(LicensesService); + const context = makeContext(`uuidv4`); - await service.activateCardLicenseKey(externalId, cardLicenseKey); + await service.activateCardLicenseKey(context, externalId, cardLicenseKey); const dbSelectResultFromCardLicense = await selectCardLicense( source, cardLicenseKey, diff --git a/dictation_server/src/features/licenses/licenses.service.ts b/dictation_server/src/features/licenses/licenses.service.ts index 25c9c41..4a87ed0 100644 --- a/dictation_server/src/features/licenses/licenses.service.ts +++ b/dictation_server/src/features/licenses/licenses.service.ts @@ -33,12 +33,17 @@ export class LicensesService { * @param body */ async licenseOrders( + context: Context, externalId: string, poNumber: string, orderCount: number, ): Promise { //アクセストークンからユーザーIDを取得する - this.logger.log(`[IN] ${this.licenseOrders.name}`); + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.licenseOrders.name + } | params: { externalId: ${externalId}, poNumber: ${poNumber}, orderCount: ${orderCount} };`, + ); let myAccountId: number; let parentAccountId: number | undefined; @@ -48,7 +53,7 @@ export class LicensesService { await this.usersRepository.findUserByExternalId(externalId) ).account_id; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); switch (e.constructor) { case UserNotFoundError: throw new HttpException( @@ -73,7 +78,7 @@ export class LicensesService { throw new Error('parent account id is undefined'); } } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); switch (e.constructor) { case AccountNotFoundError: throw new HttpException( @@ -111,9 +116,15 @@ export class LicensesService { } } async issueCardLicenseKeys( + context: Context, externalId: string, createCount: number, ): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.issueCardLicenseKeys.name + } | params: { externalId: ${externalId}, createCount: ${createCount} };`, + ); const issueCardLicensesResponse = new IssueCardLicensesResponse(); let myAccountId: number; @@ -123,7 +134,7 @@ export class LicensesService { await this.usersRepository.findUserByExternalId(externalId) ).account_id; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); switch (e.constructor) { case UserNotFoundError: throw new HttpException( @@ -145,8 +156,10 @@ export class LicensesService { issueCardLicensesResponse.cardLicenseKeys = licenseKeys; return issueCardLicensesResponse; } catch (e) { - this.logger.error(`error=${e}`); - this.logger.error('get cardlicensekeys failed'); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + this.logger.error( + `[${context.getTrackingId()}] get cardlicensekeys failed`, + ); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -160,11 +173,14 @@ export class LicensesService { * @param cardLicenseKey */ async activateCardLicenseKey( + context: Context, externalId: string, cardLicenseKey: string, ): Promise { this.logger.log( - `[IN] ${this.activateCardLicenseKey.name}, argCardLicenseKey: ${cardLicenseKey}`, + `[IN] [${context.getTrackingId()}] ${ + this.activateCardLicenseKey.name + } | params: { externalId: ${externalId}, argCardLicenseKey: ${cardLicenseKey} };`, ); let myAccountId: number; @@ -174,7 +190,7 @@ export class LicensesService { await this.usersRepository.findUserByExternalId(externalId) ).account_id; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); switch (e.constructor) { case UserNotFoundError: throw new HttpException( @@ -196,8 +212,10 @@ export class LicensesService { cardLicenseKey, ); } catch (e) { - this.logger.error(`error=${e}`); - this.logger.error('cardLicenseKey activate failed'); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + this.logger.error( + `[${context.getTrackingId()}] cardLicenseKey activate failed`, + ); switch (e.constructor) { case LicenseNotExistError: @@ -217,7 +235,9 @@ export class LicensesService { ); } } - this.logger.log(`[OUT] ${this.activateCardLicenseKey.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.activateCardLicenseKey.name}`, + ); return; } @@ -232,8 +252,9 @@ export class LicensesService { userId: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.getAllocatableLicenses.name} | params: { ` + - `userId: ${userId}, `, + `[IN] [${context.getTrackingId()}] ${ + this.getAllocatableLicenses.name + } | params: { ` + `userId: ${userId}, `, ); // ユーザIDからアカウントIDを取得する try { @@ -248,15 +269,19 @@ export class LicensesService { allocatableLicenses, }; } catch (e) { - this.logger.error(`error=${e}`); - this.logger.error('get allocatable lisences failed'); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + this.logger.error( + `[${context.getTrackingId()}] get allocatable lisences failed`, + ); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.getAllocatableLicenses.name}`, + `[OUT] [${context.getTrackingId()}] ${ + this.getAllocatableLicenses.name + }`, ); } } @@ -273,7 +298,9 @@ export class LicensesService { poNumber: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.cancelOrder.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.cancelOrder.name + } | params: { ` + `externalId: ${externalId}, ` + `poNumber: ${poNumber}, };`, ); @@ -287,7 +314,7 @@ export class LicensesService { // 注文キャンセル処理 await this.licensesRepository.cancelOrder(myAccountId, poNumber); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); switch (e.constructor) { case UserNotFoundError: throw new HttpException( @@ -306,7 +333,9 @@ export class LicensesService { ); } } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.cancelOrder.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.cancelOrder.name}`, + ); } return; } diff --git a/dictation_server/src/features/notification/notification.service.ts b/dictation_server/src/features/notification/notification.service.ts index 5ab803b..9accc7c 100644 --- a/dictation_server/src/features/notification/notification.service.ts +++ b/dictation_server/src/features/notification/notification.service.ts @@ -26,7 +26,9 @@ export class NotificationService { pnsHandler: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.register.name} | params: { externalId: ${externalId}, pns: ${pns}, pnsHandler: ${pnsHandler} }`, + `[IN] [${context.getTrackingId()}] ${ + this.register.name + } | params: { externalId: ${externalId}, pns: ${pns}, pnsHandler: ${pnsHandler} }`, ); // ユーザIDからアカウントIDを取得する @@ -34,7 +36,7 @@ export class NotificationService { try { userId = (await this.usersRepository.findUserByExternalId(externalId)).id; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); switch (e.constructor) { case UserNotFoundError: throw new HttpException( @@ -53,7 +55,7 @@ export class NotificationService { // TODO: 登録毎に新規登録する想定でUUIDを付与している // もしデバイスごとに登録を上書きするようであればUUID部分にデバイス識別子を設定 const installationId = `${pns}_${userId}_${uuidv4()}`; - this.logger.log(installationId); + this.logger.log(`[${context.getTrackingId()}] ${installationId}`); await this.notificationhubService.register( context, @@ -63,13 +65,15 @@ export class NotificationService { installationId, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.register.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.register.name}`, + ); } } } diff --git a/dictation_server/src/features/tasks/tasks.controller.ts b/dictation_server/src/features/tasks/tasks.controller.ts index aa06e6d..c1e8b0d 100644 --- a/dictation_server/src/features/tasks/tasks.controller.ts +++ b/dictation_server/src/features/tasks/tasks.controller.ts @@ -318,7 +318,7 @@ export class TasksController { HttpStatus.UNAUTHORIZED, ); } - const { userId, role } = decodedAccessToken as AccessToken; + const { userId } = decodedAccessToken as AccessToken; const context = makeContext(userId); diff --git a/dictation_server/src/features/tasks/tasks.service.ts b/dictation_server/src/features/tasks/tasks.service.ts index 408f7ef..0801572 100644 --- a/dictation_server/src/features/tasks/tasks.service.ts +++ b/dictation_server/src/features/tasks/tasks.service.ts @@ -57,7 +57,14 @@ export class TasksService { direction?: SortDirection, ): Promise<{ tasks: Task[]; total: number }> { this.logger.log( - `[IN] [${context.trackingId}] ${this.getTasks.name} | params: { offset: ${offset}, limit: ${limit}, status: ${status}, paramName: ${paramName}, direction: ${direction} };`, + `[IN] [${context.getTrackingId()}] ${this.getTasks.name} | params: { ` + + `userId: ${userId}, ` + + `roles: ${roles}, ` + + `offset: ${offset},` + + `limit: ${limit}, ` + + `status: ${status}, ` + + `paramName: ${paramName}, ` + + `direction: ${direction} };`, ); // パラメータが省略された場合のデフォルト値: 保存するソート条件の値の初期値と揃える @@ -141,7 +148,7 @@ export class TasksService { throw new Error(`invalid roles: ${roles.join(',')}`); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { if (e.constructor === Adb2cTooManyRequestsError) { throw new HttpException( @@ -155,7 +162,9 @@ export class TasksService { HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.getTasks.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getTasks.name}`, + ); } } @@ -172,7 +181,9 @@ export class TasksService { fileId: number, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.getNextTask.name} | params: { externalId: ${externalId}, fileId: ${fileId} };`, + `[IN] [${context.getTrackingId()}] ${ + this.getNextTask.name + } | params: { externalId: ${externalId}, fileId: ${fileId} };`, ); try { @@ -211,7 +222,7 @@ export class TasksService { ? undefined : nextTask.audio_file_id; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case TasksNotFoundError: @@ -231,7 +242,9 @@ export class TasksService { HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.getNextTask.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getNextTask.name}`, + ); } } @@ -250,7 +263,9 @@ export class TasksService { ): Promise { try { this.logger.log( - `[IN] [${context.trackingId}] ${this.checkout.name} | params: { audioFileId: ${audioFileId}, roles: ${roles}, externalId: ${externalId} };`, + `[IN] [${context.getTrackingId()}] ${ + this.checkout.name + } | params: { audioFileId: ${audioFileId}, roles: ${roles}, externalId: ${externalId} };`, ); const { id, account_id, author_id } = @@ -279,7 +294,7 @@ export class TasksService { throw new InvalidRoleError(`invalid roles: ${roles.join(',')}`); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case CheckoutPermissionNotFoundError: @@ -313,7 +328,9 @@ export class TasksService { HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.checkout.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.checkout.name}`, + ); } } @@ -330,7 +347,9 @@ export class TasksService { ): Promise { try { this.logger.log( - `[IN] [${context.trackingId}] ${this.checkin.name} | params: { audioFileId: ${audioFileId}, externalId: ${externalId} };`, + `[IN] [${context.getTrackingId()}] ${ + this.checkin.name + } | params: { audioFileId: ${audioFileId}, externalId: ${externalId} };`, ); const { id } = await this.usersRepository.findUserByExternalId( externalId, @@ -342,7 +361,7 @@ export class TasksService { TASK_STATUS.IN_PROGRESS, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case TasksNotFoundError: @@ -368,7 +387,9 @@ export class TasksService { HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.checkin.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.checkin.name}`, + ); } } /** @@ -385,15 +406,17 @@ export class TasksService { role: Roles[], ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.cancel.name} | params: { audioFileId: ${audioFileId}, externalId: ${externalId}, role: ${role} };`, + `[IN] [${context.getTrackingId()}] ${ + this.cancel.name + } | params: { audioFileId: ${audioFileId}, externalId: ${externalId}, role: ${role} };`, ); let user: User; try { // ユーザー取得 user = await this.usersRepository.findUserByExternalId(externalId); } catch (e) { - this.logger.error(`error=${e}`); - this.logger.log(`[OUT] [${context.trackingId}] ${this.cancel.name}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + this.logger.log(`[OUT] [${context.getTrackingId()}] ${this.cancel.name}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -409,7 +432,7 @@ export class TasksService { role.includes(ADMIN_ROLES.ADMIN) ? undefined : user.id, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case TasksNotFoundError: @@ -455,10 +478,12 @@ export class TasksService { ); } catch (e) { // 処理の本筋はタスクキャンセルのため自動ルーティングに失敗してもエラーにしない - this.logger.error(`Automatic routing or notification failed.`); - this.logger.error(`error=${e}`); + this.logger.error( + `[${context.getTrackingId()}] Automatic routing or notification failed.`, + ); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.cancel.name}`); + this.logger.log(`[OUT] [${context.getTrackingId()}] ${this.cancel.name}`); } } @@ -475,7 +500,9 @@ export class TasksService { ): Promise { try { this.logger.log( - `[IN] [${context.trackingId}] ${this.suspend.name} | params: { audioFileId: ${audioFileId}, externalId: ${externalId} };`, + `[IN] [${context.getTrackingId()}] ${ + this.suspend.name + } | params: { audioFileId: ${audioFileId}, externalId: ${externalId} };`, ); const { id } = await this.usersRepository.findUserByExternalId( externalId, @@ -487,7 +514,7 @@ export class TasksService { TASK_STATUS.IN_PROGRESS, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case TasksNotFoundError: @@ -513,7 +540,9 @@ export class TasksService { HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.suspend.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.suspend.name}`, + ); } } @@ -522,6 +551,11 @@ export class TasksService { tasks: TaskEntity[], permissions: CheckoutPermission[], ): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.getB2cUsers.name + } | params: { tasks: ${tasks}, permissions: ${permissions} };`, + ); // 割り当て候補の外部IDを列挙 const assigneesExternalIds = permissions.flatMap((permission) => permission.user ? [permission.user.external_id] : [], @@ -554,7 +588,9 @@ export class TasksService { ): Promise { try { this.logger.log( - `[IN] [${context.trackingId}] ${this.changeCheckoutPermission.name} | params: { audioFileId: ${audioFileId}, assignees: ${assignees}, externalId: ${externalId}, role: ${role} };`, + `[IN] [${context.getTrackingId()}] ${ + this.changeCheckoutPermission.name + } | params: { audioFileId: ${audioFileId}, assignees: ${assignees}, externalId: ${externalId}, role: ${role} };`, ); const { author_id, account_id } = await this.usersRepository.findUserByExternalId(externalId); @@ -592,7 +628,7 @@ export class TasksService { account_id, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case TypistUserNotFoundError: @@ -619,7 +655,9 @@ export class TasksService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.changeCheckoutPermission.name}`, + `[OUT] [${context.getTrackingId()}] ${ + this.changeCheckoutPermission.name + }`, ); } } @@ -632,6 +670,13 @@ export class TasksService { audioFileId: number, accountId: number, ): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.sendNotify.name} | params: { ` + + `typistUserIds: ${typistUserIds}, ` + + `typistGroupIds: ${typistGroupIds}, ` + + `audioFileId: ${audioFileId}, ` + + `accountId: ${accountId} };`, + ); const groupMembers = await this.userGroupsRepositoryService.getGroupMembersFromGroupIds( typistGroupIds, @@ -644,13 +689,13 @@ export class TasksService { // 割り当てられたユーザーがいない場合は通知不要 if (distinctUserIds.length === 0) { - this.logger.log('No user assigned.'); + this.logger.log(`[${context.getTrackingId()}] No user assigned.`); return; } // タグを生成 const tags = distinctUserIds.map((x) => `user_${x}`); - this.logger.log(`tags: ${tags}`); + this.logger.log(`[${context.getTrackingId()}] tags: ${tags}`); // 通知内容に含む音声ファイル情報を取得 const { file } = await this.taskRepository.getTaskAndAudioFile( diff --git a/dictation_server/src/features/templates/templates.service.ts b/dictation_server/src/features/templates/templates.service.ts index d2a88c4..f256f3a 100644 --- a/dictation_server/src/features/templates/templates.service.ts +++ b/dictation_server/src/features/templates/templates.service.ts @@ -24,7 +24,9 @@ export class TemplatesService { externalId: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.getTemplates.name} | params: { externalId: ${externalId} };`, + `[IN] [${context.getTrackingId()}] ${ + this.getTemplates.name + } | params: { externalId: ${externalId} };`, ); try { @@ -42,14 +44,14 @@ export class TemplatesService { return resTemplates; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.getTemplates.name}`, + `[OUT] [${context.getTrackingId()}] ${this.getTemplates.name}`, ); } } diff --git a/dictation_server/src/features/terms/terms.controller.ts b/dictation_server/src/features/terms/terms.controller.ts index 1d855ba..459ce27 100644 --- a/dictation_server/src/features/terms/terms.controller.ts +++ b/dictation_server/src/features/terms/terms.controller.ts @@ -3,8 +3,8 @@ import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; import { TermsService } from '../terms/terms.service'; import { ErrorResponse } from '../../common/error/types/types'; import { makeContext } from '../../common/log'; +import { GetTermsInfoResponse } from './types/types'; import { v4 as uuidv4 } from 'uuid'; -import { GetTermsInfoResponse, TermInfo } from './types/types'; @ApiTags('terms') @Controller('terms') diff --git a/dictation_server/src/features/terms/terms.service.ts b/dictation_server/src/features/terms/terms.service.ts index 526bde6..65137a1 100644 --- a/dictation_server/src/features/terms/terms.service.ts +++ b/dictation_server/src/features/terms/terms.service.ts @@ -15,7 +15,9 @@ export class TermsService { * return termsInfo */ async getTermsInfo(context: Context): Promise { - this.logger.log(`[IN] [${context.trackingId}] ${this.getTermsInfo.name}`); + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.getTermsInfo.name}`, + ); try { const { eulaVersion, dpaVersion } = await this.termsRepository.getLatestTermsInfo(); @@ -30,14 +32,14 @@ export class TermsService { }, ]; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.getTermsInfo.name}`, + `[OUT] [${context.getTrackingId()}] ${this.getTermsInfo.name}`, ); } } diff --git a/dictation_server/src/features/users/users.controller.ts b/dictation_server/src/features/users/users.controller.ts index b1fe7c9..a92bbd2 100644 --- a/dictation_server/src/features/users/users.controller.ts +++ b/dictation_server/src/features/users/users.controller.ts @@ -81,7 +81,9 @@ export class UsersController { @ApiOperation({ operationId: 'confirmUser' }) @Post('confirm') async confirmUser(@Body() body: ConfirmRequest): Promise { - await this.usersService.confirmUser(body.token); + const context = makeContext(uuidv4()); + + await this.usersService.confirmUser(context, body.token); return {}; } @@ -148,8 +150,9 @@ export class UsersController { ); } const { userId } = decodedAccessToken as AccessToken; + const context = makeContext(userId); - const users = await this.usersService.getUsers(userId); + const users = await this.usersService.getUsers(context, userId); return { users }; } @@ -325,6 +328,7 @@ export class UsersController { ); } const { userId } = decodedAccessToken as AccessToken; + const context = makeContext(userId); //型チェック if ( @@ -336,7 +340,12 @@ export class UsersController { HttpStatus.BAD_REQUEST, ); } - await this.usersService.updateSortCriteria(paramName, direction, userId); + await this.usersService.updateSortCriteria( + context, + paramName, + direction, + userId, + ); return {}; } @@ -383,8 +392,10 @@ export class UsersController { ); } const { userId } = decodedAccessToken as AccessToken; + const context = makeContext(userId); const { direction, paramName } = await this.usersService.getSortCriteria( + context, userId, ); return { direction, paramName }; @@ -618,10 +629,17 @@ export class UsersController { ): Promise { const { idToken, acceptedEULAVersion, acceptedDPAVersion } = body; - const verifiedIdToken = await this.authService.getVerifiedIdToken(idToken); - const context = makeContext(verifiedIdToken.sub); + const context = makeContext(uuidv4()); - const isVerified = await this.authService.isVerifiedUser(verifiedIdToken); + const verifiedIdToken = await this.authService.getVerifiedIdToken( + context, + idToken, + ); + + const isVerified = await this.authService.isVerifiedUser( + context, + verifiedIdToken, + ); if (!isVerified) { throw new HttpException( makeErrorResponse('E010201'), diff --git a/dictation_server/src/features/users/users.service.spec.ts b/dictation_server/src/features/users/users.service.spec.ts index 8b3df3f..0ede204 100644 --- a/dictation_server/src/features/users/users.service.spec.ts +++ b/dictation_server/src/features/users/users.service.spec.ts @@ -97,7 +97,8 @@ describe('UsersService.confirmUser', () => { // account id:1, user id: 2のトークン const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw'; - await service.confirmUser(token); + const context = makeContext(`uuidv4`); + await service.confirmUser(context, token); //result const resultUser = await getUser(source, userId); const resultLicenses = await getLicenses(source, accountId); @@ -140,7 +141,8 @@ describe('UsersService.confirmUser', () => { if (!module) fail(); const token = 'invalid.id.token'; const service = module.get(UsersService); - await expect(service.confirmUser(token)).rejects.toEqual( + const context = makeContext(`uuidv4`); + await expect(service.confirmUser(context, token)).rejects.toEqual( new HttpException(makeErrorResponse('E000101'), HttpStatus.BAD_REQUEST), ); }); @@ -175,7 +177,8 @@ describe('UsersService.confirmUser', () => { const service = module.get(UsersService); const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw'; - await expect(service.confirmUser(token)).rejects.toEqual( + const context = makeContext(`uuidv4`); + await expect(service.confirmUser(context, token)).rejects.toEqual( new HttpException(makeErrorResponse('E010202'), HttpStatus.BAD_REQUEST), ); }); @@ -186,7 +189,8 @@ describe('UsersService.confirmUser', () => { const service = module.get(UsersService); const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw'; - await expect(service.confirmUser(token)).rejects.toEqual( + const context = makeContext(`uuidv4`); + await expect(service.confirmUser(context, token)).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -1626,7 +1630,10 @@ describe('UsersService.getUsers', () => { }, ]; - expect(await service.getUsers(externalId_author)).toEqual(expectedUsers); + const context = makeContext(`uuidv4`); + expect(await service.getUsers(context, externalId_author)).toEqual( + expectedUsers, + ); }); it('ユーザーの一覧を取得できること(ライセンス割当済み)', async () => { @@ -1742,7 +1749,10 @@ describe('UsersService.getUsers', () => { }, ]; - expect(await service.getUsers(external_id1)).toEqual(expectedUsers); + const context = makeContext(`uuidv4`); + expect(await service.getUsers(context, external_id1)).toEqual( + expectedUsers, + ); }); it('DBからのユーザーの取得に失敗した場合、エラーとなる', async () => { @@ -1763,8 +1773,11 @@ describe('UsersService.getUsers', () => { prompt: false, }); + const context = makeContext(`uuidv4`); const service = module.get(UsersService); - await expect(service.getUsers('externalId_failed')).rejects.toEqual( + await expect( + service.getUsers(context, 'externalId_failed'), + ).rejects.toEqual( new HttpException(makeErrorResponse('E009999'), HttpStatus.NOT_FOUND), ); }); @@ -1788,8 +1801,9 @@ describe('UsersService.getUsers', () => { prompt: false, }); + const context = makeContext(`uuidv4`); const service = module.get(UsersService); - await expect(service.getUsers(externalId_author)).rejects.toEqual( + await expect(service.getUsers(context, externalId_author)).rejects.toEqual( new HttpException(makeErrorResponse('E009999'), HttpStatus.NOT_FOUND), ); }); @@ -1812,9 +1826,15 @@ describe('UsersService.updateSortCriteria', () => { configMockValue, sortCriteriaRepositoryMockValue, ); + const context = makeContext(`uuidv4`); expect( - await service.updateSortCriteria('AUTHOR_ID', 'ASC', 'external_id'), + await service.updateSortCriteria( + context, + 'AUTHOR_ID', + 'ASC', + 'external_id', + ), ).toEqual(undefined); }); @@ -1837,9 +1857,10 @@ describe('UsersService.updateSortCriteria', () => { configMockValue, sortCriteriaRepositoryMockValue, ); + const context = makeContext(`uuidv4`); await expect( - service.updateSortCriteria('AUTHOR_ID', 'ASC', 'external_id'), + service.updateSortCriteria(context, 'AUTHOR_ID', 'ASC', 'external_id'), ).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), @@ -1868,9 +1889,10 @@ describe('UsersService.updateSortCriteria', () => { configMockValue, sortCriteriaRepositoryMockValue, ); + const context = makeContext(`uuidv4`); await expect( - service.updateSortCriteria('AUTHOR_ID', 'ASC', 'external_id'), + service.updateSortCriteria(context, 'AUTHOR_ID', 'ASC', 'external_id'), ).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), @@ -1897,8 +1919,9 @@ describe('UsersService.getSortCriteria', () => { configMockValue, sortCriteriaRepositoryMockValue, ); + const context = makeContext(`uuidv4`); - expect(await service.getSortCriteria('external_id')).toEqual({ + expect(await service.getSortCriteria(context, 'external_id')).toEqual({ direction: 'ASC', paramName: 'JOB_NUMBER', }); @@ -1925,8 +1948,11 @@ describe('UsersService.getSortCriteria', () => { configMockValue, sortCriteriaRepositoryMockValue, ); + const context = makeContext(`uuidv4`); - await expect(service.getSortCriteria('external_id')).rejects.toEqual( + await expect( + service.getSortCriteria(context, 'external_id'), + ).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -1957,8 +1983,11 @@ describe('UsersService.getSortCriteria', () => { configMockValue, sortCriteriaRepositoryMockValue, ); + const context = makeContext(`uuidv4`); - await expect(service.getSortCriteria('external_id')).rejects.toEqual( + await expect( + service.getSortCriteria(context, 'external_id'), + ).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -2014,10 +2043,11 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + const context = makeContext(`uuidv4`); expect( await service.updateUser( - { trackingId: 'trackingId' }, + context, external_id, user1, USER_ROLES.NONE, @@ -2072,10 +2102,11 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + const context = makeContext(`uuidv4`); expect( await service.updateUser( - { trackingId: 'trackingId' }, + context, external_id, user1, USER_ROLES.TYPIST, @@ -2130,10 +2161,11 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + const context = makeContext(`uuidv4`); expect( await service.updateUser( - { trackingId: 'trackingId' }, + context, external_id, user1, USER_ROLES.AUTHOR, @@ -2188,10 +2220,11 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + const context = makeContext(`uuidv4`); expect( await service.updateUser( - { trackingId: 'trackingId' }, + context, external_id, user1, USER_ROLES.TYPIST, @@ -2246,10 +2279,11 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + const context = makeContext(`uuidv4`); expect( await service.updateUser( - { trackingId: 'trackingId' }, + context, external_id, user1, USER_ROLES.AUTHOR, @@ -2304,10 +2338,11 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + const context = makeContext(`uuidv4`); await expect( service.updateUser( - { trackingId: 'trackingId' }, + context, external_id, user1, USER_ROLES.NONE, @@ -2352,10 +2387,11 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + const context = makeContext(`uuidv4`); expect( await service.updateUser( - { trackingId: 'trackingId' }, + context, external_id, user1, USER_ROLES.AUTHOR, @@ -2410,10 +2446,11 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + const context = makeContext(`uuidv4`); expect( await service.updateUser( - { trackingId: 'trackingId' }, + context, external_id, user1, USER_ROLES.AUTHOR, @@ -2468,10 +2505,11 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + const context = makeContext(`uuidv4`); await expect( service.updateUser( - { trackingId: 'trackingId' }, + context, external_id, user1, USER_ROLES.AUTHOR, @@ -2527,10 +2565,11 @@ describe('UsersService.updateUser', () => { }); const service = module.get(UsersService); + const context = makeContext(`uuidv4`); await expect( service.updateUser( - { trackingId: 'trackingId' }, + context, external_id, user1, USER_ROLES.AUTHOR, diff --git a/dictation_server/src/features/users/users.service.ts b/dictation_server/src/features/users/users.service.ts index be5c8d4..32e4d2d 100644 --- a/dictation_server/src/features/users/users.service.ts +++ b/dictation_server/src/features/users/users.service.ts @@ -72,8 +72,10 @@ export class UsersService { * Confirms user * @param token ユーザ仮登録時に払いだされるトークン */ - async confirmUser(token: string): Promise { - this.logger.log(`[IN] ${this.confirmUser.name}`); + async confirmUser(context: Context, token: string): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.confirmUser.name}`, + ); const pubKey = getPublicKey(this.configService); const decodedToken = verify<{ @@ -95,7 +97,7 @@ export class UsersService { userId, ); } catch (e) { - this.logger.error(e); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case EmailAlreadyVerifiedError: @@ -147,14 +149,23 @@ export class UsersService { encryptionPassword?: string | undefined, prompt?: boolean | undefined, ): Promise { - this.logger.log(`[IN] [${context.trackingId}] ${this.createUser.name}`); - + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.createUser.name} | params: { ` + + `externalId: ${externalId}, ` + + `role: ${role}, ` + + `autoRenew: ${autoRenew}, ` + + `licenseAlert: ${licenseAlert}, ` + + `notification: ${notification}, ` + + `authorId: ${authorId}, ` + + `encryption: ${encryption}, ` + + `prompt: ${prompt} };`, + ); //DBよりアクセス者の所属するアカウントIDを取得する let adminUser: EntityUser; try { adminUser = await this.usersRepository.findUserByExternalId(externalId); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -172,7 +183,7 @@ export class UsersService { authorId, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -200,8 +211,10 @@ export class UsersService { name, ); } catch (e) { - this.logger.error(`error=${e}`); - this.logger.error('create externalUser failed'); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + this.logger.error( + `[${context.getTrackingId()}] create externalUser failed`, + ); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -222,6 +235,7 @@ export class UsersService { try { //roleに応じてユーザー情報を作成する const newUserInfo = this.createNewUserInfo( + context, role, accountId, externalUser.sub, @@ -236,8 +250,8 @@ export class UsersService { // ユーザ作成 newUser = await this.usersRepository.createNormalUser(newUserInfo); } catch (e) { - this.logger.error(`error=${e}`); - this.logger.error('create user failed'); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + this.logger.error(`[${context.getTrackingId()}]create user failed`); //リカバリー処理 //Azure AD B2Cに登録したユーザー情報を削除する await this.deleteB2cUser(externalUser.sub, context); @@ -262,6 +276,7 @@ export class UsersService { // メールの内容を構成 const { subject, text, html } = await this.sendgridService.createMailContentFromEmailConfirmForNormalUser( + context, accountId, newUser.id, email, @@ -277,8 +292,8 @@ export class UsersService { html, ); } catch (e) { - this.logger.error(`error=${e}`); - this.logger.error('create user failed'); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + this.logger.error(`[${context.getTrackingId()}] create user failed`); //リカバリー処理 //Azure AD B2Cに登録したユーザー情報を削除する await this.deleteB2cUser(externalUser.sub, context); @@ -289,7 +304,9 @@ export class UsersService { HttpStatus.INTERNAL_SERVER_ERROR, ); } - this.logger.log(`[OUT] ${this.createUser.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.createUser.name}`, + ); return; } @@ -299,12 +316,12 @@ export class UsersService { try { await this.adB2cService.deleteUser(externalUserId, context); this.logger.log( - `[${context.trackingId}] delete externalUser: ${externalUserId}`, + `[${context.getTrackingId()}] delete externalUser: ${externalUserId}`, ); } catch (error) { - this.logger.error(`error=${error}`); + this.logger.error(`[${context.getTrackingId()}] error=${error}`); this.logger.error( - `${MANUAL_RECOVERY_REQUIRED} [${context.trackingId}] Failed to delete externalUser: ${externalUserId}`, + `${MANUAL_RECOVERY_REQUIRED} [${context.getTrackingId()}] Failed to delete externalUser: ${externalUserId}`, ); } } @@ -313,17 +330,18 @@ export class UsersService { private async deleteUser(userId: number, context: Context) { try { await this.usersRepository.deleteNormalUser(userId); - this.logger.log(`[${context.trackingId}] delete user: ${userId}`); + this.logger.log(`[${context.getTrackingId()}] delete user: ${userId}`); } catch (error) { - this.logger.error(`error=${error}`); + this.logger.error(`[${context.getTrackingId()}] error=${error}`); this.logger.error( - `${MANUAL_RECOVERY_REQUIRED} [${context.trackingId}] Failed to delete user: ${userId}`, + `${MANUAL_RECOVERY_REQUIRED} [${context.getTrackingId()}] Failed to delete user: ${userId}`, ); } } // roleを受け取って、roleに応じたnewUserを作成して返却する private createNewUserInfo( + context: Context, role: UserRoles, accountId: number, externalId: string, @@ -335,6 +353,21 @@ export class UsersService { encryptionPassword?: string | undefined, prompt?: boolean | undefined, ): newUser { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.createNewUserInfo.name + } | params: { ` + + `role: ${role}, ` + + `accountId: ${accountId}, ` + + `authorId: ${authorId}, ` + + `externalId: ${externalId}, ` + + `autoRenew: ${autoRenew}, ` + + `licenseAlert: ${licenseAlert}, ` + + `notification: ${notification}, ` + + `authorId: ${authorId}, ` + + `encryption: ${encryption}, ` + + `prompt: ${prompt} };`, + ); switch (role) { case USER_ROLES.NONE: case USER_ROLES.TYPIST: @@ -369,7 +402,9 @@ export class UsersService { }; default: //不正なroleが指定された場合はログを出力してエラーを返す - this.logger.error(`[NOT IMPLEMENT] [RECOVER] role: ${role}`); + this.logger.error( + `[${context.getTrackingId()}] [NOT IMPLEMENT] [RECOVER] role: ${role}`, + ); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -386,7 +421,9 @@ export class UsersService { token: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.confirmUserAndInitPassword.name}`, + `[IN] [${context.getTrackingId()}] ${ + this.confirmUserAndInitPassword.name + }`, ); const pubKey = getPublicKey(this.configService); @@ -412,7 +449,11 @@ export class UsersService { const user = await this.usersRepository.findUserById(userId); const extarnalId = user.external_id; // パスワードを変更する - await this.adB2cService.changePassword(extarnalId, ramdomPassword); + await this.adB2cService.changePassword( + context, + extarnalId, + ramdomPassword, + ); // ユーザを認証済みにする await this.usersRepository.updateUserVerified(userId); // TODO [Task2163] ODMS側が正式にメッセージを決めるまで仮のメール内容とする @@ -430,7 +471,7 @@ export class UsersService { html, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case EmailAlreadyVerifiedError: @@ -453,8 +494,8 @@ export class UsersService { * @param accessToken * @returns users */ - async getUsers(externalId: string): Promise { - this.logger.log(`[IN] ${this.getUsers.name}`); + async getUsers(context: Context, externalId: string): Promise { + this.logger.log(`[IN] [${context.getTrackingId()}] ${this.getUsers.name}`); try { // DBから同一アカウントのユーザ一覧を取得する @@ -464,9 +505,10 @@ export class UsersService { // DBから取得したユーザーの外部IDをもとにADB2Cからユーザーを取得する const externalIds = dbUsers.map((x) => x.external_id); + const trackingId = new Context(context.trackingId); const adb2cUsers = await this.adB2cService.getUsers( // TODO: 外部連携以外のログ強化時に、ContollerからContextを取得するように修正する - { trackingId: 'dummy' }, + trackingId, externalIds, ); @@ -554,13 +596,15 @@ export class UsersService { return users; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.NOT_FOUND, ); } finally { - this.logger.log(`[OUT] ${this.getUsers.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getUsers.name}`, + ); } } /** @@ -571,17 +615,22 @@ export class UsersService { * @returns sort criteria */ async updateSortCriteria( + context: Context, paramName: TaskListSortableAttribute, direction: SortDirection, externalId: string, ): Promise { - this.logger.log(`[IN] ${this.updateSortCriteria.name}`); + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.updateSortCriteria.name + } | params: { paramName: ${paramName}, direction: ${direction}, externalId: ${externalId} };`, + ); let user: EntityUser; try { // ユーザー情報を取得 user = await this.usersRepository.findUserByExternalId(externalId); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), @@ -597,13 +646,15 @@ export class UsersService { direction, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] ${this.updateSortCriteria.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.updateSortCriteria.name}`, + ); } } /** @@ -611,17 +662,24 @@ export class UsersService { * @param token * @returns sort criteria */ - async getSortCriteria(externalId: string): Promise<{ + async getSortCriteria( + context: Context, + externalId: string, + ): Promise<{ paramName: TaskListSortableAttribute; direction: SortDirection; }> { - this.logger.log(`[IN] ${this.getSortCriteria.name}`); + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.getSortCriteria.name + } | params: { externalId: ${externalId} };`, + ); let user: EntityUser; try { // ユーザー情報を取得 user = await this.usersRepository.findUserByExternalId(externalId); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), @@ -644,13 +702,15 @@ export class UsersService { } return { direction, paramName: parameter }; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] ${this.getSortCriteria.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getSortCriteria.name}`, + ); } } @@ -663,7 +723,11 @@ export class UsersService { context: Context, userId: string, ): Promise { - this.logger.log(`[IN] [${context.trackingId}] ${this.getRelations.name}`); + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.getRelations.name + } | params: { userId: ${userId} };`, + ); try { const { id } = await this.usersRepository.findUserByExternalId(userId); @@ -710,7 +774,7 @@ export class UsersService { prompt: user.prompt, }; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { @@ -733,7 +797,7 @@ export class UsersService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.getRelations.name}`, + `[OUT] [${context.getTrackingId()}] ${this.getRelations.name}`, ); } } @@ -768,14 +832,17 @@ export class UsersService { ): Promise { try { this.logger.log( - `[IN] [${context.trackingId}] ${this.updateUser.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.updateUser.name + } | params: { ` + + `extarnalId: ${extarnalId}, ` + + `id: ${id}, ` + `role: ${role}, ` + `authorId: ${authorId}, ` + `autoRenew: ${autoRenew}, ` + `licenseAlart: ${licenseAlart}, ` + `notification: ${notification}, ` + `encryption: ${encryption}, ` + - `encryptionPassword: ********, ` + `prompt: ${prompt} }`, ); @@ -798,7 +865,7 @@ export class UsersService { prompt, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case UserNotFoundError: @@ -833,7 +900,9 @@ export class UsersService { HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.updateUser.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.updateUser.name}`, + ); } } @@ -849,7 +918,9 @@ export class UsersService { newLicenseId: number, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.allocateLicense.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.allocateLicense.name + } | params: { ` + `userId: ${userId}, ` + `newLicenseId: ${newLicenseId}, };`, ); @@ -864,7 +935,7 @@ export class UsersService { accountId, ); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case LicenseExpiredError: @@ -886,7 +957,7 @@ export class UsersService { } } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.allocateLicense.name}`, + `[OUT] [${context.getTrackingId()}] ${this.allocateLicense.name}`, ); } } @@ -898,8 +969,9 @@ export class UsersService { */ async deallocateLicense(context: Context, userId: number): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.deallocateLicense.name} | params: { ` + - `userId: ${userId}, };`, + `[IN] [${context.getTrackingId()}] ${ + this.deallocateLicense.name + } | params: { ` + `userId: ${userId}, };`, ); try { @@ -908,7 +980,7 @@ export class UsersService { await this.licensesRepository.deallocateLicense(userId, accountId); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case LicenseAlreadyDeallocatedError: @@ -925,7 +997,7 @@ export class UsersService { } } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.deallocateLicense.name}`, + `[OUT] [${context.getTrackingId()}] ${this.deallocateLicense.name}`, ); } } @@ -944,7 +1016,9 @@ export class UsersService { dpaVersion?: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.updateAcceptedVersion.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.updateAcceptedVersion.name + } | params: { ` + `externalId: ${externalId}, ` + `eulaVersion: ${eulaVersion}, ` + `dpaVersion: ${dpaVersion}, };`, @@ -957,7 +1031,7 @@ export class UsersService { dpaVersion, ); } catch (e) { - this.logger.error(`[${context.trackingId}] error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case UserNotFoundError: @@ -984,7 +1058,7 @@ export class UsersService { } } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.updateAcceptedVersion.name}`, + `[OUT] [${context.getTrackingId()}] ${this.updateAcceptedVersion.name}`, ); } } @@ -994,16 +1068,20 @@ export class UsersService { * @param externalId */ async getUserName(context: Context, externalId: string): Promise { - this.logger.log(`[IN] [${context.trackingId}] ${this.getUserName.name}`); + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.getUserName.name + } | params: { externalId: ${externalId} };`, + ); try { // extarnalIdの存在チェックを行う await this.usersRepository.findUserByExternalId(externalId); // ADB2Cからユーザー名を取得する - const adb2cUser = await this.adB2cService.getUser(externalId); + const adb2cUser = await this.adB2cService.getUser(context, externalId); return adb2cUser.displayName; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case UserNotFoundError: @@ -1023,7 +1101,9 @@ export class UsersService { HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.getUserName.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getUserName.name}`, + ); } } } diff --git a/dictation_server/src/features/workflows/workflows.service.ts b/dictation_server/src/features/workflows/workflows.service.ts index 6f98c95..793449b 100644 --- a/dictation_server/src/features/workflows/workflows.service.ts +++ b/dictation_server/src/features/workflows/workflows.service.ts @@ -35,7 +35,9 @@ export class WorkflowsService { externalId: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.getWorkflows.name} | params: { externalId: ${externalId} };`, + `[IN] [${context.getTrackingId()}] ${ + this.getWorkflows.name + } | params: { externalId: ${externalId} };`, ); try { const { account_id: accountId } = @@ -121,14 +123,14 @@ export class WorkflowsService { return workflows; } catch (e) { - this.logger.error(`[${context.trackingId}] error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.getWorkflows.name}`, + `[OUT] [${context.getTrackingId()}] ${this.getWorkflows.name}`, ); } } @@ -152,7 +154,9 @@ export class WorkflowsService { templateId?: number | undefined, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.createWorkflow.name} | | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.createWorkflow.name + } | params: { ` + `externalId: ${externalId}, ` + `authorId: ${authorId}, ` + `worktypeId: ${worktypeId}, ` + @@ -171,7 +175,7 @@ export class WorkflowsService { templateId, ); } catch (e) { - this.logger.error(`[${context.trackingId}] error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case UserNotFoundError: @@ -212,7 +216,7 @@ export class WorkflowsService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.createWorkflow.name}`, + `[OUT] [${context.getTrackingId()}] ${this.createWorkflow.name}`, ); } } @@ -237,7 +241,9 @@ export class WorkflowsService { templateId?: number | undefined, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.updateWorkflow.name} | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.updateWorkflow.name + } | params: { ` + `externalId: ${externalId}, ` + `workflowId: ${workflowId}, ` + `authorId: ${authorId}, ` + @@ -258,7 +264,7 @@ export class WorkflowsService { templateId, ); } catch (e) { - this.logger.error(`[${context.trackingId}] error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case WorkflowNotFoundError: @@ -304,7 +310,7 @@ export class WorkflowsService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.updateWorkflow.name}`, + `[OUT] [${context.getTrackingId()}] ${this.updateWorkflow.name}`, ); } } @@ -322,7 +328,9 @@ export class WorkflowsService { workflowId: number, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.deleteWorkflow.name} | | params: { ` + + `[IN] [${context.getTrackingId()}] ${ + this.deleteWorkflow.name + } | params: { ` + `externalId: ${externalId}, ` + `workflowId: ${workflowId} };`, ); @@ -339,7 +347,7 @@ export class WorkflowsService { await this.workflowsRepository.deleteWorkflow(account.id, workflowId); } catch (e) { - this.logger.error(`[${context.trackingId}] error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { switch (e.constructor) { case UserNotFoundError: @@ -370,7 +378,7 @@ export class WorkflowsService { ); } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.deleteWorkflow.name}`, + `[OUT] [${context.getTrackingId()}] ${this.deleteWorkflow.name}`, ); } } diff --git a/dictation_server/src/gateways/adb2c/adb2c.service.ts b/dictation_server/src/gateways/adb2c/adb2c.service.ts index 69bd890..eb1464e 100644 --- a/dictation_server/src/gateways/adb2c/adb2c.service.ts +++ b/dictation_server/src/gateways/adb2c/adb2c.service.ts @@ -1,7 +1,7 @@ import { ClientSecretCredential } from '@azure/identity'; import { Client } from '@microsoft/microsoft-graph-client'; import { TokenCredentialAuthenticationProvider } from '@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials'; -import { CACHE_MANAGER, Inject, Injectable, Logger } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import axios from 'axios'; import { B2cMetadata, JwkSignKey } from '../../common/token'; @@ -71,7 +71,9 @@ export class AdB2cService { password: string, username: string, ): Promise<{ sub: string } | ConflictError> { - this.logger.log(`[IN] [${context.trackingId}] ${this.createUser.name}`); + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.createUser.name}`, + ); try { // ユーザをADB2Cに登録 const newUser = await this.graphClient.api('users/').post({ @@ -92,7 +94,7 @@ export class AdB2cService { }); return { sub: newUser.id }; } catch (e) { - this.logger.error(e); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e?.statusCode === 400 && e?.body) { const error = JSON.parse(e.body); @@ -104,7 +106,9 @@ export class AdB2cService { throw e; } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.createUser.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.createUser.name}`, + ); } } @@ -112,8 +116,10 @@ export class AdB2cService { * ADB2Cのメタデータを取得する * @returns meta data */ - async getMetaData(): Promise { - this.logger.log(`[IN] ${this.getMetaData.name}`); + async getMetaData(context: Context): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.getMetaData.name}`, + ); try { // Azure AD B2Cのメタデータを取得する。 以下のURLから取得できる。 // https://<テナント名>.b2clogin.com/<テナント名>.onmicrosoft.com/<ユーザーフロー名>/v2.0/.well-known/openid-configuration @@ -125,10 +131,12 @@ export class AdB2cService { return metaData; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw e; } finally { - this.logger.log(`[OUT] ${this.getMetaData.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getMetaData.name}`, + ); } } @@ -136,8 +144,10 @@ export class AdB2cService { * IDトークンの署名キーセットを取得する * @returns sign key sets */ - async getSignKeySets(): Promise { - this.logger.log(`[IN] ${this.getSignKeySets.name}`); + async getSignKeySets(context: Context): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.getSignKeySets.name}`, + ); try { // 署名キーのキーセット配列を取得する。 以下のURLから取得できる。 const keySets = await axios @@ -148,10 +158,12 @@ export class AdB2cService { return keySets; } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw e; } finally { - this.logger.log(`[OUT] ${this.getSignKeySets.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getSignKeySets.name}`, + ); } } @@ -160,8 +172,16 @@ export class AdB2cService { * @param externalId ユーザ情報 * @param password パスワード */ - async changePassword(externalId: string, password: string): Promise { - this.logger.log(`[IN] ${this.changePassword.name}`); + async changePassword( + context: Context, + externalId: string, + password: string, + ): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.changePassword.name + } | params: { ` + `externalId: ${externalId}, };`, + ); try { // ADB2Cのユーザのパスワードを変更する await this.graphClient.api(`/users/${externalId}`).patch({ @@ -171,10 +191,12 @@ export class AdB2cService { }, }); } catch (e) { - this.logger.error(e); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw e; } finally { - this.logger.log(`[OUT] ${this.changePassword.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.changePassword.name}`, + ); } } @@ -183,16 +205,21 @@ export class AdB2cService { * @param externalId 外部ユーザーID * @returns ユーザ情報 */ - async getUser(externalId: string): Promise { - this.logger.log(`[IN] ${this.getUser.name}`); + async getUser(context: Context, externalId: string): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.getUser.name} | params: { ` + + `externalId: ${externalId} };`, + ); try { const key = makeADB2CKey(externalId); // キャッシュ上に存在していれば、キャッシュから取得する - const cachedUser = await this.redisService.get(key); + const cachedUser = await this.redisService.get(context, key); if (cachedUser) { - this.logger.log(`[CACHE HIT] id: ${externalId}`); + this.logger.log( + `[${context.getTrackingId()}] [CACHE HIT] id: ${externalId}`, + ); return cachedUser; } @@ -201,15 +228,19 @@ export class AdB2cService { .api(`users/${externalId}`) .select(['id', 'displayName', 'identities']) .get(); - await this.redisService.set(key, user, this.ttl); - this.logger.log(`[ADB2C GET] externalId: ${externalId}`); + await this.redisService.set(context, key, user, this.ttl); + this.logger.log( + `[${context.getTrackingId()}] [ADB2C GET] externalId: ${externalId}`, + ); return user; } catch (e) { - this.logger.error(e); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw e; } finally { - this.logger.log(`[OUT] ${this.getUser.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getUser.name}`, + ); } } /** @@ -222,19 +253,21 @@ export class AdB2cService { externalIds: string[], ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${ + `[IN] [${context.getTrackingId()}] ${ this.getUsers.name } | params: { externalIds:[${externalIds.join(',')}] };`, ); const keys = externalIds.map((externalId) => makeADB2CKey(externalId)); - const cache = await this.redisService.mget(keys); + const cache = await this.redisService.mget(context, keys); // キャッシュ上に存在していれば、キャッシュから取得する const cachedUsers = cache.flatMap((x) => (x.value ? [x.value] : [])); if (cachedUsers.length > 0) { this.logger.log( - `[CACHE HIT] ids: ${cachedUsers.map((x) => x.id).join(',')}`, + `[${context.getTrackingId()}] [CACHE HIT] ids: ${cachedUsers + .map((x) => x.id) + .join(',')}`, ); } @@ -265,15 +298,17 @@ export class AdB2cService { value: user, }; }); - await this.redisService.mset(users, this.ttl); + await this.redisService.mset(context, users, this.ttl); this.logger.log( - `[ADB2C GET] externalIds: ${res.value?.map((x) => x.id).join(',')}`, + `[${context.getTrackingId()}] [ADB2C GET] externalIds: ${res.value + ?.map((x) => x.id) + .join(',')}`, ); } return [...cachedUsers, ...b2cUsers]; } catch (e) { - this.logger.error(e); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); const { statusCode } = e; if (statusCode === 429) { throw new Adb2cTooManyRequestsError(); @@ -281,7 +316,9 @@ export class AdB2cService { throw e; } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.getUsers.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.getUsers.name}`, + ); } } /** @@ -291,26 +328,32 @@ export class AdB2cService { */ async deleteUser(externalId: string, context: Context): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.deleteUser.name} | params: { externalId: ${externalId} };`, + `[IN] [${context.getTrackingId()}] ${ + this.deleteUser.name + } | params: { externalId: ${externalId} };`, ); try { // https://learn.microsoft.com/en-us/graph/api/user-delete?view=graph-rest-1.0&tabs=javascript#example await this.graphClient.api(`users/${externalId}`).delete(); - this.logger.log(`[ADB2C DELETE] externalId: ${externalId}`); + this.logger.log( + `[${context.getTrackingId()}] [ADB2C DELETE] externalId: ${externalId}`, + ); // キャッシュからも削除する try { - await this.redisService.del(makeADB2CKey(externalId)); + await this.redisService.del(context, makeADB2CKey(externalId)); } catch (e) { // キャッシュからの削除に失敗しても、ADB2Cからの削除は成功しているため例外はスローしない - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); } } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw e; } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.deleteUser.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.deleteUser.name}`, + ); } } @@ -321,7 +364,9 @@ export class AdB2cService { */ async deleteUsers(externalIds: string[], context: Context): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.deleteUsers.name} | params: { externalIds: ${externalIds} };`, + `[IN] [${context.getTrackingId()}] ${ + this.deleteUsers.name + } | params: { externalIds: ${externalIds} };`, ); try { @@ -329,14 +374,16 @@ export class AdB2cService { const results = await Promise.allSettled( externalIds.map(async (externalId) => { await this.graphClient.api(`users/${externalId}`).delete(); - this.logger.log(`[ADB2C DELETE] externalId: ${externalId}`); + this.logger.log( + `[${context.getTrackingId()}] [ADB2C DELETE] externalId: ${externalId}`, + ); // キャッシュからも削除する try { - await this.redisService.del(makeADB2CKey(externalId)); + await this.redisService.del(context, makeADB2CKey(externalId)); } catch (e) { // キャッシュからの削除に失敗しても、ADB2Cからの削除は成功しているため例外はスローしない - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); } }), ); @@ -353,19 +400,21 @@ export class AdB2cService { const error = result.reason.toString(); this.logger.error( - `${MANUAL_RECOVERY_REQUIRED}[${context.trackingId}] Failed to delete user ${failedId}: ${error}`, + `${MANUAL_RECOVERY_REQUIRED} [${context.getTrackingId()}] Failed to delete user ${failedId}: ${error}`, ); } else { this.logger.error( - `${MANUAL_RECOVERY_REQUIRED}[${context.trackingId}] Failed to delete user ${failedId}`, + `${MANUAL_RECOVERY_REQUIRED} [${context.getTrackingId()}] Failed to delete user ${failedId}`, ); } }); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw e; } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.deleteUsers.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.deleteUsers.name}`, + ); } } } diff --git a/dictation_server/src/gateways/blobstorage/blobstorage.service.ts b/dictation_server/src/gateways/blobstorage/blobstorage.service.ts index 8d8b91e..78767f5 100644 --- a/dictation_server/src/gateways/blobstorage/blobstorage.service.ts +++ b/dictation_server/src/gateways/blobstorage/blobstorage.service.ts @@ -69,21 +69,27 @@ export class BlobstorageService { country: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.createContainer.name}`, + `[IN] [${context.getTrackingId()}] ${ + this.createContainer.name + } | params: { ` + `accountId: ${accountId} };`, ); // 国に応じたリージョンでコンテナ名を指定してClientを取得 - const containerClient = this.getContainerClient(accountId, country); + const containerClient = this.getContainerClient( + context, + accountId, + country, + ); try { // コンテナ作成 await containerClient.create(); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw e; } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.createContainer.name}`, + `[OUT] [${context.getTrackingId()}] ${this.createContainer.name}`, ); } } @@ -100,16 +106,22 @@ export class BlobstorageService { country: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.deleteContainer.name}`, + `[IN] [${context.getTrackingId()}] ${ + this.deleteContainer.name + } | params: { ` + `accountId: ${accountId} };`, ); try { // 国に応じたリージョンでコンテナ名を指定してClientを取得 - const containerClient = this.getContainerClient(accountId, country); + const containerClient = this.getContainerClient( + context, + accountId, + country, + ); const { succeeded, errorCode, date } = await containerClient.deleteIfExists(); this.logger.log( - `succeeded: ${succeeded}, errorCode: ${errorCode}, date: ${date}`, + `[${context.getTrackingId()}] succeeded: ${succeeded}, errorCode: ${errorCode}, date: ${date}`, ); // 失敗時、コンテナが存在しない場合以外はエラーとして例外をスローする @@ -121,11 +133,11 @@ export class BlobstorageService { ); } } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw e; } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.deleteContainer.name}`, + `[OUT] [${context.getTrackingId()}] ${this.deleteContainer.name}`, ); } } @@ -142,14 +154,20 @@ export class BlobstorageService { country: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.containerExists.name}`, + `[IN] [${context.getTrackingId()}] ${ + this.containerExists.name + } | params: { ` + `accountId: ${accountId} };`, ); // 国に応じたリージョンでコンテナ名を指定してClientを取得 - const containerClient = this.getContainerClient(accountId, country); + const containerClient = this.getContainerClient( + context, + accountId, + country, + ); const exists = await containerClient.exists(); this.logger.log( - `[OUT] [${context.trackingId}] ${this.containerExists.name}`, + `[OUT] [${context.getTrackingId()}] ${this.containerExists.name}`, ); return exists; } @@ -169,13 +187,23 @@ export class BlobstorageService { country: string, filePath: string, ): Promise { - this.logger.log(`[IN] [${context.trackingId}] ${this.fileExists.name}`); + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.fileExists.name} | params: { ` + + `accountId: ${accountId},` + + `filePath: ${filePath} };`, + ); - const containerClient = this.getContainerClient(accountId, country); + const containerClient = this.getContainerClient( + context, + accountId, + country, + ); const blob = containerClient.getBlobClient(`${filePath}`); const exists = await blob.exists(); - this.logger.log(`[OUT] [${context.trackingId}] ${this.fileExists.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.fileExists.name}`, + ); return exists; } @@ -191,19 +219,21 @@ export class BlobstorageService { country: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.publishUploadSas.name}`, + `[IN] [${context.getTrackingId()}] ${ + this.publishUploadSas.name + } | params: { ` + `accountId: ${accountId} };`, ); let containerClient: ContainerClient; let sharedKeyCredential: StorageSharedKeyCredential; try { // コンテナ名を指定してClientを取得 - containerClient = this.getContainerClient(accountId, country); + containerClient = this.getContainerClient(context, accountId, country); // 国に対応したリージョンの接続情報を取得する sharedKeyCredential = this.getSharedKeyCredential(country); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); this.logger.log( - `[OUT] [${context.trackingId}] ${this.publishUploadSas.name}`, + `[OUT] [${context.getTrackingId()}] ${this.publishUploadSas.name}`, ); throw e; } @@ -231,7 +261,7 @@ export class BlobstorageService { url.search = `${sasToken}`; this.logger.log( - `[OUT] [${context.trackingId}] ${ + `[OUT] [${context.getTrackingId()}] ${ this.publishUploadSas.name } url=${url.toString()}`, ); @@ -250,12 +280,18 @@ export class BlobstorageService { country: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.publishTemplateUploadSas.name}`, + `[IN] [${context.getTrackingId()}] ${ + this.publishTemplateUploadSas.name + } | params: { ` + `accountId: ${accountId} };`, ); try { // コンテナ名を指定してClientを取得 - const containerClient = this.getContainerClient(accountId, country); + const containerClient = this.getContainerClient( + context, + accountId, + country, + ); // 国に対応したリージョンの接続情報を取得する const sharedKeyCredential = this.getSharedKeyCredential(country); //SASの有効期限を設定 @@ -282,11 +318,13 @@ export class BlobstorageService { return url.toString(); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw e; } finally { this.logger.log( - `[OUT] [${context.trackingId}] ${this.publishTemplateUploadSas.name}`, + `[OUT] [${context.getTrackingId()}] ${ + this.publishTemplateUploadSas.name + }`, ); } } @@ -306,22 +344,26 @@ export class BlobstorageService { filePath: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.publishDownloadSas.name}`, + `[IN] [${context.getTrackingId()}] ${ + this.publishDownloadSas.name + }| params: { ` + + `accountId: ${accountId},` + + `filePath: ${filePath} };`, ); let containerClient: ContainerClient; let blobClient: BlobClient; let sharedKeyCredential: StorageSharedKeyCredential; try { // コンテナ名を指定してClientを取得 - containerClient = this.getContainerClient(accountId, country); + containerClient = this.getContainerClient(context, accountId, country); // コンテナ内のBlobパス名を指定してClientを取得 blobClient = containerClient.getBlobClient(`${filePath}`); // 国に対応したリージョンの接続情報を取得する sharedKeyCredential = this.getSharedKeyCredential(country); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); this.logger.log( - `[OUT] [${context.trackingId}] ${this.publishDownloadSas.name}`, + `[OUT] [${context.getTrackingId()}] ${this.publishDownloadSas.name}`, ); throw e; } @@ -350,7 +392,7 @@ export class BlobstorageService { url.search = `${sasToken}`; this.logger.log( - `[OUT] [${context.trackingId}] ${ + `[OUT] [${context.getTrackingId()}] ${ this.publishDownloadSas.name }, url=${url.toString()}`, ); @@ -363,9 +405,16 @@ export class BlobstorageService { * @returns container client */ private getContainerClient( + context: Context, accountId: number, country: string, ): ContainerClient { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.getContainerClient.name + } | params: { ` + `accountId: ${accountId} };`, + ); + const containerName = `account-${accountId}`; if (BLOB_STORAGE_REGION_US.includes(country)) { return this.blobServiceClientUS.getContainerClient(containerName); diff --git a/dictation_server/src/gateways/notificationhub/notificationhub.service.ts b/dictation_server/src/gateways/notificationhub/notificationhub.service.ts index a18025d..fe60909 100644 --- a/dictation_server/src/gateways/notificationhub/notificationhub.service.ts +++ b/dictation_server/src/gateways/notificationhub/notificationhub.service.ts @@ -39,7 +39,9 @@ export class NotificationhubService { installationId: string, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${this.register.name} | params: { userId: ${userId}, pns: ${pns}, pnsHandler: ${pnsHandler}, installationId: ${installationId} }`, + `[IN] [${context.getTrackingId()}] ${ + this.register.name + } | params: { userId: ${userId}, pns: ${pns}, pnsHandler: ${pnsHandler}, installationId: ${installationId} }`, ); const tag = `user_${userId}`; @@ -69,10 +71,12 @@ export class NotificationhubService { throw new Error('invalid pns'); } } catch (e) { - this.logger.error(`error=${e.message}`); + this.logger.error(`[${context.getTrackingId()}] error=${e.message}`); throw e; } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.register.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.register.name}`, + ); } } @@ -89,7 +93,7 @@ export class NotificationhubService { bodyContent: NotificationBody, ): Promise { this.logger.log( - `[IN] [${context.trackingId}] ${ + `[IN] [${context.getTrackingId()}] ${ this.notify.name } | params: { tags: ${tags}, bodyContent: ${JSON.stringify( bodyContent, @@ -118,9 +122,9 @@ export class NotificationhubService { const result = await this.client.sendNotification(notification, { tagExpression, }); - this.logger.log(result); + this.logger.log(`[${context.getTrackingId()}] ${result}`); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); } // Apple try { @@ -134,15 +138,15 @@ export class NotificationhubService { const result = await this.client.sendNotification(notification, { tagExpression, }); - this.logger.log(result); + this.logger.log(`[${context.getTrackingId()}] ${result}`); } catch (e) { - this.logger.error(`error=${e}`); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); } } } catch (e) { throw e; } finally { - this.logger.log(`[OUT] ${this.notify.name}`); + this.logger.log(`[OUT] [${context.getTrackingId()}] ${this.notify.name}`); } } } diff --git a/dictation_server/src/gateways/redis/redis.service.ts b/dictation_server/src/gateways/redis/redis.service.ts index 1fd7445..10653d0 100644 --- a/dictation_server/src/gateways/redis/redis.service.ts +++ b/dictation_server/src/gateways/redis/redis.service.ts @@ -1,11 +1,6 @@ -import { - CACHE_MANAGER, - Inject, - Injectable, - InternalServerErrorException, - Logger, -} from '@nestjs/common'; +import { CACHE_MANAGER, Inject, Injectable, Logger } from '@nestjs/common'; import { Cache } from 'cache-manager'; +import { Context } from '../../common/log'; @Injectable() export class RedisService { @@ -20,10 +15,17 @@ export class RedisService { * @param ttl 有効期限(秒) */ async set( + context: Context, key: string, value: unknown, ttl?: number | undefined, ): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.set.name} | params: { ` + + `ttl: ${ttl} + };`, + ); + try { // cache-manager-redis-store がcache-managerのset形式と不一致な値の渡し方を採用しているため、 // @types/cache-managerのset形式を使用すると、redisに値が保存されない。 @@ -31,7 +33,7 @@ export class RedisService { // https://www.npmjs.com/package/cache-manager await this.cacheManager.set(key, value, { ttl: ttl } as any); } catch (error) { - this.logger.error(error); + this.logger.error(`[${context.getTrackingId()}] ${error}`); } } @@ -42,17 +44,24 @@ export class RedisService { * @param ttl 有効期限(秒) */ async mset( + context: Context, records: { key: string; value: T }[], ttl?: number | undefined, ): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.mset.name} | params: { ` + + `ttl: ${ttl} + };`, + ); + try { // cache-manager-redis-store のmsetが壊れており、利用できないため、 // 一つずつsetする。 for await (const record of records) { - await this.set(record.key, record.value, ttl); + await this.set(context, record.key, record.value, ttl); } } catch (error) { - this.logger.error(error); + this.logger.error(`[${context.getTrackingId()}] ${error}`); } } @@ -62,12 +71,14 @@ export class RedisService { * @param key キー * @returns キーに対応する値 */ - async get(key: string): Promise { + async get(context: Context, key: string): Promise { + this.logger.log(`[IN] [${context.getTrackingId()}] ${this.get.name};`); + try { const value = await this.cacheManager.get(key); return value; } catch (error) { - this.logger.error(error); + this.logger.error(`[${context.getTrackingId()}] ${error}`); return undefined; } } @@ -78,7 +89,12 @@ export class RedisService { * @param keys キーの配列 * @returns キーとそのキーに対応する値のペアの配列 */ - async mget(keys: string[]): Promise<{ key: string; value: T | null }[]> { + async mget( + context: Context, + keys: string[], + ): Promise<{ key: string; value: T | null }[]> { + this.logger.log(`[IN] [${context.getTrackingId()}] ${this.mget.name};`); + if (keys.length === 0) return []; // mget操作は0件の時エラーとなるため、0件は特別扱いする try { @@ -91,7 +107,7 @@ export class RedisService { }; }); } catch (error) { - this.logger.error(error); + this.logger.error(`[${context.getTrackingId()}] ${error}`); return []; } } @@ -100,11 +116,13 @@ export class RedisService { * キーに対応する値を削除する。 * @param key キー */ - async del(key: string): Promise { + async del(context: Context, key: string): Promise { + this.logger.log(`[IN] [${context.getTrackingId()}] ${this.del.name};`); + try { await this.cacheManager.del(key); } catch (error) { - this.logger.error(error); + this.logger.error(`[${context.getTrackingId()}] ${error}`); } } } diff --git a/dictation_server/src/gateways/sendgrid/sendgrid.service.ts b/dictation_server/src/gateways/sendgrid/sendgrid.service.ts index 6b94ddc..f611e65 100644 --- a/dictation_server/src/gateways/sendgrid/sendgrid.service.ts +++ b/dictation_server/src/gateways/sendgrid/sendgrid.service.ts @@ -23,7 +23,7 @@ export class SendGridService { * Email認証用のメールコンテンツを作成する * @param accountId 認証対象のユーザーが所属するアカウントのID * @param userId 認証対象のユーザーのID - * @param email 認証対象のユーザーのメールアドレス + * @param email 認証対象のユーザーのメールアドレス * @returns メールのサブジェクトとコンテンツ */ async createMailContentFromEmailConfirm( @@ -33,7 +33,11 @@ export class SendGridService { email: string, ): Promise<{ subject: string; text: string; html: string }> { this.logger.log( - `[IN] [${context.trackingId}] ${this.createMailContentFromEmailConfirm.name}`, + `[IN] [${context.getTrackingId()}] ${ + this.createMailContentFromEmailConfirm.name + } | params: { ` + + `accountId: ${accountId},` + + `userId: ${userId} };`, ); const privateKey = getPrivateKey(this.configService); @@ -49,7 +53,9 @@ export class SendGridService { const path = 'mail-confirm/'; this.logger.log( - `[OUT] [${context.trackingId}] ${this.createMailContentFromEmailConfirm.name}`, + `[OUT] [${context.getTrackingId()}] ${ + this.createMailContentFromEmailConfirm.name + }`, ); return { subject: 'Verify your new account', @@ -62,15 +68,23 @@ export class SendGridService { * Email認証用のメールコンテンツを作成する(一般ユーザ向け) * @param accountId 認証対象のユーザーが所属するアカウントのID * @param userId 認証対象のユーザーのID - * @param email 認証対象のユーザーのメールアドレス + * @param email 認証対象のユーザーのメールアドレス * @returns メールのサブジェクトとコンテンツ */ //TODO [Task2163] 中身が管理ユーザ向けのままなので、修正の必要あり async createMailContentFromEmailConfirmForNormalUser( + context: Context, accountId: number, userId: number, email: string, ): Promise<{ subject: string; text: string; html: string }> { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.createMailContentFromEmailConfirmForNormalUser.name + } | params: { ` + + `accountId: ${accountId},` + + `userId: ${userId} };`, + ); const privateKey = getPrivateKey(this.configService); const token = sign<{ accountId: number; userId: number; email: string }>( @@ -109,7 +123,7 @@ export class SendGridService { text: string, html: string, ): Promise { - this.logger.log(`[IN] [${context.trackingId}] ${this.sendMail.name}`); + this.logger.log(`[IN] [${context.getTrackingId()}] ${this.sendMail.name}`); try { const res = await sendgrid .send({ @@ -125,13 +139,17 @@ export class SendGridService { }) .then((v) => v[0]); this.logger.log( - `status code: ${res.statusCode} body: ${JSON.stringify(res.body)}`, + `[${context.getTrackingId()}] status code: ${ + res.statusCode + } body: ${JSON.stringify(res.body)}`, ); } catch (e) { - this.logger.error(e); + this.logger.error(`[${context.getTrackingId()}] error=${e}`); throw e; } finally { - this.logger.log(`[OUT] [${context.trackingId}] ${this.sendMail.name}`); + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.sendMail.name}`, + ); } } }