Add activitypub migration script
This commit is contained in:
parent
df1966c9b4
commit
74bb2cb834
5 changed files with 224 additions and 5 deletions
|
@ -14,7 +14,7 @@ import { FollowState } from '../../shared/models/accounts/follow.model'
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const LAST_MIGRATION_VERSION = 95
|
||||
const LAST_MIGRATION_VERSION = 100
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ const dbname = CONFIG.DATABASE.DBNAME
|
|||
const username = CONFIG.DATABASE.USERNAME
|
||||
const password = CONFIG.DATABASE.PASSWORD
|
||||
|
||||
const database: {
|
||||
export type PeerTubeDatabase = {
|
||||
sequelize?: Sequelize.Sequelize,
|
||||
init?: (silent: boolean) => Promise<void>,
|
||||
|
||||
|
@ -53,7 +53,9 @@ const database: {
|
|||
BlacklistedVideo?: BlacklistedVideoModel,
|
||||
VideoTag?: VideoTagModel,
|
||||
Video?: VideoModel
|
||||
} = {}
|
||||
}
|
||||
|
||||
const database: PeerTubeDatabase = {}
|
||||
|
||||
const sequelize = new Sequelize(dbname, username, password, {
|
||||
dialect: 'postgres',
|
||||
|
|
212
server/initializers/migrations/0100-activitypub.ts
Normal file
212
server/initializers/migrations/0100-activitypub.ts
Normal file
|
@ -0,0 +1,212 @@
|
|||
import { values } from 'lodash'
|
||||
import * as Sequelize from 'sequelize'
|
||||
import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto'
|
||||
import { shareVideoByServer } from '../../lib/activitypub/share'
|
||||
import { getVideoActivityPubUrl, getVideoChannelActivityPubUrl } from '../../lib/activitypub/url'
|
||||
import { createLocalAccountWithoutKeys } from '../../lib/user'
|
||||
import { JOB_CATEGORIES, SERVER_ACCOUNT_NAME } from '../constants'
|
||||
import { PeerTubeDatabase } from '../database'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction,
|
||||
queryInterface: Sequelize.QueryInterface,
|
||||
sequelize: Sequelize.Sequelize,
|
||||
db: PeerTubeDatabase
|
||||
}): Promise<void> {
|
||||
const q = utils.queryInterface
|
||||
const db = utils.db
|
||||
|
||||
// Assert there are no friends
|
||||
{
|
||||
const query = 'SELECT COUNT(*) as total FROM "Pods"'
|
||||
const options = {
|
||||
type: Sequelize.QueryTypes.SELECT
|
||||
}
|
||||
const res = await utils.sequelize.query(query, options)
|
||||
|
||||
if (!res[0] || res[0].total !== 0) {
|
||||
throw new Error('You need to quit friends.')
|
||||
}
|
||||
}
|
||||
|
||||
// Pods -> Servers
|
||||
await utils.queryInterface.renameTable('Pods', 'Servers')
|
||||
|
||||
// Create Account table
|
||||
await db.Account.sync()
|
||||
|
||||
// Create AccountFollows table
|
||||
await db.AccountFollow.sync()
|
||||
|
||||
// Modify video abuse table
|
||||
await db.VideoAbuse.destroy({ truncate: true })
|
||||
await utils.queryInterface.removeColumn('VideoAbuses', 'reporterPodId')
|
||||
await utils.queryInterface.removeColumn('VideoAbuses', 'reporterUsername')
|
||||
|
||||
// Create column link with Account table
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: 'Accounts',
|
||||
key: 'id'
|
||||
},
|
||||
onDelete: 'CASCADE'
|
||||
}
|
||||
await q.addColumn('VideoAbuses', 'reporterAccountId', data)
|
||||
}
|
||||
|
||||
// Drop request tables
|
||||
await utils.queryInterface.dropTable('RequestToPods')
|
||||
await utils.queryInterface.dropTable('RequestVideoEvents')
|
||||
await utils.queryInterface.dropTable('RequestVideoQadus')
|
||||
await utils.queryInterface.dropTable('Requests')
|
||||
|
||||
// Create application account
|
||||
{
|
||||
const applicationInstance = await db.Application.findOne()
|
||||
const accountCreated = await createLocalAccountWithoutKeys(SERVER_ACCOUNT_NAME, null, applicationInstance.id, undefined)
|
||||
|
||||
const { publicKey, privateKey } = await createPrivateAndPublicKeys()
|
||||
accountCreated.set('publicKey', publicKey)
|
||||
accountCreated.set('privateKey', privateKey)
|
||||
|
||||
await accountCreated.save()
|
||||
}
|
||||
|
||||
// Drop old video channel foreign key (referencing Authors)
|
||||
{
|
||||
const query = 'ALTER TABLE "VideoChannels" DROP CONSTRAINT "VideoChannels_authorId_fkey"'
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
|
||||
// Recreate accounts for each user
|
||||
const users = await db.User.findAll()
|
||||
for (const user of users) {
|
||||
const account = await createLocalAccountWithoutKeys(user.username, user.id, null, undefined)
|
||||
|
||||
const { publicKey, privateKey } = await createPrivateAndPublicKeys()
|
||||
account.set('publicKey', publicKey)
|
||||
account.set('privateKey', privateKey)
|
||||
await account.save()
|
||||
}
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: true,
|
||||
onDelete: 'CASCADE',
|
||||
reference: {
|
||||
model: 'Account',
|
||||
key: 'id'
|
||||
}
|
||||
}
|
||||
await q.addColumn('VideoChannels', 'accountId', data)
|
||||
|
||||
{
|
||||
const query = 'UPDATE "VideoChannels" SET "accountId" = ' +
|
||||
'(SELECT "Accounts"."id" FROM "Accounts" INNER JOIN "Authors" ON "Authors"."userId" = "Accounts"."userId" ' +
|
||||
'WHERE "VideoChannels"."authorId" = "Authors"."id")'
|
||||
await utils.sequelize.query(query)
|
||||
}
|
||||
|
||||
data.allowNull = false
|
||||
await q.changeColumn('VideoChannels', 'accountId', data)
|
||||
|
||||
await q.removeColumn('VideoChannels', 'authorId')
|
||||
}
|
||||
|
||||
// Add url column to "Videos"
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await q.addColumn('Videos', 'url', data)
|
||||
|
||||
const videos = await db.Video.findAll()
|
||||
for (const video of videos) {
|
||||
video.url = getVideoActivityPubUrl(video)
|
||||
await video.save()
|
||||
}
|
||||
|
||||
data.allowNull = false
|
||||
await q.changeColumn('Videos', 'url', data)
|
||||
}
|
||||
|
||||
// Add url column to "VideoChannels"
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.STRING,
|
||||
defaultValue: null,
|
||||
allowNull: true
|
||||
}
|
||||
await q.addColumn('VideoChannels', 'url', data)
|
||||
|
||||
const videoChannels = await db.VideoChannel.findAll()
|
||||
for (const videoChannel of videoChannels) {
|
||||
videoChannel.url = getVideoChannelActivityPubUrl(videoChannel)
|
||||
await videoChannel.save()
|
||||
}
|
||||
|
||||
data.allowNull = false
|
||||
await q.changeColumn('VideoChannels', 'url', data)
|
||||
}
|
||||
|
||||
// Loss old video rates, whatever
|
||||
await utils.queryInterface.dropTable('UserVideoRates')
|
||||
await db.AccountVideoRate.sync()
|
||||
|
||||
{
|
||||
const data = {
|
||||
type: Sequelize.ENUM(values(JOB_CATEGORIES)),
|
||||
defaultValue: 'transcoding',
|
||||
allowNull: false
|
||||
}
|
||||
await q.addColumn('Jobs', 'category', data)
|
||||
}
|
||||
|
||||
await db.VideoShare.sync()
|
||||
await db.VideoChannelShare.sync()
|
||||
|
||||
{
|
||||
const videos = await db.Video.findAll({
|
||||
include: [
|
||||
{
|
||||
model: db.Video['sequelize'].models.VideoChannel,
|
||||
include: [
|
||||
{
|
||||
model: db.Video['sequelize'].models.Account,
|
||||
include: [ { model: db.Video['sequelize'].models.Server, required: false } ]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
model: db.Video['sequelize'].models.AccountVideoRate,
|
||||
include: [ db.Video['sequelize'].models.Account ]
|
||||
},
|
||||
{
|
||||
model: db.Video['sequelize'].models.VideoShare,
|
||||
include: [ db.Video['sequelize'].models.Account ]
|
||||
},
|
||||
db.Video['sequelize'].models.Tag,
|
||||
db.Video['sequelize'].models.VideoFile
|
||||
]
|
||||
})
|
||||
|
||||
for (const video of videos) {
|
||||
await shareVideoByServer(video, undefined)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
|
@ -26,7 +26,12 @@ async function migrate () {
|
|||
const migrationScripts = await getMigrationScripts()
|
||||
|
||||
for (const migrationScript of migrationScripts) {
|
||||
await executeMigration(actualVersion, migrationScript)
|
||||
try {
|
||||
await executeMigration(actualVersion, migrationScript)
|
||||
} catch (err) {
|
||||
logger.error('Cannot execute migration %s.', migrationScript.version, err)
|
||||
process.exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
logger.info('Migrations finished. New migration version schema: %s', LAST_MIGRATION_VERSION)
|
||||
|
|
|
@ -99,7 +99,7 @@ function associate (models) {
|
|||
VideoAbuse.belongsTo(models.Account, {
|
||||
foreignKey: {
|
||||
name: 'reporterAccountId',
|
||||
allowNull: true
|
||||
allowNull: false
|
||||
},
|
||||
onDelete: 'CASCADE'
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue