]>
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 | } | |
1735c825 | 24 | const res = await utils.sequelize.query(query, options) as any |
74bb2cb8 C |
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() |
1f20622f C |
68 | const accountCreated = await createLocalAccountWithoutKeys({ |
69 | name: SERVER_ACTOR_NAME, | |
70 | userId: null, | |
71 | applicationId: applicationInstance.id, | |
72 | t: undefined | |
73 | }) | |
74bb2cb8 C |
74 | |
75 | const { publicKey, privateKey } = await createPrivateAndPublicKeys() | |
1735c825 C |
76 | accountCreated.Actor.publicKey = publicKey |
77 | accountCreated.Actor.privateKey = privateKey | |
74bb2cb8 C |
78 | |
79 | await accountCreated.save() | |
80 | } | |
81 | ||
82 | // Drop old video channel foreign key (referencing Authors) | |
83 | { | |
84 | const query = 'ALTER TABLE "VideoChannels" DROP CONSTRAINT "VideoChannels_authorId_fkey"' | |
85 | await utils.sequelize.query(query) | |
86 | } | |
87 | ||
88 | // Recreate accounts for each user | |
89 | const users = await db.User.findAll() | |
90 | for (const user of users) { | |
1f20622f | 91 | const account = await createLocalAccountWithoutKeys({ name: user.username, userId: user.id, applicationId: null, t: undefined }) |
74bb2cb8 C |
92 | |
93 | const { publicKey, privateKey } = await createPrivateAndPublicKeys() | |
1735c825 C |
94 | account.Actor.publicKey = publicKey |
95 | account.Actor.privateKey = privateKey | |
74bb2cb8 C |
96 | await account.save() |
97 | } | |
98 | ||
99 | { | |
100 | const data = { | |
101 | type: Sequelize.INTEGER, | |
102 | allowNull: true, | |
103 | onDelete: 'CASCADE', | |
104 | reference: { | |
105 | model: 'Account', | |
106 | key: 'id' | |
107 | } | |
108 | } | |
109 | await q.addColumn('VideoChannels', 'accountId', data) | |
110 | ||
111 | { | |
112 | const query = 'UPDATE "VideoChannels" SET "accountId" = ' + | |
113 | '(SELECT "Accounts"."id" FROM "Accounts" INNER JOIN "Authors" ON "Authors"."userId" = "Accounts"."userId" ' + | |
114 | 'WHERE "VideoChannels"."authorId" = "Authors"."id")' | |
115 | await utils.sequelize.query(query) | |
116 | } | |
117 | ||
118 | data.allowNull = false | |
119 | await q.changeColumn('VideoChannels', 'accountId', data) | |
120 | ||
121 | await q.removeColumn('VideoChannels', 'authorId') | |
122 | } | |
123 | ||
124 | // Add url column to "Videos" | |
125 | { | |
126 | const data = { | |
127 | type: Sequelize.STRING, | |
128 | defaultValue: null, | |
129 | allowNull: true | |
130 | } | |
131 | await q.addColumn('Videos', 'url', data) | |
132 | ||
133 | const videos = await db.Video.findAll() | |
134 | for (const video of videos) { | |
135 | video.url = getVideoActivityPubUrl(video) | |
136 | await video.save() | |
137 | } | |
138 | ||
139 | data.allowNull = false | |
140 | await q.changeColumn('Videos', 'url', data) | |
141 | } | |
142 | ||
143 | // Add url column to "VideoChannels" | |
144 | { | |
145 | const data = { | |
146 | type: Sequelize.STRING, | |
147 | defaultValue: null, | |
148 | allowNull: true | |
149 | } | |
150 | await q.addColumn('VideoChannels', 'url', data) | |
151 | ||
152 | const videoChannels = await db.VideoChannel.findAll() | |
153 | for (const videoChannel of videoChannels) { | |
154 | videoChannel.url = getVideoChannelActivityPubUrl(videoChannel) | |
155 | await videoChannel.save() | |
156 | } | |
157 | ||
158 | data.allowNull = false | |
159 | await q.changeColumn('VideoChannels', 'url', data) | |
160 | } | |
161 | ||
162 | // Loss old video rates, whatever | |
163 | await utils.queryInterface.dropTable('UserVideoRates') | |
164 | await db.AccountVideoRate.sync() | |
165 | ||
166 | { | |
167 | const data = { | |
94a5ff8a | 168 | type: Sequelize.ENUM('transcoding', 'activitypub-http'), |
74bb2cb8 C |
169 | defaultValue: 'transcoding', |
170 | allowNull: false | |
171 | } | |
172 | await q.addColumn('Jobs', 'category', data) | |
173 | } | |
174 | ||
175 | await db.VideoShare.sync() | |
176 | await db.VideoChannelShare.sync() | |
177 | ||
178 | { | |
179 | const videos = await db.Video.findAll({ | |
180 | include: [ | |
181 | { | |
182 | model: db.Video['sequelize'].models.VideoChannel, | |
183 | include: [ | |
184 | { | |
185 | model: db.Video['sequelize'].models.Account, | |
186 | include: [ { model: db.Video['sequelize'].models.Server, required: false } ] | |
187 | } | |
188 | ] | |
189 | }, | |
190 | { | |
191 | model: db.Video['sequelize'].models.AccountVideoRate, | |
192 | include: [ db.Video['sequelize'].models.Account ] | |
193 | }, | |
194 | { | |
195 | model: db.Video['sequelize'].models.VideoShare, | |
196 | include: [ db.Video['sequelize'].models.Account ] | |
197 | }, | |
198 | db.Video['sequelize'].models.Tag, | |
199 | db.Video['sequelize'].models.VideoFile | |
200 | ] | |
201 | }) | |
202 | ||
203 | for (const video of videos) { | |
a7d647c4 | 204 | await shareVideoByServerAndChannel(video, undefined) |
74bb2cb8 C |
205 | } |
206 | } | |
207 | } | |
208 | ||
209 | function down (options) { | |
210 | throw new Error('Not implemented.') | |
211 | } | |
212 | ||
213 | export { | |
214 | up, | |
215 | down | |
216 | } |