From 05a60d85997c108d39bcfb14f1ffd4c74f8b1e93 Mon Sep 17 00:00:00 2001 From: Wicklow <123956049+wickloww@users.noreply.github.com> Date: Fri, 31 Mar 2023 07:12:21 +0000 Subject: Feature/Add replay privacy (#5692) * Add replay settings feature * Fix replay settings behaviour * Fix tests * Fix tests * Fix tests * Update openapi doc and fix tests * Add tests and fix code * Models correction * Add migration and update controller and middleware * Add check params tests * Fix video live middleware * Updated code based on review comments --- .../sql/video/shared/video-table-attributes.ts | 1 + server/models/video/video-live-replay-setting.ts | 42 ++++++++++++++++ server/models/video/video-live-session.ts | 49 ++++++++++++++++++- server/models/video/video-live.ts | 57 ++++++++++++++++++++-- server/models/video/video.ts | 1 + 5 files changed, 146 insertions(+), 4 deletions(-) create mode 100644 server/models/video/video-live-replay-setting.ts (limited to 'server/models/video') diff --git a/server/models/video/sql/video/shared/video-table-attributes.ts b/server/models/video/sql/video/shared/video-table-attributes.ts index e2c1c0f6d..34967cd20 100644 --- a/server/models/video/sql/video/shared/video-table-attributes.ts +++ b/server/models/video/sql/video/shared/video-table-attributes.ts @@ -160,6 +160,7 @@ export class VideoTableAttributes { 'permanentLive', 'latencyMode', 'videoId', + 'replaySettingId', 'createdAt', 'updatedAt' ] diff --git a/server/models/video/video-live-replay-setting.ts b/server/models/video/video-live-replay-setting.ts new file mode 100644 index 000000000..1c824dfa2 --- /dev/null +++ b/server/models/video/video-live-replay-setting.ts @@ -0,0 +1,42 @@ +import { isVideoPrivacyValid } from '@server/helpers/custom-validators/videos' +import { MLiveReplaySetting } from '@server/types/models/video/video-live-replay-setting' +import { VideoPrivacy } from '@shared/models/videos/video-privacy.enum' +import { Transaction } from 'sequelize' +import { AllowNull, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' +import { throwIfNotValid } from '../shared/sequelize-helpers' + +@Table({ + tableName: 'videoLiveReplaySetting' +}) +export class VideoLiveReplaySettingModel extends Model { + + @CreatedAt + createdAt: Date + + @UpdatedAt + updatedAt: Date + + @AllowNull(false) + @Is('VideoPrivacy', value => throwIfNotValid(value, isVideoPrivacyValid, 'privacy')) + @Column + privacy: VideoPrivacy + + static load (id: number, transaction?: Transaction): Promise { + return VideoLiveReplaySettingModel.findOne({ + where: { id }, + transaction + }) + } + + static removeSettings (id: number) { + return VideoLiveReplaySettingModel.destroy({ + where: { id } + }) + } + + toFormattedJSON () { + return { + privacy: this.privacy + } + } +} diff --git a/server/models/video/video-live-session.ts b/server/models/video/video-live-session.ts index ed386052b..dcded7872 100644 --- a/server/models/video/video-live-session.ts +++ b/server/models/video/video-live-session.ts @@ -1,10 +1,23 @@ import { FindOptions } from 'sequelize' -import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' +import { + AllowNull, + BeforeDestroy, + BelongsTo, + Column, + CreatedAt, + DataType, + ForeignKey, + Model, + Scopes, + Table, + UpdatedAt +} from 'sequelize-typescript' import { MVideoLiveSession, MVideoLiveSessionReplay } from '@server/types/models' import { uuidToShort } from '@shared/extra-utils' import { LiveVideoError, LiveVideoSession } from '@shared/models' import { AttributesOnly } from '@shared/typescript-utils' import { VideoModel } from './video' +import { VideoLiveReplaySettingModel } from './video-live-replay-setting' export enum ScopeNames { WITH_REPLAY = 'WITH_REPLAY' @@ -17,6 +30,10 @@ export enum ScopeNames { model: VideoModel.unscoped(), as: 'ReplayVideo', required: false + }, + { + model: VideoLiveReplaySettingModel, + required: false } ] } @@ -30,6 +47,10 @@ export enum ScopeNames { }, { fields: [ 'liveVideoId' ] + }, + { + fields: [ 'replaySettingId' ], + unique: true } ] }) @@ -89,6 +110,27 @@ export class VideoLiveSessionModel extends Model VideoLiveReplaySettingModel) + @Column + replaySettingId: number + + @BelongsTo(() => VideoLiveReplaySettingModel, { + foreignKey: { + allowNull: true + }, + onDelete: 'set null' + }) + ReplaySetting: VideoLiveReplaySettingModel + + @BeforeDestroy + static deleteReplaySetting (instance: VideoLiveSessionModel) { + return VideoLiveReplaySettingModel.destroy({ + where: { + id: instance.replaySettingId + } + }) + } + static load (id: number): Promise { return VideoLiveSessionModel.findOne({ where: { id } @@ -146,6 +188,10 @@ export class VideoLiveSessionModel extends Model ({ include: [ @@ -18,6 +31,10 @@ import { VideoBlacklistModel } from './video-blacklist' required: false } ] + }, + { + model: VideoLiveReplaySettingModel, + required: false } ] })) @@ -27,6 +44,10 @@ import { VideoBlacklistModel } from './video-blacklist' { fields: [ 'videoId' ], unique: true + }, + { + fields: [ 'replaySettingId' ], + unique: true } ] }) @@ -66,6 +87,27 @@ export class VideoLiveModel extends Model }) Video: VideoModel + @ForeignKey(() => VideoLiveReplaySettingModel) + @Column + replaySettingId: number + + @BelongsTo(() => VideoLiveReplaySettingModel, { + foreignKey: { + allowNull: true + }, + onDelete: 'set null' + }) + ReplaySetting: VideoLiveReplaySettingModel + + @BeforeDestroy + static deleteReplaySetting (instance: VideoLiveModel) { + return VideoLiveReplaySettingModel.destroy({ + where: { + id: instance.replaySettingId + } + }) + } + static loadByStreamKey (streamKey: string) { const query = { where: { @@ -84,11 +126,15 @@ export class VideoLiveModel extends Model required: false } ] + }, + { + model: VideoLiveReplaySettingModel.unscoped(), + required: false } ] } - return VideoLiveModel.findOne(query) + return VideoLiveModel.findOne(query) } static loadByVideoId (videoId: number) { @@ -120,11 +166,16 @@ export class VideoLiveModel extends Model } } + const replaySettings = this.replaySettingId + ? this.ReplaySetting.toFormattedJSON() + : undefined + return { ...privateInformation, permanentLive: this.permanentLive, saveReplay: this.saveReplay, + replaySettings, latencyMode: this.latencyMode } } diff --git a/server/models/video/video.ts b/server/models/video/video.ts index aa9c62e36..0c5ed64ec 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts @@ -706,6 +706,7 @@ export class VideoModel extends Model>> { name: 'videoId', allowNull: false }, + hooks: true, onDelete: 'cascade' }) VideoLive: VideoLiveModel -- cgit v1.2.3