users.ts 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158
  1. /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
  2. import { omit } from 'lodash'
  3. import 'mocha'
  4. import { join } from 'path'
  5. import { User, UserRole, VideoImport, VideoImportState } from '../../../../shared'
  6. import {
  7. addVideoChannel,
  8. blockUser,
  9. cleanupTests,
  10. createUser,
  11. deleteMe,
  12. flushAndRunServer,
  13. getMyUserInformation,
  14. getMyUserVideoRating,
  15. getUsersList,
  16. immutableAssign,
  17. killallServers,
  18. makeGetRequest,
  19. makePostBodyRequest,
  20. makePutBodyRequest,
  21. makeUploadRequest,
  22. registerUser,
  23. removeUser,
  24. reRunServer,
  25. ServerInfo,
  26. setAccessTokensToServers,
  27. unblockUser,
  28. updateUser,
  29. uploadVideo,
  30. userLogin
  31. } from '../../../../shared/extra-utils'
  32. import {
  33. checkBadCountPagination,
  34. checkBadSortPagination,
  35. checkBadStartPagination
  36. } from '../../../../shared/extra-utils/requests/check-api-params'
  37. import { getMagnetURI, getMyVideoImports, getYoutubeVideoUrl, importVideo } from '../../../../shared/extra-utils/videos/video-imports'
  38. import { VideoPrivacy } from '../../../../shared/models/videos'
  39. import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
  40. import { expect } from 'chai'
  41. import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
  42. import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
  43. describe('Test users API validators', function () {
  44. const path = '/api/v1/users/'
  45. let userId: number
  46. let rootId: number
  47. let moderatorId: number
  48. let videoId: number
  49. let server: ServerInfo
  50. let serverWithRegistrationDisabled: ServerInfo
  51. let userAccessToken = ''
  52. let moderatorAccessToken = ''
  53. let emailPort: number
  54. let overrideConfig: Object
  55. // ---------------------------------------------------------------
  56. before(async function () {
  57. this.timeout(30000)
  58. const emails: object[] = []
  59. emailPort = await MockSmtpServer.Instance.collectEmails(emails)
  60. overrideConfig = { signup: { limit: 8 } }
  61. {
  62. const res = await Promise.all([
  63. flushAndRunServer(1, overrideConfig),
  64. flushAndRunServer(2)
  65. ])
  66. server = res[0]
  67. serverWithRegistrationDisabled = res[1]
  68. await setAccessTokensToServers([ server ])
  69. }
  70. {
  71. const user = {
  72. username: 'user1',
  73. password: 'my super password'
  74. }
  75. const videoQuota = 42000000
  76. await createUser({
  77. url: server.url,
  78. accessToken: server.accessToken,
  79. username: user.username,
  80. password: user.password,
  81. videoQuota: videoQuota
  82. })
  83. userAccessToken = await userLogin(server, user)
  84. }
  85. {
  86. const moderator = {
  87. username: 'moderator1',
  88. password: 'super password'
  89. }
  90. await createUser({
  91. url: server.url,
  92. accessToken: server.accessToken,
  93. username: moderator.username,
  94. password: moderator.password,
  95. role: UserRole.MODERATOR
  96. })
  97. moderatorAccessToken = await userLogin(server, moderator)
  98. }
  99. {
  100. const moderator = {
  101. username: 'moderator2',
  102. password: 'super password'
  103. }
  104. await createUser({
  105. url: server.url,
  106. accessToken: server.accessToken,
  107. username: moderator.username,
  108. password: moderator.password,
  109. role: UserRole.MODERATOR
  110. })
  111. }
  112. {
  113. const res = await uploadVideo(server.url, server.accessToken, {})
  114. videoId = res.body.video.id
  115. }
  116. {
  117. const res = await getUsersList(server.url, server.accessToken)
  118. const users: User[] = res.body.data
  119. userId = users.find(u => u.username === 'user1').id
  120. rootId = users.find(u => u.username === 'root').id
  121. moderatorId = users.find(u => u.username === 'moderator2').id
  122. }
  123. })
  124. describe('When listing users', function () {
  125. it('Should fail with a bad start pagination', async function () {
  126. await checkBadStartPagination(server.url, path, server.accessToken)
  127. })
  128. it('Should fail with a bad count pagination', async function () {
  129. await checkBadCountPagination(server.url, path, server.accessToken)
  130. })
  131. it('Should fail with an incorrect sort', async function () {
  132. await checkBadSortPagination(server.url, path, server.accessToken)
  133. })
  134. it('Should fail with a bad blocked/banned user filter', async function () {
  135. await makeGetRequest({
  136. url: server.url,
  137. path,
  138. query: {
  139. blocked: 42
  140. },
  141. token: server.accessToken,
  142. statusCodeExpected: 400
  143. })
  144. })
  145. it('Should fail with a non authenticated user', async function () {
  146. await makeGetRequest({
  147. url: server.url,
  148. path,
  149. statusCodeExpected: 401
  150. })
  151. })
  152. it('Should fail with a non admin user', async function () {
  153. await makeGetRequest({
  154. url: server.url,
  155. path,
  156. token: userAccessToken,
  157. statusCodeExpected: 403
  158. })
  159. })
  160. })
  161. describe('When adding a new user', function () {
  162. const baseCorrectParams = {
  163. username: 'user2',
  164. email: 'test@example.com',
  165. password: 'my super password',
  166. videoQuota: -1,
  167. videoQuotaDaily: -1,
  168. role: UserRole.USER,
  169. adminFlags: UserAdminFlag.BYPASS_VIDEO_AUTO_BLACKLIST
  170. }
  171. it('Should fail with a too small username', async function () {
  172. const fields = immutableAssign(baseCorrectParams, { username: '' })
  173. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  174. })
  175. it('Should fail with a too long username', async function () {
  176. const fields = immutableAssign(baseCorrectParams, { username: 'super'.repeat(50) })
  177. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  178. })
  179. it('Should fail with a not lowercase username', async function () {
  180. const fields = immutableAssign(baseCorrectParams, { username: 'Toto' })
  181. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  182. })
  183. it('Should fail with an incorrect username', async function () {
  184. const fields = immutableAssign(baseCorrectParams, { username: 'my username' })
  185. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  186. })
  187. it('Should fail with a missing email', async function () {
  188. const fields = omit(baseCorrectParams, 'email')
  189. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  190. })
  191. it('Should fail with an invalid email', async function () {
  192. const fields = immutableAssign(baseCorrectParams, { email: 'test_example.com' })
  193. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  194. })
  195. it('Should fail with a too small password', async function () {
  196. const fields = immutableAssign(baseCorrectParams, { password: 'bla' })
  197. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  198. })
  199. it('Should fail with a too long password', async function () {
  200. const fields = immutableAssign(baseCorrectParams, { password: 'super'.repeat(61) })
  201. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  202. })
  203. it('Should fail with empty password and no smtp configured', async function () {
  204. const fields = immutableAssign(baseCorrectParams, { password: '' })
  205. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  206. })
  207. it('Should succeed with no password on a server with smtp enabled', async function () {
  208. this.timeout(10000)
  209. killallServers([ server ])
  210. const config = immutableAssign(overrideConfig, {
  211. smtp: {
  212. hostname: 'localhost',
  213. port: emailPort
  214. }
  215. })
  216. await reRunServer(server, config)
  217. const fields = immutableAssign(baseCorrectParams, {
  218. password: '',
  219. username: 'create_password',
  220. email: 'create_password@example.com'
  221. })
  222. await makePostBodyRequest({
  223. url: server.url,
  224. path: path,
  225. token: server.accessToken,
  226. fields,
  227. statusCodeExpected: 200
  228. })
  229. })
  230. it('Should fail with invalid admin flags', async function () {
  231. const fields = immutableAssign(baseCorrectParams, { adminFlags: 'toto' })
  232. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  233. })
  234. it('Should fail with an non authenticated user', async function () {
  235. await makePostBodyRequest({
  236. url: server.url,
  237. path,
  238. token: 'super token',
  239. fields: baseCorrectParams,
  240. statusCodeExpected: 401
  241. })
  242. })
  243. it('Should fail if we add a user with the same username', async function () {
  244. const fields = immutableAssign(baseCorrectParams, { username: 'user1' })
  245. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 409 })
  246. })
  247. it('Should fail if we add a user with the same email', async function () {
  248. const fields = immutableAssign(baseCorrectParams, { email: 'user1@example.com' })
  249. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 409 })
  250. })
  251. it('Should fail without a videoQuota', async function () {
  252. const fields = omit(baseCorrectParams, 'videoQuota')
  253. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  254. })
  255. it('Should fail without a videoQuotaDaily', async function () {
  256. const fields = omit(baseCorrectParams, 'videoQuotaDaily')
  257. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  258. })
  259. it('Should fail with an invalid videoQuota', async function () {
  260. const fields = immutableAssign(baseCorrectParams, { videoQuota: -5 })
  261. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  262. })
  263. it('Should fail with an invalid videoQuotaDaily', async function () {
  264. const fields = immutableAssign(baseCorrectParams, { videoQuotaDaily: -7 })
  265. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  266. })
  267. it('Should fail without a user role', async function () {
  268. const fields = omit(baseCorrectParams, 'role')
  269. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  270. })
  271. it('Should fail with an invalid user role', async function () {
  272. const fields = immutableAssign(baseCorrectParams, { role: 88989 })
  273. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  274. })
  275. it('Should fail with a "peertube" username', async function () {
  276. const fields = immutableAssign(baseCorrectParams, { username: 'peertube' })
  277. await makePostBodyRequest({
  278. url: server.url,
  279. path,
  280. token: server.accessToken,
  281. fields,
  282. statusCodeExpected: 409
  283. })
  284. })
  285. it('Should fail to create a moderator or an admin with a moderator', async function () {
  286. for (const role of [ UserRole.MODERATOR, UserRole.ADMINISTRATOR ]) {
  287. const fields = immutableAssign(baseCorrectParams, { role })
  288. await makePostBodyRequest({
  289. url: server.url,
  290. path,
  291. token: moderatorAccessToken,
  292. fields,
  293. statusCodeExpected: 403
  294. })
  295. }
  296. })
  297. it('Should succeed to create a user with a moderator', async function () {
  298. const fields = immutableAssign(baseCorrectParams, { username: 'a4656', email: 'a4656@example.com', role: UserRole.USER })
  299. await makePostBodyRequest({
  300. url: server.url,
  301. path,
  302. token: moderatorAccessToken,
  303. fields,
  304. statusCodeExpected: 200
  305. })
  306. })
  307. it('Should succeed with the correct params', async function () {
  308. await makePostBodyRequest({
  309. url: server.url,
  310. path,
  311. token: server.accessToken,
  312. fields: baseCorrectParams,
  313. statusCodeExpected: 200
  314. })
  315. })
  316. it('Should fail with a non admin user', async function () {
  317. const user = {
  318. username: 'user1',
  319. password: 'my super password'
  320. }
  321. userAccessToken = await userLogin(server, user)
  322. const fields = {
  323. username: 'user3',
  324. email: 'test@example.com',
  325. password: 'my super password',
  326. videoQuota: 42000000
  327. }
  328. await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields, statusCodeExpected: 403 })
  329. })
  330. })
  331. describe('When updating my account', function () {
  332. it('Should fail with an invalid email attribute', async function () {
  333. const fields = {
  334. email: 'blabla'
  335. }
  336. await makePutBodyRequest({ url: server.url, path: path + 'me', token: server.accessToken, fields })
  337. })
  338. it('Should fail with a too small password', async function () {
  339. const fields = {
  340. currentPassword: 'my super password',
  341. password: 'bla'
  342. }
  343. await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
  344. })
  345. it('Should fail with a too long password', async function () {
  346. const fields = {
  347. currentPassword: 'my super password',
  348. password: 'super'.repeat(61)
  349. }
  350. await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
  351. })
  352. it('Should fail without the current password', async function () {
  353. const fields = {
  354. currentPassword: 'my super password',
  355. password: 'super'.repeat(61)
  356. }
  357. await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
  358. })
  359. it('Should fail with an invalid current password', async function () {
  360. const fields = {
  361. currentPassword: 'my super password fail',
  362. password: 'super'.repeat(61)
  363. }
  364. await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 401 })
  365. })
  366. it('Should fail with an invalid NSFW policy attribute', async function () {
  367. const fields = {
  368. nsfwPolicy: 'hello'
  369. }
  370. await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
  371. })
  372. it('Should fail with an invalid autoPlayVideo attribute', async function () {
  373. const fields = {
  374. autoPlayVideo: -1
  375. }
  376. await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
  377. })
  378. it('Should fail with an invalid autoPlayNextVideo attribute', async function () {
  379. const fields = {
  380. autoPlayNextVideo: -1
  381. }
  382. await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
  383. })
  384. it('Should fail with an invalid videosHistoryEnabled attribute', async function () {
  385. const fields = {
  386. videosHistoryEnabled: -1
  387. }
  388. await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
  389. })
  390. it('Should fail with an non authenticated user', async function () {
  391. const fields = {
  392. currentPassword: 'my super password',
  393. password: 'my super password'
  394. }
  395. await makePutBodyRequest({ url: server.url, path: path + 'me', token: 'super token', fields, statusCodeExpected: 401 })
  396. })
  397. it('Should fail with a too long description', async function () {
  398. const fields = {
  399. description: 'super'.repeat(201)
  400. }
  401. await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
  402. })
  403. it('Should fail with an invalid videoLanguages attribute', async function () {
  404. {
  405. const fields = {
  406. videoLanguages: 'toto'
  407. }
  408. await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
  409. }
  410. {
  411. const languages = []
  412. for (let i = 0; i < 1000; i++) {
  413. languages.push('fr')
  414. }
  415. const fields = {
  416. videoLanguages: languages
  417. }
  418. await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
  419. }
  420. })
  421. it('Should fail with an invalid theme', async function () {
  422. const fields = { theme: 'invalid' }
  423. await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
  424. })
  425. it('Should fail with an unknown theme', async function () {
  426. const fields = { theme: 'peertube-theme-unknown' }
  427. await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
  428. })
  429. it('Should fail with an invalid noInstanceConfigWarningModal attribute', async function () {
  430. const fields = {
  431. noInstanceConfigWarningModal: -1
  432. }
  433. await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
  434. })
  435. it('Should fail with an invalid noWelcomeModal attribute', async function () {
  436. const fields = {
  437. noWelcomeModal: -1
  438. }
  439. await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
  440. })
  441. it('Should succeed to change password with the correct params', async function () {
  442. const fields = {
  443. currentPassword: 'my super password',
  444. password: 'my super password',
  445. nsfwPolicy: 'blur',
  446. autoPlayVideo: false,
  447. email: 'super_email@example.com',
  448. theme: 'default',
  449. noInstanceConfigWarningModal: true,
  450. noWelcomeModal: true
  451. }
  452. await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 204 })
  453. })
  454. it('Should succeed without password change with the correct params', async function () {
  455. const fields = {
  456. nsfwPolicy: 'blur',
  457. autoPlayVideo: false
  458. }
  459. await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 204 })
  460. })
  461. })
  462. describe('When updating my avatar', function () {
  463. it('Should fail without an incorrect input file', async function () {
  464. const fields = {}
  465. const attaches = {
  466. avatarfile: join(__dirname, '..', '..', 'fixtures', 'video_short.mp4')
  467. }
  468. await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
  469. })
  470. it('Should fail with a big file', async function () {
  471. const fields = {}
  472. const attaches = {
  473. avatarfile: join(__dirname, '..', '..', 'fixtures', 'avatar-big.png')
  474. }
  475. await makeUploadRequest({ url: server.url, path: path + '/me/avatar/pick', token: server.accessToken, fields, attaches })
  476. })
  477. it('Should fail with an unauthenticated user', async function () {
  478. const fields = {}
  479. const attaches = {
  480. avatarfile: join(__dirname, '..', '..', 'fixtures', 'avatar.png')
  481. }
  482. await makeUploadRequest({
  483. url: server.url,
  484. path: path + '/me/avatar/pick',
  485. fields,
  486. attaches,
  487. statusCodeExpected: 401
  488. })
  489. })
  490. it('Should succeed with the correct params', async function () {
  491. const fields = {}
  492. const attaches = {
  493. avatarfile: join(__dirname, '..', '..', 'fixtures', 'avatar.png')
  494. }
  495. await makeUploadRequest({
  496. url: server.url,
  497. path: path + '/me/avatar/pick',
  498. token: server.accessToken,
  499. fields,
  500. attaches,
  501. statusCodeExpected: 200
  502. })
  503. })
  504. })
  505. describe('When getting a user', function () {
  506. it('Should fail with an non authenticated user', async function () {
  507. await makeGetRequest({ url: server.url, path: path + userId, token: 'super token', statusCodeExpected: 401 })
  508. })
  509. it('Should fail with a non admin user', async function () {
  510. await makeGetRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: 403 })
  511. })
  512. it('Should succeed with the correct params', async function () {
  513. await makeGetRequest({ url: server.url, path: path + userId, token: server.accessToken, statusCodeExpected: 200 })
  514. })
  515. })
  516. describe('When updating a user', function () {
  517. it('Should fail with an invalid email attribute', async function () {
  518. const fields = {
  519. email: 'blabla'
  520. }
  521. await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
  522. })
  523. it('Should fail with an invalid emailVerified attribute', async function () {
  524. const fields = {
  525. emailVerified: 'yes'
  526. }
  527. await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
  528. })
  529. it('Should fail with an invalid videoQuota attribute', async function () {
  530. const fields = {
  531. videoQuota: -90
  532. }
  533. await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
  534. })
  535. it('Should fail with an invalid user role attribute', async function () {
  536. const fields = {
  537. role: 54878
  538. }
  539. await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
  540. })
  541. it('Should fail with a too small password', async function () {
  542. const fields = {
  543. currentPassword: 'my super password',
  544. password: 'bla'
  545. }
  546. await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
  547. })
  548. it('Should fail with a too long password', async function () {
  549. const fields = {
  550. currentPassword: 'my super password',
  551. password: 'super'.repeat(61)
  552. }
  553. await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields })
  554. })
  555. it('Should fail with an non authenticated user', async function () {
  556. const fields = {
  557. videoQuota: 42
  558. }
  559. await makePutBodyRequest({ url: server.url, path: path + userId, token: 'super token', fields, statusCodeExpected: 401 })
  560. })
  561. it('Should fail when updating root role', async function () {
  562. const fields = {
  563. role: UserRole.MODERATOR
  564. }
  565. await makePutBodyRequest({ url: server.url, path: path + rootId, token: server.accessToken, fields })
  566. })
  567. it('Should fail with invalid admin flags', async function () {
  568. const fields = { adminFlags: 'toto' }
  569. await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  570. })
  571. it('Should fail to update an admin with a moderator', async function () {
  572. const fields = {
  573. videoQuota: 42
  574. }
  575. await makePutBodyRequest({
  576. url: server.url,
  577. path: path + moderatorId,
  578. token: moderatorAccessToken,
  579. fields,
  580. statusCodeExpected: 403
  581. })
  582. })
  583. it('Should succeed to update a user with a moderator', async function () {
  584. const fields = {
  585. videoQuota: 42
  586. }
  587. await makePutBodyRequest({
  588. url: server.url,
  589. path: path + userId,
  590. token: moderatorAccessToken,
  591. fields,
  592. statusCodeExpected: 204
  593. })
  594. })
  595. it('Should succeed with the correct params', async function () {
  596. const fields = {
  597. email: 'email@example.com',
  598. emailVerified: true,
  599. videoQuota: 42,
  600. role: UserRole.USER
  601. }
  602. await makePutBodyRequest({ url: server.url, path: path + userId, token: server.accessToken, fields, statusCodeExpected: 204 })
  603. })
  604. })
  605. describe('When getting my information', function () {
  606. it('Should fail with a non authenticated user', async function () {
  607. await getMyUserInformation(server.url, 'fake_token', 401)
  608. })
  609. it('Should success with the correct parameters', async function () {
  610. await getMyUserInformation(server.url, userAccessToken)
  611. })
  612. })
  613. describe('When getting my video rating', function () {
  614. it('Should fail with a non authenticated user', async function () {
  615. await getMyUserVideoRating(server.url, 'fake_token', videoId, 401)
  616. })
  617. it('Should fail with an incorrect video uuid', async function () {
  618. await getMyUserVideoRating(server.url, server.accessToken, 'blabla', 400)
  619. })
  620. it('Should fail with an unknown video', async function () {
  621. await getMyUserVideoRating(server.url, server.accessToken, '4da6fde3-88f7-4d16-b119-108df5630b06', 404)
  622. })
  623. it('Should succeed with the correct parameters', async function () {
  624. await getMyUserVideoRating(server.url, server.accessToken, videoId)
  625. })
  626. })
  627. describe('When retrieving my global ratings', function () {
  628. const path = '/api/v1/accounts/user1/ratings'
  629. it('Should fail with a bad start pagination', async function () {
  630. await checkBadStartPagination(server.url, path, userAccessToken)
  631. })
  632. it('Should fail with a bad count pagination', async function () {
  633. await checkBadCountPagination(server.url, path, userAccessToken)
  634. })
  635. it('Should fail with an incorrect sort', async function () {
  636. await checkBadSortPagination(server.url, path, userAccessToken)
  637. })
  638. it('Should fail with a unauthenticated user', async function () {
  639. await makeGetRequest({ url: server.url, path, statusCodeExpected: 401 })
  640. })
  641. it('Should fail with a another user', async function () {
  642. await makeGetRequest({ url: server.url, path, token: server.accessToken, statusCodeExpected: 403 })
  643. })
  644. it('Should fail with a bad type', async function () {
  645. await makeGetRequest({ url: server.url, path, token: userAccessToken, query: { rating: 'toto ' }, statusCodeExpected: 400 })
  646. })
  647. it('Should succeed with the correct params', async function () {
  648. await makeGetRequest({ url: server.url, path, token: userAccessToken, statusCodeExpected: 200 })
  649. })
  650. })
  651. describe('When blocking/unblocking/removing user', function () {
  652. it('Should fail with an incorrect id', async function () {
  653. await removeUser(server.url, 'blabla', server.accessToken, 400)
  654. await blockUser(server.url, 'blabla', server.accessToken, 400)
  655. await unblockUser(server.url, 'blabla', server.accessToken, 400)
  656. })
  657. it('Should fail with the root user', async function () {
  658. await removeUser(server.url, rootId, server.accessToken, 400)
  659. await blockUser(server.url, rootId, server.accessToken, 400)
  660. await unblockUser(server.url, rootId, server.accessToken, 400)
  661. })
  662. it('Should return 404 with a non existing id', async function () {
  663. await removeUser(server.url, 4545454, server.accessToken, 404)
  664. await blockUser(server.url, 4545454, server.accessToken, 404)
  665. await unblockUser(server.url, 4545454, server.accessToken, 404)
  666. })
  667. it('Should fail with a non admin user', async function () {
  668. await removeUser(server.url, userId, userAccessToken, 403)
  669. await blockUser(server.url, userId, userAccessToken, 403)
  670. await unblockUser(server.url, userId, userAccessToken, 403)
  671. })
  672. it('Should fail on a moderator with a moderator', async function () {
  673. await removeUser(server.url, moderatorId, moderatorAccessToken, 403)
  674. await blockUser(server.url, moderatorId, moderatorAccessToken, 403)
  675. await unblockUser(server.url, moderatorId, moderatorAccessToken, 403)
  676. })
  677. it('Should succeed on a user with a moderator', async function () {
  678. await blockUser(server.url, userId, moderatorAccessToken)
  679. await unblockUser(server.url, userId, moderatorAccessToken)
  680. })
  681. })
  682. describe('When deleting our account', function () {
  683. it('Should fail with with the root account', async function () {
  684. await deleteMe(server.url, server.accessToken, 400)
  685. })
  686. })
  687. describe('When registering a new user', function () {
  688. const registrationPath = path + '/register'
  689. const baseCorrectParams = {
  690. username: 'user3',
  691. displayName: 'super user',
  692. email: 'test3@example.com',
  693. password: 'my super password'
  694. }
  695. it('Should fail with a too small username', async function () {
  696. const fields = immutableAssign(baseCorrectParams, { username: '' })
  697. await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
  698. })
  699. it('Should fail with a too long username', async function () {
  700. const fields = immutableAssign(baseCorrectParams, { username: 'super'.repeat(50) })
  701. await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
  702. })
  703. it('Should fail with an incorrect username', async function () {
  704. const fields = immutableAssign(baseCorrectParams, { username: 'my username' })
  705. await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
  706. })
  707. it('Should fail with a missing email', async function () {
  708. const fields = omit(baseCorrectParams, 'email')
  709. await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
  710. })
  711. it('Should fail with an invalid email', async function () {
  712. const fields = immutableAssign(baseCorrectParams, { email: 'test_example.com' })
  713. await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
  714. })
  715. it('Should fail with a too small password', async function () {
  716. const fields = immutableAssign(baseCorrectParams, { password: 'bla' })
  717. await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
  718. })
  719. it('Should fail with a too long password', async function () {
  720. const fields = immutableAssign(baseCorrectParams, { password: 'super'.repeat(61) })
  721. await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
  722. })
  723. it('Should fail if we register a user with the same username', async function () {
  724. const fields = immutableAssign(baseCorrectParams, { username: 'root' })
  725. await makePostBodyRequest({
  726. url: server.url,
  727. path: registrationPath,
  728. token: server.accessToken,
  729. fields,
  730. statusCodeExpected: 409
  731. })
  732. })
  733. it('Should fail with a "peertube" username', async function () {
  734. const fields = immutableAssign(baseCorrectParams, { username: 'peertube' })
  735. await makePostBodyRequest({
  736. url: server.url,
  737. path: registrationPath,
  738. token: server.accessToken,
  739. fields,
  740. statusCodeExpected: 409
  741. })
  742. })
  743. it('Should fail if we register a user with the same email', async function () {
  744. const fields = immutableAssign(baseCorrectParams, { email: 'admin' + server.internalServerNumber + '@example.com' })
  745. await makePostBodyRequest({
  746. url: server.url,
  747. path: registrationPath,
  748. token: server.accessToken,
  749. fields,
  750. statusCodeExpected: 409
  751. })
  752. })
  753. it('Should fail with a bad display name', async function () {
  754. const fields = immutableAssign(baseCorrectParams, { displayName: 'a'.repeat(150) })
  755. await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
  756. })
  757. it('Should fail with a bad channel name', async function () {
  758. const fields = immutableAssign(baseCorrectParams, { channel: { name: '[]azf', displayName: 'toto' } })
  759. await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
  760. })
  761. it('Should fail with a bad channel display name', async function () {
  762. const fields = immutableAssign(baseCorrectParams, { channel: { name: 'toto', displayName: '' } })
  763. await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
  764. })
  765. it('Should fail with a channel name that is the same as username', async function () {
  766. const source = { username: 'super_user', channel: { name: 'super_user', displayName: 'display name' } }
  767. const fields = immutableAssign(baseCorrectParams, source)
  768. await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields })
  769. })
  770. it('Should fail with an existing channel', async function () {
  771. const videoChannelAttributesArg = { name: 'existing_channel', displayName: 'hello', description: 'super description' }
  772. await addVideoChannel(server.url, server.accessToken, videoChannelAttributesArg)
  773. const fields = immutableAssign(baseCorrectParams, { channel: { name: 'existing_channel', displayName: 'toto' } })
  774. await makePostBodyRequest({ url: server.url, path: registrationPath, token: server.accessToken, fields, statusCodeExpected: 409 })
  775. })
  776. it('Should succeed with the correct params', async function () {
  777. const fields = immutableAssign(baseCorrectParams, { channel: { name: 'super_channel', displayName: 'toto' } })
  778. await makePostBodyRequest({
  779. url: server.url,
  780. path: registrationPath,
  781. token: server.accessToken,
  782. fields: fields,
  783. statusCodeExpected: 204
  784. })
  785. })
  786. it('Should fail on a server with registration disabled', async function () {
  787. const fields = {
  788. username: 'user4',
  789. email: 'test4@example.com',
  790. password: 'my super password 4'
  791. }
  792. await makePostBodyRequest({
  793. url: serverWithRegistrationDisabled.url,
  794. path: registrationPath,
  795. token: serverWithRegistrationDisabled.accessToken,
  796. fields,
  797. statusCodeExpected: 403
  798. })
  799. })
  800. })
  801. describe('When registering multiple users on a server with users limit', function () {
  802. it('Should fail when after 3 registrations', async function () {
  803. await registerUser(server.url, 'user42', 'super password', 403)
  804. })
  805. })
  806. describe('When having a video quota', function () {
  807. it('Should fail with a user having too many videos', async function () {
  808. await updateUser({
  809. url: server.url,
  810. userId: rootId,
  811. accessToken: server.accessToken,
  812. videoQuota: 42
  813. })
  814. await uploadVideo(server.url, server.accessToken, {}, 403)
  815. })
  816. it('Should fail with a registered user having too many videos', async function () {
  817. this.timeout(30000)
  818. const user = {
  819. username: 'user3',
  820. password: 'my super password'
  821. }
  822. userAccessToken = await userLogin(server, user)
  823. const videoAttributes = { fixture: 'video_short2.webm' }
  824. await uploadVideo(server.url, userAccessToken, videoAttributes)
  825. await uploadVideo(server.url, userAccessToken, videoAttributes)
  826. await uploadVideo(server.url, userAccessToken, videoAttributes)
  827. await uploadVideo(server.url, userAccessToken, videoAttributes)
  828. await uploadVideo(server.url, userAccessToken, videoAttributes)
  829. await uploadVideo(server.url, userAccessToken, videoAttributes, 403)
  830. })
  831. it('Should fail to import with HTTP/Torrent/magnet', async function () {
  832. this.timeout(120000)
  833. const baseAttributes = {
  834. channelId: 1,
  835. privacy: VideoPrivacy.PUBLIC
  836. }
  837. await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { targetUrl: getYoutubeVideoUrl() }))
  838. await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { magnetUri: getMagnetURI() }))
  839. await importVideo(server.url, server.accessToken, immutableAssign(baseAttributes, { torrentfile: 'video-720p.torrent' as any }))
  840. await waitJobs([ server ])
  841. const res = await getMyVideoImports(server.url, server.accessToken)
  842. expect(res.body.total).to.equal(3)
  843. const videoImports: VideoImport[] = res.body.data
  844. expect(videoImports).to.have.lengthOf(3)
  845. for (const videoImport of videoImports) {
  846. expect(videoImport.state.id).to.equal(VideoImportState.FAILED)
  847. expect(videoImport.error).not.to.be.undefined
  848. expect(videoImport.error).to.contain('user video quota is exceeded')
  849. }
  850. })
  851. })
  852. describe('When having a daily video quota', function () {
  853. it('Should fail with a user having too many videos', async function () {
  854. await updateUser({
  855. url: server.url,
  856. userId: rootId,
  857. accessToken: server.accessToken,
  858. videoQuotaDaily: 42
  859. })
  860. await uploadVideo(server.url, server.accessToken, {}, 403)
  861. })
  862. })
  863. describe('When having an absolute and daily video quota', function () {
  864. it('Should fail if exceeding total quota', async function () {
  865. await updateUser({
  866. url: server.url,
  867. userId: rootId,
  868. accessToken: server.accessToken,
  869. videoQuota: 42,
  870. videoQuotaDaily: 1024 * 1024 * 1024
  871. })
  872. await uploadVideo(server.url, server.accessToken, {}, 403)
  873. })
  874. it('Should fail if exceeding daily quota', async function () {
  875. await updateUser({
  876. url: server.url,
  877. userId: rootId,
  878. accessToken: server.accessToken,
  879. videoQuota: 1024 * 1024 * 1024,
  880. videoQuotaDaily: 42
  881. })
  882. await uploadVideo(server.url, server.accessToken, {}, 403)
  883. })
  884. })
  885. describe('When asking a password reset', function () {
  886. const path = '/api/v1/users/ask-reset-password'
  887. it('Should fail with a missing email', async function () {
  888. const fields = {}
  889. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  890. })
  891. it('Should fail with an invalid email', async function () {
  892. const fields = { email: 'hello' }
  893. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  894. })
  895. it('Should success with the correct params', async function () {
  896. const fields = { email: 'admin@example.com' }
  897. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 204 })
  898. })
  899. })
  900. describe('When asking for an account verification email', function () {
  901. const path = '/api/v1/users/ask-send-verify-email'
  902. it('Should fail with a missing email', async function () {
  903. const fields = {}
  904. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  905. })
  906. it('Should fail with an invalid email', async function () {
  907. const fields = { email: 'hello' }
  908. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
  909. })
  910. it('Should succeed with the correct params', async function () {
  911. const fields = { email: 'admin@example.com' }
  912. await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 204 })
  913. })
  914. })
  915. after(async function () {
  916. MockSmtpServer.Instance.kill()
  917. await cleanupTests([ server, serverWithRegistrationDisabled ])
  918. })
  919. })