From 961cbe4269e5f34639e29310fb3d90a6cb1bd6bc Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 22 Apr 2022 09:50:20 +0200 Subject: Fix getting live by anonymous user --- server/controllers/api/videos/live.ts | 18 ++++++++++---- server/middlewares/validators/videos/video-live.ts | 6 +---- server/models/video/video-live.ts | 25 ++++++++++++------- server/tests/api/check-params/live.ts | 28 ++++++++++++++++++---- 4 files changed, 54 insertions(+), 23 deletions(-) (limited to 'server') diff --git a/server/controllers/api/videos/live.ts b/server/controllers/api/videos/live.ts index c6f038079..e51658927 100644 --- a/server/controllers/api/videos/live.ts +++ b/server/controllers/api/videos/live.ts @@ -10,11 +10,11 @@ import { videoLiveAddValidator, videoLiveGetValidator, videoLiveUpdateValidator import { VideoLiveModel } from '@server/models/video/video-live' import { MVideoDetails, MVideoFullLight } from '@server/types/models' import { buildUUID, uuidToShort } from '@shared/extra-utils' -import { HttpStatusCode, LiveVideoCreate, LiveVideoLatencyMode, LiveVideoUpdate, VideoState } from '@shared/models' +import { HttpStatusCode, LiveVideoCreate, LiveVideoLatencyMode, LiveVideoUpdate, UserRight, VideoState } from '@shared/models' import { logger } from '../../../helpers/logger' import { sequelizeTypescript } from '../../../initializers/database' import { updateVideoMiniatureFromExisting } from '../../../lib/thumbnail' -import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate } from '../../../middlewares' +import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, optionalAuthenticate } from '../../../middlewares' import { VideoModel } from '../../../models/video/video' const liveRouter = express.Router() @@ -29,7 +29,7 @@ liveRouter.post('/live', ) liveRouter.get('/live/:videoId', - authenticate, + optionalAuthenticate, asyncMiddleware(videoLiveGetValidator), getLiveVideo ) @@ -52,7 +52,17 @@ export { function getLiveVideo (req: express.Request, res: express.Response) { const videoLive = res.locals.videoLive - return res.json(videoLive.toFormattedJSON()) + return res.json(videoLive.toFormattedJSON(canSeePrivateLiveInformation(res))) +} + +function canSeePrivateLiveInformation (res: express.Response) { + const user = res.locals.oauth?.token.User + if (!user) return false + + if (user.hasRight(UserRight.GET_ANY_LIVE)) return true + + const video = res.locals.videoAll + return video.VideoChannel.Account.userId === user.id } async function updateLiveVideo (req: express.Request, res: express.Response) { diff --git a/server/middlewares/validators/videos/video-live.ts b/server/middlewares/validators/videos/video-live.ts index b756c0bf1..8f821c5f9 100644 --- a/server/middlewares/validators/videos/video-live.ts +++ b/server/middlewares/validators/videos/video-live.ts @@ -33,15 +33,11 @@ const videoLiveGetValidator = [ isValidVideoIdParam('videoId'), async (req: express.Request, res: express.Response, next: express.NextFunction) => { - logger.debug('Checking videoLiveGetValidator parameters', { parameters: req.params, user: res.locals.oauth.token.User.username }) + logger.debug('Checking videoLiveGetValidator parameters', { parameters: req.params }) if (areValidationErrors(req, res)) return if (!await doesVideoExist(req.params.videoId, res, 'all')) return - // Check if the user who did the request is able to get the live info - const user = res.locals.oauth.token.User - if (!checkUserCanManageVideo(user, res.locals.videoAll, UserRight.GET_ANY_LIVE, res, false)) return - const videoLive = await VideoLiveModel.loadByVideoId(res.locals.videoAll.id) if (!videoLive) { return res.fail({ diff --git a/server/models/video/video-live.ts b/server/models/video/video-live.ts index 96c0bf7f7..68e381105 100644 --- a/server/models/video/video-live.ts +++ b/server/models/video/video-live.ts @@ -101,21 +101,28 @@ export class VideoLiveModel extends Model return VideoLiveModel.findOne(query) } - toFormattedJSON (): LiveVideo { - let rtmpUrl: string = null - let rtmpsUrl: string = null + toFormattedJSON (canSeePrivateInformation: boolean): LiveVideo { + let privateInformation: Pick | {} = {} // If we don't have a stream key, it means this is a remote live so we don't specify the rtmp URL - if (this.streamKey) { - if (CONFIG.LIVE.RTMP.ENABLED) rtmpUrl = WEBSERVER.RTMP_URL - if (CONFIG.LIVE.RTMPS.ENABLED) rtmpsUrl = WEBSERVER.RTMPS_URL + // We also display these private information only to the live owne/moderators + if (this.streamKey && canSeePrivateInformation === true) { + privateInformation = { + streamKey: this.streamKey, + + rtmpUrl: CONFIG.LIVE.RTMP.ENABLED + ? WEBSERVER.RTMP_URL + : null, + + rtmpsUrl: CONFIG.LIVE.RTMPS.ENABLED + ? WEBSERVER.RTMPS_URL + : null + } } return { - rtmpUrl, - rtmpsUrl, + ...privateInformation, - streamKey: this.streamKey, permanentLive: this.permanentLive, saveReplay: this.saveReplay, latencyMode: this.latencyMode diff --git a/server/tests/api/check-params/live.ts b/server/tests/api/check-params/live.ts index 2f1c1257e..d4a81c4f6 100644 --- a/server/tests/api/check-params/live.ts +++ b/server/tests/api/check-params/live.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ import 'mocha' +import { expect } from 'chai' import { omit } from 'lodash' import { buildAbsoluteFixturePath } from '@shared/core-utils' import { HttpStatusCode, LiveVideoLatencyMode, VideoCreateResult, VideoPrivacy } from '@shared/models' @@ -340,16 +341,33 @@ describe('Test video lives API validator', function () { describe('When getting live information', function () { - it('Should fail without access token', async function () { - await command.get({ token: '', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) - }) it('Should fail with a bad access token', async function () { await command.get({ token: 'toto', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) }) - it('Should fail with access token of another user', async function () { - await command.get({ token: userAccessToken, videoId: video.id, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) + it('Should not display private information without access token', async function () { + const live = await command.get({ token: '', videoId: video.id }) + + expect(live.rtmpUrl).to.not.exist + expect(live.streamKey).to.not.exist + expect(live.latencyMode).to.exist + }) + + it('Should not display private information with token of another user', async function () { + const live = await command.get({ token: userAccessToken, videoId: video.id }) + + expect(live.rtmpUrl).to.not.exist + expect(live.streamKey).to.not.exist + expect(live.latencyMode).to.exist + }) + + it('Should display private information with appropriate token', async function () { + const live = await command.get({ videoId: video.id }) + + expect(live.rtmpUrl).to.exist + expect(live.streamKey).to.exist + expect(live.latencyMode).to.exist }) it('Should fail with a bad video id', async function () { -- cgit v1.2.3