Skip to content

Commit

Permalink
🦺 Prevent subscribing twice to same thing
Browse files Browse the repository at this point in the history
  • Loading branch information
coyotte508 committed Jun 1, 2023
1 parent dd6ace4 commit e3528f7
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 10 deletions.
3 changes: 0 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,5 @@
},
"[css]": {
"editor.defaultFormatter": "vscode.css-language-features"
},
"[typescript]": {
"editor.defaultFormatter": "rvest.vs-code-prettier-eslint"
}
}
2 changes: 1 addition & 1 deletion src/lib/server/runtime-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { collections } from './database';
const defaultConfig = {
BTC_EUR: 30_000,
orderNumber: 0,
subscriptionDuration: "month" as "month" | "day" | "hour",
subscriptionDuration: 'month' as 'month' | 'day' | 'hour',
subscriptionReminderSeconds: 24 * 60 * 60,

checkoutButtonOnProductPage: true,
Expand Down
2 changes: 0 additions & 2 deletions src/lib/types/Order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { Product } from './Product';
import type { Currency } from './Currency';
import type { CountryAlpha3 } from './Country';
import type { Timestamps } from './Timestamps';
import type { ObjectId } from 'mongodb';

export interface Order extends Timestamps {
/**
Expand All @@ -16,7 +15,6 @@ export interface Order extends Timestamps {
items: Array<{
product: Product;
quantity: number;
subscriptionId?: ObjectId;
}>;

shippingAddress?: {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/types/PaidSubscription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ export interface PaidSubscription extends Timestamps {
npub: string;
productId: string;

paidUntil?: Date;
paidUntil: Date;
lastRemindedAt?: Date;
}
8 changes: 6 additions & 2 deletions src/routes/admin/config/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@ export const actions = {
.object({
checkoutButtonOnProductPage: z.boolean({ coerce: true }),
discovery: z.boolean({ coerce: true }),
subscriptionDuration: z.enum(["month", "day", "hour"]),
subscriptionReminderSeconds: z.number({coerce: true}).int().min(0).max(24 * 60 * 60 * 7)
subscriptionDuration: z.enum(['month', 'day', 'hour']),
subscriptionReminderSeconds: z
.number({ coerce: true })
.int()
.min(0)
.max(24 * 60 * 60 * 7)
})
.parse({
checkoutButtonOnProductPage: formData.get('checkoutButtonOnProductPage'),
Expand Down
46 changes: 45 additions & 1 deletion src/routes/checkout/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import { lndCreateInvoice } from '$lib/server/lightning.js';
import { paymentMethods } from '$lib/server/payment-methods.js';
import { COUNTRY_ALPHA3S } from '$lib/types/Country';
import { error, redirect } from '@sveltejs/kit';
import { addHours, differenceInSeconds } from 'date-fns';
import { addHours, differenceInSeconds, subSeconds } from 'date-fns';
import { z } from 'zod';
import { bech32 } from 'bech32';
import { ORIGIN } from '$env/static/private';
import { toSatoshis } from '$lib/utils/toSatoshis.js';
import { runtimeConfig } from '$lib/server/runtime-config.js';

export function load() {
return {
Expand Down Expand Up @@ -104,6 +105,49 @@ export const actions = {

const orderId = crypto.randomUUID();

const subscriptions = cart.items.filter((item) => byId[item.productId].type === 'subscription');

for (const subscription of subscriptions) {
const product = byId[subscription.productId];

if (subscription.quantity > 1) {
throw error(
400,
'Cannot order more than one of a subscription at a time for product: ' + product.name
);
}

const existingSubscription = await collections.paidSubscriptions.findOne({
npub: npubAddress,
productId: product._id
});

if (existingSubscription) {
if (
subSeconds(existingSubscription.paidUntil, runtimeConfig.subscriptionReminderSeconds) >
new Date()
) {
throw error(
400,
'You already have an active subscription for this product: ' + product.name
);
}
}

if (
await collections.orders.countDocuments(
{
'notifications.paymentStatus.npub': npubAddress,
'items.product._id': product._id,
'payment.status': 'pending'
},
{ limit: 1 }
)
) {
throw error(400, 'You already have a pending order for this product: ' + product.name);
}
}

await withTransaction(async (session) => {
const res = await collections.runtimeConfig.findOneAndUpdate(
{ _id: 'orderNumber' },
Expand Down

0 comments on commit e3528f7

Please sign in to comment.