config.ts 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
  2. import 'mocha'
  3. import * as chai from 'chai'
  4. import { parallelTests } from '@shared/core-utils'
  5. import { CustomConfig, HttpStatusCode } from '@shared/models'
  6. import {
  7. cleanupTests,
  8. createSingleServer,
  9. killallServers,
  10. makeGetRequest,
  11. PeerTubeServer,
  12. setAccessTokensToServers
  13. } from '@shared/server-commands'
  14. const expect = chai.expect
  15. function checkInitialConfig (server: PeerTubeServer, data: CustomConfig) {
  16. expect(data.instance.name).to.equal('PeerTube')
  17. expect(data.instance.shortDescription).to.equal(
  18. 'PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.'
  19. )
  20. expect(data.instance.description).to.equal('Welcome to this PeerTube instance!')
  21. expect(data.instance.terms).to.equal('No terms for now.')
  22. expect(data.instance.creationReason).to.be.empty
  23. expect(data.instance.codeOfConduct).to.be.empty
  24. expect(data.instance.moderationInformation).to.be.empty
  25. expect(data.instance.administrator).to.be.empty
  26. expect(data.instance.maintenanceLifetime).to.be.empty
  27. expect(data.instance.businessModel).to.be.empty
  28. expect(data.instance.hardwareInformation).to.be.empty
  29. expect(data.instance.languages).to.have.lengthOf(0)
  30. expect(data.instance.categories).to.have.lengthOf(0)
  31. expect(data.instance.defaultClientRoute).to.equal('/videos/trending')
  32. expect(data.instance.isNSFW).to.be.false
  33. expect(data.instance.defaultNSFWPolicy).to.equal('display')
  34. expect(data.instance.customizations.css).to.be.empty
  35. expect(data.instance.customizations.javascript).to.be.empty
  36. expect(data.services.twitter.username).to.equal('@Chocobozzz')
  37. expect(data.services.twitter.whitelisted).to.be.false
  38. expect(data.client.videos.miniature.preferAuthorDisplayName).to.be.false
  39. expect(data.client.menu.login.redirectOnSingleExternalAuth).to.be.false
  40. expect(data.cache.previews.size).to.equal(1)
  41. expect(data.cache.captions.size).to.equal(1)
  42. expect(data.cache.torrents.size).to.equal(1)
  43. expect(data.signup.enabled).to.be.true
  44. expect(data.signup.limit).to.equal(4)
  45. expect(data.signup.minimumAge).to.equal(16)
  46. expect(data.signup.requiresEmailVerification).to.be.false
  47. expect(data.admin.email).to.equal('admin' + server.internalServerNumber + '@example.com')
  48. expect(data.contactForm.enabled).to.be.true
  49. expect(data.user.videoQuota).to.equal(5242880)
  50. expect(data.user.videoQuotaDaily).to.equal(-1)
  51. expect(data.videoChannels.maxPerUser).to.equal(20)
  52. expect(data.transcoding.enabled).to.be.false
  53. expect(data.transcoding.allowAdditionalExtensions).to.be.false
  54. expect(data.transcoding.allowAudioFiles).to.be.false
  55. expect(data.transcoding.threads).to.equal(2)
  56. expect(data.transcoding.concurrency).to.equal(2)
  57. expect(data.transcoding.profile).to.equal('default')
  58. expect(data.transcoding.resolutions['144p']).to.be.false
  59. expect(data.transcoding.resolutions['240p']).to.be.true
  60. expect(data.transcoding.resolutions['360p']).to.be.true
  61. expect(data.transcoding.resolutions['480p']).to.be.true
  62. expect(data.transcoding.resolutions['720p']).to.be.true
  63. expect(data.transcoding.resolutions['1080p']).to.be.true
  64. expect(data.transcoding.resolutions['1440p']).to.be.true
  65. expect(data.transcoding.resolutions['2160p']).to.be.true
  66. expect(data.transcoding.webtorrent.enabled).to.be.true
  67. expect(data.transcoding.hls.enabled).to.be.true
  68. expect(data.live.enabled).to.be.false
  69. expect(data.live.allowReplay).to.be.false
  70. expect(data.live.latencySetting.enabled).to.be.true
  71. expect(data.live.maxDuration).to.equal(-1)
  72. expect(data.live.maxInstanceLives).to.equal(20)
  73. expect(data.live.maxUserLives).to.equal(3)
  74. expect(data.live.transcoding.enabled).to.be.false
  75. expect(data.live.transcoding.threads).to.equal(2)
  76. expect(data.live.transcoding.profile).to.equal('default')
  77. expect(data.live.transcoding.resolutions['144p']).to.be.false
  78. expect(data.live.transcoding.resolutions['240p']).to.be.false
  79. expect(data.live.transcoding.resolutions['360p']).to.be.false
  80. expect(data.live.transcoding.resolutions['480p']).to.be.false
  81. expect(data.live.transcoding.resolutions['720p']).to.be.false
  82. expect(data.live.transcoding.resolutions['1080p']).to.be.false
  83. expect(data.live.transcoding.resolutions['1440p']).to.be.false
  84. expect(data.live.transcoding.resolutions['2160p']).to.be.false
  85. expect(data.videoStudio.enabled).to.be.false
  86. expect(data.import.videos.concurrency).to.equal(2)
  87. expect(data.import.videos.http.enabled).to.be.true
  88. expect(data.import.videos.torrent.enabled).to.be.true
  89. expect(data.autoBlacklist.videos.ofUsers.enabled).to.be.false
  90. expect(data.followers.instance.enabled).to.be.true
  91. expect(data.followers.instance.manualApproval).to.be.false
  92. expect(data.followings.instance.autoFollowBack.enabled).to.be.false
  93. expect(data.followings.instance.autoFollowIndex.enabled).to.be.false
  94. expect(data.followings.instance.autoFollowIndex.indexUrl).to.equal('')
  95. expect(data.broadcastMessage.enabled).to.be.false
  96. expect(data.broadcastMessage.level).to.equal('info')
  97. expect(data.broadcastMessage.message).to.equal('')
  98. expect(data.broadcastMessage.dismissable).to.be.false
  99. }
  100. function checkUpdatedConfig (data: CustomConfig) {
  101. expect(data.instance.name).to.equal('PeerTube updated')
  102. expect(data.instance.shortDescription).to.equal('my short description')
  103. expect(data.instance.description).to.equal('my super description')
  104. expect(data.instance.terms).to.equal('my super terms')
  105. expect(data.instance.creationReason).to.equal('my super creation reason')
  106. expect(data.instance.codeOfConduct).to.equal('my super coc')
  107. expect(data.instance.moderationInformation).to.equal('my super moderation information')
  108. expect(data.instance.administrator).to.equal('Kuja')
  109. expect(data.instance.maintenanceLifetime).to.equal('forever')
  110. expect(data.instance.businessModel).to.equal('my super business model')
  111. expect(data.instance.hardwareInformation).to.equal('2vCore 3GB RAM')
  112. expect(data.instance.languages).to.deep.equal([ 'en', 'es' ])
  113. expect(data.instance.categories).to.deep.equal([ 1, 2 ])
  114. expect(data.instance.defaultClientRoute).to.equal('/videos/recently-added')
  115. expect(data.instance.isNSFW).to.be.true
  116. expect(data.instance.defaultNSFWPolicy).to.equal('blur')
  117. expect(data.instance.customizations.javascript).to.equal('alert("coucou")')
  118. expect(data.instance.customizations.css).to.equal('body { background-color: red; }')
  119. expect(data.services.twitter.username).to.equal('@Kuja')
  120. expect(data.services.twitter.whitelisted).to.be.true
  121. expect(data.client.videos.miniature.preferAuthorDisplayName).to.be.true
  122. expect(data.client.menu.login.redirectOnSingleExternalAuth).to.be.true
  123. expect(data.cache.previews.size).to.equal(2)
  124. expect(data.cache.captions.size).to.equal(3)
  125. expect(data.cache.torrents.size).to.equal(4)
  126. expect(data.signup.enabled).to.be.false
  127. expect(data.signup.limit).to.equal(5)
  128. expect(data.signup.requiresEmailVerification).to.be.false
  129. expect(data.signup.minimumAge).to.equal(10)
  130. // We override admin email in parallel tests, so skip this exception
  131. if (parallelTests() === false) {
  132. expect(data.admin.email).to.equal('superadmin1@example.com')
  133. }
  134. expect(data.contactForm.enabled).to.be.false
  135. expect(data.user.videoQuota).to.equal(5242881)
  136. expect(data.user.videoQuotaDaily).to.equal(318742)
  137. expect(data.videoChannels.maxPerUser).to.equal(24)
  138. expect(data.transcoding.enabled).to.be.true
  139. expect(data.transcoding.threads).to.equal(1)
  140. expect(data.transcoding.concurrency).to.equal(3)
  141. expect(data.transcoding.allowAdditionalExtensions).to.be.true
  142. expect(data.transcoding.allowAudioFiles).to.be.true
  143. expect(data.transcoding.profile).to.equal('vod_profile')
  144. expect(data.transcoding.resolutions['144p']).to.be.false
  145. expect(data.transcoding.resolutions['240p']).to.be.false
  146. expect(data.transcoding.resolutions['360p']).to.be.true
  147. expect(data.transcoding.resolutions['480p']).to.be.true
  148. expect(data.transcoding.resolutions['720p']).to.be.false
  149. expect(data.transcoding.resolutions['1080p']).to.be.false
  150. expect(data.transcoding.resolutions['2160p']).to.be.false
  151. expect(data.transcoding.hls.enabled).to.be.false
  152. expect(data.transcoding.webtorrent.enabled).to.be.true
  153. expect(data.live.enabled).to.be.true
  154. expect(data.live.allowReplay).to.be.true
  155. expect(data.live.latencySetting.enabled).to.be.false
  156. expect(data.live.maxDuration).to.equal(5000)
  157. expect(data.live.maxInstanceLives).to.equal(-1)
  158. expect(data.live.maxUserLives).to.equal(10)
  159. expect(data.live.transcoding.enabled).to.be.true
  160. expect(data.live.transcoding.threads).to.equal(4)
  161. expect(data.live.transcoding.profile).to.equal('live_profile')
  162. expect(data.live.transcoding.resolutions['144p']).to.be.true
  163. expect(data.live.transcoding.resolutions['240p']).to.be.true
  164. expect(data.live.transcoding.resolutions['360p']).to.be.true
  165. expect(data.live.transcoding.resolutions['480p']).to.be.true
  166. expect(data.live.transcoding.resolutions['720p']).to.be.true
  167. expect(data.live.transcoding.resolutions['1080p']).to.be.true
  168. expect(data.live.transcoding.resolutions['2160p']).to.be.true
  169. expect(data.videoStudio.enabled).to.be.true
  170. expect(data.import.videos.concurrency).to.equal(4)
  171. expect(data.import.videos.http.enabled).to.be.false
  172. expect(data.import.videos.torrent.enabled).to.be.false
  173. expect(data.autoBlacklist.videos.ofUsers.enabled).to.be.true
  174. expect(data.followers.instance.enabled).to.be.false
  175. expect(data.followers.instance.manualApproval).to.be.true
  176. expect(data.followings.instance.autoFollowBack.enabled).to.be.true
  177. expect(data.followings.instance.autoFollowIndex.enabled).to.be.true
  178. expect(data.followings.instance.autoFollowIndex.indexUrl).to.equal('https://updated.example.com')
  179. expect(data.broadcastMessage.enabled).to.be.true
  180. expect(data.broadcastMessage.level).to.equal('error')
  181. expect(data.broadcastMessage.message).to.equal('super bad message')
  182. expect(data.broadcastMessage.dismissable).to.be.true
  183. }
  184. const newCustomConfig: CustomConfig = {
  185. instance: {
  186. name: 'PeerTube updated',
  187. shortDescription: 'my short description',
  188. description: 'my super description',
  189. terms: 'my super terms',
  190. codeOfConduct: 'my super coc',
  191. creationReason: 'my super creation reason',
  192. moderationInformation: 'my super moderation information',
  193. administrator: 'Kuja',
  194. maintenanceLifetime: 'forever',
  195. businessModel: 'my super business model',
  196. hardwareInformation: '2vCore 3GB RAM',
  197. languages: [ 'en', 'es' ],
  198. categories: [ 1, 2 ],
  199. isNSFW: true,
  200. defaultNSFWPolicy: 'blur' as 'blur',
  201. defaultClientRoute: '/videos/recently-added',
  202. customizations: {
  203. javascript: 'alert("coucou")',
  204. css: 'body { background-color: red; }'
  205. }
  206. },
  207. theme: {
  208. default: 'default'
  209. },
  210. services: {
  211. twitter: {
  212. username: '@Kuja',
  213. whitelisted: true
  214. }
  215. },
  216. client: {
  217. videos: {
  218. miniature: {
  219. preferAuthorDisplayName: true
  220. }
  221. },
  222. menu: {
  223. login: {
  224. redirectOnSingleExternalAuth: true
  225. }
  226. }
  227. },
  228. cache: {
  229. previews: {
  230. size: 2
  231. },
  232. captions: {
  233. size: 3
  234. },
  235. torrents: {
  236. size: 4
  237. }
  238. },
  239. signup: {
  240. enabled: false,
  241. limit: 5,
  242. requiresEmailVerification: false,
  243. minimumAge: 10
  244. },
  245. admin: {
  246. email: 'superadmin1@example.com'
  247. },
  248. contactForm: {
  249. enabled: false
  250. },
  251. user: {
  252. videoQuota: 5242881,
  253. videoQuotaDaily: 318742
  254. },
  255. videoChannels: {
  256. maxPerUser: 24
  257. },
  258. transcoding: {
  259. enabled: true,
  260. allowAdditionalExtensions: true,
  261. allowAudioFiles: true,
  262. threads: 1,
  263. concurrency: 3,
  264. profile: 'vod_profile',
  265. resolutions: {
  266. '0p': false,
  267. '144p': false,
  268. '240p': false,
  269. '360p': true,
  270. '480p': true,
  271. '720p': false,
  272. '1080p': false,
  273. '1440p': false,
  274. '2160p': false
  275. },
  276. webtorrent: {
  277. enabled: true
  278. },
  279. hls: {
  280. enabled: false
  281. }
  282. },
  283. live: {
  284. enabled: true,
  285. allowReplay: true,
  286. latencySetting: {
  287. enabled: false
  288. },
  289. maxDuration: 5000,
  290. maxInstanceLives: -1,
  291. maxUserLives: 10,
  292. transcoding: {
  293. enabled: true,
  294. threads: 4,
  295. profile: 'live_profile',
  296. resolutions: {
  297. '144p': true,
  298. '240p': true,
  299. '360p': true,
  300. '480p': true,
  301. '720p': true,
  302. '1080p': true,
  303. '1440p': true,
  304. '2160p': true
  305. }
  306. }
  307. },
  308. videoStudio: {
  309. enabled: true
  310. },
  311. import: {
  312. videos: {
  313. concurrency: 4,
  314. http: {
  315. enabled: false
  316. },
  317. torrent: {
  318. enabled: false
  319. }
  320. }
  321. },
  322. trending: {
  323. videos: {
  324. algorithms: {
  325. enabled: [ 'hot', 'most-viewed', 'most-liked' ],
  326. default: 'hot'
  327. }
  328. }
  329. },
  330. autoBlacklist: {
  331. videos: {
  332. ofUsers: {
  333. enabled: true
  334. }
  335. }
  336. },
  337. followers: {
  338. instance: {
  339. enabled: false,
  340. manualApproval: true
  341. }
  342. },
  343. followings: {
  344. instance: {
  345. autoFollowBack: {
  346. enabled: true
  347. },
  348. autoFollowIndex: {
  349. enabled: true,
  350. indexUrl: 'https://updated.example.com'
  351. }
  352. }
  353. },
  354. broadcastMessage: {
  355. enabled: true,
  356. level: 'error',
  357. message: 'super bad message',
  358. dismissable: true
  359. },
  360. search: {
  361. remoteUri: {
  362. anonymous: true,
  363. users: true
  364. },
  365. searchIndex: {
  366. enabled: true,
  367. url: 'https://search.joinpeertube.org',
  368. disableLocalSearch: true,
  369. isDefaultSearch: true
  370. }
  371. }
  372. }
  373. describe('Test static config', function () {
  374. let server: PeerTubeServer = null
  375. before(async function () {
  376. this.timeout(30000)
  377. server = await createSingleServer(1, { webadmin: { configuration: { edition: { allowed: false } } } })
  378. await setAccessTokensToServers([ server ])
  379. })
  380. it('Should tell the client that edits are not allowed', async function () {
  381. const data = await server.config.getConfig()
  382. expect(data.webadmin.configuration.edition.allowed).to.be.false
  383. })
  384. it('Should error when client tries to update', async function () {
  385. await server.config.updateCustomConfig({ newCustomConfig, expectedStatus: 405 })
  386. })
  387. after(async function () {
  388. await cleanupTests([ server ])
  389. })
  390. })
  391. describe('Test config', function () {
  392. let server: PeerTubeServer = null
  393. before(async function () {
  394. this.timeout(30000)
  395. server = await createSingleServer(1)
  396. await setAccessTokensToServers([ server ])
  397. })
  398. it('Should have a correct config on a server with registration enabled', async function () {
  399. const data = await server.config.getConfig()
  400. expect(data.signup.allowed).to.be.true
  401. })
  402. it('Should have a correct config on a server with registration enabled and a users limit', async function () {
  403. this.timeout(5000)
  404. await Promise.all([
  405. server.users.register({ username: 'user1' }),
  406. server.users.register({ username: 'user2' }),
  407. server.users.register({ username: 'user3' })
  408. ])
  409. const data = await server.config.getConfig()
  410. expect(data.signup.allowed).to.be.false
  411. })
  412. it('Should have the correct video allowed extensions', async function () {
  413. const data = await server.config.getConfig()
  414. expect(data.video.file.extensions).to.have.lengthOf(3)
  415. expect(data.video.file.extensions).to.contain('.mp4')
  416. expect(data.video.file.extensions).to.contain('.webm')
  417. expect(data.video.file.extensions).to.contain('.ogv')
  418. await server.videos.upload({ attributes: { fixture: 'video_short.mkv' }, expectedStatus: HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415 })
  419. await server.videos.upload({ attributes: { fixture: 'sample.ogg' }, expectedStatus: HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415 })
  420. expect(data.contactForm.enabled).to.be.true
  421. })
  422. it('Should get the customized configuration', async function () {
  423. const data = await server.config.getCustomConfig()
  424. checkInitialConfig(server, data)
  425. })
  426. it('Should update the customized configuration', async function () {
  427. await server.config.updateCustomConfig({ newCustomConfig })
  428. const data = await server.config.getCustomConfig()
  429. checkUpdatedConfig(data)
  430. })
  431. it('Should have the correct updated video allowed extensions', async function () {
  432. this.timeout(10000)
  433. const data = await server.config.getConfig()
  434. expect(data.video.file.extensions).to.have.length.above(4)
  435. expect(data.video.file.extensions).to.contain('.mp4')
  436. expect(data.video.file.extensions).to.contain('.webm')
  437. expect(data.video.file.extensions).to.contain('.ogv')
  438. expect(data.video.file.extensions).to.contain('.flv')
  439. expect(data.video.file.extensions).to.contain('.wmv')
  440. expect(data.video.file.extensions).to.contain('.mkv')
  441. expect(data.video.file.extensions).to.contain('.mp3')
  442. expect(data.video.file.extensions).to.contain('.ogg')
  443. expect(data.video.file.extensions).to.contain('.flac')
  444. await server.videos.upload({ attributes: { fixture: 'video_short.mkv' }, expectedStatus: HttpStatusCode.OK_200 })
  445. await server.videos.upload({ attributes: { fixture: 'sample.ogg' }, expectedStatus: HttpStatusCode.OK_200 })
  446. })
  447. it('Should have the configuration updated after a restart', async function () {
  448. this.timeout(30000)
  449. await killallServers([ server ])
  450. await server.run()
  451. const data = await server.config.getCustomConfig()
  452. checkUpdatedConfig(data)
  453. })
  454. it('Should fetch the about information', async function () {
  455. const data = await server.config.getAbout()
  456. expect(data.instance.name).to.equal('PeerTube updated')
  457. expect(data.instance.shortDescription).to.equal('my short description')
  458. expect(data.instance.description).to.equal('my super description')
  459. expect(data.instance.terms).to.equal('my super terms')
  460. expect(data.instance.codeOfConduct).to.equal('my super coc')
  461. expect(data.instance.creationReason).to.equal('my super creation reason')
  462. expect(data.instance.moderationInformation).to.equal('my super moderation information')
  463. expect(data.instance.administrator).to.equal('Kuja')
  464. expect(data.instance.maintenanceLifetime).to.equal('forever')
  465. expect(data.instance.businessModel).to.equal('my super business model')
  466. expect(data.instance.hardwareInformation).to.equal('2vCore 3GB RAM')
  467. expect(data.instance.languages).to.deep.equal([ 'en', 'es' ])
  468. expect(data.instance.categories).to.deep.equal([ 1, 2 ])
  469. })
  470. it('Should remove the custom configuration', async function () {
  471. this.timeout(10000)
  472. await server.config.deleteCustomConfig()
  473. const data = await server.config.getCustomConfig()
  474. checkInitialConfig(server, data)
  475. })
  476. it('Should enable frameguard', async function () {
  477. this.timeout(25000)
  478. {
  479. const res = await makeGetRequest({
  480. url: server.url,
  481. path: '/api/v1/config',
  482. expectedStatus: 200
  483. })
  484. expect(res.headers['x-frame-options']).to.exist
  485. }
  486. await killallServers([ server ])
  487. const config = {
  488. security: {
  489. frameguard: { enabled: false }
  490. }
  491. }
  492. await server.run(config)
  493. {
  494. const res = await makeGetRequest({
  495. url: server.url,
  496. path: '/api/v1/config',
  497. expectedStatus: 200
  498. })
  499. expect(res.headers['x-frame-options']).to.not.exist
  500. }
  501. })
  502. after(async function () {
  503. await cleanupTests([ server ])
  504. })
  505. })