From f3dde1874d9886052f05d7e3650ec98c0e971b3b Mon Sep 17 00:00:00 2001 From: masaaki Date: Thu, 26 Oct 2023 09:19:03 +0000 Subject: [PATCH] =?UTF-8?q?Merged=20PR=20512:=20ADB2C=E3=83=A6=E3=83=BC?= =?UTF-8?q?=E3=82=B6=E3=81=8C=E4=B8=80=E6=8B=AC=E3=81=A7=E5=89=8A=E9=99=A4?= =?UTF-8?q?=E3=81=A7=E3=81=8D=E3=81=AA=E3=81=84=E3=81=93=E3=81=A8=E3=81=AB?= =?UTF-8?q?=E5=AF=BE=E3=81=99=E3=82=8B=E5=AF=BE=E5=BF=9C=E5=84=AA=E5=85=88?= =?UTF-8?q?=E5=BA=A6=E3=81=AE=E6=95=B0=E5=80=A4=E6=A0=B9=E6=8B=A0=E3=81=A0?= =?UTF-8?q?=E3=81=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 概要 [Task2831: ADB2Cユーザが一括で削除できないことに対する対応優先度の数値根拠だし](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2831) - 元PBI or タスクへのリンク(内容・目的などはそちらにあるはず) - 何をどう変更したか、追加したライブラリなど 削除処理の同期化、エラー出力の追加 - このPull Requestでの対象/対象外 - 影響範囲(他の機能にも影響があるか) ## レビューポイント - 特にレビューしてほしい箇所 - 軽微なものや自明なものは記載不要 - 修正範囲が大きい場合などに記載 - 全体的にや仕様を満たしているか等は本当に必要な時のみ記載 ## UIの変更 - Before/Afterのスクショなど - スクショ置き場 ## 動作確認状況 - ユニットテスト ## 補足 - 相談、参考資料などがあれば --- .../src/gateways/adb2c/adb2c.service.ts | 34 +++++++++++++++---- .../src/gateways/adb2c/utils/utils.ts | 10 ++++++ 2 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 dictation_server/src/gateways/adb2c/utils/utils.ts diff --git a/dictation_server/src/gateways/adb2c/adb2c.service.ts b/dictation_server/src/gateways/adb2c/adb2c.service.ts index e7dcce6..f38f5c5 100644 --- a/dictation_server/src/gateways/adb2c/adb2c.service.ts +++ b/dictation_server/src/gateways/adb2c/adb2c.service.ts @@ -6,8 +6,9 @@ import { ConfigService } from '@nestjs/config'; import axios from 'axios'; import { Aadb2cUser, B2cMetadata, JwkSignKey } from '../../common/token'; import { AdB2cResponse, AdB2cUser } from './types/types'; +import { isPromiseRejectedResult } from './utils/utils'; import { Context } from '../../common/log'; -import { ADB2C_SIGN_IN_TYPE } from '../../constants'; +import { ADB2C_SIGN_IN_TYPE, MANUAL_RECOVERY_REQUIRED } from '../../constants'; export type ConflictError = { reason: 'email'; @@ -267,12 +268,33 @@ export class AdB2cService { ); try { - // 複数ユーザーを一括削除する方法が不明なため、rate limitの懸念があるのを承知のうえ単一削除の繰り返しで実装 - // TODO 一括削除する方法が判明したら修正する - // https://learn.microsoft.com/en-us/graph/api/user-delete?view=graph-rest-1.0&tabs=javascript#example - externalIds.map( - async (x) => await this.graphClient.api(`users/${x}`).delete(), + // 複数ユーザーを一括削除する方法がないため、1人ずつで削除を行う(rate limitに大きな影響がないこと確認済) + const results = await Promise.allSettled( + externalIds.map( + async (x) => await this.graphClient.api(`users/${x}`).delete(), + ), ); + + // 失敗したプロミスを抽出 + const failedPromises = results.filter( + (result) => result.status === 'rejected', + ); + + // 失敗したプロミスのエラーをログに記録 + failedPromises.forEach((result, index) => { + const failedId = externalIds[index]; + if (isPromiseRejectedResult(result)) { + const error = result.reason.toString(); + + this.logger.error( + `${MANUAL_RECOVERY_REQUIRED}[${context.trackingId}] Failed to delete user ${failedId}: ${error}`, + ); + } else { + this.logger.error( + `${MANUAL_RECOVERY_REQUIRED}[${context.trackingId}] Failed to delete user ${failedId}`, + ); + } + }); } catch (e) { this.logger.error(`error=${e}`); throw e; diff --git a/dictation_server/src/gateways/adb2c/utils/utils.ts b/dictation_server/src/gateways/adb2c/utils/utils.ts new file mode 100644 index 0000000..1d3b4a9 --- /dev/null +++ b/dictation_server/src/gateways/adb2c/utils/utils.ts @@ -0,0 +1,10 @@ +export const isPromiseRejectedResult = ( + data: unknown, +): data is PromiseRejectedResult => { + return ( + data !== null && + typeof data === 'object' && + 'status' in data && + 'reason' in data + ); +};