]>
Commit | Line | Data |
---|---|---|
2a491182 F |
1 | import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination, FIXTURE_URLS } from '@server/tests/shared' |
2 | import { HttpStatusCode, VideoChannelSyncCreate } from '@shared/models' | |
3 | import { | |
4 | ChannelSyncsCommand, | |
5 | createSingleServer, | |
6 | makePostBodyRequest, | |
7 | PeerTubeServer, | |
8 | setAccessTokensToServers, | |
9 | setDefaultVideoChannel | |
10 | } from '@shared/server-commands' | |
11 | ||
12 | describe('Test video channel sync API validator', () => { | |
13 | const path = '/api/v1/video-channel-syncs' | |
14 | let server: PeerTubeServer | |
15 | let command: ChannelSyncsCommand | |
16 | let rootChannelId: number | |
17 | let rootChannelSyncId: number | |
18 | const userInfo = { | |
19 | accessToken: '', | |
20 | username: 'user1', | |
21 | id: -1, | |
22 | channelId: -1, | |
23 | syncId: -1 | |
24 | } | |
25 | ||
26 | async function withChannelSyncDisabled<T> (callback: () => Promise<T>): Promise<void> { | |
27 | try { | |
28 | await server.config.disableChannelSync() | |
29 | await callback() | |
30 | } finally { | |
31 | await server.config.enableChannelSync() | |
32 | } | |
33 | } | |
34 | ||
35 | async function withMaxSyncsPerUser<T> (maxSync: number, callback: () => Promise<T>): Promise<void> { | |
36 | const origConfig = await server.config.getCustomConfig() | |
37 | ||
38 | await server.config.updateExistingSubConfig({ | |
39 | newConfig: { | |
40 | import: { | |
41 | videoChannelSynchronization: { | |
42 | maxPerUser: maxSync | |
43 | } | |
44 | } | |
45 | } | |
46 | }) | |
47 | ||
48 | try { | |
49 | await callback() | |
50 | } finally { | |
51 | await server.config.updateCustomConfig({ newCustomConfig: origConfig }) | |
52 | } | |
53 | } | |
54 | ||
55 | before(async function () { | |
56 | this.timeout(30_000) | |
57 | ||
58 | server = await createSingleServer(1) | |
59 | ||
60 | await setAccessTokensToServers([ server ]) | |
61 | await setDefaultVideoChannel([ server ]) | |
62 | ||
63 | command = server.channelSyncs | |
64 | ||
65 | rootChannelId = server.store.channel.id | |
66 | ||
67 | { | |
68 | userInfo.accessToken = await server.users.generateUserAndToken(userInfo.username) | |
69 | ||
70 | const { videoChannels, id: userId } = await server.users.getMyInfo({ token: userInfo.accessToken }) | |
71 | userInfo.id = userId | |
72 | userInfo.channelId = videoChannels[0].id | |
73 | } | |
74 | ||
75 | await server.config.enableChannelSync() | |
76 | }) | |
77 | ||
78 | describe('When creating a sync', function () { | |
79 | let baseCorrectParams: VideoChannelSyncCreate | |
80 | ||
81 | before(function () { | |
82 | baseCorrectParams = { | |
83 | externalChannelUrl: FIXTURE_URLS.youtubeChannel, | |
84 | videoChannelId: rootChannelId | |
85 | } | |
86 | }) | |
87 | ||
88 | it('Should fail when sync is disabled', async function () { | |
89 | await withChannelSyncDisabled(async () => { | |
90 | await command.create({ | |
91 | token: server.accessToken, | |
92 | attributes: baseCorrectParams, | |
93 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | |
94 | }) | |
95 | }) | |
96 | }) | |
97 | ||
98 | it('Should fail with nothing', async function () { | |
99 | const fields = {} | |
100 | await makePostBodyRequest({ | |
101 | url: server.url, | |
102 | path, | |
103 | token: server.accessToken, | |
104 | fields, | |
105 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | |
106 | }) | |
107 | }) | |
108 | ||
109 | it('Should fail with no authentication', async function () { | |
110 | await command.create({ | |
111 | token: null, | |
112 | attributes: baseCorrectParams, | |
113 | expectedStatus: HttpStatusCode.UNAUTHORIZED_401 | |
114 | }) | |
115 | }) | |
116 | ||
117 | it('Should fail without a target url', async function () { | |
118 | const attributes: VideoChannelSyncCreate = { | |
119 | ...baseCorrectParams, | |
120 | externalChannelUrl: null | |
121 | } | |
122 | await command.create({ | |
123 | token: server.accessToken, | |
124 | attributes, | |
125 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | |
126 | }) | |
127 | }) | |
128 | ||
129 | it('Should fail without a channelId', async function () { | |
130 | const attributes: VideoChannelSyncCreate = { | |
131 | ...baseCorrectParams, | |
132 | videoChannelId: null | |
133 | } | |
134 | await command.create({ | |
135 | token: server.accessToken, | |
136 | attributes, | |
137 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | |
138 | }) | |
139 | }) | |
140 | ||
141 | it('Should fail with a channelId refering nothing', async function () { | |
142 | const attributes: VideoChannelSyncCreate = { | |
143 | ...baseCorrectParams, | |
144 | videoChannelId: 42 | |
145 | } | |
146 | await command.create({ | |
147 | token: server.accessToken, | |
148 | attributes, | |
149 | expectedStatus: HttpStatusCode.NOT_FOUND_404 | |
150 | }) | |
151 | }) | |
152 | ||
153 | it('Should fail to create a sync when the user does not own the channel', async function () { | |
154 | await command.create({ | |
155 | token: userInfo.accessToken, | |
156 | attributes: baseCorrectParams, | |
157 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | |
158 | }) | |
159 | }) | |
160 | ||
161 | it('Should succeed to create a sync with root and for another user\'s channel', async function () { | |
162 | const { videoChannelSync } = await command.create({ | |
163 | token: server.accessToken, | |
164 | attributes: { | |
165 | ...baseCorrectParams, | |
166 | videoChannelId: userInfo.channelId | |
167 | }, | |
168 | expectedStatus: HttpStatusCode.OK_200 | |
169 | }) | |
170 | userInfo.syncId = videoChannelSync.id | |
171 | }) | |
172 | ||
173 | it('Should succeed with the correct parameters', async function () { | |
174 | const { videoChannelSync } = await command.create({ | |
175 | token: server.accessToken, | |
176 | attributes: baseCorrectParams, | |
177 | expectedStatus: HttpStatusCode.OK_200 | |
178 | }) | |
179 | rootChannelSyncId = videoChannelSync.id | |
180 | }) | |
181 | ||
182 | it('Should fail when the user exceeds allowed number of synchronizations', async function () { | |
183 | await withMaxSyncsPerUser(1, async () => { | |
184 | await command.create({ | |
185 | token: server.accessToken, | |
186 | attributes: { | |
187 | ...baseCorrectParams, | |
188 | videoChannelId: userInfo.channelId | |
189 | }, | |
190 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | |
191 | }) | |
192 | }) | |
193 | }) | |
194 | }) | |
195 | ||
196 | describe('When listing my channel syncs', function () { | |
197 | const myPath = '/api/v1/accounts/root/video-channel-syncs' | |
198 | ||
199 | it('Should fail with a bad start pagination', async function () { | |
200 | await checkBadStartPagination(server.url, myPath, server.accessToken) | |
201 | }) | |
202 | ||
203 | it('Should fail with a bad count pagination', async function () { | |
204 | await checkBadCountPagination(server.url, myPath, server.accessToken) | |
205 | }) | |
206 | ||
207 | it('Should fail with an incorrect sort', async function () { | |
208 | await checkBadSortPagination(server.url, myPath, server.accessToken) | |
209 | }) | |
210 | ||
211 | it('Should succeed with the correct parameters', async function () { | |
212 | await command.listByAccount({ | |
213 | accountName: 'root', | |
214 | token: server.accessToken, | |
215 | expectedStatus: HttpStatusCode.OK_200 | |
216 | }) | |
217 | }) | |
218 | ||
219 | it('Should fail with no authentication', async function () { | |
220 | await command.listByAccount({ | |
221 | accountName: 'root', | |
222 | token: null, | |
223 | expectedStatus: HttpStatusCode.UNAUTHORIZED_401 | |
224 | }) | |
225 | }) | |
226 | ||
227 | it('Should fail when a simple user lists another user\'s synchronizations', async function () { | |
228 | await command.listByAccount({ | |
229 | accountName: 'root', | |
230 | token: userInfo.accessToken, | |
231 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | |
232 | }) | |
233 | }) | |
234 | ||
235 | it('Should succeed when root lists another user\'s synchronizations', async function () { | |
236 | await command.listByAccount({ | |
237 | accountName: userInfo.username, | |
238 | token: server.accessToken, | |
239 | expectedStatus: HttpStatusCode.OK_200 | |
240 | }) | |
241 | }) | |
242 | ||
243 | it('Should succeed even with synchronization disabled', async function () { | |
244 | await withChannelSyncDisabled(async function () { | |
245 | await command.listByAccount({ | |
246 | accountName: 'root', | |
247 | token: server.accessToken, | |
248 | expectedStatus: HttpStatusCode.OK_200 | |
249 | }) | |
250 | }) | |
251 | }) | |
252 | }) | |
253 | ||
254 | describe('When triggering deletion', function () { | |
255 | it('should fail with no authentication', async function () { | |
256 | await command.delete({ | |
257 | channelSyncId: userInfo.syncId, | |
258 | token: null, | |
259 | expectedStatus: HttpStatusCode.UNAUTHORIZED_401 | |
260 | }) | |
261 | }) | |
262 | ||
263 | it('Should fail when channelSyncId does not refer to any sync', async function () { | |
264 | await command.delete({ | |
265 | channelSyncId: 42, | |
266 | token: server.accessToken, | |
267 | expectedStatus: HttpStatusCode.NOT_FOUND_404 | |
268 | }) | |
269 | }) | |
270 | ||
271 | it('Should fail when sync is not owned by the user', async function () { | |
272 | await command.delete({ | |
273 | channelSyncId: rootChannelSyncId, | |
274 | token: userInfo.accessToken, | |
275 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | |
276 | }) | |
277 | }) | |
278 | ||
279 | it('Should succeed when root delete a sync they do not own', async function () { | |
280 | await command.delete({ | |
281 | channelSyncId: userInfo.syncId, | |
282 | token: server.accessToken, | |
283 | expectedStatus: HttpStatusCode.NO_CONTENT_204 | |
284 | }) | |
285 | }) | |
286 | ||
287 | it('should succeed when user delete a sync they own', async function () { | |
288 | const { videoChannelSync } = await command.create({ | |
289 | attributes: { | |
290 | externalChannelUrl: FIXTURE_URLS.youtubeChannel, | |
291 | videoChannelId: userInfo.channelId | |
292 | }, | |
293 | token: server.accessToken, | |
294 | expectedStatus: HttpStatusCode.OK_200 | |
295 | }) | |
296 | ||
297 | await command.delete({ | |
298 | channelSyncId: videoChannelSync.id, | |
299 | token: server.accessToken, | |
300 | expectedStatus: HttpStatusCode.NO_CONTENT_204 | |
301 | }) | |
302 | }) | |
303 | ||
304 | it('Should succeed even when synchronization is disabled', async function () { | |
305 | await withChannelSyncDisabled(async function () { | |
306 | await command.delete({ | |
307 | channelSyncId: rootChannelSyncId, | |
308 | token: server.accessToken, | |
309 | expectedStatus: HttpStatusCode.NO_CONTENT_204 | |
310 | }) | |
311 | }) | |
312 | }) | |
313 | }) | |
314 | ||
315 | after(async function () { | |
316 | await server?.kill() | |
317 | }) | |
318 | }) |