Skip to content

Commit b44f505

Browse files
committed
chore: expose authorize method from manager
1 parent 00857c8 commit b44f505

File tree

3 files changed

+108
-5
lines changed

3 files changed

+108
-5
lines changed

src/stream_manager.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import { Stream } from './stream.js'
99
import { Storage } from './storage.js'
1010
import type { IncomingMessage, ServerResponse } from 'node:http'
1111

12-
type AccessCallback = <T>(context: T, params?: any) => Promise<boolean> | boolean
12+
export type AccessCallback<T extends unknown, U extends Record<string, string>> = (
13+
context: T,
14+
params: U
15+
) => Promise<boolean> | boolean
1316

1417
interface OnConnectParams<T> {
1518
uid: string
@@ -59,7 +62,7 @@ export interface UnsubscribeParams<T> {
5962
export class StreamManager {
6063
#storage: Storage
6164

62-
#securedChannels = new Map<string, AccessCallback>()
65+
#securedChannels = new Map<string, AccessCallback<any, any>>()
6366

6467
constructor() {
6568
this.#storage = new Storage()
@@ -108,7 +111,10 @@ export class StreamManager {
108111
return true
109112
}
110113

111-
authorize(channel: string, callback: AccessCallback) {
114+
authorize<T extends unknown, U extends Record<string, string>>(
115+
channel: string,
116+
callback: AccessCallback<T, U>
117+
) {
112118
this.#storage.secure(channel)
113119
this.#securedChannels.set(channel, callback)
114120
}

src/transmit.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,20 @@
55
* @copyright Boring Node
66
*/
77

8+
import { clearInterval } from 'node:timers'
89
import Emittery from 'emittery'
910
import { Bus } from '@boringnode/bus'
1011
import string from '@poppinss/utils/string'
1112
import { StreamManager } from './stream_manager.js'
1213
import { TransportMessageType } from './transport_message_type.js'
1314
import type { Transport } from '@boringnode/bus/types/main'
1415
import type { Broadcastable, TransmitConfig } from './types/main.js'
15-
import type { CreateStreamParams, SubscribeParams, UnsubscribeParams } from './stream_manager.js'
16-
import { clearInterval } from 'node:timers'
16+
import type {
17+
AccessCallback,
18+
CreateStreamParams,
19+
SubscribeParams,
20+
UnsubscribeParams,
21+
} from './stream_manager.js'
1722

1823
export interface TransmitLifecycleHooks<T> {
1924
connect: { uid: string; context: T }
@@ -126,6 +131,13 @@ export class Transmit {
126131
})
127132
}
128133

134+
authorize<T extends unknown, U extends Record<string, string>>(
135+
channel: string,
136+
callback: AccessCallback<T, U>
137+
) {
138+
this.#manager.authorize(channel, callback)
139+
}
140+
129141
subscribe<T>(params: Omit<SubscribeParams<T>, 'onSubscribe'>) {
130142
return this.#manager.subscribe<T>({
131143
...params,

tests/transmit.spec.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,91 @@ test.group('Transmit', () => {
2222
assert.instanceOf(transmit.getManager(), StreamManager)
2323
})
2424

25+
test('should call the authorization callback', async ({ assert }) => {
26+
const transmit = new Transmit({
27+
transport: null,
28+
})
29+
30+
const uid = randomUUID()
31+
let authorized = false
32+
33+
transmit.authorize('channel1', () => {
34+
authorized = true
35+
return true
36+
})
37+
38+
await transmit.subscribe({ channel: 'channel1', uid })
39+
40+
assert.isTrue(authorized)
41+
})
42+
43+
test('should call the authorization callback with the context', async ({ assert }) => {
44+
assert.plan(1)
45+
46+
const transmit = new Transmit({
47+
transport: null,
48+
})
49+
50+
const uid = randomUUID()
51+
52+
transmit.authorize('channel1', (context) => {
53+
assert.equal(context, 'foo')
54+
return true
55+
})
56+
57+
await transmit.subscribe({ channel: 'channel1', uid, context: 'foo' })
58+
})
59+
60+
test('should authorize the subscription', async ({ assert }) => {
61+
const transmit = new Transmit({
62+
transport: null,
63+
})
64+
65+
const uid = randomUUID()
66+
67+
transmit.authorize('channel1', () => {
68+
return true
69+
})
70+
71+
const authorized = await transmit.subscribe({ channel: 'channel1', uid })
72+
73+
assert.isTrue(authorized)
74+
})
75+
76+
test('should not authorize the subscription', async ({ assert }) => {
77+
const transmit = new Transmit({
78+
transport: null,
79+
})
80+
81+
const uid = randomUUID()
82+
83+
transmit.authorize('channel1', () => {
84+
return false
85+
})
86+
87+
const authorized = await transmit.subscribe({ channel: 'channel1', uid })
88+
89+
assert.isFalse(authorized)
90+
})
91+
92+
test('should authorize with channel params', async ({ assert }) => {
93+
const transmit = new Transmit({
94+
transport: null,
95+
})
96+
97+
const uid = randomUUID()
98+
99+
transmit.authorize<any, { id: string }>('channel/:id', (_context, params) => {
100+
return params.id === '1'
101+
})
102+
103+
const authorized = await transmit.subscribe({ channel: 'channel/1', uid })
104+
const refused = await transmit.subscribe({ channel: 'channel/2', uid })
105+
106+
assert.isTrue(authorized)
107+
assert.isFalse(refused)
108+
})
109+
25110
test('should emit an connect event', async ({ assert }, done) => {
26111
assert.plan(2)
27112

0 commit comments

Comments
 (0)