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