diff options
-rw-r--r-- | client/src/app/+videos/+video-edit/video-update.component.ts | 5 | ||||
-rw-r--r-- | server/middlewares/validators/videos/videos.ts | 2 | ||||
-rw-r--r-- | server/tests/api/check-params/live.ts | 8 | ||||
-rw-r--r-- | shared/core-utils/common/object.ts | 24 |
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, | |||
9 | import { LiveVideoService } from '@app/shared/shared-video-live' | 9 | import { LiveVideoService } from '@app/shared/shared-video-live' |
10 | import { LoadingBarService } from '@ngx-loading-bar/core' | 10 | import { LoadingBarService } from '@ngx-loading-bar/core' |
11 | import { logger } from '@root-helpers/logger' | 11 | import { logger } from '@root-helpers/logger' |
12 | import { pick, simpleObjectsDeepEqual } from '@shared/core-utils' | ||
12 | import { LiveVideo, LiveVideoUpdate, VideoPrivacy } from '@shared/models' | 13 | import { LiveVideo, LiveVideoUpdate, VideoPrivacy } from '@shared/models' |
13 | import { VideoSource } from '@shared/models/videos/video-source' | 14 | import { VideoSource } from '@shared/models/videos/video-source' |
14 | import { hydrateFormFromVideo } from './shared/video-edit-utils' | 15 | import { 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 | ||
48 | function 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 | |||
48 | export { | 69 | export { |
49 | pick, | 70 | pick, |
50 | omit, | 71 | omit, |
51 | getKeys, | 72 | getKeys, |
52 | shallowCopy, | 73 | shallowCopy, |
53 | sortObjectComparator | 74 | sortObjectComparator, |
75 | simpleObjectsDeepEqual | ||
54 | } | 76 | } |