Files
Final-Year-Project/Backend/media/providers/mock.ts

97 lines
2.7 KiB
TypeScript

import { createHmac } from 'crypto';
import type {
MediaProvider,
MediaPublishCredentials,
MediaSessionCreateInput,
MediaSessionCreateResult,
MediaSubscribeCredentials,
} from '../types';
const secret = process.env.BETTER_AUTH_SECRET;
if (!secret) {
throw new Error('BETTER_AUTH_SECRET is required for mock media provider token signing');
}
const DEFAULT_TTL_SECONDS = 60 * 10;
const signToken = (payload: Record<string, unknown>, ttlSeconds = DEFAULT_TTL_SECONDS): { token: string; expiresInSeconds: number } => {
const body = {
...payload,
exp: Math.floor(Date.now() / 1000) + ttlSeconds,
};
const encoded = Buffer.from(JSON.stringify(body), 'utf8').toString('base64url');
const signature = createHmac('sha256', secret).update(encoded).digest('base64url');
return {
token: `${encoded}.${signature}`,
expiresInSeconds: ttlSeconds,
};
};
const getBaseUrl = (): string => process.env.MEDIA_MOCK_BASE_URL ?? process.env.BETTER_AUTH_URL ?? 'http://localhost:3000';
export class MockMediaProvider implements MediaProvider {
name = 'mock';
async createSession(input: MediaSessionCreateInput): Promise<MediaSessionCreateResult> {
const mediaSessionId = `mock_${input.streamSessionId}`;
const baseUrl = getBaseUrl();
return {
provider: this.name,
mediaSessionId,
publishUrl: `${baseUrl}/media/mock/publish/${mediaSessionId}`,
subscribeUrl: `${baseUrl}/media/mock/subscribe/${mediaSessionId}`,
};
}
async issuePublishCredentials(input: {
mediaSessionId: string;
cameraDeviceId: string;
ownerUserId: string;
}): Promise<MediaPublishCredentials> {
const baseUrl = getBaseUrl();
const { token, expiresInSeconds } = signToken({
typ: 'publish',
provider: this.name,
mediaSessionId: input.mediaSessionId,
cameraDeviceId: input.cameraDeviceId,
ownerUserId: input.ownerUserId,
});
return {
provider: this.name,
mediaSessionId: input.mediaSessionId,
publishToken: token,
publishUrl: `${baseUrl}/media/mock/publish/${input.mediaSessionId}`,
expiresInSeconds,
};
}
async issueSubscribeCredentials(input: {
mediaSessionId: string;
viewerDeviceId: string;
ownerUserId: string;
}): Promise<MediaSubscribeCredentials> {
const baseUrl = getBaseUrl();
const { token, expiresInSeconds } = signToken({
typ: 'subscribe',
provider: this.name,
mediaSessionId: input.mediaSessionId,
viewerDeviceId: input.viewerDeviceId,
ownerUserId: input.ownerUserId,
});
return {
provider: this.name,
mediaSessionId: input.mediaSessionId,
subscribeToken: token,
subscribeUrl: `${baseUrl}/media/mock/subscribe/${input.mediaSessionId}`,
expiresInSeconds,
};
}
}