Merged PR 765: データ削除ツール作成+動作確認
## 概要 [Task3569: データ削除ツール作成+動作確認](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3569) - ADB2Cからのユーザー削除が100件ごとにしか削除できていなかったので、修正しました。 - 取得が100件まででそのユーザーに対して削除処理をしていたので100件までの削除になっていました。 - 対応として、100件づつの削除をユーザーが全削除されるまで実行するようにしました。 ## レビューポイント - 対応方法として適切でしょうか? - ループで制限を設けていますが、MAX値として適切でしょうか? ## UIの変更 - なし ## 動作確認状況 - ローカルで順に実行できることを確認 - 実際の削除は別途develop環境で実施します。
This commit is contained in:
parent
e3ee9412c9
commit
dc52ec2022
12
data_migration_tools/server/package-lock.json
generated
12
data_migration_tools/server/package-lock.json
generated
@ -3107,9 +3107,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.8.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
|
||||
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
|
||||
"version": "8.11.3",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
|
||||
"integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
|
||||
"devOptional": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
@ -12333,9 +12333,9 @@
|
||||
}
|
||||
},
|
||||
"acorn": {
|
||||
"version": "8.8.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
|
||||
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
|
||||
"version": "8.11.3",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
|
||||
"integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
|
||||
"devOptional": true
|
||||
},
|
||||
"acorn-import-assertions": {
|
||||
|
||||
@ -11,6 +11,7 @@ import { ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
|
||||
import { Request } from "express";
|
||||
import { DeleteService } from "./delete.service";
|
||||
import { DeleteResponse } from "./types/types";
|
||||
import { makeContext } from "src/common/log";
|
||||
|
||||
@ApiTags("delete")
|
||||
@Controller("delete")
|
||||
@ -33,7 +34,9 @@ export class DeleteController {
|
||||
})
|
||||
@Post()
|
||||
async deleteData(): Promise<{}> {
|
||||
await this.deleteService.deleteData();
|
||||
const context = makeContext("tool", "delete");
|
||||
|
||||
await this.deleteService.deleteData(context);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ import { DeleteRepositoryService } from "../../repositories/delete/delete.reposi
|
||||
import { makeErrorResponse } from "../../common/errors/makeErrorResponse";
|
||||
import { AdB2cService } from "../../gateways/adb2c/adb2c.service";
|
||||
import { BlobstorageService } from "../../gateways/blobstorage/blobstorage.service";
|
||||
import { Context } from "../../common/log";
|
||||
|
||||
@Injectable()
|
||||
export class DeleteService {
|
||||
@ -17,21 +18,34 @@ export class DeleteService {
|
||||
* データを削除する
|
||||
* @returns data
|
||||
*/
|
||||
async deleteData(): Promise<void> {
|
||||
this.logger.log(`[IN] ${this.deleteData.name}`);
|
||||
async deleteData(context: Context): Promise<void> {
|
||||
this.logger.log(
|
||||
`[IN] [${context.getTrackingId()}] ${this.deleteData.name}`
|
||||
);
|
||||
try {
|
||||
// BlobStorageからデータを削除する
|
||||
await this.blobstorageService.deleteContainers();
|
||||
await this.blobstorageService.deleteContainers(context);
|
||||
|
||||
// 100件ずつのユーザー取得なのですべて削除するまでループする
|
||||
for (let i = 0; i < 500; i++) {
|
||||
// ADB2Cからユーザ情報を取得する
|
||||
const users = await this.adB2cService.getUsers();
|
||||
const { users, hasNext } = await this.adB2cService.getUsers(context);
|
||||
|
||||
// ユーザーがいない場合はループを抜ける
|
||||
if (!hasNext) {
|
||||
break;
|
||||
}
|
||||
|
||||
const externalIds = users.map((user) => user.id);
|
||||
await this.adB2cService.deleteUsers(externalIds);
|
||||
await this.adB2cService.deleteUsers(context, externalIds);
|
||||
}
|
||||
|
||||
// データベースからデータを削除する
|
||||
await this.deleteRepositoryService.deleteData();
|
||||
// AutoIncrementの値をリセットする
|
||||
await this.deleteRepositoryService.resetAutoIncrement();
|
||||
// 初期データを挿入する
|
||||
await this.deleteRepositoryService.insertInitData(context);
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
if (e instanceof Error) {
|
||||
|
||||
@ -30,14 +30,10 @@ export const isConflictError = (arg: unknown): arg is ConflictError => {
|
||||
export class AdB2cService {
|
||||
private readonly logger = new Logger(AdB2cService.name);
|
||||
private readonly tenantName: string;
|
||||
private readonly flowName: string;
|
||||
private readonly ttl: number;
|
||||
private graphClient: Client;
|
||||
|
||||
constructor(private readonly configService: ConfigService) {
|
||||
this.tenantName = this.configService.getOrThrow<string>("TENANT_NAME");
|
||||
this.flowName = this.configService.getOrThrow<string>("SIGNIN_FLOW_NAME");
|
||||
this.ttl = this.configService.getOrThrow<number>("ADB2C_CACHE_TTL");
|
||||
|
||||
// ADB2Cへの認証情報
|
||||
const credential = new ClientSecretCredential(
|
||||
@ -111,8 +107,10 @@ export class AdB2cService {
|
||||
* @param externalIds
|
||||
* @returns users
|
||||
*/
|
||||
async getUsers(): Promise<AdB2cUser[]> {
|
||||
this.logger.log(`[IN] ${this.getUsers.name}`);
|
||||
async getUsers(
|
||||
context: Context
|
||||
): Promise<{ users: AdB2cUser[]; hasNext: boolean }> {
|
||||
this.logger.log(`[IN] [${context.getTrackingId()}] ${this.getUsers.name}`);
|
||||
|
||||
try {
|
||||
const res: AdB2cResponse = await this.graphClient
|
||||
@ -121,7 +119,7 @@ export class AdB2cService {
|
||||
.filter(`creationType eq 'LocalAccount'`)
|
||||
.get();
|
||||
|
||||
return res.value;
|
||||
return { users: res.value, hasNext: !!res["@odata.nextLink"] };
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
const { statusCode } = e;
|
||||
@ -177,9 +175,11 @@ export class AdB2cService {
|
||||
* Azure AD B2Cからユーザ情報を削除する(複数)
|
||||
* @param externalIds 外部ユーザーID
|
||||
*/
|
||||
async deleteUsers(externalIds: string[]): Promise<void> {
|
||||
async deleteUsers(context: Context, externalIds: string[]): Promise<void> {
|
||||
this.logger.log(
|
||||
`[IN]${this.deleteUsers.name} | params: { externalIds: ${externalIds} };`
|
||||
`[IN] [${context.getTrackingId()}] ${
|
||||
this.deleteUsers.name
|
||||
} | params: { externalIds: ${externalIds} };`
|
||||
);
|
||||
|
||||
try {
|
||||
|
||||
@ -89,8 +89,10 @@ export class BlobstorageService {
|
||||
* すべてのコンテナを削除します。
|
||||
* @returns containers
|
||||
*/
|
||||
async deleteContainers(): Promise<void> {
|
||||
this.logger.log(`[IN] ${this.deleteContainers.name}`);
|
||||
async deleteContainers(context: Context): Promise<void> {
|
||||
this.logger.log(
|
||||
`[IN] [${context.getTrackingId()}] ${this.deleteContainers.name}`
|
||||
);
|
||||
|
||||
try {
|
||||
for await (const container of this.blobServiceClientAU.listContainers({
|
||||
|
||||
@ -1,11 +1,15 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { DataSource } from "typeorm";
|
||||
import { logger } from "@azure/identity";
|
||||
import { Account } from "./entity/account.entity";
|
||||
import { AUTO_INCREMENT_START } from "../../constants";
|
||||
import { Term } from "./entity/term.entity";
|
||||
import { insertEntities } from "../../common/repository";
|
||||
import { Context } from "../../common/log";
|
||||
|
||||
@Injectable()
|
||||
export class DeleteRepositoryService {
|
||||
// クエリログにコメントを出力するかどうか
|
||||
private readonly isCommentOut = process.env.STAGE !== "local";
|
||||
constructor(private dataSource: DataSource) {}
|
||||
|
||||
/**
|
||||
@ -54,4 +58,35 @@ export class DeleteRepositoryService {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初期データを挿入する
|
||||
* @returns data
|
||||
*/
|
||||
async insertInitData(context: Context): Promise<void> {
|
||||
await this.dataSource.transaction(async (entityManager) => {
|
||||
const termRepo = entityManager.getRepository(Term);
|
||||
|
||||
// ワークフローのデータ作成
|
||||
const newTarmDpa = new Term();
|
||||
newTarmDpa.document_type = "DPA";
|
||||
newTarmDpa.version = "V0.1";
|
||||
const newTarmEula = new Term();
|
||||
newTarmEula.document_type = "EULA";
|
||||
newTarmEula.version = "V0.1";
|
||||
const newTarmPrivacyNotice = new Term();
|
||||
newTarmPrivacyNotice.document_type = "PrivacyNotice";
|
||||
newTarmPrivacyNotice.version = "V0.1";
|
||||
|
||||
const initTerms = [newTarmDpa, newTarmEula, newTarmPrivacyNotice];
|
||||
|
||||
await insertEntities(
|
||||
Term,
|
||||
termRepo,
|
||||
initTerms,
|
||||
this.isCommentOut,
|
||||
context
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user