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 --- server/initializers/constants.ts | 2 +- server/initializers/database.ts | 2 + .../migrations/0760-video-live-replay-setting.ts | 125 +++++++++++++++++++++ 3 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 server/initializers/migrations/0760-video-live-replay-setting.ts (limited to 'server/initializers') diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 4703e20f2..6cad4eb23 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts @@ -26,7 +26,7 @@ import { CONFIG, registerConfigChangedHandler } from './config' // --------------------------------------------------------------------------- -const LAST_MIGRATION_VERSION = 755 +const LAST_MIGRATION_VERSION = 760 // --------------------------------------------------------------------------- diff --git a/server/initializers/database.ts b/server/initializers/database.ts index 96145f489..3f31099ed 100644 --- a/server/initializers/database.ts +++ b/server/initializers/database.ts @@ -52,6 +52,7 @@ import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-pla import { VideoTagModel } from '../models/video/video-tag' import { VideoViewModel } from '../models/view/video-view' import { CONFIG } from './config' +import { VideoLiveReplaySettingModel } from '@server/models/video/video-live-replay-setting' require('pg').defaults.parseInt8 = true // Avoid BIGINT to be converted to string @@ -141,6 +142,7 @@ async function initDatabaseModels (silent: boolean) { UserVideoHistoryModel, VideoLiveModel, VideoLiveSessionModel, + VideoLiveReplaySettingModel, AccountBlocklistModel, ServerBlocklistModel, UserNotificationModel, diff --git a/server/initializers/migrations/0760-video-live-replay-setting.ts b/server/initializers/migrations/0760-video-live-replay-setting.ts new file mode 100644 index 000000000..7878df3f7 --- /dev/null +++ b/server/initializers/migrations/0760-video-live-replay-setting.ts @@ -0,0 +1,125 @@ +import * as Sequelize from 'sequelize' + +async function up (utils: { + transaction: Sequelize.Transaction + queryInterface: Sequelize.QueryInterface + sequelize: Sequelize.Sequelize +}): Promise { + { + const query = ` + CREATE TABLE IF NOT EXISTS "videoLiveReplaySetting" ( + "id" SERIAL , + "privacy" INTEGER NOT NULL, + "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, + "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, + PRIMARY KEY ("id") + ); + ` + + await utils.sequelize.query(query, { transaction : utils.transaction }) + } + + { + await utils.queryInterface.addColumn('videoLive', 'replaySettingId', { + type: Sequelize.INTEGER, + defaultValue: null, + allowNull: true, + references: { + model: 'videoLiveReplaySetting', + key: 'id' + }, + onDelete: 'SET NULL' + }, { transaction: utils.transaction }) + } + + { + await utils.queryInterface.addColumn('videoLiveSession', 'replaySettingId', { + type: Sequelize.INTEGER, + defaultValue: null, + allowNull: true, + references: { + model: 'videoLiveReplaySetting', + key: 'id' + }, + onDelete: 'SET NULL' + }, { transaction: utils.transaction }) + } + + { + const query = ` + SELECT live."id", v."privacy" + FROM "videoLive" live + INNER JOIN "video" v ON live."videoId" = v."id" + WHERE live."saveReplay" = true + ` + + const videoLives = await utils.sequelize.query<{ id: number, privacy: number }>( + query, + { type: Sequelize.QueryTypes.SELECT, transaction: utils.transaction } + ) + + for (const videoLive of videoLives) { + const query = ` + WITH new_replay_setting AS ( + INSERT INTO "videoLiveReplaySetting" ("privacy", "createdAt", "updatedAt") + VALUES (:privacy, NOW(), NOW()) + RETURNING id + ) + UPDATE "videoLive" SET "replaySettingId" = (SELECT id FROM new_replay_setting) + WHERE "id" = :id + ` + + const options = { + replacements: { privacy: videoLive.privacy, id: videoLive.id }, + type: Sequelize.QueryTypes.UPDATE, + transaction: utils.transaction + } + + await utils.sequelize.query(query, options) + } + } + + { + const query = ` + SELECT session."id", v."privacy" + FROM "videoLiveSession" session + INNER JOIN "video" v ON session."liveVideoId" = v."id" + WHERE session."saveReplay" = true + AND session."liveVideoId" IS NOT NULL; + ` + + const videoLiveSessions = await utils.sequelize.query<{ id: number, privacy: number }>( + query, + { type: Sequelize.QueryTypes.SELECT, transaction: utils.transaction } + ) + + for (const videoLive of videoLiveSessions) { + const query = ` + WITH new_replay_setting AS ( + INSERT INTO "videoLiveReplaySetting" ("privacy", "createdAt", "updatedAt") + VALUES (:privacy, NOW(), NOW()) + RETURNING id + ) + UPDATE "videoLiveSession" SET "replaySettingId" = (SELECT id FROM new_replay_setting) + WHERE "id" = :id + ` + + const options = { + replacements: { privacy: videoLive.privacy, id: videoLive.id }, + type: Sequelize.QueryTypes.UPDATE, + transaction: utils.transaction + } + + await utils.sequelize.query(query, options) + } + } +} + +function down (options) { + throw new Error('Not implemented.') +} + +export { + up, + down +} -- cgit v1.2.3