From e5dd285e6bb12294a0516f0ae2dfaa65cf4191bc Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 15 Mar 2025 12:48:54 -0500 Subject: [PATCH] Allow custom_emojis endpoint to be accessed without a user --- packages/ditto/routes/customEmojisRoute.test.ts | 8 ++++++++ packages/ditto/routes/customEmojisRoute.ts | 6 +++++- packages/ditto/utils/custom-emoji.ts | 12 +++++------- packages/mastoapi/middleware/userMiddleware.test.ts | 12 ++++++++++++ packages/mastoapi/middleware/userMiddleware.ts | 6 ++++-- 5 files changed, 34 insertions(+), 10 deletions(-) diff --git a/packages/ditto/routes/customEmojisRoute.test.ts b/packages/ditto/routes/customEmojisRoute.test.ts index 4d52540a..c8022ca0 100644 --- a/packages/ditto/routes/customEmojisRoute.test.ts +++ b/packages/ditto/routes/customEmojisRoute.test.ts @@ -10,6 +10,14 @@ Deno.test('customEmojisRoute', async (t) => { await using test = new TestApp(route); const { relay } = test.var; + await t.step('unauth', async () => { + const response = await test.api.get('/'); + const body = await response.json(); + + assertEquals(response.status, 200); + assertEquals(body, []); + }); + const sk = generateSecretKey(); const user = test.user({ relay, signer: new NSecSigner(sk) }); const pubkey = await user.signer.getPublicKey(); diff --git a/packages/ditto/routes/customEmojisRoute.ts b/packages/ditto/routes/customEmojisRoute.ts index 156d2cf7..5dc50f28 100644 --- a/packages/ditto/routes/customEmojisRoute.ts +++ b/packages/ditto/routes/customEmojisRoute.ts @@ -13,9 +13,13 @@ interface MastodonCustomEmoji { category?: string; } -route.get('/', userMiddleware(), async (c) => { +route.get('/', userMiddleware({ required: false }), async (c) => { const { user } = c.var; + if (!user) { + return c.json([]); + } + const pubkey = await user.signer.getPublicKey(); const emojis = await getCustomEmojis(pubkey, c.var); diff --git a/packages/ditto/utils/custom-emoji.ts b/packages/ditto/utils/custom-emoji.ts index 062cb46a..a7a83a31 100644 --- a/packages/ditto/utils/custom-emoji.ts +++ b/packages/ditto/utils/custom-emoji.ts @@ -58,13 +58,11 @@ export async function getCustomEmojis( const d = event.tags.find(([name]) => name === 'd')?.[1]; for (const [t, shortcode, url] of event.tags) { - if (t === 'emoji') { - if (!emojis.has(shortcode)) { - try { - emojis.set(shortcode, { url: new URL(url), category: d }); - } catch { - // continue - } + if (t === 'emoji' && /^\w+$/.test(shortcode) && !emojis.has(shortcode)) { + try { + emojis.set(shortcode, { url: new URL(url), category: d }); + } catch { + // continue } } } diff --git a/packages/mastoapi/middleware/userMiddleware.test.ts b/packages/mastoapi/middleware/userMiddleware.test.ts index fdd0a09a..1edf5673 100644 --- a/packages/mastoapi/middleware/userMiddleware.test.ts +++ b/packages/mastoapi/middleware/userMiddleware.test.ts @@ -10,6 +10,18 @@ Deno.test('no user 401', async () => { assertEquals(response.status, 401); }); +Deno.test('no user required false', async () => { + await using app = new TestApp(); + + app + .use(userMiddleware({ required: false })) + .get('/', (c) => c.text('ok')); + + const response = await app.request('/'); + + assertEquals(response.status, 200); +}); + Deno.test('unsupported signer 400', async () => { await using app = new TestApp(); diff --git a/packages/mastoapi/middleware/userMiddleware.ts b/packages/mastoapi/middleware/userMiddleware.ts index 2b964362..b40f8dea 100644 --- a/packages/mastoapi/middleware/userMiddleware.ts +++ b/packages/mastoapi/middleware/userMiddleware.ts @@ -12,6 +12,7 @@ interface UserMiddlewareOpts { enc?: 'nip04' | 'nip44'; role?: string; verify?: boolean; + required?: boolean; } export function userMiddleware(): DittoMiddleware<{ user: User }>; @@ -19,13 +20,14 @@ export function userMiddleware(): DittoMiddleware<{ user: User }>; export function userMiddleware( opts: UserMiddlewareOpts & { enc: 'nip44' }, ): DittoMiddleware<{ user: User }>; +export function userMiddleware(opts: UserMiddlewareOpts & { required: false }): DittoMiddleware<{ user?: User }>; export function userMiddleware(opts: UserMiddlewareOpts): DittoMiddleware<{ user: User }>; export function userMiddleware(opts: UserMiddlewareOpts = {}): DittoMiddleware<{ user: User }> { return async (c, next) => { const { conf, user, relay } = c.var; - const { enc, role, verify } = opts; + const { enc, role, verify, required = true } = opts; - if (!user) { + if (!user && required) { throw new HTTPException(401, { message: 'Authorization required' }); }