Merged PR 292: 外部連携APIにログを入れ込む(強化)

## 概要
[Task2294: 外部連携APIにログを入れ込む(強化)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2294)

- 外部連携APIのログを強化しました。
  - contextオブジェクトで操作者情報を渡すようにしています。
- ログポリシーに従って追加しています。
  - [ログポリシー](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/OMDSDictation/_wiki/wikis/OMDSDictation_wiki/223/%E3%83%AD%E3%82%B0%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC)

## レビューポイント
- 出力内容に過不足はないか
- ログ追加対象に過不足はないか。
- contextで操作者情報を渡しているが想定通りか

## UIの変更
- なし

## 動作確認状況
- ローカルで確認
This commit is contained in:
makabe.t 2023-08-02 01:07:02 +00:00
parent 2a54db7c8d
commit 794099f37d
21 changed files with 576 additions and 83 deletions

View File

@ -0,0 +1,7 @@
import { Context } from './types';
export const makeContext = (externaiId: string): Context => {
return {
trackingId: externaiId,
};
};

View File

@ -0,0 +1,4 @@
import { Context } from './types';
import { makeContext } from './context';
export { Context, makeContext };

View File

@ -0,0 +1,6 @@
export class Context {
/**
* APIの操作ユーザーを追跡するためのID
*/
trackingId: string;
}

View File

@ -278,7 +278,11 @@ export class AccountsService {
const externalIds = typistUsers.map((x) => x.external_id);
// B2Cからユーザー名を取得する
const adb2cUsers = await this.adB2cService.getUsers(externalIds);
const adb2cUsers = await this.adB2cService.getUsers(
// TODO: 外部連携以外のログ強化時に、ContollerからContextを取得するように修正する
{ trackingId: 'dummy' },
externalIds,
);
const typists = typistUsers.map((x) => {
const user = adb2cUsers.find((adb2c) => adb2c.id === x.external_id);

View File

@ -21,6 +21,8 @@ import {
TokenResponse,
} from './types/types';
import { retrieveAuthorizationToken } from '../../common/http/helper';
import { makeContext } from '../../common/log';
import { v4 as uuidv4 } from 'uuid';
@ApiTags('auth')
@Controller('auth')
@ -60,12 +62,16 @@ export class AuthController {
);
}
const context = makeContext(uuidv4());
const refreshToken = await this.authService.generateRefreshToken(
context,
idToken,
body.type,
);
const accessToken = await this.authService.generateAccessToken(
context,
refreshToken,
);
@ -98,6 +104,7 @@ export class AuthController {
})
async accessToken(@Req() req): Promise<AccessTokenResponse> {
const refreshToken = retrieveAuthorizationToken(req);
if (!refreshToken) {
throw new HttpException(
makeErrorResponse('E000107'),
@ -105,7 +112,10 @@ export class AuthController {
);
}
const context = makeContext(uuidv4());
const accessToken = await this.authService.generateAccessToken(
context,
refreshToken,
);
return { accessToken };

View File

@ -21,6 +21,7 @@ import { ADMIN_ROLES, USER_ROLES } from '../../constants';
import { AdB2cService } from '../../gateways/adb2c/adb2c.service';
import { User } from '../../repositories/users/entity/user.entity';
import { UsersRepositoryService } from '../../repositories/users/users.repository.service';
import { Context } from '../../common/log';
@Injectable()
export class AuthService {
@ -59,7 +60,14 @@ export class AuthService {
* @param type (web/desktop/mobile)
* @returns refresh token
*/
async generateRefreshToken(idToken: IDToken, type: string): Promise<string> {
async generateRefreshToken(
context: Context,
idToken: IDToken,
type: string,
): Promise<string> {
this.logger.log(
`[IN] [${context.trackingId}] ${this.generateRefreshToken.name}`,
);
const lifetimeWeb = this.configService.get('REFRESH_TOKEN_LIFETIME_WEB');
const lifetimeDefault = this.configService.get(
'REFRESH_TOKEN_LIFETIME_DEFAULT',
@ -73,6 +81,9 @@ export class AuthService {
}
} catch (e) {
this.logger.error(`error=${e}`);
this.logger.log(
`[OUT] [${context.trackingId}] ${this.generateRefreshToken.name}`,
);
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
@ -86,6 +97,9 @@ export class AuthService {
this.logger.error(
`Tier from DB is unexpected value. tier=${user.account.tier}`,
);
this.logger.log(
`[OUT] [${context.trackingId}] ${this.generateRefreshToken.name}`,
);
throw new HttpException(
makeErrorResponse('E010206'),
HttpStatus.INTERNAL_SERVER_ERROR,
@ -108,6 +122,9 @@ export class AuthService {
role = USER_ROLES.TYPIST;
} else {
this.logger.error(`Role from DB is unexpected value. role=${user.role}`);
this.logger.log(
`[OUT] [${context.trackingId}] ${this.generateRefreshToken.name}`,
);
throw new HttpException(
makeErrorResponse('E010205'),
HttpStatus.INTERNAL_SERVER_ERROR,
@ -129,6 +146,10 @@ export class AuthService {
refreshTokenLifetime,
privateKey,
);
this.logger.log(
`[OUT] [${context.trackingId}] ${this.generateRefreshToken.name}`,
);
return token;
}
@ -137,7 +158,13 @@ export class AuthService {
* @param refreshToken (jwt)
* @returns access token(jwt)
*/
async generateAccessToken(refreshToken: string): Promise<string> {
async generateAccessToken(
context: Context,
refreshToken: string,
): Promise<string> {
this.logger.log(
`[IN] [${context.trackingId}] ${this.generateAccessToken.name}`,
);
const lifetime = this.configService.get('ACCESS_TOKEN_LIFETIME_WEB');
const privateKey = getPrivateKey(this.configService);
@ -146,6 +173,9 @@ export class AuthService {
const token = verify<RefreshToken>(refreshToken, pubkey);
if (isVerifyError(token)) {
this.logger.error(`${token.reason} | ${token.message}`);
this.logger.log(
`[OUT] [${context.trackingId}] ${this.generateAccessToken.name}`,
);
throw new HttpException(
makeErrorResponse('E000101'),
HttpStatus.UNAUTHORIZED,
@ -162,6 +192,9 @@ export class AuthService {
privateKey,
);
this.logger.log(
`[OUT] [${context.trackingId}] ${this.generateAccessToken.name}`,
);
return accessToken;
}
/**

View File

@ -33,6 +33,7 @@ import { RoleGuard } from '../../common/guards/role/roleguards';
import { USER_ROLES } from '../../constants';
import { retrieveAuthorizationToken } from '../../common/http/helper';
import { Request } from 'express';
import { makeContext } from '../../common/log';
@ApiTags('files')
@Controller('files')
@ -75,6 +76,8 @@ export class FilesController {
const token = retrieveAuthorizationToken(req);
const accessToken = jwt.decode(token, { json: true }) as AccessToken;
const context = makeContext(accessToken.userId);
const {
url,
authorId,
@ -93,6 +96,7 @@ export class FilesController {
} = body;
const res = await this.filesService.uploadFinished(
context,
accessToken.userId,
url,
authorId,
@ -146,7 +150,10 @@ export class FilesController {
): Promise<AudioUploadLocationResponse> {
const token = retrieveAuthorizationToken(req);
const accessToken = jwt.decode(token, { json: true }) as AccessToken;
const url = await this.filesService.publishUploadSas(accessToken);
const context = makeContext(accessToken.userId);
const url = await this.filesService.publishUploadSas(context, accessToken);
return { url };
}
@ -189,7 +196,11 @@ export class FilesController {
const token = retrieveAuthorizationToken(req);
const accessToken = jwt.decode(token, { json: true }) as AccessToken;
const context = makeContext(accessToken.userId);
const url = await this.filesService.publishAudioFileDownloadSas(
context,
accessToken.userId,
audioFileId,
);
@ -236,7 +247,11 @@ export class FilesController {
const token = retrieveAuthorizationToken(req);
const accessToken = jwt.decode(token, { json: true }) as AccessToken;
const context = makeContext(accessToken.userId);
const url = await this.filesService.publishTemplateFileDownloadSas(
context,
accessToken.userId,
audioFileId,
);

View File

@ -14,6 +14,7 @@ import {
makeTestingModuleWithBlob,
} from './test/utility';
import { FilesService } from './files.service';
import { makeContext } from '../../common/log';
describe('音声ファイルアップロードURL取得', () => {
it('アップロードSASトークンが乗っているURLを返却する', async () => {
@ -27,7 +28,7 @@ describe('音声ファイルアップロードURL取得', () => {
);
expect(
await service.publishUploadSas({
await service.publishUploadSas(makeContext('trackingId'), {
userId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
role: 'Author',
tier: 5,
@ -49,7 +50,7 @@ describe('音声ファイルアップロードURL取得', () => {
);
expect(
await service.publishUploadSas({
await service.publishUploadSas(makeContext('trackingId'), {
userId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
role: 'Author',
tier: 5,
@ -70,7 +71,7 @@ describe('音声ファイルアップロードURL取得', () => {
);
await expect(
service.publishUploadSas({
service.publishUploadSas(makeContext('trackingId'), {
userId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
role: 'Author',
tier: 5,
@ -94,7 +95,7 @@ describe('音声ファイルアップロードURL取得', () => {
blobParam.publishUploadSas = new Error('Azure service down');
await expect(
service.publishUploadSas({
service.publishUploadSas(makeContext('trackingId'), {
userId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
role: 'Author',
tier: 5,
@ -118,6 +119,7 @@ describe('タスク作成', () => {
expect(
await service.uploadFinished(
makeContext('trackingId'),
'userId',
'http://blob/url/file.zip',
'AUTHOR_01',
@ -149,6 +151,7 @@ describe('タスク作成', () => {
await expect(
service.uploadFinished(
makeContext('trackingId'),
'userId',
'http://blob/url/file.zip',
'AUTHOR_01',
@ -182,6 +185,7 @@ describe('タスク作成', () => {
await expect(
service.uploadFinished(
makeContext('trackingId'),
'userId',
'http://blob/url/file.zip',
'AUTHOR_01',
@ -222,6 +226,7 @@ describe('タスク作成', () => {
await expect(
service.uploadFinished(
makeContext('trackingId'),
'userId',
'http://blob/url/file.zip',
'AUTHOR_01',
@ -256,6 +261,7 @@ describe('タスク作成', () => {
await expect(
service.uploadFinished(
makeContext('trackingId'),
'userId',
'http://blob/url/file.zip',
'AUTHOR_01',
@ -328,7 +334,11 @@ describe('音声ファイルダウンロードURL取得', () => {
const service = module.get<FilesService>(FilesService);
expect(
await service.publishAudioFileDownloadSas(externalId, audioFileId),
await service.publishAudioFileDownloadSas(
makeContext('trackingId'),
externalId,
audioFileId,
),
).toEqual(`${url}?sas-token`);
});
@ -367,7 +377,11 @@ describe('音声ファイルダウンロードURL取得', () => {
const service = module.get<FilesService>(FilesService);
await expect(
service.publishAudioFileDownloadSas(externalId, audioFileId),
service.publishAudioFileDownloadSas(
makeContext('trackingId'),
externalId,
audioFileId,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010603'), HttpStatus.BAD_REQUEST),
);
@ -413,7 +427,11 @@ describe('音声ファイルダウンロードURL取得', () => {
const service = module.get<FilesService>(FilesService);
await expect(
service.publishTemplateFileDownloadSas(externalId, audioFileId),
service.publishTemplateFileDownloadSas(
makeContext('tracking'),
externalId,
audioFileId,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010603'), HttpStatus.BAD_REQUEST),
);
@ -448,7 +466,11 @@ describe('音声ファイルダウンロードURL取得', () => {
const service = module.get<FilesService>(FilesService);
await expect(
service.publishAudioFileDownloadSas(externalId, audioFileId),
service.publishAudioFileDownloadSas(
makeContext('trackingId'),
externalId,
audioFileId,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010603'), HttpStatus.BAD_REQUEST),
);
@ -470,7 +492,11 @@ describe('音声ファイルダウンロードURL取得', () => {
const service = module.get<FilesService>(FilesService);
await expect(
service.publishAudioFileDownloadSas(externalId, 1),
service.publishAudioFileDownloadSas(
makeContext('trackingId'),
externalId,
1,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010603'), HttpStatus.BAD_REQUEST),
);
@ -505,7 +531,11 @@ describe('音声ファイルダウンロードURL取得', () => {
const service = module.get<FilesService>(FilesService);
await expect(
service.publishAudioFileDownloadSas(externalId, audioFileId),
service.publishAudioFileDownloadSas(
makeContext('trackingId'),
externalId,
audioFileId,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010701'), HttpStatus.BAD_REQUEST),
);
@ -559,7 +589,11 @@ describe('テンプレートファイルダウンロードURL取得', () => {
const service = module.get<FilesService>(FilesService);
expect(
await service.publishTemplateFileDownloadSas(externalId, audioFileId),
await service.publishTemplateFileDownloadSas(
makeContext('tracking'),
externalId,
audioFileId,
),
).toEqual(`${url}?sas-token`);
});
@ -591,7 +625,11 @@ describe('テンプレートファイルダウンロードURL取得', () => {
const service = module.get<FilesService>(FilesService);
await expect(
service.publishTemplateFileDownloadSas(externalId, audioFileId),
service.publishTemplateFileDownloadSas(
makeContext('tracking'),
externalId,
audioFileId,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010603'), HttpStatus.BAD_REQUEST),
);
@ -632,7 +670,11 @@ describe('テンプレートファイルダウンロードURL取得', () => {
const service = module.get<FilesService>(FilesService);
await expect(
service.publishTemplateFileDownloadSas(externalId, audioFileId),
service.publishTemplateFileDownloadSas(
makeContext('tracking'),
externalId,
audioFileId,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010603'), HttpStatus.BAD_REQUEST),
);
@ -667,7 +709,11 @@ describe('テンプレートファイルダウンロードURL取得', () => {
const service = module.get<FilesService>(FilesService);
await expect(
service.publishTemplateFileDownloadSas(externalId, audioFileId),
service.publishTemplateFileDownloadSas(
makeContext('tracking'),
externalId,
audioFileId,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010603'), HttpStatus.BAD_REQUEST),
);
@ -689,7 +735,11 @@ describe('テンプレートファイルダウンロードURL取得', () => {
const service = module.get<FilesService>(FilesService);
await expect(
service.publishTemplateFileDownloadSas(externalId, 1),
service.publishTemplateFileDownloadSas(
makeContext('tracking'),
externalId,
1,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010603'), HttpStatus.BAD_REQUEST),
);
@ -724,7 +774,11 @@ describe('テンプレートファイルダウンロードURL取得', () => {
const service = module.get<FilesService>(FilesService);
await expect(
service.publishTemplateFileDownloadSas(externalId, audioFileId),
service.publishTemplateFileDownloadSas(
makeContext('tracking'),
externalId,
audioFileId,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010701'), HttpStatus.BAD_REQUEST),
);

View File

@ -22,6 +22,7 @@ import {
TasksNotFoundError,
TypistUserNotFoundError,
} from '../../repositories/tasks/errors/types';
import { Context } from '../../common/log';
@Injectable()
export class FilesService {
@ -52,6 +53,7 @@ export class FilesService {
* @returns finished
*/
async uploadFinished(
context: Context,
userId: string,
url: string,
authorId: string,
@ -68,6 +70,24 @@ export class FilesService {
optionItemList: AudioOptionItem[],
isEncrypted: boolean,
): Promise<AudioUploadFinishedResponse> {
this.logger.log(
`[IN] [${context.trackingId}] ${this.uploadFinished.name} | params: { ` +
`url: ${url}, ` +
`authorId: ${authorId}, ` +
`fileName: ${fileName}, ` +
`duration: ${duration}, ` +
`createdDate: ${createdDate}, ` +
`finishedDate: ${finishedDate}, ` +
`uploadedDate: ${uploadedDate}, ` +
`fileSize: ${fileSize}, ` +
`priority: ${priority}, ` +
`audioFormat: ${audioFormat}, ` +
`comment: ${comment}, ` +
`workType: ${workType}, ` +
`optionItemList: ${JSON.stringify(optionItemList)}, ` +
`isEncrypted: ${isEncrypted} };`,
);
const formattedCreatedDate = new Date(createdDate);
const formattedFinishedDate = new Date(finishedDate);
const formattedUploadedDate = new Date(uploadedDate);
@ -97,6 +117,9 @@ export class FilesService {
`param uploadedDate is invalid format:[uploadedDate=${uploadedDate}]`,
);
}
this.logger.log(
`[OUT] [${context.trackingId}] ${this.uploadFinished.name}`,
);
throw new HttpException(
makeErrorResponse('E010001'),
@ -109,6 +132,9 @@ export class FilesService {
this.logger.error(
`param optionItemList expects ${OPTION_ITEM_NUM} items, but has ${optionItemList.length} items`,
);
this.logger.log(
`[OUT] [${context.trackingId}] ${this.uploadFinished.name}`,
);
throw new HttpException(
makeErrorResponse('E010001'),
HttpStatus.BAD_REQUEST,
@ -121,6 +147,9 @@ export class FilesService {
user = await this.usersRepository.findUserByExternalId(userId);
} catch (e) {
this.logger.error(`error=${e}`);
this.logger.log(
`[OUT] [${context.trackingId}] ${this.uploadFinished.name}`,
);
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
@ -161,6 +190,10 @@ export class FilesService {
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
} finally {
this.logger.log(
`[OUT] [${context.trackingId}] ${this.uploadFinished.name}`,
);
}
}
@ -169,7 +202,14 @@ export class FilesService {
* @param companyName
* @returns upload sas
*/
async publishUploadSas(token: AccessToken): Promise<string> {
async publishUploadSas(
context: Context,
token: AccessToken,
): Promise<string> {
this.logger.log(
`[IN] [${context.trackingId}] ${this.publishUploadSas.name}`,
);
//DBから国情報とアカウントIDを取得する
let accountId: number;
let country: string;
@ -183,6 +223,9 @@ export class FilesService {
country = user.account.country;
} catch (e) {
this.logger.error(`error=${e}`);
this.logger.log(
`[OUT] [${context.trackingId}] ${this.publishUploadSas.name}`,
);
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
@ -192,6 +235,7 @@ export class FilesService {
try {
// 国に応じたリージョンのBlobストレージにコンテナが存在するか確認
const isContainerExist = await this.blobStorageService.containerExists(
context,
accountId,
country,
);
@ -201,6 +245,9 @@ export class FilesService {
}
} catch (e) {
this.logger.error(`error=${e}`);
this.logger.log(
`[OUT] [${context.trackingId}] ${this.publishUploadSas.name}`,
);
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
@ -210,6 +257,7 @@ export class FilesService {
try {
// SASトークン発行
const url = await this.blobStorageService.publishUploadSas(
context,
accountId,
userId,
country,
@ -221,6 +269,10 @@ export class FilesService {
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
} finally {
this.logger.log(
`[OUT] [${context.trackingId}] ${this.publishUploadSas.name}`,
);
}
}
@ -231,9 +283,14 @@ export class FilesService {
* @returns audio file download sas
*/
async publishAudioFileDownloadSas(
context: Context,
externalId: string,
audioFileId: number,
): Promise<string> {
this.logger.log(
`[IN] [${context.trackingId}] ${this.publishAudioFileDownloadSas.name} | params: { externalId: ${externalId}, audioFileId: ${audioFileId} };`,
);
//DBから国情報とアカウントID,ユーザーIDを取得する
let accountId: number;
let userId: number;
@ -250,7 +307,10 @@ export class FilesService {
authorId = user.author_id;
} catch (e) {
this.logger.error(`error=${e}`);
console.log(e);
this.logger.log(
`[OUT] [${context.trackingId}] ${this.publishAudioFileDownloadSas.name}`,
);
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
@ -294,6 +354,7 @@ export class FilesService {
const filePath = `${file.owner_user_id}/${file.file_name}`;
const isFileExist = await this.blobStorageService.fileExists(
context,
accountId,
country,
filePath,
@ -308,6 +369,7 @@ export class FilesService {
// SASトークン発行
const url = await this.blobStorageService.publishDownloadSas(
context,
accountId,
country,
filePath,
@ -342,6 +404,10 @@ export class FilesService {
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
} finally {
this.logger.log(
`[OUT] [${context.trackingId}] ${this.publishAudioFileDownloadSas.name}`,
);
}
}
@ -352,9 +418,14 @@ export class FilesService {
* @returns template file download sas
*/
async publishTemplateFileDownloadSas(
context: Context,
externalId: string,
audioFileId: number,
): Promise<string> {
this.logger.log(
`[IN] [${context.trackingId}] ${this.publishTemplateFileDownloadSas.name} | params: { externalId: ${externalId}, audioFileId: ${audioFileId} };`,
);
//DBから国情報とアカウントID,ユーザーIDを取得する
let accountId: number;
let userId: number;
@ -370,7 +441,9 @@ export class FilesService {
authorId = user.author_id;
} catch (e) {
this.logger.error(`error=${e}`);
console.log(e);
this.logger.log(
`[OUT] [${context.trackingId}] ${this.publishTemplateFileDownloadSas.name}`,
);
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
@ -415,6 +488,7 @@ export class FilesService {
const filePath = `Templates/${template_file.file_name}`;
const isFileExist = await this.blobStorageService.fileExists(
context,
accountId,
country,
filePath,
@ -428,6 +502,7 @@ export class FilesService {
// SASトークン発行
const url = await this.blobStorageService.publishDownloadSas(
context,
accountId,
country,
filePath,
@ -462,6 +537,10 @@ export class FilesService {
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
} finally {
this.logger.log(
`[OUT] [${context.trackingId}] ${this.publishTemplateFileDownloadSas.name}`,
);
}
}
}

View File

@ -20,6 +20,7 @@ import { AuthGuard } from '../../common/guards/auth/authguards';
import { retrieveAuthorizationToken } from '../../common/http/helper';
import { AccessToken } from '../../common/token';
import jwt from 'jsonwebtoken';
import { makeContext } from '../../common/log';
@ApiTags('notification')
@Controller('notification')
@ -58,7 +59,9 @@ export class NotificationController {
const accessToken = retrieveAuthorizationToken(req);
const { userId } = jwt.decode(accessToken, { json: true }) as AccessToken;
await this.notificationService.register(userId, pns, handler);
const context = makeContext(userId);
await this.notificationService.register(context, userId, pns, handler);
return {};
}
}

View File

@ -5,6 +5,7 @@ import {
makeDefaultUsersRepositoryMockValue,
} from './test/notification.service.mock';
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
import { makeContext } from '../../common/log';
describe('NotificationService.register', () => {
it('ユーザーから渡されたPNSハンドルをNotificationHubに登録できる', async () => {
@ -16,9 +17,14 @@ describe('NotificationService.register', () => {
notificationHubMockValue,
);
expect(await service.register('external_id', 'apns', 'handler')).toEqual(
undefined,
);
expect(
await service.register(
makeContext('trackingId'),
'external_id',
'apns',
'handler',
),
).toEqual(undefined);
});
it('DBからのユーザー取得に失敗した場合、エラーとなる', async () => {
const notificationHubMockValue = makeDefaultNotificationHubMockValue();
@ -31,7 +37,12 @@ describe('NotificationService.register', () => {
);
await expect(
service.register('external_id', 'apns', 'handler'),
service.register(
makeContext('trackingId'),
'external_id',
'apns',
'handler',
),
).rejects.toEqual(
new HttpException(
makeErrorResponse('E009999'),
@ -51,7 +62,12 @@ describe('NotificationService.register', () => {
);
await expect(
service.register('external_id', 'apns', 'handler'),
service.register(
makeContext('trackingId'),
'external_id',
'apns',
'handler',
),
).rejects.toEqual(
new HttpException(
makeErrorResponse('E009999'),

View File

@ -4,6 +4,7 @@ import { NotificationhubService } from '../../gateways/notificationhub/notificat
import { UsersRepositoryService } from '../../repositories/users/users.repository.service';
import { UserNotFoundError } from '../../repositories/users/errors/types';
import { v4 as uuidv4 } from 'uuid';
import { Context } from '../../common/log';
@Injectable()
export class NotificationService {
@ -19,11 +20,14 @@ export class NotificationService {
* @returns register
*/
async register(
context: Context,
externalId: string,
pns: string,
pnsHandler: string,
): Promise<void> {
this.logger.log(`[IN] ${this.register.name}`);
this.logger.log(
`[IN] [${context.trackingId}] ${this.register.name} | params: { externalId: ${externalId}, pns: ${pns}, pnsHandler: ${pnsHandler} }`,
);
// ユーザIDからアカウントIDを取得する
let userId: number;
@ -52,6 +56,7 @@ export class NotificationService {
this.logger.log(installationId);
await this.notificationhubService.register(
context,
userId,
pns,
pnsHandler,
@ -64,7 +69,7 @@ export class NotificationService {
HttpStatus.INTERNAL_SERVER_ERROR,
);
} finally {
this.logger.log(`[OUT] ${this.register.name}`);
this.logger.log(`[OUT] [${context.trackingId}] ${this.register.name}`);
}
}
}

View File

@ -42,6 +42,7 @@ import { AuthGuard } from '../../common/guards/auth/authguards';
import { RoleGuard } from '../../common/guards/role/roleguards';
import { ADMIN_ROLES, USER_ROLES } from '../../constants';
import { Roles } from '../../common/types/role';
import { makeContext } from '../../common/log';
@ApiTags('tasks')
@Controller('tasks')
@ -82,6 +83,8 @@ export class TasksController {
const accessToken = retrieveAuthorizationToken(req);
const decodedToken = jwt.decode(accessToken, { json: true }) as AccessToken;
const context = makeContext(decodedToken.userId);
const { limit, offset, status } = body;
const paramName = isTaskListSortableAttribute(body.paramName)
? body.paramName
@ -91,6 +94,7 @@ export class TasksController {
: undefined;
const { tasks, total } = await this.taskService.getTasks(
context,
decodedToken,
offset,
limit,
@ -189,7 +193,9 @@ export class TasksController {
// RoleGuardでroleの文字列に想定外の文字列や重複がないことは担保されているためここでは型変換のみ行う
const roles = role.split(' ') as Roles[];
await this.taskService.checkout(param.audioFileId, roles, userId);
const context = makeContext(userId);
await this.taskService.checkout(context, param.audioFileId, roles, userId);
return {};
}
@ -242,7 +248,9 @@ export class TasksController {
json: true,
}) as AccessToken;
await this.taskService.checkin(audioFileId, userId);
const context = makeContext(userId);
await this.taskService.checkin(context, audioFileId, userId);
return {};
}
@ -296,7 +304,10 @@ export class TasksController {
}) as AccessToken;
// RoleGuardでroleの文字列に想定外の文字列や重複がないことは担保されているためここでは型変換のみ行う
const roles = role.split(' ') as Roles[];
await this.taskService.cancel(audioFileId, userId, roles);
const context = makeContext(userId);
await this.taskService.cancel(context, audioFileId, userId, roles);
return {};
}
@ -349,7 +360,9 @@ export class TasksController {
json: true,
}) as AccessToken;
await this.taskService.suspend(audioFileId, userId);
const context = makeContext(userId);
await this.taskService.suspend(context, audioFileId, userId);
return {};
}
@ -494,7 +507,10 @@ export class TasksController {
// RoleGuardでroleの文字列に想定外の文字列や重複がないことは担保されているためここでは型変換のみ行う
const roles = role.split(' ') as Roles[];
const context = makeContext(userId);
await this.taskService.changeCheckoutPermission(
context,
audioFileId,
assignees,
userId,

View File

@ -21,6 +21,7 @@ import {
makeTaskTestingModule,
} from './test/utility';
import { Adb2cTooManyRequestsError } from '../../gateways/adb2c/adb2c.service';
import { makeContext } from '../../common/log';
describe('TasksService', () => {
it('タスク一覧を取得できるadmin', async () => {
@ -47,6 +48,7 @@ describe('TasksService', () => {
const direction = 'ASC';
expect(
await service.tasksService.getTasks(
makeContext('trackingId'),
accessToken,
offset,
limit,
@ -121,6 +123,7 @@ describe('TasksService', () => {
const direction = 'ASC';
await expect(
service.tasksService.getTasks(
makeContext('trackingId'),
accessToken,
offset,
limit,
@ -161,6 +164,7 @@ describe('TasksService', () => {
const direction = 'ASC';
await expect(
service.tasksService.getTasks(
makeContext('trackingId'),
accessToken,
offset,
limit,
@ -234,6 +238,7 @@ describe('TasksService', () => {
const direction = 'ASC';
await expect(
service.tasksService.getTasks(
makeContext('trackingId'),
accessToken,
offset,
limit,
@ -276,6 +281,7 @@ describe('TasksService', () => {
const paramName = 'JOB_NUMBER';
const direction = 'ASC';
const result = await service.tasksService.getTasks(
makeContext('trackingId'),
accessToken,
offset,
limit,
@ -357,6 +363,7 @@ describe('TasksService', () => {
const direction = 'ASC';
await expect(
service.tasksService.getTasks(
makeContext('trackingId'),
accessToken,
offset,
limit,
@ -400,6 +407,7 @@ describe('TasksService', () => {
const paramName = 'JOB_NUMBER';
const direction = 'ASC';
const result = await service.tasksService.getTasks(
makeContext('trackingId'),
accessToken,
offset,
limit,
@ -481,6 +489,7 @@ describe('TasksService', () => {
const direction = 'ASC';
await expect(
service.tasksService.getTasks(
makeContext('trackingId'),
accessToken,
offset,
limit,
@ -520,6 +529,7 @@ describe('TasksService', () => {
const direction = 'ASC';
await expect(
service.tasksService.getTasks(
makeContext('trackingId'),
accessToken,
offset,
limit,
@ -560,6 +570,7 @@ describe('TasksService', () => {
const direction = 'ASC';
await expect(
service.tasksService.getTasks(
makeContext('trackingId'),
accessToken,
offset,
limit,
@ -617,6 +628,7 @@ describe('TasksService', () => {
const direction = 'ASC';
const { tasks, total } = await service.getTasks(
makeContext('trackingId'),
accessToken,
offset,
limit,
@ -672,6 +684,7 @@ describe('TasksService', () => {
const direction = 'ASC';
const { tasks, total } = await service.getTasks(
makeContext('trackingId'),
accessToken,
offset,
limit,
@ -743,6 +756,7 @@ describe('TasksService', () => {
const direction = 'ASC';
const { tasks, total } = await service.getTasks(
makeContext('trackingId'),
accessToken,
offset,
limit,
@ -824,6 +838,7 @@ describe('changeCheckoutPermission', () => {
await createCheckoutPermissions(source, taskId, undefined, userGroupId);
const service = module.get<TasksService>(TasksService);
await service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[{ typistName: 'typist-user-2', typistUserId: typistUserId_2 }],
'author-user-external-id',
@ -892,6 +907,7 @@ describe('changeCheckoutPermission', () => {
await createCheckoutPermissions(source, taskId, undefined, userGroupId_1);
const service = module.get<TasksService>(TasksService);
await service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[{ typistName: 'USER_GROUP_B', typistGroupId: userGroupId_2 }],
'author-user-external-id',
@ -947,9 +963,13 @@ describe('changeCheckoutPermission', () => {
await createCheckoutPermissions(source, taskId, typistUserId_1);
await createCheckoutPermissions(source, taskId, undefined, userGroupId);
const service = module.get<TasksService>(TasksService);
await service.changeCheckoutPermission(1, [], 'author-user-external-id', [
'admin',
]);
await service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[],
'author-user-external-id',
['admin'],
);
const permisions = await getCheckoutPermissions(source, taskId);
expect(permisions.length).toEqual(0);
});
@ -997,6 +1017,7 @@ describe('changeCheckoutPermission', () => {
await expect(
service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[{ typistName: 'not-exist-user', typistUserId: 999 }],
'author-user-external-id',
@ -1050,6 +1071,7 @@ describe('changeCheckoutPermission', () => {
await expect(
service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[{ typistName: 'not-exist-user-group', typistGroupId: 999 }],
'author-user-external-id',
@ -1085,6 +1107,7 @@ describe('changeCheckoutPermission', () => {
await expect(
service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[{ typistName: 'typist-user', typistUserId: typistUserId }],
'author-user-external-id',
@ -1130,6 +1153,7 @@ describe('changeCheckoutPermission', () => {
await expect(
service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[{ typistName: 'typist-user', typistUserId: typistUserId }],
'author-user-external-id',
@ -1175,6 +1199,7 @@ describe('changeCheckoutPermission', () => {
await expect(
service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[{ typistName: 'typist-user', typistUserId: typistUserId }],
'author-user-external-id',
@ -1235,6 +1260,7 @@ describe('changeCheckoutPermission', () => {
await expect(
service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[{ typistName: 'typist-user-2', typistUserId: typistUserId_2 }],
'author-user-external-id',
@ -1311,7 +1337,12 @@ describe('checkout', () => {
const initTask = await getTask(source, taskId);
await service.checkout(1, ['typist'], 'typist-user-external-id');
await service.checkout(
makeContext('trackingId'),
1,
['typist'],
'typist-user-external-id',
);
const { status, typist_user_id, started_at } = await getTask(
source,
taskId,
@ -1374,7 +1405,12 @@ describe('checkout', () => {
const initTask = await getTask(source, taskId);
await service.checkout(1, ['typist'], 'typist-user-external-id');
await service.checkout(
makeContext('trackingId'),
1,
['typist'],
'typist-user-external-id',
);
const { status, typist_user_id, started_at } = await getTask(
source,
taskId,
@ -1430,7 +1466,12 @@ describe('checkout', () => {
const initTask = await getTask(source, taskId);
await service.checkout(1, ['typist'], 'typist-user-external-id');
await service.checkout(
makeContext('trackingId'),
1,
['typist'],
'typist-user-external-id',
);
const { status, typist_user_id, started_at } = await getTask(
source,
taskId,
@ -1485,7 +1526,12 @@ describe('checkout', () => {
const service = module.get<TasksService>(TasksService);
await expect(
service.checkout(1, ['typist'], 'typist-user-external-id'),
service.checkout(
makeContext('trackingId'),
1,
['typist'],
'typist-user-external-id',
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010601'), HttpStatus.BAD_REQUEST),
);
@ -1526,7 +1572,12 @@ describe('checkout', () => {
const service = module.get<TasksService>(TasksService);
await expect(
service.checkout(1, ['typist'], 'typist-user-external-id'),
service.checkout(
makeContext('trackingId'),
1,
['typist'],
'typist-user-external-id',
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010602'), HttpStatus.BAD_REQUEST),
);
@ -1560,7 +1611,12 @@ describe('checkout', () => {
const service = module.get<TasksService>(TasksService);
expect(
await service.checkout(1, ['author'], 'author-user-external-id'),
await service.checkout(
makeContext('trackingId'),
1,
['author'],
'author-user-external-id',
),
).toEqual(undefined);
});
@ -1592,7 +1648,12 @@ describe('checkout', () => {
const service = module.get<TasksService>(TasksService);
expect(
await service.checkout(1, ['author'], 'author-user-external-id'),
await service.checkout(
makeContext('trackingId'),
1,
['author'],
'author-user-external-id',
),
).toEqual(undefined);
});
@ -1614,7 +1675,12 @@ describe('checkout', () => {
const service = module.get<TasksService>(TasksService);
await expect(
service.checkout(1, ['author'], 'author-user-external-id'),
service.checkout(
makeContext('trackingId'),
1,
['author'],
'author-user-external-id',
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010601'), HttpStatus.BAD_REQUEST),
);
@ -1648,7 +1714,12 @@ describe('checkout', () => {
const service = module.get<TasksService>(TasksService);
await expect(
service.checkout(1, ['author'], 'author-user-external-id'),
service.checkout(
makeContext('trackingId'),
1,
['author'],
'author-user-external-id',
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010602'), HttpStatus.BAD_REQUEST),
);
@ -1672,7 +1743,12 @@ describe('checkout', () => {
const service = module.get<TasksService>(TasksService);
await expect(
service.checkout(1, ['none'], 'none-user-external-id'),
service.checkout(
makeContext('trackingId'),
1,
['none'],
'none-user-external-id',
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010602'), HttpStatus.BAD_REQUEST),
);
@ -1735,7 +1811,11 @@ describe('checkin', () => {
const initTask = await getTask(source, taskId);
await service.checkin(1, 'typist-user-external-id');
await service.checkin(
makeContext('trackingId'),
1,
'typist-user-external-id',
);
const { status, finished_at } = await getTask(source, taskId);
expect(status).toEqual('Finished');
@ -1777,7 +1857,9 @@ describe('checkin', () => {
await createCheckoutPermissions(source, taskId, typistUserId);
const service = module.get<TasksService>(TasksService);
await expect(service.checkin(1, 'typist-user-external-id')).rejects.toEqual(
await expect(
service.checkin(makeContext('trackingId'), 1, 'typist-user-external-id'),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010601'), HttpStatus.BAD_REQUEST),
);
});
@ -1819,7 +1901,9 @@ describe('checkin', () => {
const service = module.get<TasksService>(TasksService);
await expect(service.checkin(1, 'typist-user-external-id')).rejects.toEqual(
await expect(
service.checkin(makeContext('trackingId'), 1, 'typist-user-external-id'),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010601'), HttpStatus.BAD_REQUEST),
);
});
@ -1844,7 +1928,9 @@ describe('checkin', () => {
const service = module.get<TasksService>(TasksService);
await expect(service.checkin(1, 'typist-user-external-id')).rejects.toEqual(
await expect(
service.checkin(makeContext('trackingId'), 1, 'typist-user-external-id'),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010603'), HttpStatus.NOT_FOUND),
);
});
@ -1903,7 +1989,11 @@ describe('suspend', () => {
const service = module.get<TasksService>(TasksService);
await service.suspend(1, 'typist-user-external-id');
await service.suspend(
makeContext('trackingId'),
1,
'typist-user-external-id',
);
const { status } = await getTask(source, taskId);
expect(status).toEqual('Pending');
@ -1944,7 +2034,9 @@ describe('suspend', () => {
await createCheckoutPermissions(source, taskId, typistUserId);
const service = module.get<TasksService>(TasksService);
await expect(service.suspend(1, 'typist-user-external-id')).rejects.toEqual(
await expect(
service.suspend(makeContext('trackingId'), 1, 'typist-user-external-id'),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010601'), HttpStatus.BAD_REQUEST),
);
});
@ -1986,7 +2078,9 @@ describe('suspend', () => {
const service = module.get<TasksService>(TasksService);
await expect(service.checkin(1, 'typist-user-external-id')).rejects.toEqual(
await expect(
service.checkin(makeContext('trackingId'), 1, 'typist-user-external-id'),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010601'), HttpStatus.BAD_REQUEST),
);
});
@ -2011,7 +2105,9 @@ describe('suspend', () => {
const service = module.get<TasksService>(TasksService);
await expect(service.checkin(1, 'typist-user-external-id')).rejects.toEqual(
await expect(
service.checkin(makeContext('trackingId'), 1, 'typist-user-external-id'),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010603'), HttpStatus.NOT_FOUND),
);
});
@ -2071,7 +2167,12 @@ describe('cancel', () => {
const service = module.get<TasksService>(TasksService);
await service.cancel(1, 'typist-user-external-id', ['typist', 'standard']);
await service.cancel(
makeContext('trackingId'),
1,
'typist-user-external-id',
['typist', 'standard'],
);
const { status, typist_user_id } = await getTask(source, taskId);
const permisions = await getCheckoutPermissions(source, taskId);
@ -2115,7 +2216,12 @@ describe('cancel', () => {
await createCheckoutPermissions(source, taskId, typistUserId);
const service = module.get<TasksService>(TasksService);
await service.cancel(1, 'typist-user-external-id', ['typist', 'standard']);
await service.cancel(
makeContext('trackingId'),
1,
'typist-user-external-id',
['typist', 'standard'],
);
const { status, typist_user_id } = await getTask(source, taskId);
const permisions = await getCheckoutPermissions(source, taskId);
@ -2162,7 +2268,12 @@ describe('cancel', () => {
const service = module.get<TasksService>(TasksService);
await service.cancel(1, 'typist-user-external-id', ['admin', 'author']);
await service.cancel(
makeContext('trackingId'),
1,
'typist-user-external-id',
['admin', 'author'],
);
const { status, typist_user_id } = await getTask(source, taskId);
const permisions = await getCheckoutPermissions(source, taskId);
@ -2208,7 +2319,12 @@ describe('cancel', () => {
const service = module.get<TasksService>(TasksService);
await service.cancel(1, 'typist-user-external-id', ['admin', 'author']);
await service.cancel(
makeContext('trackingId'),
1,
'typist-user-external-id',
['admin', 'author'],
);
const { status, typist_user_id } = await getTask(source, taskId);
const permisions = await getCheckoutPermissions(source, taskId);
@ -2253,7 +2369,10 @@ describe('cancel', () => {
const service = module.get<TasksService>(TasksService);
await expect(
service.cancel(1, 'typist-user-external-id', ['admin', 'author']),
service.cancel(makeContext('trackingId'), 1, 'typist-user-external-id', [
'admin',
'author',
]),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010601'), HttpStatus.BAD_REQUEST),
);
@ -2297,7 +2416,10 @@ describe('cancel', () => {
const service = module.get<TasksService>(TasksService);
await expect(
service.cancel(1, 'typist-user-external-id', ['typist', 'standard']),
service.cancel(makeContext('trackingId'), 1, 'typist-user-external-id', [
'typist',
'standard',
]),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010601'), HttpStatus.BAD_REQUEST),
);
@ -2324,7 +2446,10 @@ describe('cancel', () => {
const service = module.get<TasksService>(TasksService);
await expect(
service.cancel(1, 'typist-user-external-id', ['typist', 'standard']),
service.cancel(makeContext('trackingId'), 1, 'typist-user-external-id', [
'typist',
'standard',
]),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010603'), HttpStatus.NOT_FOUND),
);

View File

@ -32,6 +32,7 @@ import { InvalidRoleError } from './errors/types';
import { NotificationhubService } from '../../gateways/notificationhub/notificationhub.service';
import { UserGroupsRepositoryService } from '../../repositories/user_groups/user_groups.repository.service';
import { makeNotifyMessage } from '../../common/notify/makeNotifyMessage';
import { Context } from '../../common/log';
@Injectable()
export class TasksService {
@ -46,6 +47,7 @@ export class TasksService {
// TODO [Task2244] 引数にAccessTokenがあるのは不適切なのでController側で分解したい
async getTasks(
context: Context,
accessToken: AccessToken,
offset: number,
limit: number,
@ -53,6 +55,10 @@ export class TasksService {
paramName?: TaskListSortableAttribute,
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} };`,
);
const { role, userId } = accessToken;
// TODO [Task2244] Roleに型で定義されている値が入っているかをチェックして異常値を弾く実装に修正する
const roles = role.split(' ');
@ -77,6 +83,7 @@ export class TasksService {
// B2Cからユーザー名を取得する
const b2cUsers = await this.getB2cUsers(
context,
result.tasks,
result.permissions,
);
@ -99,6 +106,7 @@ export class TasksService {
// B2Cからユーザー名を取得する
const b2cUsers = await this.getB2cUsers(
context,
result.tasks,
result.permissions,
);
@ -118,6 +126,7 @@ export class TasksService {
);
// B2Cからユーザー名を取得する
const b2cUsers = await this.getB2cUsers(
context,
result.tasks,
result.permissions,
);
@ -142,6 +151,8 @@ export class TasksService {
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
} finally {
this.logger.log(`[OUT] [${context.trackingId}] ${this.getTasks.name}`);
}
}
/**
@ -152,11 +163,16 @@ export class TasksService {
* @returns checkout
*/
async checkout(
context: Context,
audioFileId: number,
roles: Roles[],
externalId: string,
): Promise<void> {
try {
this.logger.log(
`[IN] [${context.trackingId}] ${this.checkout.name} | params: { audioFileId: ${audioFileId}, roles: ${roles}, externalId: ${externalId} };`,
);
const { id, account_id, author_id } =
await this.usersRepository.findUserByExternalId(externalId);
@ -211,6 +227,8 @@ export class TasksService {
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
} finally {
this.logger.log(`[OUT] [${context.trackingId}] ${this.checkout.name}`);
}
}
@ -220,8 +238,15 @@ export class TasksService {
* @param externalId
* @returns checkin
*/
async checkin(audioFileId: number, externalId: string): Promise<void> {
async checkin(
context: Context,
audioFileId: number,
externalId: string,
): Promise<void> {
try {
this.logger.log(
`[IN] [${context.trackingId}] ${this.checkin.name} | params: { audioFileId: ${audioFileId}, externalId: ${externalId} };`,
);
const { id } = await this.usersRepository.findUserByExternalId(
externalId,
);
@ -257,6 +282,8 @@ export class TasksService {
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
} finally {
this.logger.log(`[OUT] [${context.trackingId}] ${this.checkin.name}`);
}
}
/**
@ -267,11 +294,15 @@ export class TasksService {
* @returns cancel
*/
async cancel(
context: Context,
audioFileId: number,
externalId: string,
role: Roles[],
): Promise<void> {
try {
this.logger.log(
`[IN] [${context.trackingId}] ${this.cancel.name} | params: { audioFileId: ${audioFileId}, externalId: ${externalId}, role: ${role} };`,
);
const { id, account_id } =
await this.usersRepository.findUserByExternalId(externalId);
@ -308,6 +339,8 @@ export class TasksService {
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
} finally {
this.logger.log(`[OUT] [${context.trackingId}] ${this.cancel.name}`);
}
}
@ -317,8 +350,15 @@ export class TasksService {
* @param externalId
* @returns suspend
*/
async suspend(audioFileId: number, externalId: string): Promise<void> {
async suspend(
context: Context,
audioFileId: number,
externalId: string,
): Promise<void> {
try {
this.logger.log(
`[IN] [${context.trackingId}] ${this.suspend.name} | params: { audioFileId: ${audioFileId}, externalId: ${externalId} };`,
);
const { id } = await this.usersRepository.findUserByExternalId(
externalId,
);
@ -354,10 +394,13 @@ export class TasksService {
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
} finally {
this.logger.log(`[OUT] [${context.trackingId}] ${this.suspend.name}`);
}
}
private async getB2cUsers(
context: Context,
tasks: TaskEntity[],
permissions: CheckoutPermission[],
): Promise<AdB2cUser[]> {
@ -385,7 +428,7 @@ export class TasksService {
);
// B2Cからユーザー名を取得する
return await this.adB2cService.getUsers(filteredExternalIds);
return await this.adB2cService.getUsers(context, filteredExternalIds);
}
/**
*
@ -394,12 +437,16 @@ export class TasksService {
* @returns checkout permission
*/
async changeCheckoutPermission(
context: Context,
audioFileId: number,
assignees: Assignee[],
externalId: string,
role: Roles[],
): Promise<void> {
try {
this.logger.log(
`[IN] [${context.trackingId}] ${this.changeCheckoutPermission.name} | params: { audioFileId: ${audioFileId}, assignees: ${assignees}, externalId: ${externalId}, role: ${role} };`,
);
const { author_id, account_id } =
await this.usersRepository.findUserByExternalId(externalId);
@ -444,6 +491,7 @@ export class TasksService {
// タグ対象に通知送信
await this.notificationhubService.notify(
context,
tags,
makeNotifyMessage('M000101'),
);
@ -473,6 +521,10 @@ export class TasksService {
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
} finally {
this.logger.log(
`[OUT] [${context.trackingId}] ${this.changeCheckoutPermission.name}`,
);
}
}
}

View File

@ -41,6 +41,7 @@ import {
} from '../../common/types/sort';
import { ADMIN_ROLES } from '../../constants';
import { RoleGuard } from '../../common/guards/role/roleguards';
import { makeContext } from '../../common/log';
@ApiTags('users')
@Controller('users')
@ -205,7 +206,10 @@ export class UsersController {
async getRelations(@Req() req: Request): Promise<GetRelationsResponse> {
const token = retrieveAuthorizationToken(req);
const { userId } = jwt.decode(token, { json: true }) as AccessToken;
return await this.usersService.getRelations(userId);
const context = makeContext(userId);
return await this.usersService.getRelations(context, userId);
}
@ApiResponse({

View File

@ -27,6 +27,7 @@ import {
USER_LICENSE_STATUS,
} from '../../constants';
import { DateWithZeroTime } from '../licenses/types/types';
import { Context } from '../../common/log';
@Injectable()
export class UsersService {
@ -308,7 +309,11 @@ export class UsersService {
// DBから取得したユーザーの外部IDをもとにADB2Cからユーザーを取得する
const externalIds = dbUsers.map((x) => x.external_id);
const adb2cUsers = await this.adB2cService.getUsers(externalIds);
const adb2cUsers = await this.adB2cService.getUsers(
// TODO: 外部連携以外のログ強化時に、ContollerからContextを取得するように修正する
{ trackingId: 'dummy' },
externalIds,
);
// DBから取得した各ユーザーをもとにADB2C情報をマージしライセンス情報を算出
const users = dbUsers.map((x) => {
@ -479,8 +484,11 @@ export class UsersService {
* @param userId
* @returns relations
*/
async getRelations(userId: string): Promise<GetRelationsResponse> {
this.logger.log(`[IN] ${this.getRelations.name}`);
async getRelations(
context: Context,
userId: string,
): Promise<GetRelationsResponse> {
this.logger.log(`[IN] [${context.trackingId}] ${this.getRelations.name}`);
try {
const user = await this.usersRepository.findUserByExternalId(userId);
@ -614,7 +622,9 @@ export class UsersService {
HttpStatus.INTERNAL_SERVER_ERROR,
);
} finally {
this.logger.log(`[OUT] ${this.getRelations.name}`);
this.logger.log(
`[OUT] [${context.trackingId}] ${this.getRelations.name}`,
);
}
}
}

View File

@ -6,6 +6,7 @@ import { ConfigService } from '@nestjs/config';
import axios from 'axios';
import { Aadb2cUser, B2cMetadata, JwkSignKey } from '../../common/token';
import { AdB2cResponse, AdB2cUser } from './types/types';
import { Context } from '../../common/log';
export type ConflictError = {
reason: 'email';
@ -188,9 +189,14 @@ export class AdB2cService {
* @param externalIds
* @returns users
*/
async getUsers(externalIds: string[]): Promise<AdB2cUser[]> {
async getUsers(
context: Context,
externalIds: string[],
): Promise<AdB2cUser[]> {
this.logger.log(
`[IN] ${this.getUsers.name}; externalIds:[${externalIds.join(',')}]`,
`[IN] [${context.trackingId}] ${
this.getUsers.name
} | params: { externalIds:[${externalIds.join(',')}] };`,
);
/*
@ -223,7 +229,7 @@ export class AdB2cService {
throw e;
} finally {
this.logger.log(`[OUT] ${this.getUsers.name}`);
this.logger.log(`[OUT] [${context.trackingId}] ${this.getUsers.name}`);
}
}
}

View File

@ -14,6 +14,7 @@ import {
BLOB_STORAGE_REGION_EU,
BLOB_STORAGE_REGION_US,
} from '../../constants';
import { Context } from '../../common/log';
@Injectable()
export class BlobstorageService {
@ -77,10 +78,21 @@ export class BlobstorageService {
* @param accountId
* @returns exists
*/
async containerExists(accountId: number, country: string): Promise<boolean> {
async containerExists(
context: Context,
accountId: number,
country: string,
): Promise<boolean> {
this.logger.log(
`[IN] [${context.trackingId}] ${this.containerExists.name}`,
);
// 国に応じたリージョンでコンテナ名を指定してClientを取得
const containerClient = this.getContainerClient(accountId, country);
const exists = await containerClient.exists();
this.logger.log(
`[OUT] [${context.trackingId}] ${this.containerExists.name}`,
);
return exists;
}
@ -94,14 +106,18 @@ export class BlobstorageService {
* @returns exists
*/
async fileExists(
context: Context,
accountId: number,
country: string,
filePath: string,
): Promise<boolean> {
this.logger.log(`[IN] [${context.trackingId}] ${this.fileExists.name}`);
const containerClient = this.getContainerClient(accountId, country);
const blob = containerClient.getBlobClient(`${filePath}`);
const exists = await blob.exists();
this.logger.log(`[OUT] [${context.trackingId}] ${this.fileExists.name}`);
return exists;
}
@ -113,11 +129,14 @@ export class BlobstorageService {
* @returns upload sas
*/
async publishUploadSas(
context: Context,
accountId: number,
userId: number,
country: string,
): Promise<string> {
this.logger.log(`[IN] ${this.publishUploadSas.name}`);
this.logger.log(
`[IN] [${context.trackingId}] ${this.publishUploadSas.name}`,
);
let containerClient: ContainerClient;
let sharedKeyCredential: StorageSharedKeyCredential;
try {
@ -127,6 +146,9 @@ export class BlobstorageService {
sharedKeyCredential = this.getSharedKeyCredential(country);
} catch (e) {
this.logger.error(`error=${e}`);
this.logger.log(
`[OUT] [${context.trackingId}] ${this.publishUploadSas.name}`,
);
throw e;
}
@ -155,6 +177,10 @@ export class BlobstorageService {
const url = new URL(containerClient.url);
url.pathname += `/${userId}`;
url.search = `${sasToken}`;
this.logger.log(
`[OUT] [${context.trackingId}] ${this.publishUploadSas.name}`,
);
return url.toString();
}
@ -167,11 +193,14 @@ export class BlobstorageService {
* @returns download sas
*/
async publishDownloadSas(
context: Context,
accountId: number,
country: string,
filePath: string,
): Promise<string> {
this.logger.log(`[IN] ${this.publishDownloadSas.name}`);
this.logger.log(
`[IN] [${context.trackingId}] ${this.publishDownloadSas.name}`,
);
let containerClient: ContainerClient;
let blobClient: BlobClient;
let sharedKeyCredential: StorageSharedKeyCredential;
@ -184,6 +213,9 @@ export class BlobstorageService {
sharedKeyCredential = this.getSharedKeyCredential(country);
} catch (e) {
this.logger.error(`error=${e}`);
this.logger.log(
`[OUT] [${context.trackingId}] ${this.publishDownloadSas.name}`,
);
throw e;
}
@ -212,6 +244,10 @@ export class BlobstorageService {
const url = new URL(blobClient.url);
url.search = `${sasToken}`;
this.logger.log(
`[OUT] [${context.trackingId}] ${this.publishDownloadSas.name}`,
);
return url.toString();
}

View File

@ -11,6 +11,7 @@ import {
} from '@azure/notification-hubs';
import { TAG_MAX_COUNT } from '../../constants';
import { PNS } from '../../constants';
import { Context } from '../../common/log';
@Injectable()
export class NotificationhubService {
private readonly logger = new Logger(NotificationhubService.name);
@ -29,12 +30,15 @@ export class NotificationhubService {
* @returns register
*/
async register(
context: Context,
userId: number,
pns: string,
pnsHandler: string,
installationId: string,
): Promise<void> {
this.logger.log(`[IN] ${this.register.name}`);
this.logger.log(
`[IN] [${context.trackingId}] ${this.register.name} | params: { userId: ${userId}, pns: ${pns}, pnsHandler: ${pnsHandler}, installationId: ${installationId} }`,
);
const tag = `user_${userId}`;
@ -66,7 +70,7 @@ export class NotificationhubService {
this.logger.error(`error=${e.message}`);
throw e;
} finally {
this.logger.log(`[OUT] ${this.register.name}`);
this.logger.log(`[OUT] [${context.trackingId}] ${this.register.name}`);
}
}
@ -76,8 +80,14 @@ export class NotificationhubService {
* @param message
* @returns notify
*/
async notify(tags: string[], message: string): Promise<void> {
this.logger.log(`[IN] ${this.notify.name}`);
async notify(
context: Context,
tags: string[],
message: string,
): Promise<void> {
this.logger.log(
`[IN] [${context.trackingId}] ${this.notify.name} | params: { tags: ${tags}, message: ${message} }`,
);
try {
// OR条件によるtag指定は20個までなので分割して送信する

View File

@ -1,9 +1,7 @@
import { Injectable } from '@nestjs/common';
import { DataSource, In, IsNull } from 'typeorm';
import { UserGroup } from './entity/user_group.entity';
import { Assignee } from '../../features/tasks/types/types';
import { UserGroupMember } from './entity/user_group_member.entity';
import { User } from '../users/entity/user.entity';
@Injectable()
export class UserGroupsRepositoryService {