livekit-server-sdk 2.9.2 → 2.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AccessToken.d.cts +80 -0
- package/dist/AgentDispatchClient.d.cts +50 -0
- package/dist/EgressClient.cjs +1 -0
- package/dist/EgressClient.cjs.map +1 -1
- package/dist/EgressClient.d.cts +168 -0
- package/dist/EgressClient.d.ts.map +1 -1
- package/dist/EgressClient.js +1 -0
- package/dist/EgressClient.js.map +1 -1
- package/dist/IngressClient.d.cts +136 -0
- package/dist/RoomServiceClient.d.cts +173 -0
- package/dist/ServiceBase.d.cts +21 -0
- package/dist/SipClient.d.cts +142 -0
- package/dist/TwirpRPC.d.cts +18 -0
- package/dist/WebhookReceiver.cjs +12 -2
- package/dist/WebhookReceiver.cjs.map +1 -1
- package/dist/WebhookReceiver.d.cts +29 -0
- package/dist/WebhookReceiver.d.ts.map +1 -1
- package/dist/WebhookReceiver.js +2 -2
- package/dist/WebhookReceiver.js.map +1 -1
- package/dist/digest.cjs +44 -0
- package/dist/digest.cjs.map +1 -0
- package/dist/digest.d.cts +3 -0
- package/dist/digest.d.ts +2 -0
- package/dist/digest.d.ts.map +1 -0
- package/dist/digest.js +14 -0
- package/dist/digest.js.map +1 -0
- package/dist/grants.d.cts +71 -0
- package/dist/index.d.cts +12 -0
- package/package.json +14 -6
- package/src/AccessToken.test.ts +6 -6
- package/src/EgressClient.ts +1 -0
- package/src/WebhookReceiver.ts +2 -2
- package/src/digest.ts +14 -0
- package/src/grants.test.ts +2 -2
- package/dist/AccessToken.test.cjs +0 -147
- package/dist/AccessToken.test.cjs.map +0 -1
- package/dist/AccessToken.test.js +0 -129
- package/dist/AccessToken.test.js.map +0 -1
- package/dist/WebhookReceiver.test.cjs +0 -38
- package/dist/WebhookReceiver.test.cjs.map +0 -1
- package/dist/WebhookReceiver.test.js +0 -37
- package/dist/WebhookReceiver.test.js.map +0 -1
- package/dist/grants.test.cjs +0 -27
- package/dist/grants.test.cjs.map +0 -1
- package/dist/grants.test.js +0 -26
- package/dist/grants.test.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/digest.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\n// Use the Web Crypto API if available, otherwise fallback to Node.js crypto\nexport default async function digest(data: string): Promise<ArrayBuffer> {\n if (globalThis.crypto?.subtle) {\n const encoder = new TextEncoder();\n return crypto.subtle.digest('SHA-256', encoder.encode(data));\n } else {\n const nodeCrypto = await import('node:crypto');\n return nodeCrypto.createHash('sha256').update(data).digest();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,eAAO,OAA8B,MAAoC;AALzE;AAME,OAAI,gBAAW,WAAX,mBAAmB,QAAQ;AAC7B,UAAM,UAAU,IAAI,YAAY;AAChC,WAAO,OAAO,OAAO,OAAO,WAAW,QAAQ,OAAO,IAAI,CAAC;AAAA,EAC7D,OAAO;AACL,UAAM,aAAa,MAAM,OAAO,aAAa;AAC7C,WAAO,WAAW,WAAW,QAAQ,EAAE,OAAO,IAAI,EAAE,OAAO;AAAA,EAC7D;AACF;","names":[]}
|
package/dist/digest.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["../src/digest.ts"],"names":[],"mappings":"AAKA,wBAA8B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAQvE"}
|
package/dist/digest.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
async function digest(data) {
|
|
2
|
+
var _a;
|
|
3
|
+
if ((_a = globalThis.crypto) == null ? void 0 : _a.subtle) {
|
|
4
|
+
const encoder = new TextEncoder();
|
|
5
|
+
return crypto.subtle.digest("SHA-256", encoder.encode(data));
|
|
6
|
+
} else {
|
|
7
|
+
const nodeCrypto = await import("node:crypto");
|
|
8
|
+
return nodeCrypto.createHash("sha256").update(data).digest();
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
digest as default
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=digest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/digest.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\n// Use the Web Crypto API if available, otherwise fallback to Node.js crypto\nexport default async function digest(data: string): Promise<ArrayBuffer> {\n if (globalThis.crypto?.subtle) {\n const encoder = new TextEncoder();\n return crypto.subtle.digest('SHA-256', encoder.encode(data));\n } else {\n const nodeCrypto = await import('node:crypto');\n return nodeCrypto.createHash('sha256').update(data).digest();\n }\n}\n"],"mappings":"AAKA,eAAO,OAA8B,MAAoC;AALzE;AAME,OAAI,gBAAW,WAAX,mBAAmB,QAAQ;AAC7B,UAAM,UAAU,IAAI,YAAY;AAChC,WAAO,OAAO,OAAO,OAAO,WAAW,QAAQ,OAAO,IAAI,CAAC;AAAA,EAC7D,OAAO;AACL,UAAM,aAAa,MAAM,OAAO,aAAa;AAC7C,WAAO,WAAW,WAAW,QAAQ,EAAE,OAAO,IAAI,EAAE,OAAO;AAAA,EAC7D;AACF;","names":[]}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { TrackSource, RoomConfiguration } from '@livekit/protocol';
|
|
2
|
+
import { JWTPayload } from 'jose';
|
|
3
|
+
|
|
4
|
+
declare function trackSourceToString(source: TrackSource): "camera" | "microphone" | "screen_share" | "screen_share_audio";
|
|
5
|
+
declare function claimsToJwtPayload(grant: ClaimGrants): JWTPayload & {
|
|
6
|
+
video?: Record<string, unknown>;
|
|
7
|
+
};
|
|
8
|
+
interface VideoGrant {
|
|
9
|
+
/** permission to create a room */
|
|
10
|
+
roomCreate?: boolean;
|
|
11
|
+
/** permission to join a room as a participant, room must be set */
|
|
12
|
+
roomJoin?: boolean;
|
|
13
|
+
/** permission to list rooms */
|
|
14
|
+
roomList?: boolean;
|
|
15
|
+
/** permission to start a recording */
|
|
16
|
+
roomRecord?: boolean;
|
|
17
|
+
/** permission to control a specific room, room must be set */
|
|
18
|
+
roomAdmin?: boolean;
|
|
19
|
+
/** name of the room, must be set for admin or join permissions */
|
|
20
|
+
room?: string;
|
|
21
|
+
/** permissions to control ingress, not specific to any room or ingress */
|
|
22
|
+
ingressAdmin?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* allow participant to publish. If neither canPublish or canSubscribe is set,
|
|
25
|
+
* both publish and subscribe are enabled
|
|
26
|
+
*/
|
|
27
|
+
canPublish?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* TrackSource types that the participant is allowed to publish
|
|
30
|
+
* When set, it supersedes CanPublish. Only sources explicitly set here can be published
|
|
31
|
+
*/
|
|
32
|
+
canPublishSources?: TrackSource[];
|
|
33
|
+
/** allow participant to subscribe to other tracks */
|
|
34
|
+
canSubscribe?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* allow participants to publish data, defaults to true if not set
|
|
37
|
+
*/
|
|
38
|
+
canPublishData?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* by default, a participant is not allowed to update its own metadata
|
|
41
|
+
*/
|
|
42
|
+
canUpdateOwnMetadata?: boolean;
|
|
43
|
+
/** participant isn't visible to others */
|
|
44
|
+
hidden?: boolean;
|
|
45
|
+
/** participant is recording the room, when set, allows room to indicate it's being recorded */
|
|
46
|
+
recorder?: boolean;
|
|
47
|
+
/** participant allowed to connect to LiveKit as Agent Framework worker */
|
|
48
|
+
agent?: boolean;
|
|
49
|
+
/** allow participant to subscribe to metrics */
|
|
50
|
+
canSubscribeMetrics?: boolean;
|
|
51
|
+
}
|
|
52
|
+
interface SIPGrant {
|
|
53
|
+
/** manage sip resources */
|
|
54
|
+
admin?: boolean;
|
|
55
|
+
/** make outbound calls */
|
|
56
|
+
call?: boolean;
|
|
57
|
+
}
|
|
58
|
+
/** @internal */
|
|
59
|
+
interface ClaimGrants extends JWTPayload {
|
|
60
|
+
name?: string;
|
|
61
|
+
video?: VideoGrant;
|
|
62
|
+
sip?: SIPGrant;
|
|
63
|
+
kind?: string;
|
|
64
|
+
metadata?: string;
|
|
65
|
+
attributes?: Record<string, string>;
|
|
66
|
+
sha256?: string;
|
|
67
|
+
roomPreset?: string;
|
|
68
|
+
roomConfig?: RoomConfiguration;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export { type ClaimGrants, type SIPGrant, type VideoGrant, claimsToJwtPayload, trackSourceToString };
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { AliOSSUpload, AutoParticipantEgress, AutoTrackEgress, AzureBlobUpload, DataPacket_Kind, DirectFileOutput, EgressInfo, EgressStatus, EncodedFileOutput, EncodedFileType, EncodingOptions, EncodingOptionsPreset, GCPUpload, ImageCodec, ImageFileSuffix, ImageOutput, IngressAudioEncodingOptions, IngressAudioEncodingPreset, IngressAudioOptions, IngressInfo, IngressInput, IngressState, IngressVideoEncodingOptions, IngressVideoEncodingPreset, IngressVideoOptions, ParticipantEgressRequest, ParticipantInfo, ParticipantInfo_State, ParticipantPermission, Room, RoomCompositeEgressRequest, RoomEgress, S3Upload, SIPDispatchRuleInfo, SIPParticipantInfo, SIPTrunkInfo, SegmentedFileOutput, SegmentedFileProtocol, StreamOutput, StreamProtocol, TrackCompositeEgressRequest, TrackEgressRequest, TrackInfo, TrackSource, TrackType, WebEgressRequest } from '@livekit/protocol';
|
|
2
|
+
export { AccessToken, AccessTokenOptions, TokenVerifier } from './AccessToken.cjs';
|
|
3
|
+
export { AgentDispatchClient } from './AgentDispatchClient.cjs';
|
|
4
|
+
export { EgressClient, EncodedOutputs, ListEgressOptions, ParticipantEgressOptions, RoomCompositeOptions, TrackCompositeOptions, WebOptions } from './EgressClient.cjs';
|
|
5
|
+
export { ClaimGrants, SIPGrant, VideoGrant, claimsToJwtPayload, trackSourceToString } from './grants.cjs';
|
|
6
|
+
export { CreateIngressOptions, IngressClient, ListIngressOptions, UpdateIngressOptions } from './IngressClient.cjs';
|
|
7
|
+
export { CreateOptions, RoomServiceClient, SendDataOptions, UpdateParticipantOptions } from './RoomServiceClient.cjs';
|
|
8
|
+
export { CreateSipDispatchRuleOptions, CreateSipInboundTrunkOptions, CreateSipOutboundTrunkOptions, CreateSipParticipantOptions, CreateSipTrunkOptions, SipClient, SipDispatchRuleDirect, SipDispatchRuleIndividual, TransferSipParticipantOptions } from './SipClient.cjs';
|
|
9
|
+
export { WebhookEvent, WebhookEventNames, WebhookReceiver, authorizeHeader } from './WebhookReceiver.cjs';
|
|
10
|
+
import './ServiceBase.cjs';
|
|
11
|
+
import 'jose';
|
|
12
|
+
import '@bufbuild/protobuf';
|
package/package.json
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livekit-server-sdk",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.4",
|
|
4
4
|
"description": "Server-side SDK for LiveKit",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"require": "dist/index.cjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
-
"repository":
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/livekit/server-sdk-js.git"
|
|
11
|
+
},
|
|
9
12
|
"author": "David Zhao <david@davidzhao.com>",
|
|
10
13
|
"license": "Apache-2.0",
|
|
11
14
|
"type": "module",
|
|
12
15
|
"exports": {
|
|
13
16
|
".": {
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
"import": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"require": {
|
|
22
|
+
"types": "./dist/index.d.cts",
|
|
23
|
+
"default": "./dist/index.cjs"
|
|
24
|
+
}
|
|
17
25
|
}
|
|
18
26
|
},
|
|
19
27
|
"files": [
|
|
@@ -40,7 +48,7 @@
|
|
|
40
48
|
"vitest": "^2.0.0"
|
|
41
49
|
},
|
|
42
50
|
"engines": {
|
|
43
|
-
"node": ">=
|
|
51
|
+
"node": ">=18"
|
|
44
52
|
},
|
|
45
53
|
"scripts": {
|
|
46
54
|
"build": "tsup --onSuccess \"tsc --declaration --emitDeclarationOnly\"",
|
package/src/AccessToken.test.ts
CHANGED
|
@@ -9,8 +9,8 @@ import {
|
|
|
9
9
|
} from '@livekit/protocol';
|
|
10
10
|
import * as jose from 'jose';
|
|
11
11
|
import { describe, expect, it } from 'vitest';
|
|
12
|
-
import { AccessToken, TokenVerifier } from './AccessToken';
|
|
13
|
-
import type { ClaimGrants } from './grants';
|
|
12
|
+
import { AccessToken, TokenVerifier } from './AccessToken.js';
|
|
13
|
+
import type { ClaimGrants } from './grants.js';
|
|
14
14
|
|
|
15
15
|
const testApiKey = 'abcdefg';
|
|
16
16
|
const testSecret = 'abababa';
|
|
@@ -143,10 +143,10 @@ describe('room configuration with agents and egress', () => {
|
|
|
143
143
|
expect(decoded.roomConfig?.name).toEqual('test-room');
|
|
144
144
|
expect(decoded.roomConfig?.maxParticipants).toEqual(10);
|
|
145
145
|
expect(decoded.roomConfig?.agents).toHaveLength(2);
|
|
146
|
-
expect(decoded.roomConfig?.agents?.[0]
|
|
147
|
-
expect(decoded.roomConfig?.agents?.[0]
|
|
148
|
-
expect(decoded.roomConfig?.agents?.[1]
|
|
149
|
-
expect(decoded.roomConfig?.agents?.[1]
|
|
146
|
+
expect(decoded.roomConfig?.agents?.[0]?.agentName).toEqual('agent1');
|
|
147
|
+
expect(decoded.roomConfig?.agents?.[0]?.metadata).toEqual('metadata-1');
|
|
148
|
+
expect(decoded.roomConfig?.agents?.[1]?.agentName).toEqual('agent2');
|
|
149
|
+
expect(decoded.roomConfig?.agents?.[1]?.metadata).toEqual('metadata-2');
|
|
150
150
|
expect(decoded.roomConfig?.egress?.room?.roomName).toEqual('test-room');
|
|
151
151
|
});
|
|
152
152
|
});
|
package/src/EgressClient.ts
CHANGED
package/src/WebhookReceiver.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import type { BinaryReadOptions, JsonReadOptions, JsonValue } from '@bufbuild/protobuf';
|
|
5
5
|
import { WebhookEvent as ProtoWebhookEvent } from '@livekit/protocol';
|
|
6
6
|
import { TokenVerifier } from './AccessToken.js';
|
|
7
|
+
import digest from './digest.js';
|
|
7
8
|
|
|
8
9
|
export const authorizeHeader = 'Authorize';
|
|
9
10
|
|
|
@@ -66,8 +67,7 @@ export class WebhookReceiver {
|
|
|
66
67
|
}
|
|
67
68
|
const claims = await this.verifier.verify(authHeader);
|
|
68
69
|
// confirm sha
|
|
69
|
-
const
|
|
70
|
-
const hash = await crypto.subtle.digest('SHA-256', encoder.encode(body));
|
|
70
|
+
const hash = await digest(body);
|
|
71
71
|
const hashDecoded = btoa(
|
|
72
72
|
Array.from(new Uint8Array(hash))
|
|
73
73
|
.map((v) => String.fromCharCode(v))
|
package/src/digest.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2024 LiveKit, Inc.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
// Use the Web Crypto API if available, otherwise fallback to Node.js crypto
|
|
6
|
+
export default async function digest(data: string): Promise<ArrayBuffer> {
|
|
7
|
+
if (globalThis.crypto?.subtle) {
|
|
8
|
+
const encoder = new TextEncoder();
|
|
9
|
+
return crypto.subtle.digest('SHA-256', encoder.encode(data));
|
|
10
|
+
} else {
|
|
11
|
+
const nodeCrypto = await import('node:crypto');
|
|
12
|
+
return nodeCrypto.createHash('sha256').update(data).digest();
|
|
13
|
+
}
|
|
14
|
+
}
|
package/src/grants.test.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
// SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
import { TrackSource } from '@livekit/protocol';
|
|
5
5
|
import { describe, expect, it } from 'vitest';
|
|
6
|
-
import type { ClaimGrants, VideoGrant } from './grants';
|
|
7
|
-
import { claimsToJwtPayload } from './grants';
|
|
6
|
+
import type { ClaimGrants, VideoGrant } from './grants.js';
|
|
7
|
+
import { claimsToJwtPayload } from './grants.js';
|
|
8
8
|
|
|
9
9
|
describe('ClaimGrants are parsed correctly', () => {
|
|
10
10
|
it('parses TrackSource correctly to strings', () => {
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
-
for (let key of __getOwnPropNames(from))
|
|
11
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
-
}
|
|
14
|
-
return to;
|
|
15
|
-
};
|
|
16
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
-
mod
|
|
23
|
-
));
|
|
24
|
-
var import_protocol = require("@livekit/protocol");
|
|
25
|
-
var jose = __toESM(require("jose"), 1);
|
|
26
|
-
var import_vitest = require("vitest");
|
|
27
|
-
var import_AccessToken = require("./AccessToken");
|
|
28
|
-
const testApiKey = "abcdefg";
|
|
29
|
-
const testSecret = "abababa";
|
|
30
|
-
(0, import_vitest.describe)("encoded tokens are valid", () => {
|
|
31
|
-
const t = new import_AccessToken.AccessToken(testApiKey, testSecret, {
|
|
32
|
-
identity: "me",
|
|
33
|
-
name: "myname"
|
|
34
|
-
});
|
|
35
|
-
t.addGrant({ room: "myroom" });
|
|
36
|
-
const EncodedTestSecret = new TextEncoder().encode(testSecret);
|
|
37
|
-
(0, import_vitest.it)("can be decoded", async () => {
|
|
38
|
-
const { payload } = await jose.jwtVerify(await t.toJwt(), EncodedTestSecret, {
|
|
39
|
-
issuer: testApiKey
|
|
40
|
-
});
|
|
41
|
-
(0, import_vitest.expect)(payload).not.toBe(void 0);
|
|
42
|
-
});
|
|
43
|
-
(0, import_vitest.it)("has name set", async () => {
|
|
44
|
-
const { payload } = await jose.jwtVerify(await t.toJwt(), EncodedTestSecret, {
|
|
45
|
-
issuer: testApiKey
|
|
46
|
-
});
|
|
47
|
-
(0, import_vitest.expect)(payload.name).toBe("myname");
|
|
48
|
-
});
|
|
49
|
-
(0, import_vitest.it)("has video grants set", async () => {
|
|
50
|
-
var _a;
|
|
51
|
-
const { payload } = await jose.jwtVerify(await t.toJwt(), EncodedTestSecret, {
|
|
52
|
-
issuer: testApiKey
|
|
53
|
-
});
|
|
54
|
-
(0, import_vitest.expect)(payload.video).toBeTruthy();
|
|
55
|
-
(0, import_vitest.expect)((_a = payload.video) == null ? void 0 : _a.room).toEqual("myroom");
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
(0, import_vitest.describe)("identity is required for only join grants", () => {
|
|
59
|
-
(0, import_vitest.it)("allows empty identity for create", async () => {
|
|
60
|
-
const t = new import_AccessToken.AccessToken(testApiKey, testSecret);
|
|
61
|
-
t.addGrant({ roomCreate: true });
|
|
62
|
-
(0, import_vitest.expect)(await t.toJwt()).toBeTruthy();
|
|
63
|
-
});
|
|
64
|
-
(0, import_vitest.it)("throws error when identity is not provided for join", async () => {
|
|
65
|
-
const t = new import_AccessToken.AccessToken(testApiKey, testSecret);
|
|
66
|
-
t.addGrant({ roomJoin: true });
|
|
67
|
-
await (0, import_vitest.expect)(async () => {
|
|
68
|
-
await t.toJwt();
|
|
69
|
-
}).rejects.toThrow();
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
(0, import_vitest.describe)("verify token is valid", () => {
|
|
73
|
-
(0, import_vitest.it)("can decode encoded token", async () => {
|
|
74
|
-
var _a;
|
|
75
|
-
const t = new import_AccessToken.AccessToken(testApiKey, testSecret);
|
|
76
|
-
t.sha256 = "abcdefg";
|
|
77
|
-
t.kind = "agent";
|
|
78
|
-
t.addGrant({ roomCreate: true });
|
|
79
|
-
t.attributes = { foo: "bar", live: "kit" };
|
|
80
|
-
const v = new import_AccessToken.TokenVerifier(testApiKey, testSecret);
|
|
81
|
-
const decoded = await v.verify(await t.toJwt());
|
|
82
|
-
(0, import_vitest.expect)(decoded).not.toBe(void 0);
|
|
83
|
-
(0, import_vitest.expect)(decoded.sha256).toEqual("abcdefg");
|
|
84
|
-
(0, import_vitest.expect)((_a = decoded.video) == null ? void 0 : _a.roomCreate).toBeTruthy();
|
|
85
|
-
(0, import_vitest.expect)(decoded.kind).toEqual("agent");
|
|
86
|
-
(0, import_vitest.expect)(decoded.attributes).toEqual(t.attributes);
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
(0, import_vitest.describe)("adding grants should not overwrite existing grants", () => {
|
|
90
|
-
const EncodedTestSecret = new TextEncoder().encode(testSecret);
|
|
91
|
-
(0, import_vitest.it)("should not overwrite existing grants", async () => {
|
|
92
|
-
var _a, _b;
|
|
93
|
-
const t = new import_AccessToken.AccessToken(testApiKey, testSecret, {
|
|
94
|
-
identity: "me",
|
|
95
|
-
name: "myname"
|
|
96
|
-
});
|
|
97
|
-
t.addGrant({ roomCreate: true });
|
|
98
|
-
t.addGrant({ roomJoin: true });
|
|
99
|
-
const { payload } = await jose.jwtVerify(
|
|
100
|
-
await t.toJwt(),
|
|
101
|
-
EncodedTestSecret,
|
|
102
|
-
{ issuer: testApiKey }
|
|
103
|
-
);
|
|
104
|
-
(0, import_vitest.expect)((_a = payload.video) == null ? void 0 : _a.roomCreate).toBeTruthy();
|
|
105
|
-
(0, import_vitest.expect)((_b = payload.video) == null ? void 0 : _b.roomJoin).toBeTruthy();
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
(0, import_vitest.describe)("room configuration with agents and egress", () => {
|
|
109
|
-
(0, import_vitest.it)("should set agents and egress in room configuration", async () => {
|
|
110
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
111
|
-
const t = new import_AccessToken.AccessToken(testApiKey, testSecret, {
|
|
112
|
-
identity: "test-identity"
|
|
113
|
-
});
|
|
114
|
-
const roomConfig = new import_protocol.RoomConfiguration({
|
|
115
|
-
name: "test-room",
|
|
116
|
-
maxParticipants: 10
|
|
117
|
-
});
|
|
118
|
-
const agents = [
|
|
119
|
-
new import_protocol.RoomAgentDispatch({
|
|
120
|
-
agentName: "agent1",
|
|
121
|
-
metadata: "metadata-1"
|
|
122
|
-
}),
|
|
123
|
-
new import_protocol.RoomAgentDispatch({
|
|
124
|
-
agentName: "agent2",
|
|
125
|
-
metadata: "metadata-2"
|
|
126
|
-
})
|
|
127
|
-
];
|
|
128
|
-
const egress = new import_protocol.RoomEgress({
|
|
129
|
-
room: new import_protocol.RoomCompositeEgressRequest({ roomName: "test-room" })
|
|
130
|
-
});
|
|
131
|
-
roomConfig.agents = agents;
|
|
132
|
-
roomConfig.egress = egress;
|
|
133
|
-
t.roomConfig = roomConfig;
|
|
134
|
-
const v = new import_AccessToken.TokenVerifier(testApiKey, testSecret);
|
|
135
|
-
const decoded = await v.verify(await t.toJwt());
|
|
136
|
-
(0, import_vitest.expect)(decoded.roomConfig).toBeDefined();
|
|
137
|
-
(0, import_vitest.expect)((_a = decoded.roomConfig) == null ? void 0 : _a.name).toEqual("test-room");
|
|
138
|
-
(0, import_vitest.expect)((_b = decoded.roomConfig) == null ? void 0 : _b.maxParticipants).toEqual(10);
|
|
139
|
-
(0, import_vitest.expect)((_c = decoded.roomConfig) == null ? void 0 : _c.agents).toHaveLength(2);
|
|
140
|
-
(0, import_vitest.expect)((_e = (_d = decoded.roomConfig) == null ? void 0 : _d.agents) == null ? void 0 : _e[0].agentName).toEqual("agent1");
|
|
141
|
-
(0, import_vitest.expect)((_g = (_f = decoded.roomConfig) == null ? void 0 : _f.agents) == null ? void 0 : _g[0].metadata).toEqual("metadata-1");
|
|
142
|
-
(0, import_vitest.expect)((_i = (_h = decoded.roomConfig) == null ? void 0 : _h.agents) == null ? void 0 : _i[1].agentName).toEqual("agent2");
|
|
143
|
-
(0, import_vitest.expect)((_k = (_j = decoded.roomConfig) == null ? void 0 : _j.agents) == null ? void 0 : _k[1].metadata).toEqual("metadata-2");
|
|
144
|
-
(0, import_vitest.expect)((_n = (_m = (_l = decoded.roomConfig) == null ? void 0 : _l.egress) == null ? void 0 : _m.room) == null ? void 0 : _n.roomName).toEqual("test-room");
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
//# sourceMappingURL=AccessToken.test.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/AccessToken.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport {\n RoomAgentDispatch,\n RoomCompositeEgressRequest,\n RoomConfiguration,\n RoomEgress,\n} from '@livekit/protocol';\nimport * as jose from 'jose';\nimport { describe, expect, it } from 'vitest';\nimport { AccessToken, TokenVerifier } from './AccessToken';\nimport type { ClaimGrants } from './grants';\n\nconst testApiKey = 'abcdefg';\nconst testSecret = 'abababa';\n\ndescribe('encoded tokens are valid', () => {\n const t = new AccessToken(testApiKey, testSecret, {\n identity: 'me',\n name: 'myname',\n });\n t.addGrant({ room: 'myroom' });\n const EncodedTestSecret = new TextEncoder().encode(testSecret);\n it('can be decoded', async () => {\n const { payload } = await jose.jwtVerify(await t.toJwt(), EncodedTestSecret, {\n issuer: testApiKey,\n });\n\n expect(payload).not.toBe(undefined);\n });\n\n it('has name set', async () => {\n const { payload } = await jose.jwtVerify(await t.toJwt(), EncodedTestSecret, {\n issuer: testApiKey,\n });\n\n expect(payload.name).toBe('myname');\n });\n\n it('has video grants set', async () => {\n const { payload } = await jose.jwtVerify(await t.toJwt(), EncodedTestSecret, {\n issuer: testApiKey,\n });\n\n expect(payload.video).toBeTruthy();\n expect((payload as ClaimGrants).video?.room).toEqual('myroom');\n });\n});\n\ndescribe('identity is required for only join grants', () => {\n it('allows empty identity for create', async () => {\n const t = new AccessToken(testApiKey, testSecret);\n t.addGrant({ roomCreate: true });\n\n expect(await t.toJwt()).toBeTruthy();\n });\n it('throws error when identity is not provided for join', async () => {\n const t = new AccessToken(testApiKey, testSecret);\n t.addGrant({ roomJoin: true });\n\n await expect(async () => {\n await t.toJwt();\n }).rejects.toThrow();\n });\n});\n\ndescribe('verify token is valid', () => {\n it('can decode encoded token', async () => {\n const t = new AccessToken(testApiKey, testSecret);\n t.sha256 = 'abcdefg';\n t.kind = 'agent';\n t.addGrant({ roomCreate: true });\n t.attributes = { foo: 'bar', live: 'kit' };\n\n const v = new TokenVerifier(testApiKey, testSecret);\n const decoded = await v.verify(await t.toJwt());\n\n expect(decoded).not.toBe(undefined);\n expect(decoded.sha256).toEqual('abcdefg');\n expect(decoded.video?.roomCreate).toBeTruthy();\n expect(decoded.kind).toEqual('agent');\n expect(decoded.attributes).toEqual(t.attributes);\n });\n});\n\ndescribe('adding grants should not overwrite existing grants', () => {\n const EncodedTestSecret = new TextEncoder().encode(testSecret);\n\n it('should not overwrite existing grants', async () => {\n const t = new AccessToken(testApiKey, testSecret, {\n identity: 'me',\n name: 'myname',\n });\n t.addGrant({ roomCreate: true });\n t.addGrant({ roomJoin: true });\n\n const { payload }: jose.JWTVerifyResult<ClaimGrants> = await jose.jwtVerify(\n await t.toJwt(),\n EncodedTestSecret,\n { issuer: testApiKey },\n );\n expect(payload.video?.roomCreate).toBeTruthy();\n expect(payload.video?.roomJoin).toBeTruthy();\n });\n});\n\ndescribe('room configuration with agents and egress', () => {\n it('should set agents and egress in room configuration', async () => {\n const t = new AccessToken(testApiKey, testSecret, {\n identity: 'test-identity',\n });\n\n const roomConfig = new RoomConfiguration({\n name: 'test-room',\n maxParticipants: 10,\n });\n\n const agents: RoomAgentDispatch[] = [\n new RoomAgentDispatch({\n agentName: 'agent1',\n metadata: 'metadata-1',\n }),\n new RoomAgentDispatch({\n agentName: 'agent2',\n metadata: 'metadata-2',\n }),\n ];\n\n const egress = new RoomEgress({\n room: new RoomCompositeEgressRequest({ roomName: 'test-room' }),\n });\n\n roomConfig.agents = agents;\n roomConfig.egress = egress;\n\n t.roomConfig = roomConfig;\n\n const v = new TokenVerifier(testApiKey, testSecret);\n const decoded = await v.verify(await t.toJwt());\n\n expect(decoded.roomConfig).toBeDefined();\n expect(decoded.roomConfig?.name).toEqual('test-room');\n expect(decoded.roomConfig?.maxParticipants).toEqual(10);\n expect(decoded.roomConfig?.agents).toHaveLength(2);\n expect(decoded.roomConfig?.agents?.[0].agentName).toEqual('agent1');\n expect(decoded.roomConfig?.agents?.[0].metadata).toEqual('metadata-1');\n expect(decoded.roomConfig?.agents?.[1].agentName).toEqual('agent2');\n expect(decoded.roomConfig?.agents?.[1].metadata).toEqual('metadata-2');\n expect(decoded.roomConfig?.egress?.room?.roomName).toEqual('test-room');\n });\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAGA,sBAKO;AACP,WAAsB;AACtB,oBAAqC;AACrC,yBAA2C;AAG3C,MAAM,aAAa;AACnB,MAAM,aAAa;AAAA,IAEnB,wBAAS,4BAA4B,MAAM;AACzC,QAAM,IAAI,IAAI,+BAAY,YAAY,YAAY;AAAA,IAChD,UAAU;AAAA,IACV,MAAM;AAAA,EACR,CAAC;AACD,IAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7B,QAAM,oBAAoB,IAAI,YAAY,EAAE,OAAO,UAAU;AAC7D,wBAAG,kBAAkB,YAAY;AAC/B,UAAM,EAAE,QAAQ,IAAI,MAAM,KAAK,UAAU,MAAM,EAAE,MAAM,GAAG,mBAAmB;AAAA,MAC3E,QAAQ;AAAA,IACV,CAAC;AAED,8BAAO,OAAO,EAAE,IAAI,KAAK,MAAS;AAAA,EACpC,CAAC;AAED,wBAAG,gBAAgB,YAAY;AAC7B,UAAM,EAAE,QAAQ,IAAI,MAAM,KAAK,UAAU,MAAM,EAAE,MAAM,GAAG,mBAAmB;AAAA,MAC3E,QAAQ;AAAA,IACV,CAAC;AAED,8BAAO,QAAQ,IAAI,EAAE,KAAK,QAAQ;AAAA,EACpC,CAAC;AAED,wBAAG,wBAAwB,YAAY;AAxCzC;AAyCI,UAAM,EAAE,QAAQ,IAAI,MAAM,KAAK,UAAU,MAAM,EAAE,MAAM,GAAG,mBAAmB;AAAA,MAC3E,QAAQ;AAAA,IACV,CAAC;AAED,8BAAO,QAAQ,KAAK,EAAE,WAAW;AACjC,+BAAQ,aAAwB,UAAxB,mBAA+B,IAAI,EAAE,QAAQ,QAAQ;AAAA,EAC/D,CAAC;AACH,CAAC;AAAA,IAED,wBAAS,6CAA6C,MAAM;AAC1D,wBAAG,oCAAoC,YAAY;AACjD,UAAM,IAAI,IAAI,+BAAY,YAAY,UAAU;AAChD,MAAE,SAAS,EAAE,YAAY,KAAK,CAAC;AAE/B,8BAAO,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW;AAAA,EACrC,CAAC;AACD,wBAAG,uDAAuD,YAAY;AACpE,UAAM,IAAI,IAAI,+BAAY,YAAY,UAAU;AAChD,MAAE,SAAS,EAAE,UAAU,KAAK,CAAC;AAE7B,cAAM,sBAAO,YAAY;AACvB,YAAM,EAAE,MAAM;AAAA,IAChB,CAAC,EAAE,QAAQ,QAAQ;AAAA,EACrB,CAAC;AACH,CAAC;AAAA,IAED,wBAAS,yBAAyB,MAAM;AACtC,wBAAG,4BAA4B,YAAY;AApE7C;AAqEI,UAAM,IAAI,IAAI,+BAAY,YAAY,UAAU;AAChD,MAAE,SAAS;AACX,MAAE,OAAO;AACT,MAAE,SAAS,EAAE,YAAY,KAAK,CAAC;AAC/B,MAAE,aAAa,EAAE,KAAK,OAAO,MAAM,MAAM;AAEzC,UAAM,IAAI,IAAI,iCAAc,YAAY,UAAU;AAClD,UAAM,UAAU,MAAM,EAAE,OAAO,MAAM,EAAE,MAAM,CAAC;AAE9C,8BAAO,OAAO,EAAE,IAAI,KAAK,MAAS;AAClC,8BAAO,QAAQ,MAAM,EAAE,QAAQ,SAAS;AACxC,+BAAO,aAAQ,UAAR,mBAAe,UAAU,EAAE,WAAW;AAC7C,8BAAO,QAAQ,IAAI,EAAE,QAAQ,OAAO;AACpC,8BAAO,QAAQ,UAAU,EAAE,QAAQ,EAAE,UAAU;AAAA,EACjD,CAAC;AACH,CAAC;AAAA,IAED,wBAAS,sDAAsD,MAAM;AACnE,QAAM,oBAAoB,IAAI,YAAY,EAAE,OAAO,UAAU;AAE7D,wBAAG,wCAAwC,YAAY;AAzFzD;AA0FI,UAAM,IAAI,IAAI,+BAAY,YAAY,YAAY;AAAA,MAChD,UAAU;AAAA,MACV,MAAM;AAAA,IACR,CAAC;AACD,MAAE,SAAS,EAAE,YAAY,KAAK,CAAC;AAC/B,MAAE,SAAS,EAAE,UAAU,KAAK,CAAC;AAE7B,UAAM,EAAE,QAAQ,IAAuC,MAAM,KAAK;AAAA,MAChE,MAAM,EAAE,MAAM;AAAA,MACd;AAAA,MACA,EAAE,QAAQ,WAAW;AAAA,IACvB;AACA,+BAAO,aAAQ,UAAR,mBAAe,UAAU,EAAE,WAAW;AAC7C,+BAAO,aAAQ,UAAR,mBAAe,QAAQ,EAAE,WAAW;AAAA,EAC7C,CAAC;AACH,CAAC;AAAA,IAED,wBAAS,6CAA6C,MAAM;AAC1D,wBAAG,sDAAsD,YAAY;AA5GvE;AA6GI,UAAM,IAAI,IAAI,+BAAY,YAAY,YAAY;AAAA,MAChD,UAAU;AAAA,IACZ,CAAC;AAED,UAAM,aAAa,IAAI,kCAAkB;AAAA,MACvC,MAAM;AAAA,MACN,iBAAiB;AAAA,IACnB,CAAC;AAED,UAAM,SAA8B;AAAA,MAClC,IAAI,kCAAkB;AAAA,QACpB,WAAW;AAAA,QACX,UAAU;AAAA,MACZ,CAAC;AAAA,MACD,IAAI,kCAAkB;AAAA,QACpB,WAAW;AAAA,QACX,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAEA,UAAM,SAAS,IAAI,2BAAW;AAAA,MAC5B,MAAM,IAAI,2CAA2B,EAAE,UAAU,YAAY,CAAC;AAAA,IAChE,CAAC;AAED,eAAW,SAAS;AACpB,eAAW,SAAS;AAEpB,MAAE,aAAa;AAEf,UAAM,IAAI,IAAI,iCAAc,YAAY,UAAU;AAClD,UAAM,UAAU,MAAM,EAAE,OAAO,MAAM,EAAE,MAAM,CAAC;AAE9C,8BAAO,QAAQ,UAAU,EAAE,YAAY;AACvC,+BAAO,aAAQ,eAAR,mBAAoB,IAAI,EAAE,QAAQ,WAAW;AACpD,+BAAO,aAAQ,eAAR,mBAAoB,eAAe,EAAE,QAAQ,EAAE;AACtD,+BAAO,aAAQ,eAAR,mBAAoB,MAAM,EAAE,aAAa,CAAC;AACjD,+BAAO,mBAAQ,eAAR,mBAAoB,WAApB,mBAA6B,GAAG,SAAS,EAAE,QAAQ,QAAQ;AAClE,+BAAO,mBAAQ,eAAR,mBAAoB,WAApB,mBAA6B,GAAG,QAAQ,EAAE,QAAQ,YAAY;AACrE,+BAAO,mBAAQ,eAAR,mBAAoB,WAApB,mBAA6B,GAAG,SAAS,EAAE,QAAQ,QAAQ;AAClE,+BAAO,mBAAQ,eAAR,mBAAoB,WAApB,mBAA6B,GAAG,QAAQ,EAAE,QAAQ,YAAY;AACrE,+BAAO,yBAAQ,eAAR,mBAAoB,WAApB,mBAA4B,SAA5B,mBAAkC,QAAQ,EAAE,QAAQ,WAAW;AAAA,EACxE,CAAC;AACH,CAAC;","names":[]}
|
package/dist/AccessToken.test.js
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
RoomAgentDispatch,
|
|
3
|
-
RoomCompositeEgressRequest,
|
|
4
|
-
RoomConfiguration,
|
|
5
|
-
RoomEgress
|
|
6
|
-
} from "@livekit/protocol";
|
|
7
|
-
import * as jose from "jose";
|
|
8
|
-
import { describe, expect, it } from "vitest";
|
|
9
|
-
import { AccessToken, TokenVerifier } from "./AccessToken";
|
|
10
|
-
const testApiKey = "abcdefg";
|
|
11
|
-
const testSecret = "abababa";
|
|
12
|
-
describe("encoded tokens are valid", () => {
|
|
13
|
-
const t = new AccessToken(testApiKey, testSecret, {
|
|
14
|
-
identity: "me",
|
|
15
|
-
name: "myname"
|
|
16
|
-
});
|
|
17
|
-
t.addGrant({ room: "myroom" });
|
|
18
|
-
const EncodedTestSecret = new TextEncoder().encode(testSecret);
|
|
19
|
-
it("can be decoded", async () => {
|
|
20
|
-
const { payload } = await jose.jwtVerify(await t.toJwt(), EncodedTestSecret, {
|
|
21
|
-
issuer: testApiKey
|
|
22
|
-
});
|
|
23
|
-
expect(payload).not.toBe(void 0);
|
|
24
|
-
});
|
|
25
|
-
it("has name set", async () => {
|
|
26
|
-
const { payload } = await jose.jwtVerify(await t.toJwt(), EncodedTestSecret, {
|
|
27
|
-
issuer: testApiKey
|
|
28
|
-
});
|
|
29
|
-
expect(payload.name).toBe("myname");
|
|
30
|
-
});
|
|
31
|
-
it("has video grants set", async () => {
|
|
32
|
-
var _a;
|
|
33
|
-
const { payload } = await jose.jwtVerify(await t.toJwt(), EncodedTestSecret, {
|
|
34
|
-
issuer: testApiKey
|
|
35
|
-
});
|
|
36
|
-
expect(payload.video).toBeTruthy();
|
|
37
|
-
expect((_a = payload.video) == null ? void 0 : _a.room).toEqual("myroom");
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
describe("identity is required for only join grants", () => {
|
|
41
|
-
it("allows empty identity for create", async () => {
|
|
42
|
-
const t = new AccessToken(testApiKey, testSecret);
|
|
43
|
-
t.addGrant({ roomCreate: true });
|
|
44
|
-
expect(await t.toJwt()).toBeTruthy();
|
|
45
|
-
});
|
|
46
|
-
it("throws error when identity is not provided for join", async () => {
|
|
47
|
-
const t = new AccessToken(testApiKey, testSecret);
|
|
48
|
-
t.addGrant({ roomJoin: true });
|
|
49
|
-
await expect(async () => {
|
|
50
|
-
await t.toJwt();
|
|
51
|
-
}).rejects.toThrow();
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
describe("verify token is valid", () => {
|
|
55
|
-
it("can decode encoded token", async () => {
|
|
56
|
-
var _a;
|
|
57
|
-
const t = new AccessToken(testApiKey, testSecret);
|
|
58
|
-
t.sha256 = "abcdefg";
|
|
59
|
-
t.kind = "agent";
|
|
60
|
-
t.addGrant({ roomCreate: true });
|
|
61
|
-
t.attributes = { foo: "bar", live: "kit" };
|
|
62
|
-
const v = new TokenVerifier(testApiKey, testSecret);
|
|
63
|
-
const decoded = await v.verify(await t.toJwt());
|
|
64
|
-
expect(decoded).not.toBe(void 0);
|
|
65
|
-
expect(decoded.sha256).toEqual("abcdefg");
|
|
66
|
-
expect((_a = decoded.video) == null ? void 0 : _a.roomCreate).toBeTruthy();
|
|
67
|
-
expect(decoded.kind).toEqual("agent");
|
|
68
|
-
expect(decoded.attributes).toEqual(t.attributes);
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
describe("adding grants should not overwrite existing grants", () => {
|
|
72
|
-
const EncodedTestSecret = new TextEncoder().encode(testSecret);
|
|
73
|
-
it("should not overwrite existing grants", async () => {
|
|
74
|
-
var _a, _b;
|
|
75
|
-
const t = new AccessToken(testApiKey, testSecret, {
|
|
76
|
-
identity: "me",
|
|
77
|
-
name: "myname"
|
|
78
|
-
});
|
|
79
|
-
t.addGrant({ roomCreate: true });
|
|
80
|
-
t.addGrant({ roomJoin: true });
|
|
81
|
-
const { payload } = await jose.jwtVerify(
|
|
82
|
-
await t.toJwt(),
|
|
83
|
-
EncodedTestSecret,
|
|
84
|
-
{ issuer: testApiKey }
|
|
85
|
-
);
|
|
86
|
-
expect((_a = payload.video) == null ? void 0 : _a.roomCreate).toBeTruthy();
|
|
87
|
-
expect((_b = payload.video) == null ? void 0 : _b.roomJoin).toBeTruthy();
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
describe("room configuration with agents and egress", () => {
|
|
91
|
-
it("should set agents and egress in room configuration", async () => {
|
|
92
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
93
|
-
const t = new AccessToken(testApiKey, testSecret, {
|
|
94
|
-
identity: "test-identity"
|
|
95
|
-
});
|
|
96
|
-
const roomConfig = new RoomConfiguration({
|
|
97
|
-
name: "test-room",
|
|
98
|
-
maxParticipants: 10
|
|
99
|
-
});
|
|
100
|
-
const agents = [
|
|
101
|
-
new RoomAgentDispatch({
|
|
102
|
-
agentName: "agent1",
|
|
103
|
-
metadata: "metadata-1"
|
|
104
|
-
}),
|
|
105
|
-
new RoomAgentDispatch({
|
|
106
|
-
agentName: "agent2",
|
|
107
|
-
metadata: "metadata-2"
|
|
108
|
-
})
|
|
109
|
-
];
|
|
110
|
-
const egress = new RoomEgress({
|
|
111
|
-
room: new RoomCompositeEgressRequest({ roomName: "test-room" })
|
|
112
|
-
});
|
|
113
|
-
roomConfig.agents = agents;
|
|
114
|
-
roomConfig.egress = egress;
|
|
115
|
-
t.roomConfig = roomConfig;
|
|
116
|
-
const v = new TokenVerifier(testApiKey, testSecret);
|
|
117
|
-
const decoded = await v.verify(await t.toJwt());
|
|
118
|
-
expect(decoded.roomConfig).toBeDefined();
|
|
119
|
-
expect((_a = decoded.roomConfig) == null ? void 0 : _a.name).toEqual("test-room");
|
|
120
|
-
expect((_b = decoded.roomConfig) == null ? void 0 : _b.maxParticipants).toEqual(10);
|
|
121
|
-
expect((_c = decoded.roomConfig) == null ? void 0 : _c.agents).toHaveLength(2);
|
|
122
|
-
expect((_e = (_d = decoded.roomConfig) == null ? void 0 : _d.agents) == null ? void 0 : _e[0].agentName).toEqual("agent1");
|
|
123
|
-
expect((_g = (_f = decoded.roomConfig) == null ? void 0 : _f.agents) == null ? void 0 : _g[0].metadata).toEqual("metadata-1");
|
|
124
|
-
expect((_i = (_h = decoded.roomConfig) == null ? void 0 : _h.agents) == null ? void 0 : _i[1].agentName).toEqual("agent2");
|
|
125
|
-
expect((_k = (_j = decoded.roomConfig) == null ? void 0 : _j.agents) == null ? void 0 : _k[1].metadata).toEqual("metadata-2");
|
|
126
|
-
expect((_n = (_m = (_l = decoded.roomConfig) == null ? void 0 : _l.egress) == null ? void 0 : _m.room) == null ? void 0 : _n.roomName).toEqual("test-room");
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
//# sourceMappingURL=AccessToken.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/AccessToken.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport {\n RoomAgentDispatch,\n RoomCompositeEgressRequest,\n RoomConfiguration,\n RoomEgress,\n} from '@livekit/protocol';\nimport * as jose from 'jose';\nimport { describe, expect, it } from 'vitest';\nimport { AccessToken, TokenVerifier } from './AccessToken';\nimport type { ClaimGrants } from './grants';\n\nconst testApiKey = 'abcdefg';\nconst testSecret = 'abababa';\n\ndescribe('encoded tokens are valid', () => {\n const t = new AccessToken(testApiKey, testSecret, {\n identity: 'me',\n name: 'myname',\n });\n t.addGrant({ room: 'myroom' });\n const EncodedTestSecret = new TextEncoder().encode(testSecret);\n it('can be decoded', async () => {\n const { payload } = await jose.jwtVerify(await t.toJwt(), EncodedTestSecret, {\n issuer: testApiKey,\n });\n\n expect(payload).not.toBe(undefined);\n });\n\n it('has name set', async () => {\n const { payload } = await jose.jwtVerify(await t.toJwt(), EncodedTestSecret, {\n issuer: testApiKey,\n });\n\n expect(payload.name).toBe('myname');\n });\n\n it('has video grants set', async () => {\n const { payload } = await jose.jwtVerify(await t.toJwt(), EncodedTestSecret, {\n issuer: testApiKey,\n });\n\n expect(payload.video).toBeTruthy();\n expect((payload as ClaimGrants).video?.room).toEqual('myroom');\n });\n});\n\ndescribe('identity is required for only join grants', () => {\n it('allows empty identity for create', async () => {\n const t = new AccessToken(testApiKey, testSecret);\n t.addGrant({ roomCreate: true });\n\n expect(await t.toJwt()).toBeTruthy();\n });\n it('throws error when identity is not provided for join', async () => {\n const t = new AccessToken(testApiKey, testSecret);\n t.addGrant({ roomJoin: true });\n\n await expect(async () => {\n await t.toJwt();\n }).rejects.toThrow();\n });\n});\n\ndescribe('verify token is valid', () => {\n it('can decode encoded token', async () => {\n const t = new AccessToken(testApiKey, testSecret);\n t.sha256 = 'abcdefg';\n t.kind = 'agent';\n t.addGrant({ roomCreate: true });\n t.attributes = { foo: 'bar', live: 'kit' };\n\n const v = new TokenVerifier(testApiKey, testSecret);\n const decoded = await v.verify(await t.toJwt());\n\n expect(decoded).not.toBe(undefined);\n expect(decoded.sha256).toEqual('abcdefg');\n expect(decoded.video?.roomCreate).toBeTruthy();\n expect(decoded.kind).toEqual('agent');\n expect(decoded.attributes).toEqual(t.attributes);\n });\n});\n\ndescribe('adding grants should not overwrite existing grants', () => {\n const EncodedTestSecret = new TextEncoder().encode(testSecret);\n\n it('should not overwrite existing grants', async () => {\n const t = new AccessToken(testApiKey, testSecret, {\n identity: 'me',\n name: 'myname',\n });\n t.addGrant({ roomCreate: true });\n t.addGrant({ roomJoin: true });\n\n const { payload }: jose.JWTVerifyResult<ClaimGrants> = await jose.jwtVerify(\n await t.toJwt(),\n EncodedTestSecret,\n { issuer: testApiKey },\n );\n expect(payload.video?.roomCreate).toBeTruthy();\n expect(payload.video?.roomJoin).toBeTruthy();\n });\n});\n\ndescribe('room configuration with agents and egress', () => {\n it('should set agents and egress in room configuration', async () => {\n const t = new AccessToken(testApiKey, testSecret, {\n identity: 'test-identity',\n });\n\n const roomConfig = new RoomConfiguration({\n name: 'test-room',\n maxParticipants: 10,\n });\n\n const agents: RoomAgentDispatch[] = [\n new RoomAgentDispatch({\n agentName: 'agent1',\n metadata: 'metadata-1',\n }),\n new RoomAgentDispatch({\n agentName: 'agent2',\n metadata: 'metadata-2',\n }),\n ];\n\n const egress = new RoomEgress({\n room: new RoomCompositeEgressRequest({ roomName: 'test-room' }),\n });\n\n roomConfig.agents = agents;\n roomConfig.egress = egress;\n\n t.roomConfig = roomConfig;\n\n const v = new TokenVerifier(testApiKey, testSecret);\n const decoded = await v.verify(await t.toJwt());\n\n expect(decoded.roomConfig).toBeDefined();\n expect(decoded.roomConfig?.name).toEqual('test-room');\n expect(decoded.roomConfig?.maxParticipants).toEqual(10);\n expect(decoded.roomConfig?.agents).toHaveLength(2);\n expect(decoded.roomConfig?.agents?.[0].agentName).toEqual('agent1');\n expect(decoded.roomConfig?.agents?.[0].metadata).toEqual('metadata-1');\n expect(decoded.roomConfig?.agents?.[1].agentName).toEqual('agent2');\n expect(decoded.roomConfig?.agents?.[1].metadata).toEqual('metadata-2');\n expect(decoded.roomConfig?.egress?.room?.roomName).toEqual('test-room');\n });\n});\n"],"mappings":"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","names":[]}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var import_vitest = require("vitest");
|
|
3
|
-
var import_AccessToken = require("./AccessToken.cjs");
|
|
4
|
-
var import_WebhookReceiver = require("./WebhookReceiver.cjs");
|
|
5
|
-
const testApiKey = "abcdefg";
|
|
6
|
-
const testSecret = "abababa";
|
|
7
|
-
(0, import_vitest.describe)("webhook receiver", () => {
|
|
8
|
-
const body = '{"event":"room_started", "room":{"sid":"RM_TkVjUvAqgzKz", "name":"mytestroom", "emptyTimeout":300, "creationTime":"1628545903", "turnPassword":"ICkSr2rEeslkN6e9bXL4Ji5zzMD5Z7zzr6ulOaxMj6N", "enabledCodecs":[{"mime":"audio/opus"}, {"mime":"video/VP8"}]}}';
|
|
9
|
-
const sha = "CoEQz1chqJ9bnZRcORddjplkvpjmPujmLTR42DbefYI=";
|
|
10
|
-
const t = new import_AccessToken.AccessToken(testApiKey, testSecret);
|
|
11
|
-
t.sha256 = sha;
|
|
12
|
-
const receiver = new import_WebhookReceiver.WebhookReceiver(testApiKey, testSecret);
|
|
13
|
-
(0, import_vitest.it)("should receive and decode WebhookEvent", async () => {
|
|
14
|
-
var _a;
|
|
15
|
-
const token = await t.toJwt();
|
|
16
|
-
const event = await receiver.receive(body, token);
|
|
17
|
-
(0, import_vitest.expect)(event).toBeTruthy();
|
|
18
|
-
(0, import_vitest.expect)((_a = event.room) == null ? void 0 : _a.name).toBe("mytestroom");
|
|
19
|
-
(0, import_vitest.expect)(event.event).toBe("room_started");
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
(0, import_vitest.describe)("decoding json payload", () => {
|
|
23
|
-
(0, import_vitest.it)("should allow server to return extra fields", () => {
|
|
24
|
-
var _a;
|
|
25
|
-
const obj = {
|
|
26
|
-
type: "room_started",
|
|
27
|
-
room: {
|
|
28
|
-
sid: "RM_TkVjUvAqgzKz",
|
|
29
|
-
name: "mytestroom"
|
|
30
|
-
},
|
|
31
|
-
extra: "extra"
|
|
32
|
-
};
|
|
33
|
-
const event = new import_WebhookReceiver.WebhookEvent(obj);
|
|
34
|
-
(0, import_vitest.expect)(event).toBeTruthy();
|
|
35
|
-
(0, import_vitest.expect)((_a = event.room) == null ? void 0 : _a.name).toBe("mytestroom");
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
//# sourceMappingURL=WebhookReceiver.test.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/WebhookReceiver.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { describe, expect, it } from 'vitest';\nimport { AccessToken } from './AccessToken.js';\nimport { WebhookEvent, WebhookReceiver } from './WebhookReceiver.js';\n\nconst testApiKey = 'abcdefg';\nconst testSecret = 'abababa';\n\ndescribe('webhook receiver', () => {\n const body =\n '{\"event\":\"room_started\", \"room\":{\"sid\":\"RM_TkVjUvAqgzKz\", \"name\":\"mytestroom\", \"emptyTimeout\":300, \"creationTime\":\"1628545903\", \"turnPassword\":\"ICkSr2rEeslkN6e9bXL4Ji5zzMD5Z7zzr6ulOaxMj6N\", \"enabledCodecs\":[{\"mime\":\"audio/opus\"}, {\"mime\":\"video/VP8\"}]}}';\n const sha = 'CoEQz1chqJ9bnZRcORddjplkvpjmPujmLTR42DbefYI=';\n const t = new AccessToken(testApiKey, testSecret);\n t.sha256 = sha;\n\n const receiver = new WebhookReceiver(testApiKey, testSecret);\n\n it('should receive and decode WebhookEvent', async () => {\n const token = await t.toJwt();\n const event = await receiver.receive(body, token);\n expect(event).toBeTruthy();\n expect(event.room?.name).toBe('mytestroom');\n expect(event.event).toBe('room_started');\n });\n});\n\ndescribe('decoding json payload', () => {\n it('should allow server to return extra fields', () => {\n const obj = {\n type: 'room_started',\n room: {\n sid: 'RM_TkVjUvAqgzKz',\n name: 'mytestroom',\n },\n extra: 'extra',\n };\n\n const event = new WebhookEvent(obj);\n expect(event).toBeTruthy();\n expect(event.room?.name).toBe('mytestroom');\n });\n});\n"],"mappings":";AAGA,oBAAqC;AACrC,yBAA4B;AAC5B,6BAA8C;AAE9C,MAAM,aAAa;AACnB,MAAM,aAAa;AAAA,IAEnB,wBAAS,oBAAoB,MAAM;AACjC,QAAM,OACJ;AACF,QAAM,MAAM;AACZ,QAAM,IAAI,IAAI,+BAAY,YAAY,UAAU;AAChD,IAAE,SAAS;AAEX,QAAM,WAAW,IAAI,uCAAgB,YAAY,UAAU;AAE3D,wBAAG,0CAA0C,YAAY;AAnB3D;AAoBI,UAAM,QAAQ,MAAM,EAAE,MAAM;AAC5B,UAAM,QAAQ,MAAM,SAAS,QAAQ,MAAM,KAAK;AAChD,8BAAO,KAAK,EAAE,WAAW;AACzB,+BAAO,WAAM,SAAN,mBAAY,IAAI,EAAE,KAAK,YAAY;AAC1C,8BAAO,MAAM,KAAK,EAAE,KAAK,cAAc;AAAA,EACzC,CAAC;AACH,CAAC;AAAA,IAED,wBAAS,yBAAyB,MAAM;AACtC,wBAAG,8CAA8C,MAAM;AA7BzD;AA8BI,UAAM,MAAM;AAAA,MACV,MAAM;AAAA,MACN,MAAM;AAAA,QACJ,KAAK;AAAA,QACL,MAAM;AAAA,MACR;AAAA,MACA,OAAO;AAAA,IACT;AAEA,UAAM,QAAQ,IAAI,oCAAa,GAAG;AAClC,8BAAO,KAAK,EAAE,WAAW;AACzB,+BAAO,WAAM,SAAN,mBAAY,IAAI,EAAE,KAAK,YAAY;AAAA,EAC5C,CAAC;AACH,CAAC;","names":[]}
|