UNPKG

@chevre/domain

Version:

Chevre Domain Library for Node.js

163 lines (162 loc) 9.02 kB
"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.validateStartRequest = validateStartRequest; const jwt = require("jsonwebtoken"); const factory = require("../../../../factory"); function verifyMembershipToken(params) { return __awaiter(this, void 0, void 0, function* () { let result; const { issuer, secret, token } = params; if (typeof token === 'string' && token.length > 0) { try { result = yield new Promise((resolve, reject) => { jwt.verify(token, secret, { issuer // ...(Array.isArray(params.audience)) ? { audience: params.audience } : undefined }, (err, decoded) => { if (err instanceof Error) { reject(err); } else { resolve(decoded); } }); }); } catch (error) { // JWTエラーをハンドリング if (error instanceof jwt.TokenExpiredError) { throw new factory.errors.Argument('memberOfToken', `invalid token. [${error.message} expiredAt:${error.expiredAt}]`); } else if (error instanceof jwt.JsonWebTokenError) { throw new factory.errors.Argument('memberOfToken', `invalid token. [${error.message}]`); } throw error; } } else { throw new factory.errors.ArgumentNull('memberOfToken'); } return result; }); } function validateStartRequest(params) { // tslint:disable-next-line:cyclomatic-complexity max-func-body-length return (repos) => __awaiter(this, void 0, void 0, function* () { var _a, _b, _c; const clientId = (_a = params.clientUser) === null || _a === void 0 ? void 0 : _a.client_id; if (typeof clientId !== 'string' || clientId.length === 0) { throw new factory.errors.ArgumentNull('client_id'); } let projectMakesOffer; projectMakesOffer = (yield repos.projectMakesOffer.search({ limit: 1, page: 1, offeredBy: { id: { $eq: params.project.id } }, availableAtOrFrom: { id: { $eq: clientId } } })).shift(); if (projectMakesOffer === undefined) { throw new factory.errors.Argument('project', 'project makes no offers'); } const seller = (yield repos.seller.projectFields({ limit: 1, page: 1, project: { id: { $eq: params.project.id } }, id: { $eq: params.seller.id } }, ['name', 'project', 'typeOf', 'makesOffer', 'additionalProperty'])).shift(); if (seller === undefined) { throw new factory.errors.NotFound(factory.organizationType.Corporation); } // support non-array(2024-10-19~) const sellerMakesOffer = (_b = seller.makesOffer) === null || _b === void 0 ? void 0 : _b.find(({ availableAtOrFrom }) => { return (Array.isArray(availableAtOrFrom) && (availableAtOrFrom === null || availableAtOrFrom === void 0 ? void 0 : availableAtOrFrom.some(({ id }) => id === clientId))) || (!Array.isArray(availableAtOrFrom) && (availableAtOrFrom === null || availableAtOrFrom === void 0 ? void 0 : availableAtOrFrom.id) === clientId); }); if (sellerMakesOffer === undefined) { throw new factory.errors.Argument('seller', 'seller makes no offers'); } // eligibleCustomerType検証(2023-11-20~) const { customerType } = params; if (typeof customerType === 'string') { // 適用カスタマータイプが存在すれば検証(存在しなければあらゆるカスタマータイプを受け入れる) const eligibleCustomerTypeByProject = projectMakesOffer === null || projectMakesOffer === void 0 ? void 0 : projectMakesOffer.eligibleCustomerType; if (Array.isArray(eligibleCustomerTypeByProject)) { const isCustomerTypeEligible = eligibleCustomerTypeByProject.some(({ codeValue }) => codeValue === customerType); if (!isCustomerTypeEligible) { throw new factory.errors.Argument('customerType', `cutomer type ineligible according to the project settings. [${customerType}]`); } } const { eligibleCustomerType } = sellerMakesOffer; // 適用カスタマータイプが存在すれば検証(存在しなければあらゆるカスタマータイプを受け入れる) if (Array.isArray(eligibleCustomerType)) { const isCustomerTypeEligible = eligibleCustomerType.some(({ codeValue }) => codeValue === customerType); if (!isCustomerTypeEligible) { throw new factory.errors.Argument('customerType', `cutomer type ineligible according to the seller settings. [${customerType}]`); } } } // IAM存在検証(2024-02-06~) const iamMember = (yield repos.member.searchCustomerMembers({ limit: 1, page: 1, project: { id: seller.project.id }, member: { // typeOf: { $eq: factory.creativeWorkType.WebApplication }, id: { $eq: clientId } // memberOf: { typeOf: { $eq: factory.organizationType.Project } } // プロジェクトメンバーのはず } })).shift(); if (iamMember === undefined) { throw new factory.errors.NotFound(factory.role.RoleType.OrganizationRole); } // メンバーシップトークン検証(2024-01-31~) let memeberOfPayload; // 適用メンバーシップについてはproject.makesOfferを参照(2025-01-13~) const validMemberProgramIdentifier = (_c = projectMakesOffer.validForMemberTier) === null || _c === void 0 ? void 0 : _c.isTierOf.identifier; if (typeof validMemberProgramIdentifier === 'string') { // メンバープログラムと発行者を参照(2025-01-16~) const memberProgram = (yield repos.memberProgram.projectMemberPrograms({ limit: 1, page: 1, project: { id: { $eq: params.project.id } }, identifier: { $eq: validMemberProgramIdentifier } })).shift(); if (memberProgram === undefined) { throw new factory.errors.NotFound('MemberProgram'); } const issuer = yield repos.issuer.findByIdentifier({ project: { id: params.project.id }, identifier: memberProgram.hostingOrganization.identifier }); if (typeof issuer.tokenSecret !== 'string' || issuer.tokenSecret === '') { throw new factory.errors.NotFound('issuer.tokenSecret'); } memeberOfPayload = yield verifyMembershipToken(Object.assign({ secret: issuer.tokenSecret, // issuer: issuer.identifier, issuer: issuer.url }, (typeof params.memberOfToken === 'string') ? { token: params.memberOfToken } : undefined)); } // discontinue(2025-01-14~) // if (Array.isArray(iamMember.member.member)) { // const verifySecret = iamMember.member.member[0]?.memberOf?.secret; // ひとまず1種類のメンバーシップのみ対応 // const verifyIssuer = iamMember.member.member[0]?.memberOf?.issuer; // ひとまず1種類のメンバーシップのみ対応 // if (typeof verifySecret === 'string') { // memeberOfPayload = await verifyMembershipToken({ // secret: verifySecret, // ...(typeof params.memberOfToken === 'string') ? { token: params.memberOfToken } : undefined, // ...(typeof verifyIssuer === 'string') ? { issuer: verifyIssuer } : undefined // }); // } // } return Object.assign({ sellerMakesOffer, seller }, (memeberOfPayload !== undefined) ? { memeberOfPayload } : undefined); }); }