Unfollow with host
[oweals/peertube.git] / server / initializers / migrations / 0130-video-channel-actor.ts
1 import * as Sequelize from 'sequelize'
2 import { DataType } from 'sequelize-typescript'
3
4 async function up (utils: {
5   transaction: Sequelize.Transaction,
6   queryInterface: Sequelize.QueryInterface,
7   sequelize: Sequelize.Sequelize
8 }): Promise<void> {
9   // Create actor table
10   {
11     const queries = [
12       `
13       CREATE TYPE enum_actor_type AS ENUM (
14         'Group',
15         'Person',
16         'Application'
17       )
18       `,
19       `
20       CREATE TABLE actor (
21         id integer NOT NULL,
22         type enum_actor_type NOT NULL,
23         uuid uuid NOT NULL,
24         name character varying(255) NOT NULL,
25         url character varying(2000) NOT NULL,
26         "publicKey" character varying(5000),
27         "privateKey" character varying(5000),
28         "followersCount" integer NOT NULL,
29         "followingCount" integer NOT NULL,
30         "inboxUrl" character varying(2000) NOT NULL,
31         "outboxUrl" character varying(2000) NOT NULL,
32         "sharedInboxUrl" character varying(2000) NOT NULL,
33         "followersUrl" character varying(2000) NOT NULL,
34         "followingUrl" character varying(2000) NOT NULL,
35         "avatarId" integer,
36         "serverId" integer,
37         "createdAt" timestamp with time zone NOT NULL,
38         "updatedAt" timestamp with time zone NOT NULL
39       );`,
40       `
41       CREATE SEQUENCE actor_id_seq
42       AS integer
43       START WITH 1
44       INCREMENT BY 1
45       NO MINVALUE
46       NO MAXVALUE
47       CACHE 1
48       `,
49       `ALTER SEQUENCE actor_id_seq OWNED BY actor.id`,
50       `ALTER TABLE ONLY actor ALTER COLUMN id SET DEFAULT nextval('actor_id_seq'::regclass)`,
51       `ALTER TABLE ONLY actor ADD CONSTRAINT actor_pkey PRIMARY KEY (id);`,
52       `CREATE UNIQUE INDEX actor_name_server_id ON actor USING btree (name, "serverId")`,
53       `ALTER TABLE ONLY actor
54         ADD CONSTRAINT "actor_avatarId_fkey" FOREIGN KEY ("avatarId") REFERENCES avatar(id) ON UPDATE CASCADE ON DELETE CASCADE`,
55       `ALTER TABLE ONLY actor
56         ADD CONSTRAINT "actor_serverId_fkey" FOREIGN KEY ("serverId") REFERENCES server(id) ON UPDATE CASCADE ON DELETE CASCADE;`
57     ]
58
59     for (const query of queries) {
60       await utils.sequelize.query(query)
61     }
62   }
63
64   {
65     // tslint:disable:no-trailing-whitespace
66     const query1 =
67       `
68       INSERT INTO "actor"
69         (
70           type, uuid, name, url, "publicKey", "privateKey", "followersCount", "followingCount", "inboxUrl", "outboxUrl",
71           "sharedInboxUrl", "followersUrl", "followingUrl", "avatarId", "serverId", "createdAt", "updatedAt"
72         )
73         SELECT 
74           'Application', uuid, name, url, "publicKey", "privateKey", "followersCount", "followingCount", "inboxUrl", "outboxUrl",
75           "sharedInboxUrl", "followersUrl", "followingUrl", "avatarId", "serverId", "createdAt", "updatedAt" 
76         FROM account 
77         WHERE "applicationId" IS NOT NULL
78         `
79     await utils.sequelize.query(query1)
80
81     const query2 =
82       `
83       INSERT INTO "actor"
84         (
85           type, uuid, name, url, "publicKey", "privateKey", "followersCount", "followingCount", "inboxUrl", "outboxUrl",
86           "sharedInboxUrl", "followersUrl", "followingUrl", "avatarId", "serverId", "createdAt", "updatedAt"
87         )
88         SELECT 
89           'Person', uuid, name, url, "publicKey", "privateKey", "followersCount", "followingCount", "inboxUrl", "outboxUrl",
90           "sharedInboxUrl", "followersUrl", "followingUrl", "avatarId", "serverId", "createdAt", "updatedAt" 
91         FROM account 
92         WHERE "applicationId" IS NULL
93         `
94     await utils.sequelize.query(query2)
95   }
96
97   {
98     const data = {
99       type: DataType.INTEGER,
100       allowNull: true,
101       defaultValue: null
102     }
103     await utils.queryInterface.addColumn('account', 'actorId', data)
104
105     const query1 = `UPDATE account SET "actorId" = (SELECT id FROM actor WHERE actor.url = account.url)`
106     await utils.sequelize.query(query1)
107
108     data.allowNull = false
109     await utils.queryInterface.changeColumn('account', 'actorId', data)
110
111     const query2 = `ALTER TABLE ONLY account
112     ADD CONSTRAINT "account_actorId_fkey" FOREIGN KEY ("actorId") REFERENCES actor(id) ON UPDATE CASCADE ON DELETE CASCADE;
113   `
114     await utils.sequelize.query(query2)
115   }
116
117   {
118     const query = `  
119     INSERT INTO actor 
120     (
121     type, uuid, name, url, "publicKey", "privateKey", "followersCount", "followingCount", "inboxUrl", "outboxUrl", 
122     "sharedInboxUrl", "followersUrl", "followingUrl", "avatarId", "serverId", "createdAt", "updatedAt"
123     )
124     SELECT 
125     'Group', "videoChannel".uuid, "videoChannel".uuid, "videoChannel".url, null, null, 0, 0, "videoChannel".url || '/inbox', 
126     "videoChannel".url || '/outbox', "videoChannel".url || '/inbox', "videoChannel".url || '/followers', "videoChannel".url || '/following',
127      null, account."serverId", "videoChannel"."createdAt", "videoChannel"."updatedAt" 
128      FROM "videoChannel" 
129      INNER JOIN "account" on "videoChannel"."accountId" = "account".id
130     `
131     await utils.sequelize.query(query)
132   }
133
134   {
135     const data = {
136       type: DataType.INTEGER,
137       allowNull: true,
138       defaultValue: null
139     }
140     await utils.queryInterface.addColumn('videoChannel', 'actorId', data)
141
142     const query1 = `UPDATE "videoChannel" SET "actorId" = (SELECT id FROM actor WHERE actor.url = "videoChannel".url)`
143     await utils.sequelize.query(query1)
144
145     data.allowNull = false
146     await utils.queryInterface.changeColumn('videoChannel', 'actorId', data)
147
148     const query2 = `
149     ALTER TABLE ONLY "videoChannel"
150     ADD CONSTRAINT "videoChannel_actorId_fkey" FOREIGN KEY ("actorId") REFERENCES actor(id) ON UPDATE CASCADE ON DELETE CASCADE;
151     `
152     await utils.sequelize.query(query2)
153   }
154
155   {
156     await utils.queryInterface.renameTable('accountFollow', 'actorFollow')
157     await utils.queryInterface.renameColumn('actorFollow', 'accountId', 'actorId')
158     await utils.queryInterface.renameColumn('actorFollow', 'targetAccountId', 'targetActorId')
159
160     try {
161       await utils.queryInterface.removeConstraint('actorFollow', 'AccountFollows_accountId_fkey')
162       await utils.queryInterface.removeConstraint('actorFollow', 'AccountFollows_targetAccountId_fkey')
163     } catch {
164       await utils.queryInterface.removeConstraint('actorFollow', 'accountFollow_accountId_fkey')
165       await utils.queryInterface.removeConstraint('actorFollow', 'accountFollow_targetAccountId_fkey')
166     }
167
168     const query1 = `UPDATE "actorFollow" 
169       SET "actorId" = 
170       (SELECT "account"."actorId" FROM account WHERE "account"."id" = "actorFollow"."actorId")`
171     await utils.sequelize.query(query1)
172
173     const query2 = `UPDATE "actorFollow" 
174       SET "targetActorId" = 
175       (SELECT "account"."actorId" FROM account WHERE "account"."id" = "actorFollow"."targetActorId")`
176
177     await utils.sequelize.query(query2)
178   }
179
180   {
181     await utils.queryInterface.renameColumn('videoShare', 'accountId', 'actorId')
182
183     try {
184       await utils.queryInterface.removeConstraint('videoShare', 'VideoShares_accountId_fkey')
185     } catch {
186       await utils.queryInterface.removeConstraint('videoShare', 'videoShare_accountId_fkey')
187     }
188
189     const query = `UPDATE "videoShare" 
190       SET "actorId" = 
191       (SELECT "actorId" FROM account WHERE id = "videoShare"."actorId")`
192     await utils.sequelize.query(query)
193   }
194
195   {
196     const columnsToDelete = [
197       'uuid',
198       'url',
199       'publicKey',
200       'privateKey',
201       'followersCount',
202       'followingCount',
203       'inboxUrl',
204       'outboxUrl',
205       'sharedInboxUrl',
206       'followersUrl',
207       'followingUrl',
208       'serverId',
209       'avatarId'
210     ]
211     for (const columnToDelete of columnsToDelete) {
212       await utils.queryInterface.removeColumn('account', columnToDelete)
213     }
214   }
215
216   {
217     const columnsToDelete = [
218       'uuid',
219       'remote',
220       'url'
221     ]
222     for (const columnToDelete of columnsToDelete) {
223       await utils.queryInterface.removeColumn('videoChannel', columnToDelete)
224     }
225   }
226 }
227
228 function down (options) {
229   throw new Error('Not implemented.')
230 }
231
232 export {
233   up,
234   down
235 }