@chevre/domain 23.0.0-alpha.2 → 23.0.0-alpha.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/example/src/chevre/assetTransaction/processReserve.ts +102 -40
- package/example/src/chevre/event/updateSellerMakesOffersByIdentifier.ts +106 -0
- package/example/src/chevre/note/findNotes.ts +34 -0
- package/example/src/chevre/note/upsertNotesByIdentifier.ts +10 -5
- package/example/src/chevre/offerCatalog/updateManyOfferCatalogsByIds.ts +49 -0
- package/example/src/chevre/paymentServices/findPaymentServices.ts +37 -0
- package/example/src/chevre/product/findHasOfferCatalog.ts +31 -0
- package/example/src/chevre/reIndex.ts +1 -3
- package/example/src/chevre/roles/addAdminNotePermissionIfNotExists.ts +48 -0
- package/example/src/chevre/roles/{addAdminProductOfferPermissionIfNotExists.ts → addAdminPaymentServiceReadPermissionIfNotExists.ts} +20 -19
- package/example/src/chevre/roles/addAdminProductHasOfferCatalogReadPermissionIfNotExists.ts +33 -0
- package/example/src/chevre/roles/removeConsolePermissionIfExists.ts +1 -1
- package/example/src/chevre/roles/removePermissionIfExists.ts +1 -6
- package/example/src/chevre/unsetUnnecessaryFields.ts +5 -7
- package/example/src/objectId.ts +12 -0
- package/example/src/signPayload.ts +12 -7
- package/lib/chevre/errorHandler.d.ts +6 -2
- package/lib/chevre/errorHandler.js +18 -2
- package/lib/chevre/repo/categoryCode.d.ts +50 -7
- package/lib/chevre/repo/categoryCode.js +56 -15
- package/lib/chevre/repo/event.d.ts +14 -11
- package/lib/chevre/repo/event.js +44 -35
- package/lib/chevre/repo/eventSellerMakesOffer.d.ts +24 -39
- package/lib/chevre/repo/eventSellerMakesOffer.js +88 -43
- package/lib/chevre/repo/mongoose/schemas/eventSeries.d.ts +2 -2
- package/lib/chevre/repo/mongoose/schemas/eventSeries.js +5 -14
- package/lib/chevre/repo/mongoose/schemas/note.js +9 -0
- package/lib/chevre/repo/mongoose/schemas/product.d.ts +4 -4
- package/lib/chevre/repo/mongoose/schemas/product.js +2 -2
- package/lib/chevre/repo/note.d.ts +2 -9
- package/lib/chevre/repo/note.js +52 -18
- package/lib/chevre/repo/noteAboutOrder.d.ts +4 -0
- package/lib/chevre/repo/noteAboutOrder.js +17 -0
- package/lib/chevre/repo/offerCatalog.d.ts +17 -2
- package/lib/chevre/repo/offerCatalog.js +5 -2
- package/lib/chevre/repo/product.js +15 -14
- package/lib/chevre/repo/productHasOfferCatalog.d.ts +43 -0
- package/lib/chevre/repo/productHasOfferCatalog.js +71 -0
- package/lib/chevre/repository.d.ts +5 -0
- package/lib/chevre/repository.js +14 -1
- package/lib/chevre/service/assetTransaction/reserve/start.js +2 -2
- package/lib/chevre/service/assetTransaction/reserve/validateStartRequest/validateIssuedOfferIfExists.d.ts +15 -0
- package/lib/chevre/service/assetTransaction/reserve/validateStartRequest/validateIssuedOfferIfExists.js +159 -0
- package/lib/chevre/service/assetTransaction/reserve/validateStartRequest/validateMemberTierIfExists.d.ts +16 -0
- package/lib/chevre/service/assetTransaction/reserve/validateStartRequest/validateMemberTierIfExists.js +184 -0
- package/lib/chevre/service/assetTransaction/reserve/validateStartRequest.d.ts +4 -1
- package/lib/chevre/service/assetTransaction/reserve/validateStartRequest.js +25 -138
- package/lib/chevre/service/event.js +1 -1
- package/lib/chevre/service/offer/eventServiceByCOA/authorize.js +3 -3
- package/lib/chevre/service/offer/eventServiceByCOA/changeOffers.js +3 -3
- package/lib/chevre/service/offer/onEventChanged.js +2 -1
- package/lib/chevre/service/task/createEvent/createEventBySchedule/factory.js +19 -105
- package/lib/chevre/service/task/onResourceUpdated/syncCategoryCode.js +1 -1
- package/lib/chevre/service/task/onResourceUpdated.js +1 -1
- package/package.json +4 -4
- package/example/src/chevre/aggregateEventSellerMakesOffer.ts +0 -32
- package/example/src/chevre/searchCategoryCodesByAggregate.ts +0 -31
- package/example/src/chevre/searchOfferCatalogItems.ts +0 -59
- package/example/src/chevre/searchPaymentServices.ts +0 -32
- package/example/src/chevre/unsetUnnecessaryFieldsInAction.ts +0 -50
- package/example/src/chevre/unsetUnnecessaryFieldsInTransaction.ts +0 -46
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.ProductHasOfferCatalogRepo = void 0;
|
|
13
|
+
const mongoose_1 = require("mongoose");
|
|
14
|
+
const factory = require("../factory");
|
|
15
|
+
const settings_1 = require("../settings");
|
|
16
|
+
const product_1 = require("./mongoose/schemas/product");
|
|
17
|
+
/**
|
|
18
|
+
* プロダクトオファーカタログリポジトリ
|
|
19
|
+
*/
|
|
20
|
+
class ProductHasOfferCatalogRepo {
|
|
21
|
+
constructor(connection) {
|
|
22
|
+
this.productModel = connection.model(product_1.modelName, (0, product_1.createSchema)());
|
|
23
|
+
}
|
|
24
|
+
findOfferCatalogs(params) {
|
|
25
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
var _a, _b, _c, _d, _e, _f;
|
|
27
|
+
const matchStages = [];
|
|
28
|
+
const projectIdEq = (_b = (_a = params.project) === null || _a === void 0 ? void 0 : _a.id) === null || _b === void 0 ? void 0 : _b.$eq;
|
|
29
|
+
if (typeof projectIdEq === 'string') {
|
|
30
|
+
matchStages.push({ $match: { 'project.id': { $eq: projectIdEq } } });
|
|
31
|
+
}
|
|
32
|
+
const productIdEq = (_d = (_c = params.product) === null || _c === void 0 ? void 0 : _c.id) === null || _d === void 0 ? void 0 : _d.$eq;
|
|
33
|
+
if (typeof productIdEq === 'string') {
|
|
34
|
+
matchStages.push({ $match: { _id: { $eq: new mongoose_1.Types.ObjectId(productIdEq) } } });
|
|
35
|
+
}
|
|
36
|
+
const productIdIn = (_f = (_e = params.product) === null || _e === void 0 ? void 0 : _e.id) === null || _f === void 0 ? void 0 : _f.$in;
|
|
37
|
+
if (Array.isArray(productIdIn)) {
|
|
38
|
+
matchStages.push({ $match: { _id: { $in: productIdIn.map((productId) => new mongoose_1.Types.ObjectId(productId)) } } });
|
|
39
|
+
}
|
|
40
|
+
const aggregate = this.productModel.aggregate([
|
|
41
|
+
{
|
|
42
|
+
$unwind: {
|
|
43
|
+
path: '$hasOfferCatalog.itemListElement'
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
...matchStages,
|
|
47
|
+
{ $sort: { productID: factory.sortType.Ascending } },
|
|
48
|
+
{
|
|
49
|
+
$project: {
|
|
50
|
+
_id: 0,
|
|
51
|
+
id: '$hasOfferCatalog.itemListElement.id',
|
|
52
|
+
aggregateElement: {
|
|
53
|
+
itemOffered: {
|
|
54
|
+
id: { $toString: '$_id' },
|
|
55
|
+
typeOf: '$typeOf'
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
]);
|
|
61
|
+
if (typeof params.limit === 'number' && params.limit > 0) {
|
|
62
|
+
const page = (typeof params.page === 'number' && params.page > 0) ? params.page : 1;
|
|
63
|
+
aggregate.skip(params.limit * (page - 1))
|
|
64
|
+
.limit(params.limit);
|
|
65
|
+
}
|
|
66
|
+
return aggregate.option({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
|
|
67
|
+
.exec();
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.ProductHasOfferCatalogRepo = ProductHasOfferCatalogRepo;
|
|
@@ -56,6 +56,7 @@ import type { SectionRepo } from './repo/place/section';
|
|
|
56
56
|
import type { PotentialActionRepo } from './repo/potentialAction';
|
|
57
57
|
import type { PriceSpecificationRepo } from './repo/priceSpecification';
|
|
58
58
|
import type { ProductRepo } from './repo/product';
|
|
59
|
+
import type { ProductHasOfferCatalogRepo } from './repo/productHasOfferCatalog';
|
|
59
60
|
import type { ProductModelRepo } from './repo/productModel';
|
|
60
61
|
import type { ProductOfferRepo } from './repo/productOffer';
|
|
61
62
|
import type { ProjectRepo } from './repo/project';
|
|
@@ -348,6 +349,10 @@ export type Product = ProductRepo;
|
|
|
348
349
|
export declare namespace Product {
|
|
349
350
|
function createInstance(...params: ConstructorParameters<typeof ProductRepo>): Promise<ProductRepo>;
|
|
350
351
|
}
|
|
352
|
+
export type ProductHasOfferCatalog = ProductHasOfferCatalogRepo;
|
|
353
|
+
export declare namespace ProductHasOfferCatalog {
|
|
354
|
+
function createInstance(...params: ConstructorParameters<typeof ProductHasOfferCatalogRepo>): Promise<ProductHasOfferCatalogRepo>;
|
|
355
|
+
}
|
|
351
356
|
export type ProductModel = ProductModelRepo;
|
|
352
357
|
export declare namespace ProductModel {
|
|
353
358
|
function createInstance(...params: ConstructorParameters<typeof ProductModelRepo>): Promise<ProductModelRepo>;
|
package/lib/chevre/repository.js
CHANGED
|
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.Permit = exports.Person = exports.paymentMethod = exports.PendingReservation = exports.PaymentServiceProvider = exports.PaymentServiceChannel = exports.PaymentService = exports.Passport = exports.OwnershipInfo = exports.OrderNumber = exports.OrderInTransaction = exports.Order = exports.Offer = exports.OfferItemCondition = exports.OfferCatalogItem = exports.OfferCatalog = exports.NoteAboutOrder = exports.Note = exports.Message = exports.MerchantReturnPolicy = exports.MemberProgram = exports.Member = exports.Issuer = exports.IdentityProvider = exports.Identity = exports.EventSeries = exports.EventSellerMakesOffer = exports.Event = exports.EmailMessage = exports.CustomerType = exports.Customer = exports.Credentials = exports.CreativeWork = exports.ConfirmationNumber = exports.Comment = exports.Authorization = exports.CategoryCode = exports.AssetTransaction = exports.Aggregation = exports.AggregateReservation = exports.AggregateOrder = exports.AggregateOffer = exports.AdvanceBookingRequirement = exports.AdditionalProperty = exports.Action = exports.AccountTransaction = exports.AccountTitle = exports.AccountingReport = exports.Account = exports.AcceptedOffer = void 0;
|
|
13
|
-
exports.WebSite = exports.rateLimit = exports.Trip = exports.TransactionProcess = exports.TransactionNumber = exports.Transaction = exports.Ticket = exports.Telemetry = exports.Task = exports.StockHolder = exports.setting = exports.Setting = exports.ServiceOutputIdentifier = exports.ServiceOutput = exports.ServiceAvailableHour = exports.SellerReturnPolicy = exports.SellerPaymentAccepted = exports.SellerMakesOffer = exports.Seller = exports.Schedule = exports.Role = exports.ReserveInterface = exports.Reservation = exports.ProjectMakesOffer = exports.Project = exports.ProductOffer = exports.ProductModel = exports.Product = exports.PriceSpecification = exports.PotentialAction = exports.place = void 0;
|
|
13
|
+
exports.WebSite = exports.rateLimit = exports.Trip = exports.TransactionProcess = exports.TransactionNumber = exports.Transaction = exports.Ticket = exports.Telemetry = exports.Task = exports.StockHolder = exports.setting = exports.Setting = exports.ServiceOutputIdentifier = exports.ServiceOutput = exports.ServiceAvailableHour = exports.SellerReturnPolicy = exports.SellerPaymentAccepted = exports.SellerMakesOffer = exports.Seller = exports.Schedule = exports.Role = exports.ReserveInterface = exports.Reservation = exports.ProjectMakesOffer = exports.Project = exports.ProductOffer = exports.ProductModel = exports.ProductHasOfferCatalog = exports.Product = exports.PriceSpecification = exports.PotentialAction = exports.place = void 0;
|
|
14
14
|
var AcceptedOffer;
|
|
15
15
|
(function (AcceptedOffer) {
|
|
16
16
|
let repo;
|
|
@@ -802,6 +802,19 @@ var Product;
|
|
|
802
802
|
}
|
|
803
803
|
Product.createInstance = createInstance;
|
|
804
804
|
})(Product || (exports.Product = Product = {}));
|
|
805
|
+
var ProductHasOfferCatalog;
|
|
806
|
+
(function (ProductHasOfferCatalog) {
|
|
807
|
+
let repo;
|
|
808
|
+
function createInstance(...params) {
|
|
809
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
810
|
+
if (repo === undefined) {
|
|
811
|
+
repo = (yield Promise.resolve().then(() => require('./repo/productHasOfferCatalog'))).ProductHasOfferCatalogRepo;
|
|
812
|
+
}
|
|
813
|
+
return new repo(...params);
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
ProductHasOfferCatalog.createInstance = createInstance;
|
|
817
|
+
})(ProductHasOfferCatalog || (exports.ProductHasOfferCatalog = ProductHasOfferCatalog = {}));
|
|
805
818
|
var ProductModel;
|
|
806
819
|
(function (ProductModel) {
|
|
807
820
|
let repo;
|
|
@@ -100,9 +100,9 @@ function fixEvent(params) {
|
|
|
100
100
|
// additionalProperty, // discontinue(2024-07-20~)
|
|
101
101
|
'name', 'doorTime', 'endDate', 'eventStatus',
|
|
102
102
|
'location', 'startDate', 'superEvent',
|
|
103
|
-
'offers', 'maximumPhysicalAttendeeCapacity'
|
|
103
|
+
'offers', 'maximumPhysicalAttendeeCapacity',
|
|
104
|
+
'identifier' // support identifier(2025-10-24~)
|
|
104
105
|
// 'coaInfo', // discontinue(2024-07-24~)
|
|
105
|
-
// 'identifier' // discontinue(2024-07-24~)
|
|
106
106
|
]);
|
|
107
107
|
const offeredThroughIdentifier = (_b = event.offers.offeredThrough) === null || _b === void 0 ? void 0 : _b.identifier;
|
|
108
108
|
if (offeredThroughIdentifier === factory.service.webAPI.Identifier.COA) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as factory from '../../../../factory';
|
|
2
|
+
import { IMinimizedIndividualEvent } from '../../../../factory/event';
|
|
3
|
+
import type { IssuerRepo } from '../../../../repo/issuer';
|
|
4
|
+
/**
|
|
5
|
+
* オファートークン検証(2025-10-21~)
|
|
6
|
+
*/
|
|
7
|
+
declare function validateIssuedOfferIfExists(params: {
|
|
8
|
+
event: Pick<IMinimizedIndividualEvent, 'offers' | 'id' | 'project' | 'identifier'>;
|
|
9
|
+
now: Date;
|
|
10
|
+
object: factory.assetTransaction.reserve.IObjectWithoutDetail;
|
|
11
|
+
makesOfferOnApplication: factory.event.screeningEvent.ISellerMakesOffer;
|
|
12
|
+
}): (repos: {
|
|
13
|
+
issuer: IssuerRepo;
|
|
14
|
+
}) => Promise<void>;
|
|
15
|
+
export { validateIssuedOfferIfExists };
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.validateIssuedOfferIfExists = validateIssuedOfferIfExists;
|
|
13
|
+
const jwt = require("jsonwebtoken");
|
|
14
|
+
const moment = require("moment");
|
|
15
|
+
const factory = require("../../../../factory");
|
|
16
|
+
const NUM_ACCEPTED_OFFERS_MAX_VALUE = 50;
|
|
17
|
+
function verifyOfferToken(params) {
|
|
18
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
let result;
|
|
20
|
+
const { issuer, secret, token } = params;
|
|
21
|
+
try {
|
|
22
|
+
result = yield new Promise((resolve, reject) => {
|
|
23
|
+
jwt.verify(token, secret, {
|
|
24
|
+
algorithms: ['HS256'],
|
|
25
|
+
issuer
|
|
26
|
+
// ...(Array.isArray(params.audience)) ? { audience: params.audience } : undefined
|
|
27
|
+
}, (err, decoded) => {
|
|
28
|
+
if (err instanceof Error) {
|
|
29
|
+
reject(err);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
resolve(decoded);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
// JWTエラーをハンドリング
|
|
39
|
+
if (error instanceof jwt.TokenExpiredError) {
|
|
40
|
+
throw new factory.errors.Argument('reservationFor.offers.token', `invalid token. [${error.message} expiredAt:${error.expiredAt}]`);
|
|
41
|
+
}
|
|
42
|
+
else if (error instanceof jwt.JsonWebTokenError) {
|
|
43
|
+
throw new factory.errors.Argument('reservationFor.offers.token', `invalid token. [${error.message}]`);
|
|
44
|
+
}
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const OFFER_TOKEN_DATE_FORMAT = 'YYYY-MM-DDTHH:mm:ssZ';
|
|
51
|
+
function validateOfferToken(params) {
|
|
52
|
+
return () => __awaiter(this, void 0, void 0, function* () {
|
|
53
|
+
var _a, _b;
|
|
54
|
+
const { event, acceptedDate, verifiedOffer, makesOfferOnApplication } = params;
|
|
55
|
+
// イベント識別子一致検証
|
|
56
|
+
const itemOfferedIdentifier = verifiedOffer.itemOffered.identifier;
|
|
57
|
+
if (typeof itemOfferedIdentifier !== 'string' || itemOfferedIdentifier === '') {
|
|
58
|
+
throw new factory.errors.Argument('reservationFor.offers.token', 'itemOffered.identifier must be string');
|
|
59
|
+
}
|
|
60
|
+
const itemOfferedIdentifierMustBe = event.identifier;
|
|
61
|
+
if (typeof itemOfferedIdentifierMustBe !== 'string') {
|
|
62
|
+
throw new factory.errors.NotFound('identifier', 'the event must have an identifier');
|
|
63
|
+
}
|
|
64
|
+
if (itemOfferedIdentifier !== itemOfferedIdentifierMustBe) {
|
|
65
|
+
throw new factory.errors.Argument('reservationFor.offers.token', 'itemOffered.identifier not matched');
|
|
66
|
+
}
|
|
67
|
+
// アプリケーションオファーコード一致検証
|
|
68
|
+
const applicationOfferIdentifier = verifiedOffer.identifier;
|
|
69
|
+
if (typeof applicationOfferIdentifier !== 'string' || applicationOfferIdentifier === '') {
|
|
70
|
+
throw new factory.errors.Argument('reservationFor.offers.token', 'identifier must be string');
|
|
71
|
+
}
|
|
72
|
+
const applicationOfferIdentifierMustBe = makesOfferOnApplication.identifier;
|
|
73
|
+
if (typeof applicationOfferIdentifierMustBe !== 'string') {
|
|
74
|
+
throw new factory.errors.NotFound('makesOffer.identifier');
|
|
75
|
+
}
|
|
76
|
+
if (applicationOfferIdentifier !== applicationOfferIdentifierMustBe) {
|
|
77
|
+
throw new factory.errors.Argument('reservationFor.offers.token', 'identifier not matched');
|
|
78
|
+
}
|
|
79
|
+
// 有効期間検証
|
|
80
|
+
let validThroughMoment;
|
|
81
|
+
let validFromMoment;
|
|
82
|
+
validThroughMoment = moment(verifiedOffer.validThrough, OFFER_TOKEN_DATE_FORMAT, true);
|
|
83
|
+
validFromMoment = moment(verifiedOffer.validFrom, OFFER_TOKEN_DATE_FORMAT, true);
|
|
84
|
+
if (!validThroughMoment.isValid()) {
|
|
85
|
+
throw new factory.errors.Argument('reservationFor.offers.token', 'invalid validThrough');
|
|
86
|
+
}
|
|
87
|
+
if (!validFromMoment.isValid()) {
|
|
88
|
+
throw new factory.errors.Argument('reservationFor.offers.token', 'invalid validFrom');
|
|
89
|
+
}
|
|
90
|
+
if (acceptedDate.isBefore(validFromMoment)) {
|
|
91
|
+
throw new factory.errors.Argument('reservationFor.offers.token', `the offer id valid from ${validFromMoment}`);
|
|
92
|
+
}
|
|
93
|
+
if (acceptedDate.isAfter(validThroughMoment)) {
|
|
94
|
+
throw new factory.errors.Argument('reservationFor.offers.token', `the offer id valid through ${validThroughMoment}`);
|
|
95
|
+
}
|
|
96
|
+
// maxValueを検証
|
|
97
|
+
const maxValue = (_a = verifiedOffer === null || verifiedOffer === void 0 ? void 0 : verifiedOffer.eligibleQuantity) === null || _a === void 0 ? void 0 : _a.maxValue;
|
|
98
|
+
if (typeof maxValue !== 'number') {
|
|
99
|
+
throw new factory.errors.Argument('reservationFor.offers.token', 'eligibleQuantity.maxValue must be number');
|
|
100
|
+
}
|
|
101
|
+
if (maxValue > NUM_ACCEPTED_OFFERS_MAX_VALUE) {
|
|
102
|
+
throw new factory.errors.Argument('reservationFor.offers.token', `eligibleQuantity.maxValue must be <= ${NUM_ACCEPTED_OFFERS_MAX_VALUE}`);
|
|
103
|
+
}
|
|
104
|
+
const numAcceptedOffers = (_b = params.object.acceptedOffer) === null || _b === void 0 ? void 0 : _b.length;
|
|
105
|
+
if (typeof numAcceptedOffers === 'number' && numAcceptedOffers > 0) {
|
|
106
|
+
if (numAcceptedOffers > maxValue) {
|
|
107
|
+
throw new factory.errors.Argument('reservationFor.id', `Maximum number of offers exceeded`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* オファートークン検証(2025-10-21~)
|
|
114
|
+
*/
|
|
115
|
+
function validateIssuedOfferIfExists(params) {
|
|
116
|
+
return (repos) => __awaiter(this, void 0, void 0, function* () {
|
|
117
|
+
var _a, _b, _c, _d, _e;
|
|
118
|
+
const { event, makesOfferOnApplication } = params;
|
|
119
|
+
const acceptedDate = moment(params.now);
|
|
120
|
+
const offerTokenIssuer = (_a = makesOfferOnApplication.offeredBy) === null || _a === void 0 ? void 0 : _a.identifier;
|
|
121
|
+
const offerTokenRequired = typeof offerTokenIssuer === 'string';
|
|
122
|
+
if (offerTokenRequired) {
|
|
123
|
+
const offerIdentifierMustBe = (_c = (_b = params.object.reservationFor) === null || _b === void 0 ? void 0 : _b.offers) === null || _c === void 0 ? void 0 : _c.identifier;
|
|
124
|
+
const offerToken = (_e = (_d = params.object.reservationFor) === null || _d === void 0 ? void 0 : _d.offers) === null || _e === void 0 ? void 0 : _e.token;
|
|
125
|
+
if (typeof offerIdentifierMustBe !== 'string' || offerIdentifierMustBe === '') {
|
|
126
|
+
throw new factory.errors.ArgumentNull('object.reservationFor.offers.identifier');
|
|
127
|
+
}
|
|
128
|
+
if (typeof offerToken !== 'string' || offerToken === '') {
|
|
129
|
+
throw new factory.errors.ArgumentNull('object.reservationFor.offers.token');
|
|
130
|
+
}
|
|
131
|
+
if (typeof makesOfferOnApplication.identifier !== 'string' || makesOfferOnApplication.identifier === '') {
|
|
132
|
+
throw new factory.errors.NotFound('seller.makesOffer.identifier');
|
|
133
|
+
}
|
|
134
|
+
// アプリケーションオファーコード一致検証
|
|
135
|
+
if (makesOfferOnApplication.identifier !== offerIdentifierMustBe) {
|
|
136
|
+
throw new factory.errors.Argument('object.reservationFor.offers.identifier', 'offers.identifier not matched');
|
|
137
|
+
}
|
|
138
|
+
const issuer = yield repos.issuer.findByIdentifier({
|
|
139
|
+
project: { id: event.project.id },
|
|
140
|
+
identifier: offerTokenIssuer
|
|
141
|
+
});
|
|
142
|
+
if (typeof issuer.tokenSecret !== 'string' || issuer.tokenSecret === '') {
|
|
143
|
+
throw new factory.errors.NotFound('issuer.tokenSecret');
|
|
144
|
+
}
|
|
145
|
+
const verifiedOffer = yield verifyOfferToken({
|
|
146
|
+
secret: issuer.tokenSecret,
|
|
147
|
+
issuer: issuer.url,
|
|
148
|
+
token: offerToken
|
|
149
|
+
});
|
|
150
|
+
yield validateOfferToken({
|
|
151
|
+
event,
|
|
152
|
+
acceptedDate,
|
|
153
|
+
verifiedOffer,
|
|
154
|
+
makesOfferOnApplication,
|
|
155
|
+
object: params.object
|
|
156
|
+
})();
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as factory from '../../../../factory';
|
|
2
|
+
import { IMinimizedIndividualEvent } from '../../../../factory/event';
|
|
3
|
+
import type { IssuerRepo } from '../../../../repo/issuer';
|
|
4
|
+
import type { MemberProgramRepo } from '../../../../repo/memberProgram';
|
|
5
|
+
import type { ProductOfferRepo } from '../../../../repo/productOffer';
|
|
6
|
+
declare function validateMemberTierIfExists(params: {
|
|
7
|
+
event: Pick<IMinimizedIndividualEvent, 'offers' | 'id' | 'project'>;
|
|
8
|
+
now: Date;
|
|
9
|
+
object: factory.assetTransaction.reserve.IObjectWithoutDetail;
|
|
10
|
+
makesOfferOnApplication: factory.event.screeningEvent.ISellerMakesOffer;
|
|
11
|
+
}): (repos: {
|
|
12
|
+
issuer: IssuerRepo;
|
|
13
|
+
memberProgram: MemberProgramRepo;
|
|
14
|
+
productOffer: ProductOfferRepo;
|
|
15
|
+
}) => Promise<void>;
|
|
16
|
+
export { validateMemberTierIfExists };
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.validateMemberTierIfExists = validateMemberTierIfExists;
|
|
13
|
+
const jwt = require("jsonwebtoken");
|
|
14
|
+
const moment = require("moment");
|
|
15
|
+
const factory = require("../../../../factory");
|
|
16
|
+
function validateMemberTier(params) {
|
|
17
|
+
return (repos) => __awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
var _a, _b, _c, _d, _e;
|
|
19
|
+
const { acceptedDate, event, verifiedValidForMemberTier, memberProgramIdentifierMustBe, aggregateOfferIdentifier } = params;
|
|
20
|
+
const tierIdentifier = (_b = (_a = verifiedValidForMemberTier.member) === null || _a === void 0 ? void 0 : _a.memberOf) === null || _b === void 0 ? void 0 : _b.identifier;
|
|
21
|
+
const memberProgramIdentifier = (_e = (_d = (_c = verifiedValidForMemberTier.member) === null || _c === void 0 ? void 0 : _c.memberOf) === null || _d === void 0 ? void 0 : _d.isTierOf) === null || _e === void 0 ? void 0 : _e.identifier;
|
|
22
|
+
if (typeof tierIdentifier !== 'string') {
|
|
23
|
+
throw new factory.errors.Argument('reservationFor.offers.validForMemberTier', 'tier identifier must be string');
|
|
24
|
+
}
|
|
25
|
+
if (typeof memberProgramIdentifier !== 'string') {
|
|
26
|
+
throw new factory.errors.Argument('reservationFor.offers.validForMemberTier', 'member program must be string');
|
|
27
|
+
}
|
|
28
|
+
if (memberProgramIdentifier !== memberProgramIdentifierMustBe) {
|
|
29
|
+
throw new factory.errors.Argument('reservationFor.offers.validForMemberTier', 'member program not matched');
|
|
30
|
+
}
|
|
31
|
+
const sellerId = event.offers.seller.id;
|
|
32
|
+
if (typeof sellerId !== 'string' || sellerId === '') {
|
|
33
|
+
throw new factory.errors.NotFound('event.offers.seller.id');
|
|
34
|
+
}
|
|
35
|
+
// 有効なプロダクトオファーを検証
|
|
36
|
+
const productOfferForMemberTier = (yield repos.productOffer.findProductOffers({
|
|
37
|
+
limit: 1,
|
|
38
|
+
page: 1,
|
|
39
|
+
project: { id: { $eq: event.project.id } },
|
|
40
|
+
// availableAtOrFrom: { id: { $eq: availableAt.id } },
|
|
41
|
+
itemOffered: { identifier: { $eq: aggregateOfferIdentifier } }, // オファーコレクションコード
|
|
42
|
+
validForMemberTier: { identifier: { $eq: tierIdentifier } },
|
|
43
|
+
validFrom: { $lte: acceptedDate.toDate() },
|
|
44
|
+
validThrough: { $gte: acceptedDate.toDate() },
|
|
45
|
+
offeredBy: { id: { $eq: sellerId } } // オファー提供者も検証する
|
|
46
|
+
}, ['identifier'])).shift();
|
|
47
|
+
if (productOfferForMemberTier === undefined) {
|
|
48
|
+
throw new factory.errors.NotFound(factory.offerType.Offer, 'valid product offers for member tier not found');
|
|
49
|
+
}
|
|
50
|
+
// let validThroughMoment: moment.Moment;
|
|
51
|
+
// let validFromMoment: moment.Moment;
|
|
52
|
+
// validThroughMoment = moment(productOfferForMemberTier.validThrough, ROLE_DATE_FORMAT, true);
|
|
53
|
+
// validFromMoment = moment(productOfferForMemberTier.validFrom, ROLE_DATE_FORMAT, true);
|
|
54
|
+
// if (acceptedDate.isBefore(validFromMoment)) {
|
|
55
|
+
// throw new factory.errors.Argument(
|
|
56
|
+
// 'reservationFor.offers.validForMemberTier',
|
|
57
|
+
// `the offer id valid from ${validFromMoment}`
|
|
58
|
+
// );
|
|
59
|
+
// }
|
|
60
|
+
// if (acceptedDate.isAfter(validThroughMoment)) {
|
|
61
|
+
// throw new factory.errors.Argument(
|
|
62
|
+
// 'reservationFor.offers.validForMemberTier',
|
|
63
|
+
// `the offer id valid through ${validThroughMoment}`
|
|
64
|
+
// );
|
|
65
|
+
// }
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function verifyMemberTierToken(params) {
|
|
69
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
70
|
+
let result;
|
|
71
|
+
const { issuer, secret, token } = params;
|
|
72
|
+
try {
|
|
73
|
+
result = yield new Promise((resolve, reject) => {
|
|
74
|
+
jwt.verify(token, secret, {
|
|
75
|
+
algorithms: ['HS256'],
|
|
76
|
+
issuer
|
|
77
|
+
// ...(Array.isArray(params.audience)) ? { audience: params.audience } : undefined
|
|
78
|
+
}, (err, decoded) => {
|
|
79
|
+
if (err instanceof Error) {
|
|
80
|
+
reject(err);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
resolve(decoded);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
// JWTエラーをハンドリング
|
|
90
|
+
if (error instanceof jwt.TokenExpiredError) {
|
|
91
|
+
throw new factory.errors.Argument('reservationFor.offers.validForMemberTier', `invalid token. [${error.message} expiredAt:${error.expiredAt}]`);
|
|
92
|
+
}
|
|
93
|
+
else if (error instanceof jwt.JsonWebTokenError) {
|
|
94
|
+
throw new factory.errors.Argument('reservationFor.offers.validForMemberTier', `invalid token. [${error.message}]`);
|
|
95
|
+
}
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
return result;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function validateMemberTierIfExists(params) {
|
|
102
|
+
// tslint:disable-next-line:cyclomatic-complexity max-func-body-length
|
|
103
|
+
return (repos) => __awaiter(this, void 0, void 0, function* () {
|
|
104
|
+
var _a, _b, _c, _d;
|
|
105
|
+
const { event, makesOfferOnApplication } = params;
|
|
106
|
+
const acceptedDate = moment(params.now);
|
|
107
|
+
const eventOffers = event.offers;
|
|
108
|
+
// 有効メンバープログラムティアが存在する場合
|
|
109
|
+
// support validForMemberTier(2025-05-14~)
|
|
110
|
+
const validForMemberTierExists = ((_a = makesOfferOnApplication.validForMemberTier) === null || _a === void 0 ? void 0 : _a.typeOf) === 'MemberProgramTier';
|
|
111
|
+
if (validForMemberTierExists) {
|
|
112
|
+
const tokenizedMemberProgramTier = (_c = (_b = params.object.reservationFor) === null || _b === void 0 ? void 0 : _b.offers) === null || _c === void 0 ? void 0 : _c.validForMemberTier;
|
|
113
|
+
const validForMemberTierToken = tokenizedMemberProgramTier === null || tokenizedMemberProgramTier === void 0 ? void 0 : tokenizedMemberProgramTier.token;
|
|
114
|
+
const memberProgramIdentifierMustBe = (_d = tokenizedMemberProgramTier === null || tokenizedMemberProgramTier === void 0 ? void 0 : tokenizedMemberProgramTier.isTierOf) === null || _d === void 0 ? void 0 : _d.identifier;
|
|
115
|
+
// ティアトークンが必須
|
|
116
|
+
if (typeof validForMemberTierToken !== 'string' || validForMemberTierToken === '') {
|
|
117
|
+
throw new factory.errors.ArgumentNull('reservationFor.offers.validForMemberTier.token');
|
|
118
|
+
}
|
|
119
|
+
// メンバープログラムコード指定が必須
|
|
120
|
+
if (typeof memberProgramIdentifierMustBe !== 'string' || memberProgramIdentifierMustBe === '') {
|
|
121
|
+
throw new factory.errors.ArgumentNull('reservationFor.offers.validForMemberTier.isTierOf.identifier');
|
|
122
|
+
}
|
|
123
|
+
// 有効メンバープログラムティアが存在する場合、オファーコレクションコードが必須
|
|
124
|
+
const aggregateOfferIdentifier = eventOffers.identifier;
|
|
125
|
+
if (typeof aggregateOfferIdentifier !== 'string' || aggregateOfferIdentifier === '') {
|
|
126
|
+
throw new factory.errors.NotFound('makesOfferOnApplication.identifier');
|
|
127
|
+
}
|
|
128
|
+
// トークン検証
|
|
129
|
+
const memberProgram = (yield repos.memberProgram.projectMemberPrograms({
|
|
130
|
+
limit: 1,
|
|
131
|
+
page: 1,
|
|
132
|
+
project: { id: { $eq: params.event.project.id } },
|
|
133
|
+
identifier: { $eq: memberProgramIdentifierMustBe }
|
|
134
|
+
})).shift();
|
|
135
|
+
if (memberProgram === undefined) {
|
|
136
|
+
throw new factory.errors.NotFound('MemberProgram', `MemberProgram '${memberProgramIdentifierMustBe}' not found`);
|
|
137
|
+
}
|
|
138
|
+
const issuer = yield repos.issuer.findByIdentifier({
|
|
139
|
+
project: { id: params.event.project.id },
|
|
140
|
+
identifier: memberProgram.hostingOrganization.identifier
|
|
141
|
+
});
|
|
142
|
+
if (typeof issuer.tokenSecret !== 'string' || issuer.tokenSecret === '') {
|
|
143
|
+
throw new factory.errors.NotFound('issuer.tokenSecret');
|
|
144
|
+
}
|
|
145
|
+
const verifiedValidForMemberTier = yield verifyMemberTierToken({
|
|
146
|
+
secret: issuer.tokenSecret,
|
|
147
|
+
issuer: issuer.url,
|
|
148
|
+
token: validForMemberTierToken
|
|
149
|
+
});
|
|
150
|
+
yield validateMemberTier({
|
|
151
|
+
event, acceptedDate, verifiedValidForMemberTier,
|
|
152
|
+
memberProgramIdentifierMustBe, aggregateOfferIdentifier
|
|
153
|
+
})(repos);
|
|
154
|
+
}
|
|
155
|
+
// tslint:disable-next-line:no-suspicious-comment
|
|
156
|
+
// TODO オファートークン検証(2025-10-21~)
|
|
157
|
+
// const offerTokenIssuer = makesOfferOnApplication.issuedBy?.identifier;
|
|
158
|
+
// const offerTokenRequired = typeof offerTokenIssuer === 'string';
|
|
159
|
+
// if (offerTokenRequired) {
|
|
160
|
+
// const offerToken = params.object.reservationFor?.offers?.token;
|
|
161
|
+
// if (typeof offerToken !== 'string' || offerToken === '') {
|
|
162
|
+
// throw new factory.errors.ArgumentNull('object.reservationFor.offers.token');
|
|
163
|
+
// }
|
|
164
|
+
// const issuer = await repos.issuer.findByIdentifier({
|
|
165
|
+
// project: { id: params.event.project.id },
|
|
166
|
+
// identifier: offerTokenIssuer
|
|
167
|
+
// });
|
|
168
|
+
// if (typeof issuer.tokenSecret !== 'string' || issuer.tokenSecret === '') {
|
|
169
|
+
// throw new factory.errors.NotFound('issuer.tokenSecret');
|
|
170
|
+
// }
|
|
171
|
+
// const verifiedOffer = await verifyOfferToken({
|
|
172
|
+
// secret: issuer.tokenSecret,
|
|
173
|
+
// issuer: issuer.url,
|
|
174
|
+
// token: offerToken
|
|
175
|
+
// });
|
|
176
|
+
// await validateOfferToken({
|
|
177
|
+
// acceptedDate,
|
|
178
|
+
// verifiedOffer,
|
|
179
|
+
// makesOfferOnApplication,
|
|
180
|
+
// object: params.object
|
|
181
|
+
// })();
|
|
182
|
+
// }
|
|
183
|
+
});
|
|
184
|
+
}
|
|
@@ -5,7 +5,10 @@ import type { MemberProgramRepo } from '../../../repo/memberProgram';
|
|
|
5
5
|
import type { ProductOfferRepo } from '../../../repo/productOffer';
|
|
6
6
|
declare function validateStartRequest(params: {
|
|
7
7
|
object: factory.assetTransaction.reserve.IObjectWithoutDetail;
|
|
8
|
-
event: Pick<IMinimizedIndividualEvent, 'offers' | 'id' | 'project'>;
|
|
8
|
+
event: Pick<IMinimizedIndividualEvent, 'offers' | 'id' | 'project' | 'identifier'>;
|
|
9
|
+
/**
|
|
10
|
+
* アプリケーションごとのオファーを検証するかどうか
|
|
11
|
+
*/
|
|
9
12
|
validateEventOfferPeriod?: boolean;
|
|
10
13
|
validateEvent?: boolean;
|
|
11
14
|
now: Date;
|