From 754b6f5f41bdc40aaaeefdb3c351666c305abe20 Mon Sep 17 00:00:00 2001 From: Florian CUNY Date: Tue, 26 Oct 2021 16:42:10 +0200 Subject: [PATCH] Made the video channels limit (per user) server-wide configurable (#4491) * Made the video channels limit (per user) server-wide configurable Implements https://github.com/Chocobozzz/PeerTube/issues/3092 Also added a "quota bar" in the account's settings page * Fixed lint errors * Another pass at fixing lint errors * Applied code suggestions * Removed 'video channels quota' --- .../edit-basic-configuration.component.html | 22 +++++++++++++++++++ .../edit-custom-config.component.ts | 6 ++++- .../custom-config-validators.ts | 9 ++++++++ .../shared/shared-main/shared-main.module.ts | 7 +++++- config/default.yaml | 3 +++ config/production.yaml.example | 3 +++ server/controllers/api/config.ts | 3 +++ server/initializers/checker-before-init.ts | 1 + server/initializers/config.ts | 3 +++ server/initializers/constants.ts | 5 ----- server/lib/server-config-manager.ts | 3 +++ server/middlewares/validators/config.ts | 2 ++ .../validators/videos/video-channels.ts | 6 ++--- server/models/video/video-channel.ts | 5 +++-- server/tests/api/check-params/config.ts | 3 +++ server/tests/api/server/config.ts | 7 ++++++ shared/extra-utils/server/config-command.ts | 3 +++ shared/models/server/custom-config.model.ts | 4 ++++ shared/models/server/server-config.model.ts | 4 ++++ 19 files changed, 87 insertions(+), 12 deletions(-) diff --git a/client/src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html b/client/src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html index 537e06d4d..318c8e2c2 100644 --- a/client/src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html +++ b/client/src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.html @@ -272,6 +272,28 @@ +
+
+
VIDEO CHANNELS
+
+ +
+
+ + +
+ + {form.value['videoChannels']['maxPerUser'], plural, =1 {channel} other {channels}} +
+ +
{{ formErrors.videoChannels.maxPerUser }}
+
+
+
+
SEARCH
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts index 96c67fac7..fdb0a7532 100644 --- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts +++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts @@ -22,7 +22,8 @@ import { SERVICES_TWITTER_USERNAME_VALIDATOR, SIGNUP_LIMIT_VALIDATOR, SIGNUP_MINIMUM_AGE_VALIDATOR, - TRANSCODING_THREADS_VALIDATOR + TRANSCODING_THREADS_VALIDATOR, + MAX_VIDEO_CHANNELS_PER_USER_VALIDATOR } from '@app/shared/form-validators/custom-config-validators' import { USER_VIDEO_QUOTA_DAILY_VALIDATOR, USER_VIDEO_QUOTA_VALIDATOR } from '@app/shared/form-validators/user-validators' import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' @@ -151,6 +152,9 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit { videoQuota: USER_VIDEO_QUOTA_VALIDATOR, videoQuotaDaily: USER_VIDEO_QUOTA_DAILY_VALIDATOR }, + videoChannels: { + maxPerUser: MAX_VIDEO_CHANNELS_PER_USER_VALIDATOR + }, transcoding: { enabled: null, threads: TRANSCODING_THREADS_VALIDATOR, diff --git a/client/src/app/shared/form-validators/custom-config-validators.ts b/client/src/app/shared/form-validators/custom-config-validators.ts index fbf423d08..ba8512e95 100644 --- a/client/src/app/shared/form-validators/custom-config-validators.ts +++ b/client/src/app/shared/form-validators/custom-config-validators.ts @@ -98,6 +98,15 @@ export const MAX_USER_LIVES_VALIDATOR: BuildFormValidator = { } } +export const MAX_VIDEO_CHANNELS_PER_USER_VALIDATOR: BuildFormValidator = { + VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ], + MESSAGES: { + required: $localize`Max video channels per user is required.`, + min: $localize`Max video channels per user must be greater or equal to 1.`, + pattern: $localize`Max video channels per user must be a number.` + } +} + export const CONCURRENCY_VALIDATOR: BuildFormValidator = { VALIDATORS: [ Validators.required, Validators.min(1) ], MESSAGES: { diff --git a/client/src/app/shared/shared-main/shared-main.module.ts b/client/src/app/shared/shared-main/shared-main.module.ts index 80d0a84f3..93989780d 100644 --- a/client/src/app/shared/shared-main/shared-main.module.ts +++ b/client/src/app/shared/shared-main/shared-main.module.ts @@ -43,7 +43,12 @@ import { } from './misc' import { PluginPlaceholderComponent } from './plugins' import { ActorRedirectGuard } from './router' -import { UserHistoryService, UserNotificationsComponent, UserNotificationService, UserQuotaComponent } from './users' +import { + UserHistoryService, + UserNotificationsComponent, + UserNotificationService, + UserQuotaComponent +} from './users' import { RedundancyService, VideoImportService, VideoOwnershipService, VideoService } from './video' import { VideoCaptionService } from './video-caption' import { VideoChannelService } from './video-channel' diff --git a/config/default.yaml b/config/default.yaml index f545382c8..cf9d69a62 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -296,6 +296,9 @@ user: video_quota: -1 video_quota_daily: -1 +video_channels: + max_per_user: 20 # Allows each user to create up to 20 video channels. + # If enabled, the video will be transcoded to mp4 (x264) with `faststart` flag # In addition, if some resolutions are enabled the mp4 video file will be transcoded to these new resolutions # Please, do not disable transcoding since many uploaded videos will not work diff --git a/config/production.yaml.example b/config/production.yaml.example index 2e0d029ce..70993bf57 100644 --- a/config/production.yaml.example +++ b/config/production.yaml.example @@ -306,6 +306,9 @@ user: video_quota: -1 video_quota_daily: -1 +video_channels: + max_per_user: 20 # Allows each user to create up to 20 video channels. + # If enabled, the video will be transcoded to mp4 (x264) with `faststart` flag # In addition, if some resolutions are enabled the mp4 video file will be transcoded to these new resolutions # Please, do not disable transcoding since many uploaded videos will not work diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts index 5ea1f67c9..8965cacc9 100644 --- a/server/controllers/api/config.ts +++ b/server/controllers/api/config.ts @@ -196,6 +196,9 @@ function customConfig (): CustomConfig { videoQuota: CONFIG.USER.VIDEO_QUOTA, videoQuotaDaily: CONFIG.USER.VIDEO_QUOTA_DAILY }, + videoChannels: { + maxPerUser: CONFIG.VIDEO_CHANNELS.MAX_PER_USER + }, transcoding: { enabled: CONFIG.TRANSCODING.ENABLED, allowAdditionalExtensions: CONFIG.TRANSCODING.ALLOW_ADDITIONAL_EXTENSIONS, diff --git a/server/initializers/checker-before-init.ts b/server/initializers/checker-before-init.ts index 16dc137c0..72acdd422 100644 --- a/server/initializers/checker-before-init.ts +++ b/server/initializers/checker-before-init.ts @@ -19,6 +19,7 @@ function checkMissedConfig () { 'storage.redundancy', 'storage.tmp', 'storage.streaming_playlists', 'storage.plugins', 'log.level', 'user.video_quota', 'user.video_quota_daily', + 'video_channels.max_per_user', 'csp.enabled', 'csp.report_only', 'csp.report_uri', 'security.frameguard.enabled', 'cache.previews.size', 'cache.captions.size', 'cache.torrents.size', 'admin.email', 'contact_form.enabled', diff --git a/server/initializers/config.ts b/server/initializers/config.ts index cab60a61f..8375bf430 100644 --- a/server/initializers/config.ts +++ b/server/initializers/config.ts @@ -233,6 +233,9 @@ const CONFIG = { get VIDEO_QUOTA () { return parseBytes(config.get('user.video_quota')) }, get VIDEO_QUOTA_DAILY () { return parseBytes(config.get('user.video_quota_daily')) } }, + VIDEO_CHANNELS: { + get MAX_PER_USER () { return config.get('video_channels.max_per_user') } + }, TRANSCODING: { get ENABLED () { return config.get('transcoding.enabled') }, get ALLOW_ADDITIONAL_EXTENSIONS () { return config.get('transcoding.allow_additional_extensions') }, diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index f6c19dab4..3781f9508 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts @@ -512,10 +512,6 @@ const OVERVIEWS = { } } -const VIDEO_CHANNELS = { - MAX_PER_USER: 20 -} - // --------------------------------------------------------------------------- const SERVER_ACTOR_NAME = 'peertube' @@ -897,7 +893,6 @@ export { VIDEO_TRANSCODING_FPS, FFMPEG_NICE, ABUSE_STATES, - VIDEO_CHANNELS, LRU_CACHE, REQUEST_TIMEOUT, USER_PASSWORD_RESET_LIFETIME, diff --git a/server/lib/server-config-manager.ts b/server/lib/server-config-manager.ts index b78251e8c..bdf6492f9 100644 --- a/server/lib/server-config-manager.ts +++ b/server/lib/server-config-manager.ts @@ -184,6 +184,9 @@ class ServerConfigManager { videoQuota: CONFIG.USER.VIDEO_QUOTA, videoQuotaDaily: CONFIG.USER.VIDEO_QUOTA_DAILY }, + videoChannels: { + maxPerUser: CONFIG.VIDEO_CHANNELS.MAX_PER_USER + }, trending: { videos: { intervalDays: CONFIG.TRENDING.VIDEOS.INTERVAL_DAYS, diff --git a/server/middlewares/validators/config.ts b/server/middlewares/validators/config.ts index f0385ab44..da52b14ba 100644 --- a/server/middlewares/validators/config.ts +++ b/server/middlewares/validators/config.ts @@ -38,6 +38,8 @@ const customConfigUpdateValidator = [ body('user.videoQuota').custom(isUserVideoQuotaValid).withMessage('Should have a valid video quota'), body('user.videoQuotaDaily').custom(isUserVideoQuotaDailyValid).withMessage('Should have a valid daily video quota'), + body('videoChannels.maxPerUser').isInt().withMessage("Should have a valid maximum amount of video channels per user"), + body('transcoding.enabled').isBoolean().withMessage('Should have a valid transcoding enabled boolean'), body('transcoding.allowAdditionalExtensions').isBoolean().withMessage('Should have a valid additional extensions boolean'), body('transcoding.threads').isInt().withMessage('Should have a valid transcoding threads number'), diff --git a/server/middlewares/validators/videos/video-channels.ts b/server/middlewares/validators/videos/video-channels.ts index c4705192a..edce48c7f 100644 --- a/server/middlewares/validators/videos/video-channels.ts +++ b/server/middlewares/validators/videos/video-channels.ts @@ -1,6 +1,5 @@ import express from 'express' import { body, param, query } from 'express-validator' -import { VIDEO_CHANNELS } from '@server/initializers/constants' import { MChannelAccountDefault, MUser } from '@server/types/models' import { UserRight } from '../../../../shared' import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes' @@ -15,6 +14,7 @@ import { logger } from '../../../helpers/logger' import { ActorModel } from '../../../models/actor/actor' import { VideoChannelModel } from '../../../models/video/video-channel' import { areValidationErrors, doesLocalVideoChannelNameExist, doesVideoChannelNameWithHostExist } from '../shared' +import { CONFIG } from '@server/initializers/config' const videoChannelsAddValidator = [ body('name').custom(isVideoChannelUsernameValid).withMessage('Should have a valid channel name'), @@ -37,8 +37,8 @@ const videoChannelsAddValidator = [ } const count = await VideoChannelModel.countByAccount(res.locals.oauth.token.User.Account.id) - if (count >= VIDEO_CHANNELS.MAX_PER_USER) { - res.fail({ message: `You cannot create more than ${VIDEO_CHANNELS.MAX_PER_USER} channels` }) + if (count >= CONFIG.VIDEO_CHANNELS.MAX_PER_USER) { + res.fail({ message: `You cannot create more than ${CONFIG.VIDEO_CHANNELS.MAX_PER_USER} channels` }) return false } diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index 4151dc5b5..b652d8531 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts @@ -26,7 +26,7 @@ import { isVideoChannelDisplayNameValid, isVideoChannelSupportValid } from '../../helpers/custom-validators/video-channels' -import { CONSTRAINTS_FIELDS, VIDEO_CHANNELS, WEBSERVER } from '../../initializers/constants' +import { CONSTRAINTS_FIELDS, WEBSERVER } from '../../initializers/constants' import { sendDeleteActor } from '../../lib/activitypub/send' import { MChannelActor, @@ -44,6 +44,7 @@ import { setAsUpdated } from '../shared' import { buildServerIdsFollowedBy, buildTrigramSearchIndex, createSimilarityAttribute, getSort, throwIfNotValid } from '../utils' import { VideoModel } from './video' import { VideoPlaylistModel } from './video-playlist' +import { CONFIG } from '@server/initializers/config' export enum ScopeNames { FOR_API = 'FOR_API', @@ -584,7 +585,7 @@ ON "Account->Actor"."serverId" = "Account->Actor->Server"."id"` static listAllByAccount (accountId: number) { const query = { - limit: VIDEO_CHANNELS.MAX_PER_USER, + limit: CONFIG.VIDEO_CHANNELS.MAX_PER_USER, include: [ { attributes: [], diff --git a/server/tests/api/check-params/config.ts b/server/tests/api/check-params/config.ts index 87cb2287e..273b1f718 100644 --- a/server/tests/api/check-params/config.ts +++ b/server/tests/api/check-params/config.ts @@ -81,6 +81,9 @@ describe('Test config API validators', function () { videoQuota: 5242881, videoQuotaDaily: 318742 }, + videoChannels: { + maxPerUser: 20 + }, transcoding: { enabled: true, allowAdditionalExtensions: true, diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts index 1d996d454..8d5b3ac7f 100644 --- a/server/tests/api/server/config.ts +++ b/server/tests/api/server/config.ts @@ -58,6 +58,8 @@ function checkInitialConfig (server: PeerTubeServer, data: CustomConfig) { expect(data.user.videoQuota).to.equal(5242880) expect(data.user.videoQuotaDaily).to.equal(-1) + expect(data.videoChannels.maxPerUser).to.equal(20) + expect(data.transcoding.enabled).to.be.false expect(data.transcoding.allowAdditionalExtensions).to.be.false expect(data.transcoding.allowAudioFiles).to.be.false @@ -153,6 +155,8 @@ function checkUpdatedConfig (data: CustomConfig) { expect(data.user.videoQuota).to.equal(5242881) expect(data.user.videoQuotaDaily).to.equal(318742) + expect(data.videoChannels.maxPerUser).to.equal(24) + expect(data.transcoding.enabled).to.be.true expect(data.transcoding.threads).to.equal(1) expect(data.transcoding.concurrency).to.equal(3) @@ -265,6 +269,9 @@ const newCustomConfig: CustomConfig = { videoQuota: 5242881, videoQuotaDaily: 318742 }, + videoChannels: { + maxPerUser: 24 + }, transcoding: { enabled: true, allowAdditionalExtensions: true, diff --git a/shared/extra-utils/server/config-command.ts b/shared/extra-utils/server/config-command.ts index 51d04fa63..2746e9ac4 100644 --- a/shared/extra-utils/server/config-command.ts +++ b/shared/extra-utils/server/config-command.ts @@ -220,6 +220,9 @@ export class ConfigCommand extends AbstractCommand { videoQuota: 5242881, videoQuotaDaily: 318742 }, + videoChannels: { + maxPerUser: 20 + }, transcoding: { enabled: true, allowAdditionalExtensions: true, diff --git a/shared/models/server/custom-config.model.ts b/shared/models/server/custom-config.model.ts index 75d04423a..322fbb797 100644 --- a/shared/models/server/custom-config.model.ts +++ b/shared/models/server/custom-config.model.ts @@ -85,6 +85,10 @@ export interface CustomConfig { videoQuotaDaily: number } + videoChannels: { + maxPerUser: number + } + transcoding: { enabled: boolean diff --git a/shared/models/server/server-config.model.ts b/shared/models/server/server-config.model.ts index a0313b8da..e75eefd47 100644 --- a/shared/models/server/server-config.model.ts +++ b/shared/models/server/server-config.model.ts @@ -203,6 +203,10 @@ export interface ServerConfig { videoQuotaDaily: number } + videoChannels: { + maxPerUser: number + } + trending: { videos: { intervalDays: number -- 2.41.0