meet/app/api/token/route.ts
Jonas Schell 15e58cd797
Migrate to Next app router (#297)
* Migrate Home Page to App Router

* Update themeColor from layout.tsx

* port room page to app router

* small changes

* port custom page to app router

* port token and url api routes

* port start stop routes

* Refactor error handling in GET function

* delete pages folder

* remove unused function

* remove deprecated field

from docs: @deprecated — will be enabled by default and removed in Next.js 15

* wrap useSearchParams in Suspense

* split up custom page into server and client component

* update imports

* simplify

* Refactor error handling in GET function

* refactor to use props for components

* Refactor video codec validation and handling

* Refactor LiveKitRoom component to handle null liveKitUrl

* refactor: improve video codec validation and handling

* add video codec typeguard

* fix isVideoCodec
2024-08-21 14:05:42 +02:00

68 lines
2.1 KiB
TypeScript

import { AccessToken } from 'livekit-server-sdk';
import type { AccessTokenOptions, VideoGrant } from 'livekit-server-sdk';
import { TokenResult } from '@/lib/types';
import { NextResponse } from 'next/server';
const apiKey = process.env.LIVEKIT_API_KEY;
const apiSecret = process.env.LIVEKIT_API_SECRET;
const createToken = (userInfo: AccessTokenOptions, grant: VideoGrant) => {
const at = new AccessToken(apiKey, apiSecret, userInfo);
at.ttl = '5m';
at.addGrant(grant);
return at.toJwt();
};
const roomPattern = /\w{4}\-\w{4}/;
export async function GET(req: Request) {
try {
const url = new URL(req.url);
const searchParams = url.searchParams;
const roomName = searchParams.get('roomName');
const identity = searchParams.get('identity');
const name = searchParams.get('name');
const metadata = searchParams.get('metadata') ?? '';
if (typeof identity !== 'string' || typeof roomName !== 'string') {
return new NextResponse('Forbidden', { status: 401 });
}
if (name === null) {
return new NextResponse('Provide a name.', { status: 400 });
}
if (Array.isArray(name)) {
return new NextResponse('Provide only one room name.', { status: 400 });
}
if (Array.isArray(metadata)) {
return new NextResponse('Provide only one metadata string.', { status: 400 });
}
// enforce room name to be xxxx-xxxx
// this is simple & naive way to prevent user from guessing room names
// please use your own authentication mechanisms in your own app
if (!roomName.match(roomPattern)) {
return new NextResponse('Invalid room name format.', { status: 400 });
}
const grant: VideoGrant = {
room: roomName,
roomJoin: true,
canPublish: true,
canPublishData: true,
canSubscribe: true,
};
const token = await createToken({ identity, name, metadata }, grant);
const result: TokenResult = {
identity,
accessToken: token,
};
return NextResponse.json(result);
} catch (error) {
if (error instanceof Error) {
return new NextResponse(error.message, { status: 500 });
}
}
}