mirror of
https://github.com/djdevin/recflare.git
synced 2026-10-25 23:18:51 -07:00
[cards] Authenticate channel routes and return channel lists (#121)
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@repo/hono-helpers": "workspace:*",
|
||||
"@repo/jwt": "workspace:*",
|
||||
"hono": "4.13.5",
|
||||
"workers-tagged-logger": "1.0.1"
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Hono } from 'hono'
|
||||
import { useWorkersLogger } from 'workers-tagged-logger'
|
||||
|
||||
import { withNotFound, withOnError } from '@repo/hono-helpers'
|
||||
import { validateAndGetAccountId } from '@repo/jwt'
|
||||
|
||||
import type { App } from './context'
|
||||
|
||||
@@ -22,5 +23,15 @@ const app = new Hono<App>()
|
||||
.get('/', async (c) => {
|
||||
return c.text('hello, world!')
|
||||
})
|
||||
.get('/iam/me/channels/:channel', async (c) => {
|
||||
const accountId = await validateAndGetAccountId(c.req.raw, await c.env.JWT_SECRET.get())
|
||||
if (accountId === null) return c.body(null, 401)
|
||||
const channel = c.req.param('channel')
|
||||
if (!['None', 'Announcements', 'JustInTimeTutorials'].includes(channel)) {
|
||||
return c.body(null, 400)
|
||||
}
|
||||
// GetChannelMessages decodes a bare List<InAppMessageDTO>. No campaigns are configured.
|
||||
return c.json([])
|
||||
})
|
||||
|
||||
export default app
|
||||
|
||||
@@ -1,8 +1,44 @@
|
||||
import { SELF } from 'cloudflare:test'
|
||||
import { expect, it } from 'vitest'
|
||||
import { adminSecretsStore, env, SELF } from 'cloudflare:test'
|
||||
import { sign } from 'hono/jwt'
|
||||
import { beforeAll, expect, it } from 'vitest'
|
||||
|
||||
import type { Env } from '../../context'
|
||||
|
||||
declare module 'cloudflare:test' {
|
||||
interface ProvidedEnv extends Env {}
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
await adminSecretsStore(env.JWT_SECRET).create('cards-test-secret')
|
||||
})
|
||||
|
||||
async function bearer() {
|
||||
const token = await sign(
|
||||
{ sub: '205', exp: Math.floor(Date.now() / 1000) + 60 },
|
||||
'cards-test-secret',
|
||||
'HS256'
|
||||
)
|
||||
return { Authorization: `Bearer ${token}` }
|
||||
}
|
||||
|
||||
it('response with hello world', async () => {
|
||||
const res = await SELF.fetch('https://example.com')
|
||||
expect(res.status).toBe(200)
|
||||
expect(await res.text()).toMatchInlineSnapshot(`"hello, world!"`)
|
||||
})
|
||||
|
||||
it('in-app message channels return a bare list and require authentication', async () => {
|
||||
const url = 'https://example.com/iam/me/channels/Announcements'
|
||||
expect((await SELF.fetch(url)).status).toBe(401)
|
||||
for (const channel of ['Announcements', 'JustInTimeTutorials', 'None']) {
|
||||
const response = await SELF.fetch(`https://example.com/iam/me/channels/${channel}`, {
|
||||
headers: await bearer(),
|
||||
})
|
||||
expect(response.status).toBe(200)
|
||||
expect(await response.json()).toEqual([])
|
||||
}
|
||||
expect(
|
||||
(await SELF.fetch('https://example.com/iam/me/channels/Unknown', { headers: await bearer() }))
|
||||
.status
|
||||
).toBe(400)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user