Skip to content
This repository has been archived by the owner on Dec 18, 2024. It is now read-only.

Commit

Permalink
feat(match-transfer): prevent double ISBN handout
Browse files Browse the repository at this point in the history
We were previously only checking that the same BLID was not transferred
twice in a UserMatch, now we check that the same ISBN (or actually
Item ID) is not transferred twice with different BLIDs.
  • Loading branch information
LarsSelbekk committed Jun 17, 2024
1 parent 612ff26 commit 8492917
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 96 deletions.
19 changes: 9 additions & 10 deletions src/collections/customer-item/helpers/customer-item-active-blid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@ import { BlCollectionName } from "../../bl-collection";
import { customerItemSchema } from "../customer-item.schema";

export class CustomerItemActiveBlid {
private readonly _customerItemStorage: BlDocumentStorage<CustomerItem>;
private customerItemActive: CustomerItemActive;
private dbQueryBuilder: SEDbQueryBuilder;

constructor(private customerItemStorage?: BlDocumentStorage<CustomerItem>) {
this.customerItemStorage = customerItemStorage
? customerItemStorage
: new BlDocumentStorage<CustomerItem>(
BlCollectionName.CustomerItems,
customerItemSchema,
);
constructor(customerItemStorage?: BlDocumentStorage<CustomerItem>) {
this._customerItemStorage =
customerItemStorage ??
new BlDocumentStorage<CustomerItem>(
BlCollectionName.CustomerItems,
customerItemSchema,
);
this.customerItemActive = new CustomerItemActive();
this.dbQueryBuilder = new SEDbQueryBuilder();
}
Expand All @@ -34,9 +35,7 @@ export class CustomerItemActiveBlid {
{ fieldName: "blid", type: "string" },
]);

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const customerItems = await this.customerItemStorage.getByQuery(dbQuery);
const customerItems = await this._customerItemStorage.getByQuery(dbQuery);

const activeCustomerItems = customerItems.filter((customerItem) =>
this.customerItemActive.isActive(customerItem),
Expand Down
62 changes: 27 additions & 35 deletions src/collections/match/operations/match-getall-me.operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,57 +14,49 @@ import { BlDocumentStorage } from "../../../storage/blDocumentStorage";
import { BlCollectionName } from "../../bl-collection";
import { itemSchema } from "../../item/item.schema";
import { uniqueItemSchema } from "../../unique-item/unique-item.schema";
import { User } from "../../user/user";
import { UserSchema } from "../../user/user.schema";
import { userDetailSchema } from "../../user-detail/user-detail.schema";
import { matchSchema } from "../match.schema";

export class GetMyMatchesOperation implements Operation {
private readonly _userDetailStorage: BlDocumentStorage<UserDetail>;
private readonly _matchStorage: BlDocumentStorage<Match>;
private readonly _uniqueItemStorage: BlDocumentStorage<UniqueItem>;
private readonly _itemStorage: BlDocumentStorage<Item>;

constructor(
private userStorage?: BlDocumentStorage<User>,
private userDetailStorage?: BlDocumentStorage<UserDetail>,
private matchStorage?: BlDocumentStorage<Match>,
private uniqueItemStorage?: BlDocumentStorage<UniqueItem>,
private itemStorage?: BlDocumentStorage<Item>,
userDetailStorage?: BlDocumentStorage<UserDetail>,
matchStorage?: BlDocumentStorage<Match>,
uniqueItemStorage?: BlDocumentStorage<UniqueItem>,
itemStorage?: BlDocumentStorage<Item>,
) {
this.userStorage ??= new BlDocumentStorage(
BlCollectionName.Users,
UserSchema,
);
this.userDetailStorage ??= new BlDocumentStorage(
BlCollectionName.UserDetails,
userDetailSchema,
);
this.matchStorage ??= new BlDocumentStorage(
BlCollectionName.Matches,
matchSchema,
);
this.uniqueItemStorage ??= new BlDocumentStorage(
BlCollectionName.UniqueItems,
uniqueItemSchema,
);
this.itemStorage ??= new BlDocumentStorage(
BlCollectionName.Items,
itemSchema,
);
this._userDetailStorage =
userDetailStorage ??
new BlDocumentStorage(BlCollectionName.UserDetails, userDetailSchema);
this._matchStorage =
matchStorage ??
new BlDocumentStorage(BlCollectionName.Matches, matchSchema);
this._uniqueItemStorage =
uniqueItemStorage ??
new BlDocumentStorage(BlCollectionName.UniqueItems, uniqueItemSchema);
this._itemStorage =
itemStorage ?? new BlDocumentStorage(BlCollectionName.Items, itemSchema);
}

async run(blApiRequest: BlApiRequest): Promise<BlapiResponse> {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const matches = await getAllMatchesForUser(blApiRequest.user.details);
const matches = await getAllMatchesForUser(
blApiRequest.user!.details,
this._matchStorage,
);

if (matches.length === 0) {
return new BlapiResponse(matches);
}

const matchesWithDetails = await addDetailsToAllMatches(
matches,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this.userDetailStorage,
this.itemStorage,
this.uniqueItemStorage,
this._userDetailStorage,
this._itemStorage,
this._uniqueItemStorage,
);

return new BlapiResponse(matchesWithDetails);
Expand Down
13 changes: 1 addition & 12 deletions src/collections/match/operations/match-operation-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { BlCollectionName } from "../../bl-collection";
import { branchSchema } from "../../branch/branch.schema";
import { itemSchema } from "../../item/item.schema";
import { OrderActive } from "../../order/helpers/order-active/order-active";
import { matchSchema } from "../match.schema";

export async function createMatchOrder(
customerItem: CustomerItem,
Expand Down Expand Up @@ -57,13 +56,6 @@ export async function createMatchOrder(
const orderActive = new OrderActive();
const activeReceiverOrders =
await orderActive.getActiveOrders(userDetailId);
console.log(
activeReceiverOrders.map((order) =>
order.orderItems.filter((orderItem) =>
orderActive.isOrderItemActive(orderItem),
),
),
);
const originalReceiverOrder = activeReceiverOrders.find((order) =>
order.orderItems
.filter((orderItem) => orderActive.isOrderItemActive(orderItem))
Expand Down Expand Up @@ -118,6 +110,7 @@ export async function createMatchOrder(

export async function getAllMatchesForUser(
userDetailId: string,
matchStorage: BlDocumentStorage<Match>,
): Promise<Match[]> {
const query = new SEDbQuery();
query.objectIdFilters = [
Expand All @@ -127,10 +120,6 @@ export async function getAllMatchesForUser(
{ fieldName: "receiver", value: [userDetailId] },
];

const matchStorage = new BlDocumentStorage(
BlCollectionName.Matches,
matchSchema,
);
try {
return (await matchStorage.getByQuery(query)) as Match[];
} catch (e) {
Expand Down
90 changes: 51 additions & 39 deletions src/collections/match/operations/match-transfer-item.operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
Match,
MatchVariant,
Order,
UserDetail,
UniqueItem,
UserMatch,
} from "@boklisten/bl-model";

Expand All @@ -15,6 +15,7 @@ import {
} from "./match-operation-utils";
import { SystemUser } from "../../../auth/permission/permission.service";
import { Operation } from "../../../operation/operation";
import { SEDbQuery } from "../../../query/se.db-query";
import { BlApiRequest } from "../../../request/bl-api-request";
import { BlDocumentStorage } from "../../../storage/blDocumentStorage";
import { BlCollectionName } from "../../bl-collection";
Expand All @@ -24,24 +25,33 @@ import { OrderToCustomerItemGenerator } from "../../customer-item/helpers/order-
import { OrderItemMovedFromOrderHandler } from "../../order/helpers/order-item-moved-from-order-handler/order-item-moved-from-order-handler";
import { OrderValidator } from "../../order/helpers/order-validator/order-validator";
import { orderSchema } from "../../order/order.schema";
import { userDetailSchema } from "../../user-detail/user-detail.schema";
import { uniqueItemSchema } from "../../unique-item/unique-item.schema";
import { matchSchema } from "../match.schema";

export class MatchTransferItemOperation implements Operation {
private readonly _matchStorage: BlDocumentStorage<Match>;
private readonly _orderStorage: BlDocumentStorage<Order>;
private readonly _customerItemStorage: BlDocumentStorage<CustomerItem>;
private readonly _uniqueItemStorage: BlDocumentStorage<UniqueItem>;

constructor(
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
private matchStorage?: BlDocumentStorage<Match>,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
private userDetailStorage?: BlDocumentStorage<UserDetail>,
matchStorage?: BlDocumentStorage<Match>,
orderStorage?: BlDocumentStorage<Order>,
customerItemStorage?: BlDocumentStorage<CustomerItem>,
uniqueItemStorage?: BlDocumentStorage<UniqueItem>,
) {
this.matchStorage =
this._matchStorage =
matchStorage ??
new BlDocumentStorage(BlCollectionName.Matches, matchSchema);
this.userDetailStorage =
userDetailStorage ??
new BlDocumentStorage(BlCollectionName.UserDetails, userDetailSchema);
this._orderStorage =
orderStorage ??
new BlDocumentStorage(BlCollectionName.Orders, orderSchema);
this._customerItemStorage =
customerItemStorage ??
new BlDocumentStorage(BlCollectionName.CustomerItems, customerItemSchema);
this._uniqueItemStorage =
uniqueItemStorage ??
new BlDocumentStorage(BlCollectionName.UniqueItems, uniqueItemSchema);
}

private isValidBlid(scannedText: string): boolean {
Expand All @@ -68,11 +78,12 @@ export class MatchTransferItemOperation implements Operation {
throw new BlError("blid is not a valid blid").code(803);
}

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const receiverUserDetailId = blApiRequest.user.details;
const receiverUserDetailId = blApiRequest.user!.details;

const receiverMatches = await getAllMatchesForUser(receiverUserDetailId);
const receiverMatches = await getAllMatchesForUser(
receiverUserDetailId,
this._matchStorage,
);
const receiverUserMatches = receiverMatches.filter(
(match) => match._variant === MatchVariant.UserMatch,
) as UserMatch[];
Expand Down Expand Up @@ -104,8 +115,23 @@ export class MatchTransferItemOperation implements Operation {
if (receiverUserMatch.receivedBlIds.includes(customerItem.blid!)) {
throw new BlError("Receiver has already received this item").code(806);
}

const receivedItemIds = await Promise.all(
receiverUserMatch.receivedBlIds.map(async (blId) => {
const uniqueItemQuery = new SEDbQuery();
uniqueItemQuery.stringFilters = [{ fieldName: "blid", value: blId }];
return (await this._uniqueItemStorage.getByQuery(uniqueItemQuery))[0]!
.item;
}),
);

if (receivedItemIds.includes(customerItem.item as string)) {
throw new BlError("Receiver has already received this item").code(806);
}

const senderMatches = await getAllMatchesForUser(
customerItem.customer as string,
this._matchStorage,
);
const senderUserMatches = senderMatches.filter(
(match) => match._variant === MatchVariant.UserMatch,
Expand All @@ -123,24 +149,9 @@ export class MatchTransferItemOperation implements Operation {
userFeedback = `Boken du skannet tilhørte en annen elev enn den som ga deg den. Du skal beholde den, men eleven som ga deg boken er fortsatt ansvarlig for at den opprinnelige boken blir levert.`;
}

const matchStorage = new BlDocumentStorage<Match>(
BlCollectionName.Matches,
matchSchema,
);

const orderStorage = new BlDocumentStorage<Order>(
BlCollectionName.Orders,
orderSchema,
);

const customerItemStorage = new BlDocumentStorage<CustomerItem>(
BlCollectionName.CustomerItems,
customerItemSchema,
);

const orderValidator = new OrderValidator();

await matchStorage.update(
await this._matchStorage.update(
receiverUserMatch.id,
{
receivedBlIds: [...receiverUserMatch.receivedBlIds, customerItem.blid!],
Expand All @@ -155,7 +166,7 @@ export class MatchTransferItemOperation implements Operation {
receiverUserMatch.deadlineOverrides,
);

const placedReceiverOrder = await orderStorage.add(
const placedReceiverOrder = await this._orderStorage.add(
receiverOrder,
new SystemUser(),
);
Expand All @@ -165,7 +176,7 @@ export class MatchTransferItemOperation implements Operation {
await orderMovedToHandler.updateOrderItems(placedReceiverOrder);

if (senderUserMatch !== undefined) {
await matchStorage.update(
await this._matchStorage.update(
senderUserMatch.id,
{
deliveredBlIds: [
Expand All @@ -182,14 +193,14 @@ export class MatchTransferItemOperation implements Operation {
true,
);

const placedSenderOrder = await orderStorage.add(
const placedSenderOrder = await this._orderStorage.add(
senderOrder,
new SystemUser(),
);
await orderValidator.validate(placedSenderOrder, false);
}

await customerItemStorage.update(
await this._customerItemStorage.update(
customerItem.id,
{
returned: true,
Expand All @@ -206,9 +217,10 @@ export class MatchTransferItemOperation implements Operation {
throw new BlError("Failed to create new customer item");
}

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
await customerItemStorage.add(generatedCustomerItems[0], new SystemUser());
await this._customerItemStorage.add(
generatedCustomerItems[0]!,
new SystemUser(),
);

return new BlapiResponse([{ feedback: userFeedback }]);
}
Expand Down

0 comments on commit 8492917

Please sign in to comment.