Store the Push Subscription in the database

This commit is contained in:
Alex Gleason
2024-10-02 22:20:47 -05:00
parent 049d99af9b
commit 4561ec0d00
4 changed files with 56 additions and 20 deletions

View File

@@ -1,7 +1,10 @@
import { nip19 } from 'nostr-tools';
import { z } from 'zod';
import { AppController } from '@/app.ts';
import { Storages } from '@/storages.ts';
import { parseBody } from '@/utils/api.ts';
import { getTokenHash } from '@/utils/auth.ts';
const pushSubscribeSchema = z.object({
subscription: z.object({
@@ -10,30 +13,62 @@ const pushSubscribeSchema = z.object({
p256dh: z.string(),
auth: z.string(),
}),
data: z.object({
alerts: z.object({
mention: z.boolean().optional(),
status: z.boolean().optional(),
reblog: z.boolean().optional(),
follow: z.boolean().optional(),
follow_request: z.boolean().optional(),
favourite: z.boolean().optional(),
poll: z.boolean().optional(),
update: z.boolean().optional(),
'admin.sign_up': z.boolean().optional(),
'admin.report': z.boolean().optional(),
}).optional(),
policy: z.enum(['all', 'followed', 'follower', 'none']).optional(),
}),
}),
data: z.object({
alerts: z.object({
mention: z.boolean().optional(),
status: z.boolean().optional(),
reblog: z.boolean().optional(),
follow: z.boolean().optional(),
follow_request: z.boolean().optional(),
favourite: z.boolean().optional(),
poll: z.boolean().optional(),
update: z.boolean().optional(),
'admin.sign_up': z.boolean().optional(),
'admin.report': z.boolean().optional(),
}).optional(),
policy: z.enum(['all', 'followed', 'follower', 'none']).optional(),
}).optional(),
});
export const pushSubscribeController: AppController = async (c) => {
const data = pushSubscribeSchema.safeParse(await parseBody(c.req.raw));
const BEARER_REGEX = new RegExp(`^Bearer (${nip19.BECH32_REGEX.source})$`);
if (!data.success) {
return c.json({ error: 'Invalid request', schema: data.error }, 400);
const header = c.req.header('authorization');
const match = header?.match(BEARER_REGEX);
if (!match) {
return c.json({ error: 'Unauthorized' }, 401);
}
const [_, bech32] = match;
if (!bech32.startsWith('token1')) {
return c.json({ error: 'Unauthorized' }, 401);
}
const kysely = await Storages.kysely();
const signer = c.get('signer')!;
const result = pushSubscribeSchema.safeParse(await parseBody(c.req.raw));
if (!result.success) {
return c.json({ error: 'Invalid request', schema: result.error }, 400);
}
const { subscription, data } = result.data;
await kysely
.insertInto('push_subscriptions')
.values({
pubkey: await signer.getPublicKey(),
token_hash: await getTokenHash(bech32 as `token1${string}`),
endpoint: subscription.endpoint,
p256dh: subscription.keys.p256dh,
auth: subscription.keys.auth,
data,
})
.execute();
return c.json({});
};