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