]>
Commit | Line | Data |
---|---|---|
74bb2cb8 C |
1 | import * as Sequelize from 'sequelize' |
2 | import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto' | |
a7d647c4 | 3 | import { shareVideoByServerAndChannel } from '../../lib/activitypub/share' |
74bb2cb8 C |
4 | import { getVideoActivityPubUrl, getVideoChannelActivityPubUrl } from '../../lib/activitypub/url' |
5 | import { createLocalAccountWithoutKeys } from '../../lib/user' | |
3fd3ab2d | 6 | import { ApplicationModel } from '../../models/application/application' |
94a5ff8a | 7 | import { SERVER_ACTOR_NAME } from '../constants' |
74bb2cb8 C |
8 | |
9 | async function up (utils: { | |
10 | transaction: Sequelize.Transaction, | |
11 | queryInterface: Sequelize.QueryInterface, | |
12 | sequelize: Sequelize.Sequelize, | |
3fd3ab2d | 13 | db: any |
74bb2cb8 C |
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 | { | |
3fd3ab2d | 67 | const applicationInstance = await ApplicationModel.findOne() |
50d6de9c | 68 | const accountCreated = await createLocalAccountWithoutKeys(SERVER_ACTOR_NAME, null, applicationInstance.id, undefined) |
74bb2cb8 C |
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 = { | |
94a5ff8a | 163 | type: Sequelize.ENUM('transcoding', 'activitypub-http'), |
74bb2cb8 C |
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) { | |
a7d647c4 | 199 | await shareVideoByServerAndChannel(video, undefined) |
74bb2cb8 C |
200 | } |
201 | } | |
202 | } | |
203 | ||
204 | function down (options) { | |
205 | throw new Error('Not implemented.') | |
206 | } | |
207 | ||
208 | export { | |
209 | up, | |
210 | down | |
211 | } |