]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/initializers/migrations/0100-activitypub.ts
Move job queue to redis
[github/Chocobozzz/PeerTube.git] / server / initializers / migrations / 0100-activitypub.ts
1 import * as Sequelize from 'sequelize'
2 import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto'
3 import { shareVideoByServerAndChannel } from '../../lib/activitypub/share'
4 import { getVideoActivityPubUrl, getVideoChannelActivityPubUrl } from '../../lib/activitypub/url'
5 import { createLocalAccountWithoutKeys } from '../../lib/user'
6 import { ApplicationModel } from '../../models/application/application'
7 import { SERVER_ACTOR_NAME } from '../constants'
8
9 async function up (utils: {
10 transaction: Sequelize.Transaction,
11 queryInterface: Sequelize.QueryInterface,
12 sequelize: Sequelize.Sequelize,
13 db: any
14 }): Promise<void> {
15 const q = utils.queryInterface
16 const db = utils.db
17
18 // Assert there are no friends
19 {
20 const query = 'SELECT COUNT(*) as total FROM "Pods"'
21 const options = {
22 type: Sequelize.QueryTypes.SELECT
23 }
24 const res = await utils.sequelize.query(query, options)
25
26 if (!res[0] || res[0].total !== 0) {
27 throw new Error('You need to quit friends.')
28 }
29 }
30
31 // Pods -> Servers
32 await utils.queryInterface.renameTable('Pods', 'Servers')
33
34 // Create Account table
35 await db.Account.sync()
36
37 // Create AccountFollows table
38 await db.AccountFollow.sync()
39
40 // Modify video abuse table
41 await db.VideoAbuse.destroy({ truncate: true })
42 await utils.queryInterface.removeColumn('VideoAbuses', 'reporterPodId')
43 await utils.queryInterface.removeColumn('VideoAbuses', 'reporterUsername')
44
45 // Create column link with Account table
46 {
47 const data = {
48 type: Sequelize.INTEGER,
49 allowNull: false,
50 references: {
51 model: 'Accounts',
52 key: 'id'
53 },
54 onDelete: 'CASCADE'
55 }
56 await q.addColumn('VideoAbuses', 'reporterAccountId', data)
57 }
58
59 // Drop request tables
60 await utils.queryInterface.dropTable('RequestToPods')
61 await utils.queryInterface.dropTable('RequestVideoEvents')
62 await utils.queryInterface.dropTable('RequestVideoQadus')
63 await utils.queryInterface.dropTable('Requests')
64
65 // Create application account
66 {
67 const applicationInstance = await ApplicationModel.findOne()
68 const accountCreated = await createLocalAccountWithoutKeys(SERVER_ACTOR_NAME, null, applicationInstance.id, undefined)
69
70 const { publicKey, privateKey } = await createPrivateAndPublicKeys()
71 accountCreated.set('publicKey', publicKey)
72 accountCreated.set('privateKey', privateKey)
73
74 await accountCreated.save()
75 }
76
77 // Drop old video channel foreign key (referencing Authors)
78 {
79 const query = 'ALTER TABLE "VideoChannels" DROP CONSTRAINT "VideoChannels_authorId_fkey"'
80 await utils.sequelize.query(query)
81 }
82
83 // Recreate accounts for each user
84 const users = await db.User.findAll()
85 for (const user of users) {
86 const account = await createLocalAccountWithoutKeys(user.username, user.id, null, undefined)
87
88 const { publicKey, privateKey } = await createPrivateAndPublicKeys()
89 account.set('publicKey', publicKey)
90 account.set('privateKey', privateKey)
91 await account.save()
92 }
93
94 {
95 const data = {
96 type: Sequelize.INTEGER,
97 allowNull: true,
98 onDelete: 'CASCADE',
99 reference: {
100 model: 'Account',
101 key: 'id'
102 }
103 }
104 await q.addColumn('VideoChannels', 'accountId', data)
105
106 {
107 const query = 'UPDATE "VideoChannels" SET "accountId" = ' +
108 '(SELECT "Accounts"."id" FROM "Accounts" INNER JOIN "Authors" ON "Authors"."userId" = "Accounts"."userId" ' +
109 'WHERE "VideoChannels"."authorId" = "Authors"."id")'
110 await utils.sequelize.query(query)
111 }
112
113 data.allowNull = false
114 await q.changeColumn('VideoChannels', 'accountId', data)
115
116 await q.removeColumn('VideoChannels', 'authorId')
117 }
118
119 // Add url column to "Videos"
120 {
121 const data = {
122 type: Sequelize.STRING,
123 defaultValue: null,
124 allowNull: true
125 }
126 await q.addColumn('Videos', 'url', data)
127
128 const videos = await db.Video.findAll()
129 for (const video of videos) {
130 video.url = getVideoActivityPubUrl(video)
131 await video.save()
132 }
133
134 data.allowNull = false
135 await q.changeColumn('Videos', 'url', data)
136 }
137
138 // Add url column to "VideoChannels"
139 {
140 const data = {
141 type: Sequelize.STRING,
142 defaultValue: null,
143 allowNull: true
144 }
145 await q.addColumn('VideoChannels', 'url', data)
146
147 const videoChannels = await db.VideoChannel.findAll()
148 for (const videoChannel of videoChannels) {
149 videoChannel.url = getVideoChannelActivityPubUrl(videoChannel)
150 await videoChannel.save()
151 }
152
153 data.allowNull = false
154 await q.changeColumn('VideoChannels', 'url', data)
155 }
156
157 // Loss old video rates, whatever
158 await utils.queryInterface.dropTable('UserVideoRates')
159 await db.AccountVideoRate.sync()
160
161 {
162 const data = {
163 type: Sequelize.ENUM('transcoding', 'activitypub-http'),
164 defaultValue: 'transcoding',
165 allowNull: false
166 }
167 await q.addColumn('Jobs', 'category', data)
168 }
169
170 await db.VideoShare.sync()
171 await db.VideoChannelShare.sync()
172
173 {
174 const videos = await db.Video.findAll({
175 include: [
176 {
177 model: db.Video['sequelize'].models.VideoChannel,
178 include: [
179 {
180 model: db.Video['sequelize'].models.Account,
181 include: [ { model: db.Video['sequelize'].models.Server, required: false } ]
182 }
183 ]
184 },
185 {
186 model: db.Video['sequelize'].models.AccountVideoRate,
187 include: [ db.Video['sequelize'].models.Account ]
188 },
189 {
190 model: db.Video['sequelize'].models.VideoShare,
191 include: [ db.Video['sequelize'].models.Account ]
192 },
193 db.Video['sequelize'].models.Tag,
194 db.Video['sequelize'].models.VideoFile
195 ]
196 })
197
198 for (const video of videos) {
199 await shareVideoByServerAndChannel(video, undefined)
200 }
201 }
202 }
203
204 function down (options) {
205 throw new Error('Not implemented.')
206 }
207
208 export {
209 up,
210 down
211 }