aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/src/app/+videos/+video-edit/video-update.component.ts5
-rw-r--r--server/middlewares/validators/videos/videos.ts2
-rw-r--r--server/tests/api/check-params/live.ts8
-rw-r--r--shared/core-utils/common/object.ts24
4 files changed, 34 insertions, 5 deletions
diff --git a/client/src/app/+videos/+video-edit/video-update.component.ts b/client/src/app/+videos/+video-edit/video-update.component.ts
index 412b43967..b70270261 100644
--- a/client/src/app/+videos/+video-edit/video-update.component.ts
+++ b/client/src/app/+videos/+video-edit/video-update.component.ts
@@ -9,6 +9,7 @@ import { Video, VideoCaptionEdit, VideoCaptionService, VideoDetails, VideoEdit,
9import { LiveVideoService } from '@app/shared/shared-video-live' 9import { LiveVideoService } from '@app/shared/shared-video-live'
10import { LoadingBarService } from '@ngx-loading-bar/core' 10import { LoadingBarService } from '@ngx-loading-bar/core'
11import { logger } from '@root-helpers/logger' 11import { logger } from '@root-helpers/logger'
12import { pick, simpleObjectsDeepEqual } from '@shared/core-utils'
12import { LiveVideo, LiveVideoUpdate, VideoPrivacy } from '@shared/models' 13import { LiveVideo, LiveVideoUpdate, VideoPrivacy } from '@shared/models'
13import { VideoSource } from '@shared/models/videos/video-source' 14import { VideoSource } from '@shared/models/videos/video-source'
14import { hydrateFormFromVideo } from './shared/video-edit-utils' 15import { hydrateFormFromVideo } from './shared/video-edit-utils'
@@ -134,8 +135,8 @@ export class VideoUpdateComponent extends FormReactive implements OnInit {
134 } 135 }
135 136
136 // Don't update live attributes if they did not change 137 // Don't update live attributes if they did not change
137 const liveChanged = Object.keys(liveVideoUpdate) 138 const baseVideo = pick(this.liveVideo, Object.keys(liveVideoUpdate) as (keyof LiveVideoUpdate)[])
138 .some(key => this.liveVideo[key] !== liveVideoUpdate[key]) 139 const liveChanged = !simpleObjectsDeepEqual(baseVideo, liveVideoUpdate)
139 if (!liveChanged) return of(undefined) 140 if (!liveChanged) return of(undefined)
140 141
141 return this.liveVideoService.updateLive(this.videoEdit.id, liveVideoUpdate) 142 return this.liveVideoService.updateLive(this.videoEdit.id, liveVideoUpdate)
diff --git a/server/middlewares/validators/videos/videos.ts b/server/middlewares/validators/videos/videos.ts
index ea6bd0721..d3014e8e7 100644
--- a/server/middlewares/validators/videos/videos.ts
+++ b/server/middlewares/validators/videos/videos.ts
@@ -234,7 +234,7 @@ const videosUpdateValidator = getCommonVideoEditAttributes().concat([
234 if (!await doesVideoExist(req.params.id, res)) return cleanUpReqFiles(req) 234 if (!await doesVideoExist(req.params.id, res)) return cleanUpReqFiles(req)
235 235
236 const video = getVideoWithAttributes(res) 236 const video = getVideoWithAttributes(res)
237 if (req.body.privacy && video.isLive && video.state !== VideoState.WAITING_FOR_LIVE) { 237 if (video.isLive && video.privacy !== req.body.privacy && video.state !== VideoState.WAITING_FOR_LIVE) {
238 return res.fail({ message: 'Cannot update privacy of a live that has already started' }) 238 return res.fail({ message: 'Cannot update privacy of a live that has already started' })
239 } 239 }
240 240
diff --git a/server/tests/api/check-params/live.ts b/server/tests/api/check-params/live.ts
index 81f10ed8e..2dc735c23 100644
--- a/server/tests/api/check-params/live.ts
+++ b/server/tests/api/check-params/live.ts
@@ -553,9 +553,15 @@ describe('Test video lives API validator', function () {
553 const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey }) 553 const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey })
554 554
555 await command.waitUntilPublished({ videoId: video.id }) 555 await command.waitUntilPublished({ videoId: video.id })
556
557 await server.videos.update({
558 id: video.id,
559 attributes: { privacy: VideoPrivacy.PUBLIC } // Same privacy, it's fine
560 })
561
556 await server.videos.update({ 562 await server.videos.update({
557 id: video.id, 563 id: video.id,
558 attributes: { privacy: VideoPrivacy.PUBLIC }, 564 attributes: { privacy: VideoPrivacy.UNLISTED },
559 expectedStatus: HttpStatusCode.BAD_REQUEST_400 565 expectedStatus: HttpStatusCode.BAD_REQUEST_400
560 }) 566 })
561 567
diff --git a/shared/core-utils/common/object.ts b/shared/core-utils/common/object.ts
index 7f1f147f4..9780b2594 100644
--- a/shared/core-utils/common/object.ts
+++ b/shared/core-utils/common/object.ts
@@ -45,10 +45,32 @@ function shallowCopy <T> (o: T): T {
45 return Object.assign(Object.create(Object.getPrototypeOf(o)), o) 45 return Object.assign(Object.create(Object.getPrototypeOf(o)), o)
46} 46}
47 47
48function simpleObjectsDeepEqual (a: any, b: any) {
49 if (a === b) return true
50
51 if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) {
52 return false
53 }
54
55 const keysA = Object.keys(a)
56 const keysB = Object.keys(b)
57
58 if (keysA.length !== keysB.length) return false
59
60 for (const key of keysA) {
61 if (!keysB.includes(key)) return false
62
63 if (!simpleObjectsDeepEqual(a[key], b[key])) return false
64 }
65
66 return true
67}
68
48export { 69export {
49 pick, 70 pick,
50 omit, 71 omit,
51 getKeys, 72 getKeys,
52 shallowCopy, 73 shallowCopy,
53 sortObjectComparator 74 sortObjectComparator,
75 simpleObjectsDeepEqual
54} 76}