mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 11:29:46 +00:00
Add requireVar middleware
This commit is contained in:
parent
d1f8e3b92c
commit
b360dfaf06
6 changed files with 34 additions and 7 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
import type { DittoConf } from '@ditto/conf';
|
import type { DittoConf } from '@ditto/conf';
|
||||||
import type { DittoDatabase } from '@ditto/db';
|
import type { DittoDatabase } from '@ditto/db';
|
||||||
import type { Env } from '@hono/hono';
|
import type { Env } from '@hono/hono';
|
||||||
import type { NRelay } from '@nostrify/nostrify';
|
import type { NostrSigner, NRelay, NStore } from '@nostrify/nostrify';
|
||||||
|
|
||||||
export interface DittoEnv extends Env {
|
export interface DittoEnv extends Env {
|
||||||
Variables: {
|
Variables: {
|
||||||
|
|
@ -13,5 +13,12 @@ export interface DittoEnv extends Env {
|
||||||
db: DittoDatabase;
|
db: DittoDatabase;
|
||||||
/** Abort signal for the request. */
|
/** Abort signal for the request. */
|
||||||
signal: AbortSignal;
|
signal: AbortSignal;
|
||||||
|
/** The current user */
|
||||||
|
user?: {
|
||||||
|
/** The user's signer. */
|
||||||
|
signer: NostrSigner;
|
||||||
|
/** The user's store. */
|
||||||
|
store: NStore;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ export class DittoRoute extends Hono<DittoEnv> {
|
||||||
if (!vars.signal) this.throwMissingVar('signal');
|
if (!vars.signal) this.throwMissingVar('signal');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
...vars,
|
||||||
db: vars.db,
|
db: vars.db,
|
||||||
conf: vars.conf,
|
conf: vars.conf,
|
||||||
store: vars.store,
|
store: vars.store,
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
|
export { requireVar } from './requireVar.ts';
|
||||||
export { userMiddleware } from './userMiddleware.ts';
|
export { userMiddleware } from './userMiddleware.ts';
|
||||||
|
|
|
||||||
17
packages/api/middleware/requireVar.ts
Normal file
17
packages/api/middleware/requireVar.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { HTTPException } from '@hono/hono/http-exception';
|
||||||
|
|
||||||
|
import type { SetRequired } from 'type-fest';
|
||||||
|
import type { DittoEnv } from '../DittoEnv.ts';
|
||||||
|
import type { DittoMiddleware } from '../DittoMiddleware.ts';
|
||||||
|
|
||||||
|
type DittoVars = DittoEnv['Variables'];
|
||||||
|
|
||||||
|
export function requireVar<K extends keyof DittoVars>(key: K): DittoMiddleware<SetRequired<DittoVars, K>> {
|
||||||
|
return (c, next) => {
|
||||||
|
if (!c.var[key]) {
|
||||||
|
throw new HTTPException(500, { message: `Missing required variable: ${key}` });
|
||||||
|
}
|
||||||
|
|
||||||
|
return next();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -18,14 +18,15 @@ interface UserMiddlewareOpts {
|
||||||
privileged: boolean;
|
privileged: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-ignore The types are right.
|
export function userMiddleware(opts: { privileged: false; required: true }): DittoMiddleware<{ user: User }>;
|
||||||
export function userMiddleware(opts: { privileged: boolean; required: true }): DittoMiddleware<{ user: User }>;
|
|
||||||
export function userMiddleware(opts: { privileged: true; required?: boolean }): DittoMiddleware<{ user: User }>;
|
export function userMiddleware(opts: { privileged: true; required?: boolean }): DittoMiddleware<{ user: User }>;
|
||||||
export function userMiddleware(opts: { privileged: false; required?: boolean }): DittoMiddleware<{ user?: User }>;
|
export function userMiddleware(opts: { privileged: false; required?: boolean }): DittoMiddleware<{ user?: User }>;
|
||||||
export function userMiddleware(opts: { privileged?: boolean; required?: boolean }): DittoMiddleware<{ user?: User }> {
|
export function userMiddleware(opts: { privileged: boolean; required?: boolean }): DittoMiddleware<{ user?: User }> {
|
||||||
/** We only accept "Bearer" type. */
|
/** We only accept "Bearer" type. */
|
||||||
const BEARER_REGEX = new RegExp(`^Bearer (${nip19.BECH32_REGEX.source})$`);
|
const BEARER_REGEX = new RegExp(`^Bearer (${nip19.BECH32_REGEX.source})$`);
|
||||||
|
|
||||||
|
const { privileged, required = false } = opts;
|
||||||
|
|
||||||
return async (c, next) => {
|
return async (c, next) => {
|
||||||
const { conf, db, store } = c.var;
|
const { conf, db, store } = c.var;
|
||||||
|
|
||||||
|
|
@ -83,7 +84,7 @@ export function userMiddleware(opts: { privileged?: boolean; required?: boolean
|
||||||
if (signer) {
|
if (signer) {
|
||||||
const user: User = { signer, store };
|
const user: User = { signer, store };
|
||||||
c.set('user', user);
|
c.set('user', user);
|
||||||
} else {
|
} else if (required) {
|
||||||
throw new HTTPException(401);
|
throw new HTTPException(401);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { DittoRoute } from '@ditto/api';
|
import { DittoRoute } from '@ditto/api';
|
||||||
import { userMiddleware } from '@ditto/api/middleware';
|
import { requireVar, userMiddleware } from '@ditto/api/middleware';
|
||||||
import { booleanParamSchema, languageSchema } from '@ditto/api/schema';
|
import { booleanParamSchema, languageSchema } from '@ditto/api/schema';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
|
@ -12,7 +12,7 @@ const homeQuerySchema = z.object({
|
||||||
only_media: booleanParamSchema.optional(),
|
only_media: booleanParamSchema.optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
route.get('/home', async (c) => {
|
route.get('/home', requireVar('user'), async (c) => {
|
||||||
const { user, pagination } = c.var;
|
const { user, pagination } = c.var;
|
||||||
|
|
||||||
const pubkey = await user.signer.getPublicKey()!;
|
const pubkey = await user.signer.getPublicKey()!;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue