Init commit
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
|
||||
{
|
||||
const field = {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('user', 'lastLoginDate', field)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
|
||||
// We made a mistake with the migration in 2.2.0-rc.1
|
||||
// Docker containers did not include this migration file
|
||||
// So we check the table definition and add the column if it does not exist
|
||||
const tableDefinition = await utils.queryInterface.describeTable('videoFile')
|
||||
|
||||
if (!tableDefinition['metadata']) {
|
||||
const metadata = {
|
||||
type: Sequelize.JSONB,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('videoFile', 'metadata', metadata)
|
||||
}
|
||||
|
||||
if (!tableDefinition['metadataUrl']) {
|
||||
const metadataUrl = {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('videoFile', 'metadataUrl', metadataUrl)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
await utils.queryInterface.addColumn('videoAbuse', 'predefinedReasons', {
|
||||
type: Sequelize.ARRAY(Sequelize.INTEGER),
|
||||
allowNull: true
|
||||
})
|
||||
|
||||
await utils.queryInterface.addColumn('videoAbuse', 'startAt', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true
|
||||
})
|
||||
|
||||
await utils.queryInterface.addColumn('videoAbuse', 'endAt', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true
|
||||
})
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
83
server/core/initializers/migrations/0520-abuses-split.ts
Normal file
83
server/core/initializers/migrations/0520-abuses-split.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
await utils.queryInterface.renameTable('videoAbuse', 'abuse')
|
||||
|
||||
await utils.sequelize.query(`
|
||||
ALTER TABLE "abuse"
|
||||
ADD COLUMN "flaggedAccountId" INTEGER REFERENCES "account" ("id") ON DELETE SET NULL ON UPDATE CASCADE
|
||||
`)
|
||||
|
||||
await utils.sequelize.query(`
|
||||
UPDATE "abuse" SET "videoId" = NULL
|
||||
WHERE "videoId" NOT IN (SELECT "id" FROM "video")
|
||||
`)
|
||||
|
||||
await utils.sequelize.query(`
|
||||
UPDATE "abuse" SET "flaggedAccountId" = "videoChannel"."accountId"
|
||||
FROM "video" INNER JOIN "videoChannel" ON "video"."channelId" = "videoChannel"."id"
|
||||
WHERE "abuse"."videoId" = "video"."id"
|
||||
`)
|
||||
|
||||
await utils.sequelize.query('DROP INDEX IF EXISTS video_abuse_video_id;')
|
||||
await utils.sequelize.query('DROP INDEX IF EXISTS video_abuse_reporter_account_id;')
|
||||
|
||||
await utils.sequelize.query(`
|
||||
CREATE TABLE IF NOT EXISTS "videoAbuse" (
|
||||
"id" serial,
|
||||
"startAt" integer DEFAULT NULL,
|
||||
"endAt" integer DEFAULT NULL,
|
||||
"deletedVideo" jsonb DEFAULT NULL,
|
||||
"abuseId" integer NOT NULL REFERENCES "abuse" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"videoId" integer REFERENCES "video" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
|
||||
"createdAt" TIMESTAMP WITH time zone NOT NULL,
|
||||
"updatedAt" timestamp WITH time zone NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
`)
|
||||
|
||||
await utils.sequelize.query(`
|
||||
CREATE TABLE IF NOT EXISTS "commentAbuse" (
|
||||
"id" serial,
|
||||
"abuseId" integer NOT NULL REFERENCES "abuse" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"videoCommentId" integer REFERENCES "videoComment" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
|
||||
"createdAt" timestamp WITH time zone NOT NULL,
|
||||
"updatedAt" timestamp WITH time zone NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
`)
|
||||
|
||||
await utils.sequelize.query(`
|
||||
INSERT INTO "videoAbuse" ("startAt", "endAt", "deletedVideo", "abuseId", "videoId", "createdAt", "updatedAt")
|
||||
SELECT "abuse"."startAt", "abuse"."endAt", "abuse"."deletedVideo", "abuse"."id", "abuse"."videoId",
|
||||
"abuse"."createdAt", "abuse"."updatedAt"
|
||||
FROM "abuse"
|
||||
`)
|
||||
|
||||
await utils.queryInterface.removeColumn('abuse', 'startAt')
|
||||
await utils.queryInterface.removeColumn('abuse', 'endAt')
|
||||
await utils.queryInterface.removeColumn('abuse', 'deletedVideo')
|
||||
await utils.queryInterface.removeColumn('abuse', 'videoId')
|
||||
|
||||
await utils.sequelize.query('DROP INDEX IF EXISTS user_notification_video_abuse_id')
|
||||
await utils.queryInterface.renameColumn('userNotification', 'videoAbuseId', 'abuseId')
|
||||
|
||||
await utils.sequelize.query(
|
||||
'ALTER INDEX IF EXISTS "videoAbuse_pkey" RENAME TO "abuse_pkey"'
|
||||
)
|
||||
|
||||
await utils.queryInterface.renameColumn('userNotificationSetting', 'videoAbuseAsModerator', 'abuseAsModerator')
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
54
server/core/initializers/migrations/0525-abuse-messages.ts
Normal file
54
server/core/initializers/migrations/0525-abuse-messages.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
await utils.sequelize.query(`
|
||||
CREATE TABLE IF NOT EXISTS "abuseMessage" (
|
||||
"id" serial,
|
||||
"message" text NOT NULL,
|
||||
"byModerator" boolean NOT NULL,
|
||||
"accountId" integer REFERENCES "account" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
|
||||
"abuseId" integer NOT NULL REFERENCES "abuse" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"createdAt" timestamp WITH time zone NOT NULL,
|
||||
"updatedAt" timestamp WITH time zone NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
`)
|
||||
|
||||
const notificationSettingColumns = [ 'abuseStateChange', 'abuseNewMessage' ]
|
||||
|
||||
for (const column of notificationSettingColumns) {
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('userNotificationSetting', column, data)
|
||||
}
|
||||
|
||||
{
|
||||
const query = 'UPDATE "userNotificationSetting" SET "abuseStateChange" = 3, "abuseNewMessage" = 3'
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
|
||||
for (const column of notificationSettingColumns) {
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: false
|
||||
}
|
||||
await utils.queryInterface.changeColumn('userNotificationSetting', column, data)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
import { WEBSERVER } from '../constants.js'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
{
|
||||
const field = {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.changeColumn('videoPlaylistElement', 'url', field)
|
||||
}
|
||||
|
||||
{
|
||||
await utils.sequelize.query('DROP INDEX IF EXISTS video_playlist_element_video_playlist_id_video_id;')
|
||||
}
|
||||
|
||||
{
|
||||
const selectPlaylistUUID = 'SELECT "uuid" FROM "videoPlaylist" WHERE "id" = "videoPlaylistElement"."videoPlaylistId"'
|
||||
const url = `'${WEBSERVER.URL}' || '/video-playlists/' || (${selectPlaylistUUID}) || '/videos/' || "videoPlaylistElement"."id"`
|
||||
|
||||
const query = `
|
||||
UPDATE "videoPlaylistElement" SET "url" = ${url} WHERE id IN (
|
||||
SELECT "videoPlaylistElement"."id" FROM "videoPlaylistElement"
|
||||
INNER JOIN "videoPlaylist" ON "videoPlaylist".id = "videoPlaylistElement"."videoPlaylistId"
|
||||
INNER JOIN account ON account.id = "videoPlaylist"."ownerAccountId"
|
||||
INNER JOIN actor ON actor.id = account."actorId"
|
||||
WHERE actor."serverId" IS NULL
|
||||
)`
|
||||
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
39
server/core/initializers/migrations/0535-video-live.ts
Normal file
39
server/core/initializers/migrations/0535-video-live.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
{
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "videoLive" (
|
||||
"id" SERIAL ,
|
||||
"streamKey" VARCHAR(255),
|
||||
"videoId" INTEGER NOT NULL REFERENCES "video" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"createdAt" TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
"updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
`
|
||||
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('video', 'isLive', {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: false,
|
||||
allowNull: false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
|
||||
await utils.queryInterface.changeColumn('videoFile', 'infoHash', data)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: false,
|
||||
allowNull: false
|
||||
}
|
||||
|
||||
await utils.queryInterface.addColumn('videoLive', 'saveReplay', data)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const query = `
|
||||
WITH t AS (
|
||||
SELECT actor.id FROM actor
|
||||
LEFT JOIN "videoChannel" ON "videoChannel"."actorId" = actor.id
|
||||
LEFT JOIN account ON account."actorId" = "actor"."id"
|
||||
WHERE "videoChannel".id IS NULL and "account".id IS NULL
|
||||
) DELETE FROM "actorFollow" WHERE "actorId" IN (SELECT t.id FROM t) OR "targetActorId" in (SELECT t.id FROM t)
|
||||
`
|
||||
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
26
server/core/initializers/migrations/0555-actor-follow-url.ts
Normal file
26
server/core/initializers/migrations/0555-actor-follow-url.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.STRING(2000),
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
|
||||
await utils.queryInterface.addColumn('actorFollow', 'url', data)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
51
server/core/initializers/migrations/0560-user-feed-token.ts
Normal file
51
server/core/initializers/migrations/0560-user-feed-token.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
import { buildUUID } from '@peertube/peertube-node-utils'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
const q = utils.queryInterface
|
||||
|
||||
{
|
||||
// Create uuid column for users
|
||||
const userFeedTokenUUID = {
|
||||
type: Sequelize.UUID,
|
||||
defaultValue: Sequelize.UUIDV4,
|
||||
allowNull: true
|
||||
}
|
||||
await q.addColumn('user', 'feedToken', userFeedTokenUUID)
|
||||
}
|
||||
|
||||
// Set UUID to previous users
|
||||
{
|
||||
const query = 'SELECT * FROM "user" WHERE "feedToken" IS NULL'
|
||||
const options = { type: Sequelize.QueryTypes.SELECT as Sequelize.QueryTypes.SELECT }
|
||||
const users = await utils.sequelize.query<any>(query, options)
|
||||
|
||||
for (const user of users) {
|
||||
const queryUpdate = `UPDATE "user" SET "feedToken" = '${buildUUID()}' WHERE id = ${user.id}`
|
||||
await utils.sequelize.query(queryUpdate)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const userFeedTokenUUID = {
|
||||
type: Sequelize.UUID,
|
||||
defaultValue: Sequelize.UUIDV4,
|
||||
allowNull: false
|
||||
}
|
||||
await q.changeColumn('user', 'feedToken', userFeedTokenUUID)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
{
|
||||
const query = `
|
||||
UPDATE "actorFollow" SET url = follower.url || '/follows/' || following.id
|
||||
FROM actor follower, actor following
|
||||
WHERE follower."serverId" IS NULL AND follower.id = "actorFollow"."actorId" AND following.id = "actorFollow"."targetActorId"
|
||||
`
|
||||
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
27
server/core/initializers/migrations/0570-permanent-live.ts
Normal file
27
server/core/initializers/migrations/0570-permanent-live.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: false,
|
||||
allowNull: false
|
||||
}
|
||||
|
||||
await utils.queryInterface.addColumn('videoLive', 'permanentLive', data)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
{
|
||||
const query = 'DELETE FROM "thumbnail" s1 ' +
|
||||
'USING (SELECT MIN(id) as id, "filename", "type" FROM "thumbnail" GROUP BY "filename", "type" HAVING COUNT(*) > 1) s2 ' +
|
||||
'WHERE s1."filename" = s2."filename" AND s1."type" = s2."type" AND s1.id <> s2.id'
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
48
server/core/initializers/migrations/0580-caption-filename.ts
Normal file
48
server/core/initializers/migrations/0580-caption-filename.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: true,
|
||||
defaultValue: null
|
||||
}
|
||||
|
||||
await utils.queryInterface.addColumn('videoCaption', 'filename', data)
|
||||
}
|
||||
|
||||
{
|
||||
const query = `UPDATE "videoCaption" SET "filename" = s.uuid || '-' || s.language || '.vtt' ` +
|
||||
`FROM (` +
|
||||
` SELECT "videoCaption"."id", video.uuid, "videoCaption".language ` +
|
||||
` FROM "videoCaption" INNER JOIN video ON video.id = "videoCaption"."videoId"` +
|
||||
`) AS s ` +
|
||||
`WHERE "videoCaption".id = s.id`
|
||||
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
defaultValue: null
|
||||
}
|
||||
|
||||
await utils.queryInterface.changeColumn('videoCaption', 'filename', data)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
55
server/core/initializers/migrations/0585-video-file-names.ts
Normal file
55
server/core/initializers/migrations/0585-video-file-names.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
for (const column of [ 'filename', 'fileUrl', 'torrentFilename', 'torrentUrl' ]) {
|
||||
const data = {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: true,
|
||||
defaultValue: null
|
||||
}
|
||||
|
||||
await utils.queryInterface.addColumn('videoFile', column, data)
|
||||
}
|
||||
|
||||
// Generate filenames for webtorrent files
|
||||
{
|
||||
const webtorrentQuery = `SELECT "videoFile".id, "video".uuid, "videoFile".resolution, "videoFile".extname ` +
|
||||
`FROM video INNER JOIN "videoFile" ON "videoFile"."videoId" = video.id`
|
||||
|
||||
const query = `UPDATE "videoFile" ` +
|
||||
`SET filename = t.uuid || '-' || t.resolution || t.extname, ` +
|
||||
`"torrentFilename" = t.uuid || '-' || t.resolution || '.torrent' ` +
|
||||
`FROM (${webtorrentQuery}) AS t WHERE t.id = "videoFile"."id"`
|
||||
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
|
||||
// Generate filenames for HLS files
|
||||
{
|
||||
const hlsQuery = `SELECT "videoFile".id, "video".uuid, "videoFile".resolution, "videoFile".extname ` +
|
||||
`FROM video ` +
|
||||
`INNER JOIN "videoStreamingPlaylist" ON "videoStreamingPlaylist"."videoId" = video.id ` +
|
||||
`INNER JOIN "videoFile" ON "videoFile"."videoStreamingPlaylistId" = "videoStreamingPlaylist".id`
|
||||
|
||||
const query = `UPDATE "videoFile" ` +
|
||||
`SET filename = t.uuid || '-' || t.resolution || '-fragmented' || t.extname, ` +
|
||||
`"torrentFilename" = t.uuid || '-' || t.resolution || '-hls.torrent' ` +
|
||||
`FROM (${hlsQuery}) AS t WHERE t.id = "videoFile"."id"`
|
||||
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
44
server/core/initializers/migrations/0590-trackers.ts
Normal file
44
server/core/initializers/migrations/0590-trackers.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
{
|
||||
const query = `CREATE TABLE IF NOT EXISTS "tracker" (
|
||||
"id" serial,
|
||||
"url" varchar(255) NOT NULL,
|
||||
"createdAt" timestamp WITH time zone NOT NULL,
|
||||
"updatedAt" timestamp WITH time zone NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);`
|
||||
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
|
||||
{
|
||||
const query = `CREATE TABLE IF NOT EXISTS "videoTracker" (
|
||||
"videoId" integer REFERENCES "video" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"trackerId" integer REFERENCES "tracker" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"createdAt" timestamp WITH time zone NOT NULL,
|
||||
"updatedAt" timestamp WITH time zone NOT NULL,
|
||||
UNIQUE ("videoId", "trackerId"),
|
||||
PRIMARY KEY ("videoId", "trackerId")
|
||||
);`
|
||||
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
|
||||
await utils.sequelize.query(`CREATE UNIQUE INDEX "tracker_url" ON "tracker" ("url")`)
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
130
server/core/initializers/migrations/0595-remote-url.ts
Normal file
130
server/core/initializers/migrations/0595-remote-url.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
|
||||
// Torrent and file URLs
|
||||
{
|
||||
const fromQueryWebtorrent = `SELECT 'https://' || server.host AS "serverUrl", '/static/webseed/' AS "filePath", "videoFile".id ` +
|
||||
`FROM video ` +
|
||||
`INNER JOIN "videoChannel" ON "videoChannel".id = video."channelId" ` +
|
||||
`INNER JOIN actor ON actor.id = "videoChannel"."actorId" ` +
|
||||
`INNER JOIN server ON server.id = actor."serverId" ` +
|
||||
`INNER JOIN "videoFile" ON "videoFile"."videoId" = video.id ` +
|
||||
`WHERE video.remote IS TRUE`
|
||||
|
||||
const fromQueryHLS = `SELECT 'https://' || server.host AS "serverUrl", ` +
|
||||
`'/static/streaming-playlists/hls/' || video.uuid || '/' AS "filePath", "videoFile".id ` +
|
||||
`FROM video ` +
|
||||
`INNER JOIN "videoChannel" ON "videoChannel".id = video."channelId" ` +
|
||||
`INNER JOIN actor ON actor.id = "videoChannel"."actorId" ` +
|
||||
`INNER JOIN server ON server.id = actor."serverId" ` +
|
||||
`INNER JOIN "videoStreamingPlaylist" ON "videoStreamingPlaylist"."videoId" = video.id ` +
|
||||
`INNER JOIN "videoFile" ON "videoFile"."videoStreamingPlaylistId" = "videoStreamingPlaylist".id ` +
|
||||
`WHERE video.remote IS TRUE`
|
||||
|
||||
for (const fromQuery of [ fromQueryWebtorrent, fromQueryHLS ]) {
|
||||
const query = `UPDATE "videoFile" ` +
|
||||
`SET "torrentUrl" = t."serverUrl" || '/static/torrents/' || "videoFile"."torrentFilename", ` +
|
||||
`"fileUrl" = t."serverUrl" || t."filePath" || "videoFile"."filename" ` +
|
||||
`FROM (${fromQuery}) AS t WHERE t.id = "videoFile"."id" AND "videoFile"."fileUrl" IS NULL`
|
||||
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
}
|
||||
|
||||
// Caption URLs
|
||||
{
|
||||
const fromQuery = `SELECT 'https://' || server.host AS "serverUrl", "video".uuid, "videoCaption".id ` +
|
||||
`FROM video ` +
|
||||
`INNER JOIN "videoChannel" ON "videoChannel".id = video."channelId" ` +
|
||||
`INNER JOIN actor ON actor.id = "videoChannel"."actorId" ` +
|
||||
`INNER JOIN server ON server.id = actor."serverId" ` +
|
||||
`INNER JOIN "videoCaption" ON "videoCaption"."videoId" = video.id ` +
|
||||
`WHERE video.remote IS TRUE`
|
||||
|
||||
const query = `UPDATE "videoCaption" ` +
|
||||
`SET "fileUrl" = t."serverUrl" || '/lazy-static/video-captions/' || t.uuid || '-' || "videoCaption"."language" || '.vtt' ` +
|
||||
`FROM (${fromQuery}) AS t WHERE t.id = "videoCaption"."id" AND "videoCaption"."fileUrl" IS NULL`
|
||||
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
|
||||
// Thumbnail URLs
|
||||
{
|
||||
const fromQuery = `SELECT 'https://' || server.host AS "serverUrl", "video".uuid, "thumbnail".id ` +
|
||||
`FROM video ` +
|
||||
`INNER JOIN "videoChannel" ON "videoChannel".id = video."channelId" ` +
|
||||
`INNER JOIN actor ON actor.id = "videoChannel"."actorId" ` +
|
||||
`INNER JOIN server ON server.id = actor."serverId" ` +
|
||||
`INNER JOIN "thumbnail" ON "thumbnail"."videoId" = video.id ` +
|
||||
`WHERE video.remote IS TRUE`
|
||||
|
||||
// Thumbnails
|
||||
{
|
||||
const query = `UPDATE "thumbnail" ` +
|
||||
`SET "fileUrl" = t."serverUrl" || '/static/thumbnails/' || t.uuid || '.jpg' ` +
|
||||
`FROM (${fromQuery}) AS t WHERE t.id = "thumbnail"."id" AND "thumbnail"."fileUrl" IS NULL AND thumbnail.type = 1`
|
||||
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
|
||||
{
|
||||
// Previews
|
||||
const query = `UPDATE "thumbnail" ` +
|
||||
`SET "fileUrl" = t."serverUrl" || '/lazy-static/previews/' || t.uuid || '.jpg' ` +
|
||||
`FROM (${fromQuery}) AS t WHERE t.id = "thumbnail"."id" AND "thumbnail"."fileUrl" IS NULL AND thumbnail.type = 2`
|
||||
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
}
|
||||
|
||||
// Trackers
|
||||
{
|
||||
const trackerUrls = [
|
||||
`'https://' || server.host || '/tracker/announce'`,
|
||||
`'wss://' || server.host || '/tracker/socket'`
|
||||
]
|
||||
|
||||
for (const trackerUrl of trackerUrls) {
|
||||
{
|
||||
const query = `INSERT INTO "tracker" ("url", "createdAt", "updatedAt") ` +
|
||||
`SELECT ${trackerUrl} AS "url", NOW(), NOW() ` +
|
||||
`FROM video ` +
|
||||
`INNER JOIN "videoChannel" ON "videoChannel".id = video."channelId" ` +
|
||||
`INNER JOIN actor ON actor.id = "videoChannel"."actorId" ` +
|
||||
`INNER JOIN server ON server.id = actor."serverId" ` +
|
||||
`WHERE video.remote IS TRUE ` +
|
||||
`ON CONFLICT DO NOTHING`
|
||||
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
|
||||
{
|
||||
const query = `INSERT INTO "videoTracker" ("videoId", "trackerId", "createdAt", "updatedAt") ` +
|
||||
`SELECT video.id, (SELECT tracker.id FROM tracker WHERE url = ${trackerUrl}) AS "trackerId", NOW(), NOW()` +
|
||||
`FROM video ` +
|
||||
`INNER JOIN "videoChannel" ON "videoChannel".id = video."channelId" ` +
|
||||
`INNER JOIN actor ON actor.id = "videoChannel"."actorId" ` +
|
||||
`INNER JOIN server ON server.id = actor."serverId" ` +
|
||||
`WHERE video.remote IS TRUE`
|
||||
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
|
||||
{
|
||||
const query = 'DELETE FROM "videoFile" f1 ' +
|
||||
'USING (SELECT MIN(id) as id, "torrentFilename" FROM "videoFile" GROUP BY "torrentFilename" HAVING COUNT(*) > 1) f2 ' +
|
||||
'WHERE f1."torrentFilename" = f2."torrentFilename" AND f1.id <> f2.id'
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
|
||||
{
|
||||
const query = 'DELETE FROM "videoFile" f1 ' +
|
||||
'USING (SELECT MIN(id) as id, "filename" FROM "videoFile" GROUP BY "filename" HAVING COUNT(*) > 1) f2 ' +
|
||||
'WHERE f1."filename" = f2."filename" AND f1.id <> f2.id'
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
import { generateRSAKeyPairPromise } from '../../helpers/core-utils.js'
|
||||
import { PRIVATE_RSA_KEY_SIZE } from '../constants.js'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
|
||||
{
|
||||
const query = 'SELECT * FROM "actor" WHERE "serverId" IS NULL AND "publicKey" IS NULL'
|
||||
const options = { type: Sequelize.QueryTypes.SELECT as Sequelize.QueryTypes.SELECT }
|
||||
const actors = await utils.sequelize.query<any>(query, options)
|
||||
|
||||
for (const actor of actors) {
|
||||
const { privateKey, publicKey } = await generateRSAKeyPairPromise(PRIVATE_RSA_KEY_SIZE)
|
||||
|
||||
const queryUpdate = `UPDATE "actor" SET "publicKey" = '${publicKey}', "privateKey" = '${privateKey}' WHERE id = ${actor.id}`
|
||||
await utils.sequelize.query(queryUpdate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
20
server/core/initializers/migrations/0610-views-index copy.ts
Normal file
20
server/core/initializers/migrations/0610-views-index copy.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
|
||||
await utils.sequelize.query('DROP INDEX IF EXISTS video_views;')
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
23
server/core/initializers/migrations/0612-captions-unique.ts
Normal file
23
server/core/initializers/migrations/0612-captions-unique.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
|
||||
await utils.sequelize.query(
|
||||
'DELETE FROM "videoCaption" v1 USING (SELECT MIN(id) as id, "filename" FROM "videoCaption" ' +
|
||||
'GROUP BY "filename" HAVING COUNT(*) > 1) v2 WHERE v1."filename" = v2."filename" AND v1.id <> v2.id'
|
||||
)
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
{
|
||||
const notificationSettingColumns = [ 'newPeerTubeVersion', 'newPluginVersion' ]
|
||||
|
||||
for (const column of notificationSettingColumns) {
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('userNotificationSetting', column, data)
|
||||
}
|
||||
|
||||
{
|
||||
const query = 'UPDATE "userNotificationSetting" SET "newPeerTubeVersion" = 3, "newPluginVersion" = 1'
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
|
||||
for (const column of notificationSettingColumns) {
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: false
|
||||
}
|
||||
await utils.queryInterface.changeColumn('userNotificationSetting', column, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('application', 'latestPeerTubeVersion', data)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
|
||||
{
|
||||
await utils.sequelize.query(`
|
||||
ALTER TABLE "userNotification"
|
||||
ADD COLUMN "applicationId" INTEGER REFERENCES "application" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
|
||||
ADD COLUMN "pluginId" INTEGER REFERENCES "plugin" ("id") ON DELETE SET NULL ON UPDATE CASCADE
|
||||
`)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
50
server/core/initializers/migrations/0630-banner.ts
Normal file
50
server/core/initializers/migrations/0630-banner.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
|
||||
{
|
||||
await utils.sequelize.query(`ALTER TABLE "avatar" RENAME to "actorImage"`)
|
||||
}
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('actorImage', 'type', data)
|
||||
}
|
||||
|
||||
{
|
||||
await utils.sequelize.query(`UPDATE "actorImage" SET "type" = 1`)
|
||||
}
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: false
|
||||
}
|
||||
await utils.queryInterface.changeColumn('actorImage', 'type', data)
|
||||
}
|
||||
|
||||
{
|
||||
await utils.sequelize.query(
|
||||
`ALTER TABLE "actor" ADD COLUMN "bannerId" INTEGER REFERENCES "actorImage" ("id") ON DELETE SET NULL ON UPDATE CASCADE`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
35
server/core/initializers/migrations/0635-actor-image-size.ts
Normal file
35
server/core/initializers/migrations/0635-actor-image-size.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('actorImage', 'height', data)
|
||||
}
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('actorImage', 'width', data)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
39
server/core/initializers/migrations/0640-unique-keys.ts
Normal file
39
server/core/initializers/migrations/0640-unique-keys.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
{
|
||||
await utils.sequelize.query(
|
||||
'DELETE FROM "actor" v1 USING (SELECT MIN(id) as id, "preferredUsername", "serverId" FROM "actor" ' +
|
||||
'GROUP BY "preferredUsername", "serverId" HAVING COUNT(*) > 1 AND "serverId" IS NOT NULL) v2 ' +
|
||||
'WHERE v1."preferredUsername" = v2."preferredUsername" AND v1."serverId" = v2."serverId" AND v1.id <> v2.id'
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
await utils.sequelize.query(
|
||||
'DELETE FROM "actor" v1 USING (SELECT MIN(id) as id, "url" FROM "actor" GROUP BY "url" HAVING COUNT(*) > 1) v2 ' +
|
||||
'WHERE v1."url" = v2."url" AND v1.id <> v2.id'
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
await utils.sequelize.query(
|
||||
'DELETE FROM "tag" v1 USING (SELECT MIN(id) as id, "name" FROM "tag" GROUP BY "name" HAVING COUNT(*) > 1) v2 ' +
|
||||
'WHERE v1."name" = v2."name" AND v1.id <> v2.id'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.DATE,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('actor', 'remoteCreatedAt', data)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
{
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "actorCustomPage" (
|
||||
"id" serial,
|
||||
"content" TEXT,
|
||||
"type" varchar(255) NOT NULL,
|
||||
"actorId" integer NOT NULL REFERENCES "actor" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"createdAt" timestamp WITH time zone NOT NULL,
|
||||
"updatedAt" timestamp WITH time zone NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
`
|
||||
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
{
|
||||
for (const column of [ 'playlistUrl', 'segmentsSha256Url' ]) {
|
||||
const data = {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: true,
|
||||
defaultValue: null
|
||||
}
|
||||
|
||||
await utils.queryInterface.changeColumn('videoStreamingPlaylist', column, data)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
await utils.sequelize.query(
|
||||
`UPDATE "videoStreamingPlaylist" SET "playlistUrl" = NULL, "segmentsSha256Url" = NULL ` +
|
||||
`WHERE "videoId" IN (SELECT id FROM video WHERE remote IS FALSE)`
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
for (const column of [ 'playlistFilename', 'segmentsSha256Filename' ]) {
|
||||
const data = {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: true,
|
||||
defaultValue: null
|
||||
}
|
||||
|
||||
await utils.queryInterface.addColumn('videoStreamingPlaylist', column, data)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
await utils.sequelize.query(
|
||||
`UPDATE "videoStreamingPlaylist" SET "playlistFilename" = 'master.m3u8', "segmentsSha256Filename" = 'segments-sha256.json'`
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
for (const column of [ 'playlistFilename', 'segmentsSha256Filename' ]) {
|
||||
const data = {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: false,
|
||||
defaultValue: null
|
||||
}
|
||||
|
||||
await utils.queryInterface.changeColumn('videoStreamingPlaylist', column, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
56
server/core/initializers/migrations/0660-object-storage.ts
Normal file
56
server/core/initializers/migrations/0660-object-storage.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
import { FileStorage } from '@peertube/peertube-models'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
{
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "videoJobInfo" (
|
||||
"id" serial,
|
||||
"pendingMove" INTEGER NOT NULL,
|
||||
"pendingTranscode" INTEGER NOT NULL,
|
||||
"videoId" serial UNIQUE NOT NULL REFERENCES "video" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"createdAt" timestamp WITH time zone NOT NULL,
|
||||
"updatedAt" timestamp WITH time zone NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
`
|
||||
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoFile', 'storage', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: FileStorage.FILE_SYSTEM
|
||||
})
|
||||
await utils.queryInterface.changeColumn('videoFile', 'storage', { type: Sequelize.INTEGER, allowNull: false, defaultValue: null })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoStreamingPlaylist', 'storage', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: FileStorage.FILE_SYSTEM
|
||||
})
|
||||
await utils.queryInterface.changeColumn('videoStreamingPlaylist', 'storage', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: null
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false
|
||||
}
|
||||
|
||||
await utils.queryInterface.addColumn('user', 'noAccountSetupWarningModal', data)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
for (const column of [ 'pendingMove', 'pendingTranscode' ]) {
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 0
|
||||
}
|
||||
|
||||
await utils.queryInterface.changeColumn('videoJobInfo', column, data)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
21
server/core/initializers/migrations/0675-p2p-enabled.ts
Normal file
21
server/core/initializers/migrations/0675-p2p-enabled.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
await utils.queryInterface.renameColumn('user', 'webTorrentEnabled', 'p2pEnabled')
|
||||
|
||||
await utils.sequelize.query('ALTER TABLE "user" ALTER COLUMN "p2pEnabled" DROP DEFAULT')
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
await utils.sequelize.query('ALTER TABLE "videoFile" ALTER COLUMN "storage" SET DEFAULT 0')
|
||||
await utils.sequelize.query('ALTER TABLE "videoStreamingPlaylist" ALTER COLUMN "storage" SET DEFAULT 0')
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
{
|
||||
await utils.queryInterface.addColumn('actorImage', 'actorId', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: true,
|
||||
references: {
|
||||
model: 'actor',
|
||||
key: 'id'
|
||||
},
|
||||
onDelete: 'CASCADE'
|
||||
}, { transaction: utils.transaction })
|
||||
|
||||
// Avatars
|
||||
{
|
||||
const query = `UPDATE "actorImage" SET "actorId" = (SELECT "id" FROM "actor" WHERE "actor"."avatarId" = "actorImage"."id") ` +
|
||||
`WHERE "type" = 1`
|
||||
await utils.sequelize.query(query, { type: Sequelize.QueryTypes.UPDATE, transaction: utils.transaction })
|
||||
}
|
||||
|
||||
// Banners
|
||||
{
|
||||
const query = `UPDATE "actorImage" SET "actorId" = (SELECT "id" FROM "actor" WHERE "actor"."bannerId" = "actorImage"."id") ` +
|
||||
`WHERE "type" = 2`
|
||||
await utils.sequelize.query(query, { type: Sequelize.QueryTypes.UPDATE, transaction: utils.transaction })
|
||||
}
|
||||
|
||||
// Remove orphans
|
||||
{
|
||||
const query = `DELETE FROM "actorImage" WHERE id NOT IN (` +
|
||||
`SELECT "bannerId" FROM actor WHERE "bannerId" IS NOT NULL ` +
|
||||
`UNION select "avatarId" FROM actor WHERE "avatarId" IS NOT NULL` +
|
||||
`);`
|
||||
|
||||
await utils.sequelize.query(query, { type: Sequelize.QueryTypes.DELETE, transaction: utils.transaction })
|
||||
}
|
||||
|
||||
await utils.queryInterface.changeColumn('actorImage', 'actorId', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false
|
||||
}, { transaction: utils.transaction })
|
||||
|
||||
await utils.queryInterface.removeColumn('actor', 'avatarId', { transaction: utils.transaction })
|
||||
await utils.queryInterface.removeColumn('actor', 'bannerId', { transaction: utils.transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down () {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { LiveVideoLatencyMode } from '@peertube/peertube-models'
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
await utils.queryInterface.addColumn('videoLive', 'latencyMode', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}, { transaction: utils.transaction })
|
||||
|
||||
{
|
||||
const query = `UPDATE "videoLive" SET "latencyMode" = ${LiveVideoLatencyMode.DEFAULT}`
|
||||
await utils.sequelize.query(query, { type: Sequelize.QueryTypes.UPDATE, transaction: utils.transaction })
|
||||
}
|
||||
|
||||
await utils.queryInterface.changeColumn('videoLive', 'latencyMode', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: false
|
||||
}, { transaction: utils.transaction })
|
||||
}
|
||||
|
||||
function down () {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
const query = 'DELETE FROM "accountVideoRate" ' +
|
||||
'WHERE "accountVideoRate".id IN (' +
|
||||
'SELECT "accountVideoRate".id FROM "accountVideoRate" ' +
|
||||
'INNER JOIN account ON account.id = "accountVideoRate"."accountId" ' +
|
||||
'INNER JOIN actor ON actor.id = account."actorId" ' +
|
||||
'INNER JOIN video ON video.id = "accountVideoRate"."videoId" ' +
|
||||
'WHERE actor."serverId" IS NOT NULL AND video.remote IS TRUE' +
|
||||
')'
|
||||
|
||||
await utils.sequelize.query(query, { type: Sequelize.QueryTypes.BULKDELETE, transaction: utils.transaction })
|
||||
}
|
||||
|
||||
function down () {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('userNotificationSetting', 'myVideoStudioEditionFinished', data, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const query = 'UPDATE "userNotificationSetting" SET "myVideoStudioEditionFinished" = 1'
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: false
|
||||
}
|
||||
await utils.queryInterface.changeColumn('userNotificationSetting', 'myVideoStudioEditionFinished', data, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down () {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "localVideoViewer" (
|
||||
"id" serial,
|
||||
"startDate" timestamp with time zone NOT NULL,
|
||||
"endDate" timestamp with time zone NOT NULL,
|
||||
"watchTime" integer NOT NULL,
|
||||
"country" varchar(255),
|
||||
"uuid" uuid NOT NULL,
|
||||
"url" varchar(255) NOT NULL,
|
||||
"videoId" integer NOT NULL REFERENCES "video" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"createdAt" timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
`
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "localVideoViewerWatchSection" (
|
||||
"id" serial,
|
||||
"watchStart" integer NOT NULL,
|
||||
"watchEnd" integer NOT NULL,
|
||||
"localVideoViewerId" integer NOT NULL REFERENCES "localVideoViewer" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"createdAt" timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
`
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function down () {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
34
server/core/initializers/migrations/0710-live-sessions.ts
Normal file
34
server/core/initializers/migrations/0710-live-sessions.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "videoLiveSession" (
|
||||
"id" serial,
|
||||
"startDate" timestamp with time zone NOT NULL,
|
||||
"endDate" timestamp with time zone,
|
||||
"error" integer,
|
||||
"replayVideoId" integer REFERENCES "video" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
|
||||
"liveVideoId" integer REFERENCES "video" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
|
||||
"createdAt" timestamp with time zone NOT NULL,
|
||||
"updatedAt" timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
`
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
function down () {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
34
server/core/initializers/migrations/0715-video-source.ts
Normal file
34
server/core/initializers/migrations/0715-video-source.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
{
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "videoSource" (
|
||||
"id" SERIAL ,
|
||||
"createdAt" TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
"updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
"filename" VARCHAR(255) DEFAULT NULL,
|
||||
"videoId" INTEGER
|
||||
REFERENCES "video" ("id")
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE CASCADE,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
`
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('videoLiveSession', 'endingProcessed', data, { transaction })
|
||||
await utils.queryInterface.addColumn('videoLiveSession', 'saveReplay', data, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const query = `UPDATE "videoLiveSession" SET "saveReplay" = (
|
||||
SELECT "videoLive"."saveReplay" FROM "videoLive" WHERE "videoLive"."videoId" = "videoLiveSession"."liveVideoId"
|
||||
) WHERE "videoLiveSession"."liveVideoId" IS NOT NULL`
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const query = `UPDATE "videoLiveSession" SET "saveReplay" = FALSE WHERE "saveReplay" IS NULL`
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const query = `UPDATE "videoLiveSession" SET "endingProcessed" = TRUE`
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: null,
|
||||
allowNull: false
|
||||
}
|
||||
await utils.queryInterface.changeColumn('videoLiveSession', 'endingProcessed', data, { transaction })
|
||||
await utils.queryInterface.changeColumn('videoLiveSession', 'saveReplay', data, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
66
server/core/initializers/migrations/0725-node-version.ts
Normal file
66
server/core/initializers/migrations/0725-node-version.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('application', 'nodeVersion', data, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('application', 'nodeABIVersion', data, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const query = `UPDATE "application" SET "nodeVersion" = '${process.version}'`
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const nodeABIVersion = parseInt(process.versions.modules)
|
||||
const query = `UPDATE "application" SET "nodeABIVersion" = ${nodeABIVersion}`
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: false
|
||||
}
|
||||
await utils.queryInterface.changeColumn('application', 'nodeVersion', data, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: false
|
||||
}
|
||||
await utils.queryInterface.changeColumn('application', 'nodeABIVersion', data, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "videoChannelSync" (
|
||||
"id" SERIAL,
|
||||
"externalChannelUrl" VARCHAR(2000) NOT NULL DEFAULT NULL,
|
||||
"videoChannelId" INTEGER NOT NULL REFERENCES "videoChannel" ("id")
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE CASCADE,
|
||||
"state" INTEGER NOT NULL DEFAULT 1,
|
||||
"createdAt" TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
"updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
"lastSyncAt" TIMESTAMP WITH TIME ZONE,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
`
|
||||
await utils.sequelize.query(query, { transaction: utils.transaction })
|
||||
}
|
||||
|
||||
async function down (utils: {
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
transaction: Sequelize.Transaction
|
||||
}) {
|
||||
await utils.queryInterface.dropTable('videoChannelSync', { transaction: utils.transaction })
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
await utils.queryInterface.addColumn('videoImport', 'videoChannelSyncId', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: true,
|
||||
references: {
|
||||
model: 'videoChannelSync',
|
||||
key: 'id'
|
||||
},
|
||||
onUpdate: 'CASCADE',
|
||||
onDelete: 'SET NULL'
|
||||
}, { transaction: utils.transaction })
|
||||
}
|
||||
|
||||
async function down (utils: {
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
transaction: Sequelize.Transaction
|
||||
}) {
|
||||
await utils.queryInterface.dropTable('videoChannelSync', { transaction: utils.transaction })
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
33
server/core/initializers/migrations/0740-fix-old-enums.ts
Normal file
33
server/core/initializers/migrations/0740-fix-old-enums.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
try {
|
||||
await utils.sequelize.query('drop type "enum_actorFollow_state"')
|
||||
await utils.sequelize.query('alter type "enum_AccountFollows_state" rename to "enum_actorFollow_state";')
|
||||
} catch {
|
||||
// empty
|
||||
}
|
||||
|
||||
try {
|
||||
await utils.sequelize.query('drop type "enum_accountVideoRate_type"')
|
||||
await utils.sequelize.query('alter type "enum_AccountVideoRates_type" rename to "enum_accountVideoRate_type";')
|
||||
} catch {
|
||||
// empty
|
||||
}
|
||||
}
|
||||
|
||||
async function down (utils: {
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
transaction: Sequelize.Transaction
|
||||
}) {
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
29
server/core/initializers/migrations/0745-user-otp.ts
Normal file
29
server/core/initializers/migrations/0745-user-otp.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
const data = {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('user', 'otpSecret', data, { transaction })
|
||||
|
||||
}
|
||||
|
||||
async function down (utils: {
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
transaction: Sequelize.Transaction
|
||||
}) {
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
{
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "userRegistration" (
|
||||
"id" serial,
|
||||
"state" integer NOT NULL,
|
||||
"registrationReason" text NOT NULL,
|
||||
"moderationResponse" text,
|
||||
"password" varchar(255),
|
||||
"username" varchar(255) NOT NULL,
|
||||
"email" varchar(400) NOT NULL,
|
||||
"emailVerified" boolean,
|
||||
"accountDisplayName" varchar(255),
|
||||
"channelHandle" varchar(255),
|
||||
"channelDisplayName" varchar(255),
|
||||
"userId" integer REFERENCES "user" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
|
||||
"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('userNotification', 'userRegistrationId', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: true,
|
||||
references: {
|
||||
model: 'userRegistration',
|
||||
key: 'id'
|
||||
},
|
||||
onUpdate: 'CASCADE',
|
||||
onDelete: 'SET NULL'
|
||||
}, { transaction: utils.transaction })
|
||||
}
|
||||
}
|
||||
|
||||
async function down (utils: {
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
transaction: Sequelize.Transaction
|
||||
}) {
|
||||
await utils.queryInterface.dropTable('videoChannelSync', { transaction: utils.transaction })
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
const query = 'DELETE FROM "localVideoViewer" t1 ' +
|
||||
'USING (SELECT MIN(id) as id, "url" FROM "localVideoViewer" GROUP BY "url" HAVING COUNT(*) > 1) t2 ' +
|
||||
'WHERE t1."url" = t2."url" AND t1.id <> t2.id'
|
||||
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
async function down (utils: {
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
transaction: Sequelize.Transaction
|
||||
}) {
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
{
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
{
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "runnerRegistrationToken"(
|
||||
"id" serial,
|
||||
"registrationToken" varchar(255) 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 })
|
||||
}
|
||||
|
||||
{
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "runner"(
|
||||
"id" serial,
|
||||
"runnerToken" varchar(255) NOT NULL,
|
||||
"name" varchar(255) NOT NULL,
|
||||
"description" varchar(1000),
|
||||
"lastContact" timestamp with time zone NOT NULL,
|
||||
"ip" varchar(255) NOT NULL,
|
||||
"runnerRegistrationTokenId" integer REFERENCES "runnerRegistrationToken"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"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 })
|
||||
}
|
||||
|
||||
{
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "runnerJob"(
|
||||
"id" serial,
|
||||
"uuid" uuid NOT NULL,
|
||||
"type" varchar(255) NOT NULL,
|
||||
"payload" jsonb NOT NULL,
|
||||
"privatePayload" jsonb NOT NULL,
|
||||
"state" integer NOT NULL,
|
||||
"failures" integer NOT NULL DEFAULT 0,
|
||||
"error" varchar(5000),
|
||||
"priority" integer NOT NULL,
|
||||
"processingJobToken" varchar(255),
|
||||
"progress" integer,
|
||||
"startedAt" timestamp with time zone,
|
||||
"finishedAt" timestamp with time zone,
|
||||
"dependsOnRunnerJobId" integer REFERENCES "runnerJob"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"runnerId" integer REFERENCES "runner"("id") ON DELETE SET NULL ON UPDATE CASCADE,
|
||||
"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 })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
await utils.sequelize.query('drop index if exists "actor_preferred_username"', { transaction })
|
||||
await utils.sequelize.query('drop index if exists "actor_preferred_username_server_id"', { transaction })
|
||||
|
||||
await utils.sequelize.query(
|
||||
'DELETE FROM "actor" v1 USING (' +
|
||||
'SELECT MIN(id) as id, lower("preferredUsername") AS "lowerPreferredUsername", "serverId" ' +
|
||||
'FROM "actor" ' +
|
||||
'GROUP BY "lowerPreferredUsername", "serverId" HAVING COUNT(*) > 1 AND "serverId" IS NOT NULL' +
|
||||
') v2 ' +
|
||||
'WHERE lower(v1."preferredUsername") = v2."lowerPreferredUsername" AND v1."serverId" = v2."serverId" AND v1.id <> v2.id',
|
||||
{ transaction }
|
||||
)
|
||||
|
||||
await utils.sequelize.query(
|
||||
'DELETE FROM "actor" v1 USING (' +
|
||||
'SELECT MIN(id) as id, lower("preferredUsername") AS "lowerPreferredUsername", "serverId" ' +
|
||||
'FROM "actor" ' +
|
||||
'GROUP BY "lowerPreferredUsername", "serverId" HAVING COUNT(*) > 1 AND "serverId" IS NULL' +
|
||||
') v2 ' +
|
||||
'WHERE lower(v1."preferredUsername") = v2."lowerPreferredUsername" AND v1."serverId" IS NULL AND v1.id <> v2.id',
|
||||
{ transaction }
|
||||
)
|
||||
}
|
||||
|
||||
async function down (utils: {
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
transaction: Sequelize.Transaction
|
||||
}) {
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
|
||||
const data = {
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false
|
||||
}
|
||||
|
||||
await utils.queryInterface.addColumn('user', 'emailPublic', data)
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
await utils.sequelize.query('DELETE FROM "userNotification" WHERE type = 20 AND "userRegistrationId" IS NULL', { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.sequelize.query(
|
||||
'ALTER TABLE "userNotification" DROP CONSTRAINT "userNotification_userRegistrationId_fkey", ' +
|
||||
'ADD CONSTRAINT "userNotification_userRegistrationId_fkey" ' +
|
||||
'FOREIGN KEY ("userRegistrationId") REFERENCES "userRegistration" ("id") ON DELETE CASCADE ON UPDATE CASCADE',
|
||||
{ transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
{
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "videoPassword" (
|
||||
"id" SERIAL,
|
||||
"password" VARCHAR(255) NOT NULL,
|
||||
"videoId" INTEGER NOT NULL REFERENCES "video" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"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 })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
47
server/core/initializers/migrations/0790-thumbnail-disk.ts
Normal file
47
server/core/initializers/migrations/0790-thumbnail-disk.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: true,
|
||||
defaultValue: true
|
||||
}
|
||||
|
||||
await utils.queryInterface.addColumn('thumbnail', 'onDisk', data, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
// Remote previews are not on the disk
|
||||
await utils.sequelize.query(
|
||||
'UPDATE "thumbnail" SET "onDisk" = FALSE ' +
|
||||
'WHERE "type" = 2 AND "videoId" NOT IN (SELECT "id" FROM "video" WHERE "remote" IS FALSE)',
|
||||
{ transaction }
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: null
|
||||
}
|
||||
|
||||
await utils.queryInterface.changeColumn('thumbnail', 'onDisk', data, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
const query = 'DELETE FROM "runner" r1 ' +
|
||||
'USING (SELECT MIN(id) as id, "name" FROM "runner" GROUP BY "name" HAVING COUNT(*) > 1) r2 ' +
|
||||
'WHERE r1."name" = r2."name" AND r1.id <> r2.id'
|
||||
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
const query = 'DELETE FROM "videoSource" WHERE "videoId" IS NULL'
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const query = 'ALTER TABLE "videoSource" ALTER COLUMN "videoId" SET NOT NULL'
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true,
|
||||
defaultValue: null
|
||||
}
|
||||
|
||||
await utils.queryInterface.addColumn('video', 'inputFileUpdatedAt', data, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: true
|
||||
}
|
||||
|
||||
await utils.queryInterface.addColumn('localVideoViewer', 'subdivisionName', data, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
33
server/core/initializers/migrations/0810-user-export.ts
Normal file
33
server/core/initializers/migrations/0810-user-export.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "userExport" (
|
||||
"id" SERIAL,
|
||||
"filename" VARCHAR(255),
|
||||
"withVideoFiles" BOOLEAN NOT NULL,
|
||||
"state" INTEGER NOT NULL,
|
||||
"error" TEXT,
|
||||
"size" INTEGER,
|
||||
"storage" INTEGER NOT NULL,
|
||||
"userId" INTEGER NOT NULL REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"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 })
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
31
server/core/initializers/migrations/0815-user-import.ts
Normal file
31
server/core/initializers/migrations/0815-user-import.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "userImport" (
|
||||
"id" SERIAL,
|
||||
"filename" VARCHAR(255),
|
||||
"state" INTEGER NOT NULL,
|
||||
"error" TEXT,
|
||||
"resultSummary" JSONB,
|
||||
"userId" INTEGER NOT NULL REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"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 })
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.DATE,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('userRegistration', 'processedAt', data)
|
||||
}
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.DATE,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('abuse', 'processedAt', data)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
43
server/core/initializers/migrations/0825-video-ratio.ts
Normal file
43
server/core/initializers/migrations/0825-video-ratio.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('videoFile', 'width', data)
|
||||
}
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('videoFile', 'height', data)
|
||||
}
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.FLOAT,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('video', 'aspectRatio', data)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoSource', 'keptOriginalFilename', {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoSource', 'storage', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoSource', 'resolution', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoSource', 'width', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoSource', 'height', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoSource', 'fps', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoSource', 'size', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoSource', 'metadata', {
|
||||
type: Sequelize.JSONB,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoSource', 'fileUrl', {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.renameColumn('videoSource', 'filename', 'inputFilename', { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('userExport', 'fileUrl', {
|
||||
type: Sequelize.STRING,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down, up
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
await utils.queryInterface.changeColumn('videoSource', 'size', {
|
||||
type: Sequelize.BIGINT,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down, up
|
||||
}
|
||||
24
server/core/initializers/migrations/0840-user-export-size.ts
Normal file
24
server/core/initializers/migrations/0840-user-export-size.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
await utils.queryInterface.changeColumn('userExport', 'size', {
|
||||
type: Sequelize.BIGINT,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down, up
|
||||
}
|
||||
122
server/core/initializers/migrations/0845-auto-tags.ts
Normal file
122
server/core/initializers/migrations/0845-auto-tags.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
const query = `CREATE TABLE IF NOT EXISTS "automaticTag" ("id" SERIAL , "name" VARCHAR(255) NOT NULL, PRIMARY KEY ("id"));`
|
||||
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "videoAutomaticTag"(
|
||||
"videoId" integer REFERENCES "video"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"automaticTagId" integer NOT NULL REFERENCES "automaticTag"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"accountId" integer REFERENCES "account"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"createdAt" timestamp with time zone NOT NULL,
|
||||
"updatedAt" timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ("videoId", "automaticTagId", "accountId")
|
||||
);`
|
||||
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "commentAutomaticTag"(
|
||||
"commentId" integer REFERENCES "videoComment"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"automaticTagId" integer NOT NULL REFERENCES "automaticTag"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"accountId" integer REFERENCES "account"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"createdAt" timestamp with time zone NOT NULL,
|
||||
"updatedAt" timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ("commentId", "automaticTagId", "accountId")
|
||||
);`
|
||||
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "watchedWordsList"(
|
||||
"id" serial,
|
||||
"listName" varchar(255) NOT NULL,
|
||||
"words" varchar(255)[] NOT NULL,
|
||||
"accountId" integer NOT NULL REFERENCES "account"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"createdAt" timestamp with time zone NOT NULL,
|
||||
"updatedAt" timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);`
|
||||
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "accountAutomaticTagPolicy"(
|
||||
"id" serial,
|
||||
"policy" integer,
|
||||
"accountId" integer NOT NULL REFERENCES "account"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"automaticTagId" integer NOT NULL REFERENCES "automaticTag"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"createdAt" timestamp with time zone NOT NULL,
|
||||
"updatedAt" timestamp with time zone NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);`
|
||||
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('video', 'commentsPolicy', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: 1, // ENABLED
|
||||
allowNull: false
|
||||
}, { transaction })
|
||||
|
||||
const query = `UPDATE "video" SET "commentsPolicy" = 2 WHERE "commentsEnabled" IS FALSE` // Disabled
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
|
||||
await utils.queryInterface.changeColumn('video', 'commentsPolicy', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: false
|
||||
}, { transaction })
|
||||
|
||||
await utils.queryInterface.removeColumn('video', 'commentsEnabled', { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoComment', 'heldForReview', {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: false,
|
||||
allowNull: false
|
||||
}, { transaction })
|
||||
|
||||
await utils.queryInterface.changeColumn('videoComment', 'heldForReview', {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: null,
|
||||
allowNull: false
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoComment', 'replyApproval', {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down, up
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
await utils.queryInterface.changeColumn('videoStreamingPlaylist', 'segmentsSha256Filename', {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down, up
|
||||
}
|
||||
67
server/core/initializers/migrations/0855-transcription.ts
Normal file
67
server/core/initializers/migrations/0855-transcription.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
// Notification
|
||||
{
|
||||
await utils.queryInterface.addColumn('userNotification', 'videoCaptionId', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: true,
|
||||
references: {
|
||||
model: 'videoCaption',
|
||||
key: 'id'
|
||||
},
|
||||
onUpdate: 'CASCADE',
|
||||
onDelete: 'CASCADE'
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
// Notification settings
|
||||
{
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('userNotificationSetting', 'myVideoTranscriptionGenerated', data, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const query = 'UPDATE "userNotificationSetting" SET "myVideoTranscriptionGenerated" = 1'
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: false
|
||||
}
|
||||
await utils.queryInterface.changeColumn('userNotificationSetting', 'myVideoTranscriptionGenerated', data, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
// Video job info
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoJobInfo', 'pendingTranscription', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 0
|
||||
}, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down, up
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoCaption', 'automaticallyGenerated', {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: false,
|
||||
allowNull: false
|
||||
}, { transaction })
|
||||
|
||||
await utils.queryInterface.changeColumn('videoCaption', 'automaticallyGenerated', {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: null,
|
||||
allowNull: false
|
||||
}, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down, up
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
await utils.sequelize.query('DROP INDEX IF EXISTS "video_file_video_id"')
|
||||
await utils.sequelize.query('DROP INDEX IF EXISTS "video_file_video_streaming_playlist_id"')
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoFile', 'formatFlags', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: 2, // fragmented
|
||||
allowNull: false
|
||||
}, { transaction })
|
||||
|
||||
// Web videos will be updated in the migration script because the query can be slow
|
||||
|
||||
await utils.queryInterface.changeColumn('videoFile', 'formatFlags', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: false
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoFile', 'streams', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: 3, // audio + video
|
||||
allowNull: false
|
||||
}, { transaction })
|
||||
|
||||
// Case where there is only an audio stream
|
||||
const query = 'UPDATE "videoFile" SET "streams" = 2 WHERE "resolution" = 0'
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
|
||||
await utils.queryInterface.changeColumn('videoFile', 'streams', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: false
|
||||
}, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down, up
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import { logger } from '@server/helpers/logger.js'
|
||||
import { VideoFileModel } from '@server/models/video/video-file.js'
|
||||
import { remove } from 'fs-extra'
|
||||
import { join } from 'path'
|
||||
import * as Sequelize from 'sequelize'
|
||||
import { QueryTypes } from 'sequelize'
|
||||
import { CONFIG } from '../config.js'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
const query = 'SELECT "videoFileId" FROM "videoRedundancy" WHERE "strategy" IS NOT NULL AND "videoFileId" IS NOT NULL'
|
||||
|
||||
const rows = await utils.sequelize.query<{ videoFileId: number }>(query, {
|
||||
transaction,
|
||||
type: QueryTypes.SELECT as QueryTypes.SELECT
|
||||
})
|
||||
|
||||
for (const { videoFileId } of rows) {
|
||||
try {
|
||||
const videoFile = await VideoFileModel.loadWithVideo(videoFileId, transaction)
|
||||
const filePath = join(CONFIG.STORAGE.REDUNDANCY_DIR, videoFile.filename)
|
||||
|
||||
await remove(filePath)
|
||||
} catch (err) {
|
||||
logger.error(`Cannot delete redundancy file (videoFileId: ${videoFileId}).`, { err })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const query = 'DELETE FROM "videoRedundancy" WHERE "videoFileId" IS NOT NULL'
|
||||
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.sequelize.query('DROP INDEX IF EXISTS video_redundancy_video_file_id', { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.removeColumn('videoRedundancy', 'videoFileId', { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: false
|
||||
}
|
||||
|
||||
await utils.queryInterface.changeColumn('videoRedundancy', 'videoStreamingPlaylistId', data, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down, up
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { FileStorage } from '@peertube/peertube-models'
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoCaption', 'storage', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
defaultValue: FileStorage.FILE_SYSTEM
|
||||
}, { transaction })
|
||||
|
||||
await utils.queryInterface.changeColumn('videoCaption', 'storage', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: null
|
||||
}, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down, up
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('video', 'comments', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: 0,
|
||||
allowNull: false
|
||||
}, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down,
|
||||
up
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('localVideoViewer', 'client', {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('localVideoViewer', 'device', {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('localVideoViewer', 'operatingSystem', {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down,
|
||||
up
|
||||
}
|
||||
34
server/core/initializers/migrations/0890-hls-caption.ts
Normal file
34
server/core/initializers/migrations/0890-hls-caption.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoCaption', 'm3u8Filename', {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoCaption', 'm3u8Url', {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down,
|
||||
up
|
||||
}
|
||||
58
server/core/initializers/migrations/0895-nsfw-flags.ts
Normal file
58
server/core/initializers/migrations/0895-nsfw-flags.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('video', 'nsfwSummary', {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
|
||||
await utils.queryInterface.addColumn('video', 'nsfwFlags', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: 0,
|
||||
allowNull: false
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('user', 'nsfwFlagsDisplayed', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: 0,
|
||||
allowNull: false
|
||||
}, { transaction })
|
||||
|
||||
await utils.queryInterface.addColumn('user', 'nsfwFlagsHidden', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: 0,
|
||||
allowNull: false
|
||||
}, { transaction })
|
||||
|
||||
await utils.queryInterface.addColumn('user', 'nsfwFlagsWarned', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: 0,
|
||||
allowNull: false
|
||||
}, { transaction })
|
||||
|
||||
await utils.queryInterface.addColumn('user', 'nsfwFlagsBlurred', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: 0,
|
||||
allowNull: false
|
||||
}, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down,
|
||||
up
|
||||
}
|
||||
31
server/core/initializers/migrations/0900-uploads.ts
Normal file
31
server/core/initializers/migrations/0900-uploads.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const query = `CREATE TABLE IF NOT EXISTS "uploadImage"(
|
||||
"id" serial,
|
||||
"filename" varchar(255) NOT NULL,
|
||||
"height" integer DEFAULT NULL,
|
||||
"width" integer DEFAULT NULL,
|
||||
"fileUrl" varchar(255),
|
||||
"type" integer NOT NULL,
|
||||
"actorId" integer NOT NULL REFERENCES "actor"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"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 })
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoPlaylist', 'videoChannelPosition', {
|
||||
type: Sequelize.INTEGER,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.sequelize.query(
|
||||
`UPDATE "videoPlaylist" SET "videoChannelPosition" = tmp.position FROM (` +
|
||||
`SELECT tmp.*, ROW_NUMBER () ` +
|
||||
`OVER (PARTITION BY "videoChannelId" ORDER BY "updatedAt" DESC) AS "position" from "videoPlaylist" "tmp" ` +
|
||||
`WHERE "tmp"."videoChannelPosition" IS NULL AND "tmp"."videoChannelId" IS NOT NULL` +
|
||||
`) tmp ` +
|
||||
`WHERE "videoPlaylist"."id" = tmp.id`,
|
||||
{ transaction }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
26
server/core/initializers/migrations/0910-user-language.ts
Normal file
26
server/core/initializers/migrations/0910-user-language.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('user', 'language', {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down,
|
||||
up
|
||||
}
|
||||
26
server/core/initializers/migrations/0915-runner-version.ts
Normal file
26
server/core/initializers/migrations/0915-runner-version.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('runner', 'version', {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down,
|
||||
up
|
||||
}
|
||||
46
server/core/initializers/migrations/0920-token-sessions.ts
Normal file
46
server/core/initializers/migrations/0920-token-sessions.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
const stringColumns = [
|
||||
'loginDevice',
|
||||
'loginIP',
|
||||
'lastActivityDevice',
|
||||
'lastActivityIP'
|
||||
]
|
||||
|
||||
for (const c of stringColumns) {
|
||||
await utils.queryInterface.addColumn('oAuthToken', c, {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
|
||||
const dateColumns = [
|
||||
'loginDate',
|
||||
'lastActivityDate'
|
||||
]
|
||||
|
||||
for (const c of dateColumns) {
|
||||
await utils.queryInterface.addColumn('oAuthToken', c, {
|
||||
type: Sequelize.DATE,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}, { transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down,
|
||||
up
|
||||
}
|
||||
24
server/core/initializers/migrations/0925-live-schedule-at.ts
Normal file
24
server/core/initializers/migrations/0925-live-schedule-at.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const { transaction } = utils
|
||||
|
||||
const query =
|
||||
// eslint-disable-next-line max-len
|
||||
`CREATE TABLE IF NOT EXISTS "videoLiveSchedule" ("id" SERIAL , "startAt" TIMESTAMP WITH TIME ZONE NOT NULL, "liveVideoId" INTEGER REFERENCES "videoLive" ("id") ON DELETE CASCADE ON UPDATE CASCADE, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, PRIMARY KEY ("id"));`
|
||||
|
||||
await utils.sequelize.query(query, { transaction })
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
28
server/core/initializers/migrations/0930-player-settings.ts
Normal file
28
server/core/initializers/migrations/0930-player-settings.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const query = `CREATE TABLE IF NOT EXISTS "playerSetting" (
|
||||
"id" SERIAL,
|
||||
"theme" VARCHAR(255) NOT NULL DEFAULT 'instance-default',
|
||||
"videoId" INTEGER REFERENCES "video" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"channelId" INTEGER REFERENCES "videoChannel" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"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 })
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
{
|
||||
const query = `CREATE TABLE IF NOT EXISTS "videoChannelCollaborator" (
|
||||
"id" SERIAL,
|
||||
"state" INTEGER NOT NULL,
|
||||
"accountId" INTEGER REFERENCES "account" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"channelId" INTEGER NOT NULL REFERENCES "videoChannel" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"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 })
|
||||
}
|
||||
|
||||
{
|
||||
const metadata = {
|
||||
type: Sequelize.JSONB,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('userNotification', 'data', metadata, { transaction: utils.transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.sequelize.query(
|
||||
`ALTER TABLE "userNotification" ` +
|
||||
`ADD COLUMN "channelCollaboratorId" INTEGER REFERENCES "videoChannelCollaborator" ("id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||
{ transaction: utils.transaction }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
{
|
||||
await utils.sequelize.query(
|
||||
`ALTER TABLE "application" ALTER COLUMN "nodeABIVersion" TYPE VARCHAR(255)`,
|
||||
{ transaction: utils.transaction }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down,
|
||||
up
|
||||
}
|
||||
48
server/core/initializers/migrations/0945-channel-activity.ts
Normal file
48
server/core/initializers/migrations/0945-channel-activity.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
{
|
||||
await utils.sequelize.query(
|
||||
`CREATE TABLE IF NOT EXISTS "videoChannelActivity" (
|
||||
"id" SERIAL,
|
||||
"action" INTEGER NOT NULL,
|
||||
"targetType" INTEGER NOT NULL,
|
||||
"data" JSONB NOT NULL,
|
||||
"details" JSONB,
|
||||
"videoChannelId" INTEGER NOT NULL REFERENCES "videoChannel" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"accountId" INTEGER REFERENCES "account" ("id") ON DELETE
|
||||
SET
|
||||
NULL ON UPDATE CASCADE,
|
||||
"videoId" INTEGER REFERENCES "video" ("id") ON DELETE
|
||||
SET
|
||||
NULL ON UPDATE CASCADE,
|
||||
"videoPlaylistId" INTEGER REFERENCES "videoPlaylist" ("id") ON DELETE
|
||||
SET
|
||||
NULL ON UPDATE CASCADE,
|
||||
"videoChannelSyncId" INTEGER REFERENCES "videoChannelSync" ("id") ON DELETE
|
||||
SET
|
||||
NULL ON UPDATE CASCADE,
|
||||
"videoImportId" INTEGER REFERENCES "videoImport" ("id") ON DELETE
|
||||
SET
|
||||
NULL ON UPDATE CASCADE,
|
||||
"createdAt" TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
"updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);`,
|
||||
{ transaction: utils.transaction }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down,
|
||||
up
|
||||
}
|
||||
31
server/core/initializers/migrations/0950-retry-import.ts
Normal file
31
server/core/initializers/migrations/0950-retry-import.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoImport', 'attempts', {
|
||||
type: Sequelize.DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 0
|
||||
}, { transaction: utils.transaction })
|
||||
}
|
||||
|
||||
{
|
||||
await utils.queryInterface.addColumn('videoImport', 'payload', {
|
||||
type: Sequelize.DataTypes.JSONB,
|
||||
allowNull: true
|
||||
}, { transaction: utils.transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down,
|
||||
up
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
{
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "actorReserved" (
|
||||
"id" SERIAL,
|
||||
"preferredUsername" VARCHAR(255) 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 })
|
||||
}
|
||||
|
||||
{
|
||||
const query = `ALTER TABLE "actor" ADD COLUMN IF NOT EXISTS "accountId" INTEGER ` +
|
||||
`REFERENCES "account" ("id") ON DELETE CASCADE ON UPDATE CASCADE`
|
||||
await utils.sequelize.query(query, { transaction: utils.transaction })
|
||||
}
|
||||
|
||||
{
|
||||
const query = `ALTER TABLE "actor" ADD COLUMN IF NOT EXISTS "videoChannelId" INTEGER ` +
|
||||
`REFERENCES "videoChannel" ("id") ON DELETE CASCADE ON UPDATE CASCADE`
|
||||
await utils.sequelize.query(query, { transaction: utils.transaction })
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
{
|
||||
await utils.sequelize.query(
|
||||
`
|
||||
INSERT INTO "actorReserved" ("preferredUsername", "createdAt", "updatedAt")
|
||||
SELECT "preferredUsername", NOW(), NOW()
|
||||
FROM "actor"
|
||||
WHERE "accountId" IS NULL AND "videoChannelId" IS NULL AND "serverId" IS NULL
|
||||
`,
|
||||
{ transaction: utils.transaction }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down,
|
||||
up
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
import { QueryTypes } from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const batchSize = 1000
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Do not use transaction on purpose, to speed up chunk updates
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Fill "actor"."accountId"
|
||||
while (true) {
|
||||
const query = `
|
||||
WITH batch AS (
|
||||
SELECT a."id" AS actor_id, ac."id" AS account_id
|
||||
FROM "actor" a INNER JOIN "account" ac ON ac."actorId" = a."id"
|
||||
WHERE a."accountId" IS DISTINCT FROM ac."id" ORDER BY a."id"
|
||||
LIMIT ${batchSize}
|
||||
) UPDATE "actor" SET "accountId" = batch.account_id FROM batch WHERE "actor"."id" = batch.actor_id`
|
||||
|
||||
const [ , rowsUpdated ] = await utils.sequelize.query(query, {
|
||||
type: QueryTypes.UPDATE,
|
||||
replacements: { limit: batchSize }
|
||||
})
|
||||
|
||||
if (rowsUpdated < batchSize) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Fill "actor"."videoChannelId"
|
||||
while (true) {
|
||||
const query = `
|
||||
WITH batch AS (
|
||||
SELECT a."id" AS actor_id, vc."id" AS channel_id
|
||||
FROM "actor" a INNER JOIN "videoChannel" vc ON vc."actorId" = a."id"
|
||||
WHERE a."videoChannelId" IS DISTINCT FROM vc."id" ORDER BY a."id"
|
||||
LIMIT ${batchSize}
|
||||
) UPDATE "actor" SET "videoChannelId" = batch.channel_id FROM batch WHERE "actor"."id" = batch.actor_id`
|
||||
|
||||
const [ , rowsUpdated ] = await utils.sequelize.query(query, {
|
||||
type: QueryTypes.UPDATE,
|
||||
replacements: { limit: batchSize }
|
||||
})
|
||||
|
||||
if (rowsUpdated < batchSize) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
{
|
||||
await utils.sequelize.query(`ALTER TABLE "account" DROP COLUMN "actorId"`, { transaction: utils.transaction })
|
||||
await utils.sequelize.query(`ALTER TABLE "videoChannel" DROP COLUMN "actorId"`, { transaction: utils.transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down,
|
||||
up
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
await utils.queryInterface.addColumn('user', 'newFeaturesInfoRead', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true
|
||||
}, { transaction: utils.transaction })
|
||||
|
||||
await utils.sequelize.query('UPDATE "user" SET "newFeaturesInfoRead" = 0', { transaction: utils.transaction })
|
||||
|
||||
await utils.queryInterface.changeColumn('user', 'newFeaturesInfoRead', {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false
|
||||
}, { transaction: utils.transaction })
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down,
|
||||
up
|
||||
}
|
||||
50
server/core/initializers/migrations/0970-actor-reserved.ts
Normal file
50
server/core/initializers/migrations/0970-actor-reserved.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
await utils.sequelize.query('DROP TABLE "actorReserved"', { transaction: utils.transaction })
|
||||
|
||||
{
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "actorReserved" (
|
||||
"id" SERIAL,
|
||||
"preferredUsername" VARCHAR(255) NOT NULL,
|
||||
"publicKey" VARCHAR(5000) NOT NULL,
|
||||
"privateKey" VARCHAR(5000) NOT NULL,
|
||||
"url" VARCHAR(2000) NOT NULL,
|
||||
"actorId" INTEGER NOT NULL,
|
||||
"accountId" INTEGER,
|
||||
"videoChannelId" INTEGER,
|
||||
"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.sequelize.query(
|
||||
`
|
||||
INSERT INTO "actorReserved"
|
||||
("preferredUsername", "publicKey", "privateKey", "url", "actorId", "accountId", "videoChannelId", "createdAt", "updatedAt")
|
||||
SELECT "preferredUsername", "publicKey", "privateKey", "url", "id", "accountId", "videoChannelId", NOW(), NOW()
|
||||
FROM "actor"
|
||||
WHERE "accountId" IS NULL AND "videoChannelId" IS NULL AND "serverId" IS NULL
|
||||
`,
|
||||
{ transaction: utils.transaction }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down,
|
||||
up
|
||||
}
|
||||
45
server/core/initializers/migrations/0975-pkcs8.ts
Normal file
45
server/core/initializers/migrations/0975-pkcs8.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { createPrivateKey } from 'crypto'
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const rows = await utils.sequelize.query<{ id: number, privateKey: string }>(
|
||||
'SELECT "id", "privateKey" FROM "actor" WHERE "serverId" IS NULL',
|
||||
{ type: Sequelize.QueryTypes.SELECT as Sequelize.QueryTypes.SELECT, transaction: utils.transaction }
|
||||
)
|
||||
|
||||
for (const { id, privateKey } of rows) {
|
||||
const newPrivateKey = toPKCS8(privateKey)
|
||||
|
||||
await utils.sequelize.query('UPDATE "actor" SET "privateKey" = :newPrivateKey WHERE "id" = :id', {
|
||||
replacements: { newPrivateKey, id },
|
||||
transaction: utils.transaction
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down,
|
||||
up
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function toPKCS8 (privateKeyPEM: string) {
|
||||
const keyObject = createPrivateKey({
|
||||
key: privateKeyPEM,
|
||||
format: 'pem'
|
||||
})
|
||||
|
||||
return keyObject.export({
|
||||
type: 'pkcs8',
|
||||
format: 'pem'
|
||||
}).toString()
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
{
|
||||
const metadata = {
|
||||
type: Sequelize.JSONB,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('application', 'configPart', metadata, { transaction: utils.transaction })
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
down,
|
||||
up
|
||||
}
|
||||
62
server/core/initializers/migrations/0985-events.ts
Normal file
62
server/core/initializers/migrations/0985-events.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "event" (
|
||||
"id" SERIAL PRIMARY KEY,
|
||||
"channelId" INTEGER NOT NULL REFERENCES "videoChannel" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"title" VARCHAR(255) NOT NULL,
|
||||
"description" TEXT,
|
||||
"startTime" TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
"endTime" TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
"thumbnailFilename" VARCHAR(255),
|
||||
"liveUrl" VARCHAR(2048),
|
||||
"state" VARCHAR(50) NOT NULL DEFAULT 'active',
|
||||
"createdAt" TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
"updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL
|
||||
)
|
||||
`
|
||||
|
||||
await utils.sequelize.query(query, { transaction: utils.transaction })
|
||||
|
||||
// Create indexes
|
||||
await utils.sequelize.query(
|
||||
`CREATE INDEX "idx_event_channelId" ON "event" ("channelId")`,
|
||||
{ transaction: utils.transaction }
|
||||
)
|
||||
|
||||
await utils.sequelize.query(
|
||||
`CREATE INDEX "idx_event_state" ON "event" ("state")`,
|
||||
{ transaction: utils.transaction }
|
||||
)
|
||||
|
||||
await utils.sequelize.query(
|
||||
`CREATE INDEX "idx_event_startTime" ON "event" ("startTime")`,
|
||||
{ transaction: utils.transaction }
|
||||
)
|
||||
|
||||
// Add constraint for end_time > start_time
|
||||
await utils.sequelize.query(
|
||||
`ALTER TABLE "event" ADD CONSTRAINT "event_valid_end_time" CHECK ("endTime" > "startTime")`,
|
||||
{ transaction: utils.transaction }
|
||||
)
|
||||
|
||||
// Allow only states used by the current event workflow
|
||||
await utils.sequelize.query(
|
||||
`ALTER TABLE "event" ADD CONSTRAINT "event_valid_state" CHECK ("state" IN ('active', 'disabled'))`,
|
||||
{ transaction: utils.transaction }
|
||||
)
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
62
server/core/initializers/migrations/0990-live-videos.ts
Normal file
62
server/core/initializers/migrations/0990-live-videos.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "liveVideo" (
|
||||
"id" SERIAL PRIMARY KEY,
|
||||
"title" VARCHAR(255) NOT NULL,
|
||||
"thumbnailFilename" VARCHAR(255),
|
||||
"videoOriginalName" VARCHAR(255) NOT NULL,
|
||||
"videoStoragePath" TEXT NOT NULL,
|
||||
"videoMimeType" VARCHAR(255) NOT NULL,
|
||||
"videoSize" BIGINT NOT NULL,
|
||||
"startTime" TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
"endTime" TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
"targetCamera" VARCHAR(255) NOT NULL,
|
||||
"status" VARCHAR(50) NOT NULL DEFAULT 'scheduled',
|
||||
"createdByUserId" INTEGER NOT NULL REFERENCES "user" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||
"createdAt" TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
"updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL
|
||||
)
|
||||
`
|
||||
|
||||
await utils.sequelize.query(query, { transaction: utils.transaction })
|
||||
|
||||
await utils.sequelize.query(
|
||||
`CREATE INDEX "idx_live_video_target_camera" ON "liveVideo" ("targetCamera")`,
|
||||
{ transaction: utils.transaction }
|
||||
)
|
||||
|
||||
await utils.sequelize.query(
|
||||
`CREATE INDEX "idx_live_video_start_time" ON "liveVideo" ("startTime")`,
|
||||
{ transaction: utils.transaction }
|
||||
)
|
||||
|
||||
await utils.sequelize.query(
|
||||
`CREATE INDEX "idx_live_video_status" ON "liveVideo" ("status")`,
|
||||
{ transaction: utils.transaction }
|
||||
)
|
||||
|
||||
await utils.sequelize.query(
|
||||
`ALTER TABLE "liveVideo" ADD CONSTRAINT "live_video_valid_end_time" CHECK ("endTime" > "startTime")`,
|
||||
{ transaction: utils.transaction }
|
||||
)
|
||||
|
||||
await utils.sequelize.query(
|
||||
`ALTER TABLE "liveVideo" ADD CONSTRAINT "live_video_valid_status" CHECK ("status" IN ('scheduled', 'cancelled', 'completed'))`,
|
||||
{ transaction: utils.transaction }
|
||||
)
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const query = `
|
||||
CREATE TABLE IF NOT EXISTS "eventRegistration" (
|
||||
"id" SERIAL PRIMARY KEY,
|
||||
"eventId" INTEGER NOT NULL REFERENCES "event" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
"firstName" VARCHAR(255) NOT NULL,
|
||||
"lastName" VARCHAR(255) NOT NULL,
|
||||
"email" VARCHAR(320) NOT NULL,
|
||||
"phone" VARCHAR(50) NOT NULL,
|
||||
"companyName" VARCHAR(255) NOT NULL,
|
||||
"jobTitle" VARCHAR(255) NOT NULL,
|
||||
"country" VARCHAR(100) NOT NULL,
|
||||
"createdAt" TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
"updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL
|
||||
)
|
||||
`
|
||||
|
||||
await utils.sequelize.query(query, { transaction: utils.transaction })
|
||||
|
||||
await utils.sequelize.query(
|
||||
`CREATE INDEX "idx_event_registration_eventId" ON "eventRegistration" ("eventId")`,
|
||||
{ transaction: utils.transaction }
|
||||
)
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user