@chevre/domain
Version:
Chevre Domain Library for Node.js
476 lines (475 loc) • 22.9 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.call = call;
const GMO = require("@motionpicture/gmo-service");
const createDebug = require("debug");
const factory = require("../../factory");
const person2username_1 = require("../payment/any/person2username");
const account_1 = require("../../repo/account");
const action_1 = require("../../repo/action");
const ownershipInfo_1 = require("../../repo/ownershipInfo");
const creditCard_1 = require("../../repo/paymentMethod/creditCard");
const paymentService_1 = require("../../repo/paymentService");
const person_1 = require("../../repo/person");
const setting_1 = require("../../repo/setting");
const task_1 = require("../../repo/task");
const debug = createDebug('chevre-domain:service:task:deletePerson');
// type IOwnershipInfoPermit = factory.ownershipInfo.IPermitAsGood;
const ADMIN_PROVIDER_NAME = 'Google';
let cognitoIdentityServiceProvider;
/**
* タスク実行関数
*/
function call(params) {
return (_a) => __awaiter(this, [_a], void 0, function* ({ connection, settings }) {
if (cognitoIdentityServiceProvider === undefined) {
const { CognitoIdentityProvider } = yield Promise.resolve().then(() => require('@aws-sdk/client-cognito-identity-provider'));
const { fromEnv } = yield Promise.resolve().then(() => require('@aws-sdk/credential-providers'));
cognitoIdentityServiceProvider = new CognitoIdentityProvider({
apiVersion: 'latest',
region: 'ap-northeast-1',
credentials: fromEnv()
});
}
const settingRepo = new setting_1.SettingRepo(connection);
const setting = yield settingRepo.findOne({ project: { id: { $eq: '*' } } }, ['userPoolIdOld']);
if (typeof (setting === null || setting === void 0 ? void 0 : setting.userPoolIdOld) !== 'string') {
throw new factory.errors.NotFound('setting.userPoolIdOld');
}
const newPersonRepo = new person_1.PersonRepo({
userPoolId: params.data.userPoolId,
cognitoIdentityServiceProvider
});
const oldPersonRepo = new person_1.PersonRepo({
// userPoolId: settings.userPoolIdOld,
userPoolId: setting.userPoolIdOld,
cognitoIdentityServiceProvider
});
const paymentServiceRepo = new paymentService_1.PaymentServiceRepo(connection);
let creditCardRepo;
if (typeof params.data.paymentMethodType4creditCard === 'string' && params.data.paymentMethodType4creditCard.length > 0) {
const credentials = yield getCreditCardPaymentServiceChannel({
project: { id: params.project.id },
paymentMethodType: params.data.paymentMethodType4creditCard
})({ paymentService: paymentServiceRepo });
creditCardRepo = new creditCard_1.CreditCardRepo({
siteId: credentials.siteId,
sitePass: credentials.sitePass,
cardService: new GMO.service.Card({
endpoint: credentials.endpoint,
useFetch: settings.gmo.useFetch
}, {
timeout: (params.data.executeBackground)
? settings.gmo.timeout
// tslint:disable-next-line:no-magic-numbers
: 20000 // cronで実行の場合は長めに(2024-10-05~)
})
});
}
yield deleteById(Object.assign(Object.assign({}, params.data), { project: { id: params.project.id } }), setting)({
account: new account_1.AccountRepo(connection),
action: new action_1.ActionRepo(connection),
creditCard: creditCardRepo,
ownershipInfo: new ownershipInfo_1.OwnershipInfoRepo(connection),
paymentService: paymentServiceRepo,
newPerson: newPersonRepo,
oldPerson: oldPersonRepo,
task: new task_1.TaskRepo(connection),
cognitoIdentityServiceProvider
});
});
}
/**
* 会員削除処理
*/
function deleteById(params, setting) {
// tslint:disable-next-line:max-func-body-length
return (repos) => __awaiter(this, void 0, void 0, function* () {
var _a;
const deleteMemberAction = {
agent: params.agent,
object: {
id: params.id,
typeOf: factory.personType.Person,
migrate: params.migrate,
physically: params.physically
// discontinue(2025-03-29~)
// ...(typeof params.migratePersonRecipientUrl === 'string')
// ? { migratePersonRecipientUrl: params.migratePersonRecipientUrl } : undefined
},
project: { id: params.project.id, typeOf: factory.organizationType.Project },
typeOf: factory.actionType.DeleteAction
};
const action = yield repos.action.start(deleteMemberAction);
let existingPeople;
try {
// const project = <Pick<factory.project.IProject, 'settings' | 'id'>>await repos.project.findById({
// id: params.project.id,
// inclusion: ['settings']
// });
existingPeople = yield repos.newPerson.search({ id: params.id });
// exclude ADMIN_PROVIDER_NAME
const username = (_a = existingPeople.at(0)) === null || _a === void 0 ? void 0 : _a.Username;
const isAdminPerson = typeof username === 'string' && username.startsWith(ADMIN_PROVIDER_NAME, 0);
if (isAdminPerson) {
throw new factory.errors.Argument('id', `${ADMIN_PROVIDER_NAME} people cannot be deleted`);
}
// discontinue(2025-03-29~)
// 移行の場合、全所有権情報通知タスクを作成
// if (params.migrate && typeof params.migratePersonRecipientUrl === 'string') {
// await createInformTask({
// id: params.id,
// project: { id: params.project.id },
// now: action.startDate,
// migratePersonRecipientUrl: params.migratePersonRecipientUrl
// })(repos);
// }
if (!params.migrate) {
// 移行でなければDeleteTransactionタスクを作成(2023-07-03~)
yield createDeleteTransactionTask({
id: params.id,
project: { id: params.project.id },
now: action.startDate
})({ task: repos.task });
}
if (existingPeople.length > 0) {
if (repos.creditCard !== undefined) {
// クレジットカード削除
yield deleteCreditCardsById({
id: params.id,
useUsernameAsGMOMemberId: params.useUsernameAsGMOMemberId
}, setting)({
person: repos.newPerson,
creditCard: repos.creditCard,
cognitoIdentityServiceProvider: repos.cognitoIdentityServiceProvider
});
}
}
// 所有権削除
debug('task:deletePerson:deleteById: deleteOwnershipInfosById processing... personId:', params.id);
yield deleteOwnershipInfosById({
id: params.id,
project: { id: params.project.id }
})({ ownershipInfo: repos.ownershipInfo });
if (existingPeople.length > 0) {
// 会員削除
if (params.physically === true) {
debug('task:deletePerson:deleteById: deleteById processing...userId:', params.id);
yield repos.newPerson.deleteById({ userId: params.id });
}
else {
// Cognitoユーザを無効にする
yield repos.newPerson.globalSignOutAndDisable({ userId: params.id });
}
}
}
catch (error) {
try {
yield repos.action.giveUp({ typeOf: action.typeOf, id: action.id, error });
}
catch (__) {
// no op
}
throw error;
}
const actionResult = { existingPeople };
yield repos.action.completeWithVoid({ typeOf: action.typeOf, id: action.id, result: actionResult });
});
}
function getCreditCardPaymentServiceChannel(params) {
return (repos) => __awaiter(this, void 0, void 0, function* () {
var _a, _b;
const paymentServices = yield repos.paymentService.projectFields({
limit: 1,
project: { id: { $eq: params.project.id } },
typeOf: { $eq: factory.service.paymentService.PaymentServiceType.CreditCard },
serviceType: { codeValue: { $eq: params.paymentMethodType } }
}, ['availableChannel']);
const paymentService = paymentServices.shift();
if (paymentService === undefined) {
throw new factory.errors.NotFound('PaymentService');
}
if (typeof paymentService.id !== 'string') {
throw new factory.errors.NotFound('paymentService.id.id');
}
const availableChannel = yield repos.paymentService.findAvailableChannelCreditCard({
project: { id: params.project.id },
id: paymentService.id
});
// const availableChannel = paymentService?.availableChannel;
if (typeof (availableChannel === null || availableChannel === void 0 ? void 0 : availableChannel.serviceUrl) !== 'string') {
throw new factory.errors.NotFound('paymentService.availableChannel.serviceUrl');
}
if (typeof ((_a = availableChannel === null || availableChannel === void 0 ? void 0 : availableChannel.credentials) === null || _a === void 0 ? void 0 : _a.siteId) !== 'string') {
throw new factory.errors.NotFound('paymentService.availableChannel.credentials.siteId');
}
if (typeof ((_b = availableChannel === null || availableChannel === void 0 ? void 0 : availableChannel.credentials) === null || _b === void 0 ? void 0 : _b.sitePass) !== 'string') {
throw new factory.errors.NotFound('paymentService.availableChannel.credentials.sitePass');
}
return {
endpoint: availableChannel.serviceUrl,
siteId: availableChannel.credentials.siteId,
sitePass: availableChannel.credentials.sitePass
};
});
}
// function createInformTask(params: {
// id: string;
// project: { id: string };
// now: Date;
// migratePersonRecipientUrl: string;
// }) {
// // tslint:disable-next-line:max-func-body-length
// return async (repos: {
// account: AccountRepo;
// ownershipInfo: OwnershipInfoRepo;
// newPerson: PersonRepo;
// oldPerson: PersonRepo;
// task: TaskRepo;
// }) => {
// const person = await repos.newPerson.findById({ userId: params.id });
// let oldUser: factory.person.IPerson | undefined;
// const userIdentitiesStr = person.additionalProperty?.find((p) => p.name === 'identities')?.value;
// if (typeof userIdentitiesStr === 'string' && userIdentitiesStr.length > 0) {
// try {
// const identities = JSON.parse(userIdentitiesStr);
// if (Array.isArray(identities) && identities.length > 0) {
// const userIdByIdentities = identities[0].userId;
// if (typeof userIdByIdentities === 'string' && userIdByIdentities.length > 0) {
// // oldUserは必ず存在するはず
// oldUser = await repos.oldPerson.findById({ userId: userIdByIdentities });
// }
// }
// } catch (error) {
// // tslint:disable-next-line:no-console
// console.error('find oldUser throwed', error);
// throw error;
// }
// }
// const reservations = await repos.ownershipInfo.projectFields({
// project: { id: { $eq: params.project.id } },
// ownedBy: { id: params.id },
// typeOfGood: { issuedThrough: { typeOf: { $eq: factory.product.ProductType.EventService } } }
// });
// const memberships = <factory.ownershipInfo.IOwnershipInfo<factory.ownershipInfo.IPermitAsGood>[]>
// await repos.ownershipInfo.projectFields({
// limit: 1,
// page: 1,
// project: { id: { $eq: params.project.id } },
// ownedBy: { id: params.id },
// typeOfGood: { issuedThrough: { typeOf: { $eq: factory.product.ProductType.MembershipService } } },
// ownedFrom: params.now,
// ownedThrough: params.now
// });
// let paymentCards = <factory.ownershipInfo.IOwnershipInfo<factory.ownershipInfo.IPermitAsGood & {
// balance: number;
// }>[]>
// await repos.ownershipInfo.projectFields({
// // 最も古い所有ペイメントカードをデフォルトペイメントカードとして扱う使用なので、ソート条件は以下の通り
// sort: { ownedFrom: factory.sortType.Ascending },
// limit: 1,
// page: 1,
// project: { id: { $eq: params.project.id } },
// ownedBy: { id: params.id },
// typeOfGood: { issuedThrough: { typeOf: { $eq: factory.product.ProductType.PaymentCard } } },
// ownedFrom: params.now,
// ownedThrough: params.now
// });
// paymentCards = await Promise.all(paymentCards.map(async (paymentCard) => {
// // 口座検索
// const accountNumber = String((<IOwnershipInfoPermit>paymentCard.typeOfGood).identifier);
// const account = await repos.account.findByAccountNumber({ accountNumber });
// return {
// ...paymentCard,
// typeOfGood: {
// ...paymentCard.typeOfGood,
// balance: account.balance
// }
// };
// }));
// // create task
// let informTask: factory.task.IAttributes<factory.taskName.TriggerWebhook> & {
// data: factory.task.triggerWebhook.IInformAnyResourceAction & {
// object: factory.notification.person.IPersonAsNotification;
// };
// };
// const informObject: factory.notification.person.IPersonAsNotification = {
// id: person.id,
// memberOf: person.memberOf,
// typeOf: person.typeOf,
// cognitoUser: {
// Attributes: (<any>oldUser)?.Attributes,
// Enabled: (<any>oldUser)?.Enabled,
// UserCreateDate: (<any>oldUser)?.UserCreateDate,
// UserLastModifiedDate: (<any>oldUser)?.UserLastModifiedDate,
// UserStatus: (<any>oldUser)?.UserStatus,
// Username: (<any>oldUser)?.Username
// },
// reservations: reservations.map((ownershipInfo) => {
// const { id, typeOf, typeOfGood, ownedFrom, ownedThrough } = ownershipInfo;
// return { id, typeOf, typeOfGood, ownedFrom, ownedThrough };
// }),
// memberships: memberships.map((ownershipInfo) => {
// const { id, typeOf, typeOfGood, ownedFrom, ownedThrough } = ownershipInfo;
// const { identifier } = typeOfGood;
// return {
// id,
// typeOf,
// typeOfGood: { identifier },
// ownedFrom,
// ownedThrough
// };
// }),
// paymentCards: paymentCards.map((ownershipInfo) => {
// const { id, typeOf, typeOfGood } = ownershipInfo;
// const { balance, identifier } = typeOfGood;
// return {
// id,
// typeOf,
// typeOfGood: { balance, identifier }
// };
// })
// };
// const informActionAttributes: factory.task.triggerWebhook.IInformAnyResourceAction & {
// object: factory.notification.person.IPersonAsNotification;
// } = { // optimize(2024-07-01~)
// object: informObject,
// recipient: {
// // url: params.migratePersonRecipientUrl, // discontinue(2025-02-13~)
// id: '',
// name: 'NewUserPool',
// typeOf: factory.creativeWorkType.WebApplication
// },
// target: {
// httpMethod: 'POST',
// encodingType: factory.encodingFormat.Application.json,
// typeOf: 'EntryPoint',
// urlTemplate: params.migratePersonRecipientUrl
// }
// };
// informTask = {
// project: { id: params.project.id, typeOf: factory.organizationType.Project },
// name: factory.taskName.TriggerWebhook,
// status: factory.taskStatus.Ready,
// runsAt: params.now,
// remainingNumberOfTries: 10,
// numberOfTried: 0,
// executionResults: [],
// data: informActionAttributes
// };
// await repos.task.createInformTaskIfNotExist(informTask, { emitImmediately: true });
// };
// }
function createDeleteTransactionTask(params) {
return (repos) => __awaiter(this, void 0, void 0, function* () {
const deleteTransactionTasks = [
factory.transactionType.MoneyTransfer,
factory.transactionType.PlaceOrder,
factory.transactionType.ReturnOrder
].map((transactionType) => {
return {
project: { id: params.project.id, typeOf: factory.organizationType.Project },
name: factory.taskName.DeleteTransaction,
status: factory.taskStatus.Ready,
runsAt: params.now,
remainingNumberOfTries: 3,
numberOfTried: 0,
executionResults: [],
data: {
object: {
specifyingMethod: factory.task.deleteTransaction.SpecifyingMethod.AgentId,
agent: { id: params.id },
project: { id: params.project.id },
typeOf: transactionType
}
}
};
});
yield repos.task.saveMany(deleteTransactionTasks, { emitImmediately: true });
});
}
function deleteOwnershipInfosById(params) {
return (repos) => __awaiter(this, void 0, void 0, function* () {
// まず所有権削除
yield repos.ownershipInfo.deleteByOwnedById({
project: { id: params.project.id },
ownedBy: { id: params.id }
});
});
}
function sleep(waitTime) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, waitTime);
});
});
}
const DELETE_CREDIT_CARD_MAX_RETRY_COUNT = 2;
const DELETE_CREDIT_CARD_RETRY_INTERVAL_IN_MS = 1000;
function deleteCreditCardsById(params, setting) {
return (repos) => __awaiter(this, void 0, void 0, function* () {
let retry = true;
let numberOfTry = 0;
while (numberOfTry >= 0) {
try {
numberOfTry += 1;
if (numberOfTry > DELETE_CREDIT_CARD_MAX_RETRY_COUNT) {
retry = false;
}
// retryInterval
if (numberOfTry > 1) {
yield sleep(DELETE_CREDIT_CARD_RETRY_INTERVAL_IN_MS * (numberOfTry - 1));
}
// クレジットカード削除
if (params.useUsernameAsGMOMemberId) {
const person = yield repos.person.findById({ userId: params.id });
let oldUsername;
try {
oldUsername = yield (0, person2username_1.person2username)(person, repos.cognitoIdentityServiceProvider,
// settings
setting);
}
catch (error) {
let throwsPerson2usernameError = true;
// oldUserが存在しないケースをハンドル
if (error instanceof factory.errors.NotFound && error.entityName === 'User') {
debug('task:deletePerson:deleteById: deleteCreditCardsById oldUsername not found', 'personId:', params.id, 'numberOfTry:', numberOfTry);
throwsPerson2usernameError = false;
}
if (throwsPerson2usernameError) {
throw error;
}
}
if (typeof oldUsername === 'string') {
debug('task:deletePerson:deleteById: deleteCreditCardsById processing... oldUsername:', oldUsername, 'personId:', params.id, 'numberOfTry:', numberOfTry);
yield repos.creditCard.deleteAll({ personId: oldUsername });
}
}
else {
yield repos.creditCard.deleteAll({ personId: params.id });
}
debug('task:deletePerson:deleteById: deleteCreditCardsById processed. personId:', params.id, 'numberOfTry:', numberOfTry);
break;
}
catch (error) {
if (retry) {
continue;
}
else {
throw error;
}
}
}
});
}