Skip to content

Commit 75a245a

Browse files
authored
Reject publishing with insufficient permissions present (#1418)
1 parent 61e6380 commit 75a245a

File tree

4 files changed

+55
-1
lines changed

4 files changed

+55
-1
lines changed

.changeset/smart-countries-deny.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"livekit-client": patch
3+
---
4+
5+
Reject publishing with insufficient permissions present

src/room/errors.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,16 @@ export class PublishDataError extends LivekitError {
8484
}
8585
}
8686

87+
export class PublishTrackError extends LivekitError {
88+
status: number;
89+
90+
constructor(message: string, status: number) {
91+
super(15, message);
92+
this.name = 'PublishTrackError';
93+
this.status = status;
94+
}
95+
}
96+
8797
export type RequestErrorReason =
8898
| Exclude<RequestResponse_Reason, RequestResponse_Reason.OK>
8999
| 'TimeoutError';

src/room/participant/LocalParticipant.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { defaultVideoCodec } from '../defaults';
3434
import {
3535
DeviceUnsupportedError,
3636
LivekitError,
37+
PublishTrackError,
3738
SignalRequestError,
3839
TrackInvalidError,
3940
UnexpectedConnectionState,
@@ -64,6 +65,7 @@ import {
6465
constraintsForOptions,
6566
extractProcessorsFromOptions,
6667
getLogContextFromTrack,
68+
getTrackSourceFromProto,
6769
mergeDefaultOptions,
6870
mimeTypeToVideoCodecString,
6971
screenCaptureToDisplayMediaStreamOptions,
@@ -871,7 +873,29 @@ export default class LocalParticipant extends Participant {
871873
}
872874
}
873875

876+
private hasPermissionsToPublish(track: LocalTrack): boolean {
877+
if (!this.permissions) {
878+
return false;
879+
}
880+
const { canPublish, canPublishSources } = this.permissions;
881+
if (
882+
!canPublish ||
883+
(canPublishSources &&
884+
!canPublishSources.map((source) => getTrackSourceFromProto(source)).includes(track.source))
885+
) {
886+
this.log.error('insufficient permissions to publish', {
887+
...this.logContext,
888+
...getLogContextFromTrack(track),
889+
});
890+
return false;
891+
}
892+
return true;
893+
}
894+
874895
private async publish(track: LocalTrack, opts: TrackPublishOptions, isStereo: boolean) {
896+
if (!this.hasPermissionsToPublish(track)) {
897+
throw new PublishTrackError('failed to publish track, insufficient permissions', 403);
898+
}
875899
const existingTrackOfSource = Array.from(this.trackPublications.values()).find(
876900
(publishedTrack) => isLocalTrack(track) && publishedTrack.source === track.source,
877901
);

src/room/track/utils.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { TrackPublishedResponse } from '@livekit/protocol';
1+
import { TrackPublishedResponse, TrackSource } from '@livekit/protocol';
22
import type { AudioProcessorOptions, TrackProcessor, VideoProcessorOptions } from '../..';
33
import { cloneDeep } from '../../utils/cloneDeep';
44
import { isSafari, sleep } from '../utils';
@@ -294,3 +294,18 @@ export function extractProcessorsFromOptions(options: CreateLocalTracksOptions)
294294

295295
return { audioProcessor, videoProcessor, optionsWithoutProcessor: newOptions };
296296
}
297+
298+
export function getTrackSourceFromProto(source: TrackSource): Track.Source {
299+
switch (source) {
300+
case TrackSource.CAMERA:
301+
return Track.Source.Camera;
302+
case TrackSource.MICROPHONE:
303+
return Track.Source.Microphone;
304+
case TrackSource.SCREEN_SHARE:
305+
return Track.Source.ScreenShare;
306+
case TrackSource.SCREEN_SHARE_AUDIO:
307+
return Track.Source.ScreenShareAudio;
308+
default:
309+
return Track.Source.Unknown;
310+
}
311+
}

0 commit comments

Comments
 (0)