diff options
19 files changed, 147 insertions, 5 deletions
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html index 2f3202e06..686f3601b 100644 --- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html +++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html | |||
@@ -740,6 +740,16 @@ | |||
740 | </div> | 740 | </div> |
741 | 741 | ||
742 | <div class="form-group" [ngClass]="{ 'disabled-checkbox-extra': !isLiveEnabled() }"> | 742 | <div class="form-group" [ngClass]="{ 'disabled-checkbox-extra': !isLiveEnabled() }"> |
743 | <label i18n for="liveMaxInstanceLives">Max lives created on your instance (-1 for "unlimited")</label> | ||
744 | <input type="number" name="liveMaxInstanceLives" formControlName="maxInstanceLives" /> | ||
745 | </div> | ||
746 | |||
747 | <div class="form-group" [ngClass]="{ 'disabled-checkbox-extra': !isLiveEnabled() }"> | ||
748 | <label i18n for="liveMaxUserLives">Max lives created per user (-1 for "unlimited")</label> | ||
749 | <input type="number" name="liveMaxUserLives" formControlName="maxUserLives" /> | ||
750 | </div> | ||
751 | |||
752 | <div class="form-group" [ngClass]="{ 'disabled-checkbox-extra': !isLiveEnabled() }"> | ||
743 | <label i18n for="liveMaxDuration">Max live duration</label> | 753 | <label i18n for="liveMaxDuration">Max live duration</label> |
744 | <div class="peertube-select-container"> | 754 | <div class="peertube-select-container"> |
745 | <select id="liveMaxDuration" formControlName="maxDuration" class="form-control"> | 755 | <select id="liveMaxDuration" formControlName="maxDuration" class="form-control"> |
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 745238647..de1cf46b1 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 | |||
@@ -216,6 +216,8 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit, A | |||
216 | enabled: null, | 216 | enabled: null, |
217 | 217 | ||
218 | maxDuration: null, | 218 | maxDuration: null, |
219 | maxInstanceLives: null, | ||
220 | maxUserLives: null, | ||
219 | allowReplay: null, | 221 | allowReplay: null, |
220 | 222 | ||
221 | transcoding: { | 223 | transcoding: { |
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts index 9868c37d2..870a70d3d 100644 --- a/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts +++ b/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts | |||
@@ -7,7 +7,7 @@ import { scrollToTop } from '@app/helpers' | |||
7 | import { FormValidatorService } from '@app/shared/shared-forms' | 7 | import { FormValidatorService } from '@app/shared/shared-forms' |
8 | import { LiveVideoService, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main' | 8 | import { LiveVideoService, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main' |
9 | import { LoadingBarService } from '@ngx-loading-bar/core' | 9 | import { LoadingBarService } from '@ngx-loading-bar/core' |
10 | import { LiveVideo, LiveVideoCreate, LiveVideoUpdate, VideoPrivacy } from '@shared/models' | 10 | import { LiveVideo, LiveVideoCreate, LiveVideoUpdate, ServerErrorCode, VideoPrivacy } from '@shared/models' |
11 | import { VideoSend } from './video-send' | 11 | import { VideoSend } from './video-send' |
12 | 12 | ||
13 | @Component({ | 13 | @Component({ |
@@ -81,7 +81,16 @@ export class VideoGoLiveComponent extends VideoSend implements OnInit, CanCompon | |||
81 | 81 | ||
82 | err => { | 82 | err => { |
83 | this.firstStepError.emit() | 83 | this.firstStepError.emit() |
84 | this.notifier.error(err.message) | 84 | |
85 | let message = err.message | ||
86 | |||
87 | if (err.body?.code === ServerErrorCode.MAX_INSTANCE_LIVES_LIMIT_REACHED) { | ||
88 | message = $localize`Cannot create live because this instance have too many created lives` | ||
89 | } else if (err.body?.code) { | ||
90 | message = $localize`Cannot create live because you created too many lives` | ||
91 | } | ||
92 | |||
93 | this.notifier.error(message) | ||
85 | } | 94 | } |
86 | ) | 95 | ) |
87 | } | 96 | } |
diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts index c19c3c12e..1abf87118 100644 --- a/client/src/app/core/server/server.service.ts +++ b/client/src/app/core/server/server.service.ts | |||
@@ -78,6 +78,8 @@ export class ServerService { | |||
78 | enabled: false, | 78 | enabled: false, |
79 | allowReplay: true, | 79 | allowReplay: true, |
80 | maxDuration: null, | 80 | maxDuration: null, |
81 | maxInstanceLives: -1, | ||
82 | maxUserLives: -1, | ||
81 | transcoding: { | 83 | transcoding: { |
82 | enabled: false, | 84 | enabled: false, |
83 | enabledResolutions: [] | 85 | enabledResolutions: [] |
diff --git a/client/src/app/shared/shared-instance/instance-features-table.component.html b/client/src/app/shared/shared-instance/instance-features-table.component.html index 002695238..ce2557147 100644 --- a/client/src/app/shared/shared-instance/instance-features-table.component.html +++ b/client/src/app/shared/shared-instance/instance-features-table.component.html | |||
@@ -82,6 +82,13 @@ | |||
82 | </tr> | 82 | </tr> |
83 | 83 | ||
84 | <tr> | 84 | <tr> |
85 | <th i18n class="sub-label" scope="row">Max parallel lives</th> | ||
86 | <td i18n> | ||
87 | {{ maxUserLives }} per user / {{ maxInstanceLives }} per instance | ||
88 | </td> | ||
89 | </tr> | ||
90 | |||
91 | <tr> | ||
85 | <th i18n class="label" colspan="2">Import</th> | 92 | <th i18n class="label" colspan="2">Import</th> |
86 | </tr> | 93 | </tr> |
87 | 94 | ||
diff --git a/client/src/app/shared/shared-instance/instance-features-table.component.ts b/client/src/app/shared/shared-instance/instance-features-table.component.ts index 76b595c20..0166157f9 100644 --- a/client/src/app/shared/shared-instance/instance-features-table.component.ts +++ b/client/src/app/shared/shared-instance/instance-features-table.component.ts | |||
@@ -21,6 +21,20 @@ export class InstanceFeaturesTableComponent implements OnInit { | |||
21 | return Math.min(this.initialUserVideoQuota, this.serverConfig.user.videoQuotaDaily) | 21 | return Math.min(this.initialUserVideoQuota, this.serverConfig.user.videoQuotaDaily) |
22 | } | 22 | } |
23 | 23 | ||
24 | get maxInstanceLives () { | ||
25 | const value = this.serverConfig.live.maxInstanceLives | ||
26 | if (value === -1) return $localize`Unlimited` | ||
27 | |||
28 | return value | ||
29 | } | ||
30 | |||
31 | get maxUserLives () { | ||
32 | const value = this.serverConfig.live.maxUserLives | ||
33 | if (value === -1) return $localize`Unlimited` | ||
34 | |||
35 | return value | ||
36 | } | ||
37 | |||
24 | ngOnInit () { | 38 | ngOnInit () { |
25 | this.serverConfig = this.serverService.getTmpConfig() | 39 | this.serverConfig = this.serverService.getTmpConfig() |
26 | this.serverService.getConfig() | 40 | this.serverService.getConfig() |
diff --git a/config/default.yaml b/config/default.yaml index d0937bfc8..af16f081f 100644 --- a/config/default.yaml +++ b/config/default.yaml | |||
@@ -250,6 +250,14 @@ live: | |||
250 | # Set null to disable duration limit | 250 | # Set null to disable duration limit |
251 | max_duration: 5 hours | 251 | max_duration: 5 hours |
252 | 252 | ||
253 | # Limit max number of live videos created on your instance | ||
254 | # -1 == unlimited | ||
255 | max_instance_lives: 20 | ||
256 | |||
257 | # Limit max number of live videos created by a user on your instance | ||
258 | # -1 == unlimited | ||
259 | max_user_lives: 3 | ||
260 | |||
253 | # Allow your users to save a replay of their live | 261 | # Allow your users to save a replay of their live |
254 | # PeerTube will transcode segments in a video file | 262 | # PeerTube will transcode segments in a video file |
255 | # If the user daily/total quota is reached, PeerTube will stop the live | 263 | # If the user daily/total quota is reached, PeerTube will stop the live |
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts index 99aabba62..eb9f5f4b4 100644 --- a/server/controllers/api/config.ts +++ b/server/controllers/api/config.ts | |||
@@ -120,6 +120,8 @@ async function getConfig (req: express.Request, res: express.Response) { | |||
120 | 120 | ||
121 | allowReplay: CONFIG.LIVE.ALLOW_REPLAY, | 121 | allowReplay: CONFIG.LIVE.ALLOW_REPLAY, |
122 | maxDuration: CONFIG.LIVE.MAX_DURATION, | 122 | maxDuration: CONFIG.LIVE.MAX_DURATION, |
123 | maxInstanceLives: CONFIG.LIVE.MAX_INSTANCE_LIVES, | ||
124 | maxUserLives: CONFIG.LIVE.MAX_USER_LIVES, | ||
123 | 125 | ||
124 | transcoding: { | 126 | transcoding: { |
125 | enabled: CONFIG.LIVE.TRANSCODING.ENABLED, | 127 | enabled: CONFIG.LIVE.TRANSCODING.ENABLED, |
@@ -430,6 +432,8 @@ function customConfig (): CustomConfig { | |||
430 | enabled: CONFIG.LIVE.ENABLED, | 432 | enabled: CONFIG.LIVE.ENABLED, |
431 | allowReplay: CONFIG.LIVE.ALLOW_REPLAY, | 433 | allowReplay: CONFIG.LIVE.ALLOW_REPLAY, |
432 | maxDuration: CONFIG.LIVE.MAX_DURATION, | 434 | maxDuration: CONFIG.LIVE.MAX_DURATION, |
435 | maxInstanceLives: CONFIG.LIVE.MAX_INSTANCE_LIVES, | ||
436 | maxUserLives: CONFIG.LIVE.MAX_USER_LIVES, | ||
433 | transcoding: { | 437 | transcoding: { |
434 | enabled: CONFIG.LIVE.TRANSCODING.ENABLED, | 438 | enabled: CONFIG.LIVE.TRANSCODING.ENABLED, |
435 | threads: CONFIG.LIVE.TRANSCODING.THREADS, | 439 | threads: CONFIG.LIVE.TRANSCODING.THREADS, |
diff --git a/server/initializers/checker-before-init.ts b/server/initializers/checker-before-init.ts index d4140e3fa..93b71a242 100644 --- a/server/initializers/checker-before-init.ts +++ b/server/initializers/checker-before-init.ts | |||
@@ -38,7 +38,7 @@ function checkMissedConfig () { | |||
38 | 'federation.videos.federate_unlisted', | 38 | 'federation.videos.federate_unlisted', |
39 | 'search.remote_uri.users', 'search.remote_uri.anonymous', 'search.search_index.enabled', 'search.search_index.url', | 39 | 'search.remote_uri.users', 'search.remote_uri.anonymous', 'search.search_index.enabled', 'search.search_index.url', |
40 | 'search.search_index.disable_local_search', 'search.search_index.is_default_search', | 40 | 'search.search_index.disable_local_search', 'search.search_index.is_default_search', |
41 | 'live.enabled', 'live.allow_replay', 'live.max_duration', | 41 | 'live.enabled', 'live.allow_replay', 'live.max_duration', 'live.max_user_lives', 'live.max_instance_lives', |
42 | 'live.transcoding.enabled', 'live.transcoding.threads', | 42 | 'live.transcoding.enabled', 'live.transcoding.threads', |
43 | 'live.transcoding.resolutions.240p', 'live.transcoding.resolutions.360p', 'live.transcoding.resolutions.480p', | 43 | 'live.transcoding.resolutions.240p', 'live.transcoding.resolutions.360p', 'live.transcoding.resolutions.480p', |
44 | 'live.transcoding.resolutions.720p', 'live.transcoding.resolutions.1080p', 'live.transcoding.resolutions.2160p' | 44 | 'live.transcoding.resolutions.720p', 'live.transcoding.resolutions.1080p', 'live.transcoding.resolutions.2160p' |
diff --git a/server/initializers/config.ts b/server/initializers/config.ts index 9e8927350..b70361aa9 100644 --- a/server/initializers/config.ts +++ b/server/initializers/config.ts | |||
@@ -202,6 +202,9 @@ const CONFIG = { | |||
202 | get ENABLED () { return config.get<boolean>('live.enabled') }, | 202 | get ENABLED () { return config.get<boolean>('live.enabled') }, |
203 | 203 | ||
204 | get MAX_DURATION () { return parseDurationToMs(config.get<string>('live.max_duration')) }, | 204 | get MAX_DURATION () { return parseDurationToMs(config.get<string>('live.max_duration')) }, |
205 | get MAX_INSTANCE_LIVES () { return config.get<number>('live.max_instance_lives') }, | ||
206 | get MAX_USER_LIVES () { return config.get<number>('live.max_user_lives') }, | ||
207 | |||
205 | get ALLOW_REPLAY () { return config.get<boolean>('live.allow_replay') }, | 208 | get ALLOW_REPLAY () { return config.get<boolean>('live.allow_replay') }, |
206 | 209 | ||
207 | RTMP: { | 210 | RTMP: { |
diff --git a/server/middlewares/validators/config.ts b/server/middlewares/validators/config.ts index 41a6ae4f9..d0071ccc1 100644 --- a/server/middlewares/validators/config.ts +++ b/server/middlewares/validators/config.ts | |||
@@ -65,6 +65,8 @@ const customConfigUpdateValidator = [ | |||
65 | body('live.enabled').isBoolean().withMessage('Should have a valid live enabled boolean'), | 65 | body('live.enabled').isBoolean().withMessage('Should have a valid live enabled boolean'), |
66 | body('live.allowReplay').isBoolean().withMessage('Should have a valid live allow replay boolean'), | 66 | body('live.allowReplay').isBoolean().withMessage('Should have a valid live allow replay boolean'), |
67 | body('live.maxDuration').custom(isIntOrNull).withMessage('Should have a valid live max duration'), | 67 | body('live.maxDuration').custom(isIntOrNull).withMessage('Should have a valid live max duration'), |
68 | body('live.maxInstanceLives').custom(isIntOrNull).withMessage('Should have a valid max instance lives'), | ||
69 | body('live.maxUserLives').custom(isIntOrNull).withMessage('Should have a valid max user lives'), | ||
68 | body('live.transcoding.enabled').isBoolean().withMessage('Should have a valid live transcoding enabled boolean'), | 70 | body('live.transcoding.enabled').isBoolean().withMessage('Should have a valid live transcoding enabled boolean'), |
69 | body('live.transcoding.threads').isInt().withMessage('Should have a valid live transcoding threads'), | 71 | body('live.transcoding.threads').isInt().withMessage('Should have a valid live transcoding threads'), |
70 | body('live.transcoding.resolutions.240p').isBoolean().withMessage('Should have a valid transcoding 240p resolution enabled boolean'), | 72 | body('live.transcoding.resolutions.240p').isBoolean().withMessage('Should have a valid transcoding 240p resolution enabled boolean'), |
diff --git a/server/middlewares/validators/videos/video-live.ts b/server/middlewares/validators/videos/video-live.ts index ab57e67bf..69200cb60 100644 --- a/server/middlewares/validators/videos/video-live.ts +++ b/server/middlewares/validators/videos/video-live.ts | |||
@@ -2,7 +2,7 @@ import * as express from 'express' | |||
2 | import { body, param } from 'express-validator' | 2 | import { body, param } from 'express-validator' |
3 | import { checkUserCanManageVideo, doesVideoChannelOfAccountExist, doesVideoExist } from '@server/helpers/middlewares/videos' | 3 | import { checkUserCanManageVideo, doesVideoChannelOfAccountExist, doesVideoExist } from '@server/helpers/middlewares/videos' |
4 | import { VideoLiveModel } from '@server/models/video/video-live' | 4 | import { VideoLiveModel } from '@server/models/video/video-live' |
5 | import { UserRight, VideoState } from '@shared/models' | 5 | import { ServerErrorCode, UserRight, VideoState } from '@shared/models' |
6 | import { isBooleanValid, isIdOrUUIDValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../../helpers/custom-validators/misc' | 6 | import { isBooleanValid, isIdOrUUIDValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../../helpers/custom-validators/misc' |
7 | import { isVideoNameValid } from '../../../helpers/custom-validators/videos' | 7 | import { isVideoNameValid } from '../../../helpers/custom-validators/videos' |
8 | import { cleanUpReqFiles } from '../../../helpers/express-utils' | 8 | import { cleanUpReqFiles } from '../../../helpers/express-utils' |
@@ -10,6 +10,7 @@ import { logger } from '../../../helpers/logger' | |||
10 | import { CONFIG } from '../../../initializers/config' | 10 | import { CONFIG } from '../../../initializers/config' |
11 | import { areValidationErrors } from '../utils' | 11 | import { areValidationErrors } from '../utils' |
12 | import { getCommonVideoEditAttributes } from './videos' | 12 | import { getCommonVideoEditAttributes } from './videos' |
13 | import { VideoModel } from '@server/models/video/video' | ||
13 | 14 | ||
14 | const videoLiveGetValidator = [ | 15 | const videoLiveGetValidator = [ |
15 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), | 16 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), |
@@ -50,11 +51,15 @@ const videoLiveAddValidator = getCommonVideoEditAttributes().concat([ | |||
50 | logger.debug('Checking videoLiveAddValidator parameters', { parameters: req.body }) | 51 | logger.debug('Checking videoLiveAddValidator parameters', { parameters: req.body }) |
51 | 52 | ||
52 | if (CONFIG.LIVE.ENABLED !== true) { | 53 | if (CONFIG.LIVE.ENABLED !== true) { |
54 | cleanUpReqFiles(req) | ||
55 | |||
53 | return res.status(403) | 56 | return res.status(403) |
54 | .json({ error: 'Live is not enabled on this instance' }) | 57 | .json({ error: 'Live is not enabled on this instance' }) |
55 | } | 58 | } |
56 | 59 | ||
57 | if (CONFIG.LIVE.ALLOW_REPLAY !== true && req.body.saveReplay === true) { | 60 | if (CONFIG.LIVE.ALLOW_REPLAY !== true && req.body.saveReplay === true) { |
61 | cleanUpReqFiles(req) | ||
62 | |||
58 | return res.status(403) | 63 | return res.status(403) |
59 | .json({ error: 'Saving live replay is not allowed instance' }) | 64 | .json({ error: 'Saving live replay is not allowed instance' }) |
60 | } | 65 | } |
@@ -64,6 +69,34 @@ const videoLiveAddValidator = getCommonVideoEditAttributes().concat([ | |||
64 | const user = res.locals.oauth.token.User | 69 | const user = res.locals.oauth.token.User |
65 | if (!await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req) | 70 | if (!await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req) |
66 | 71 | ||
72 | if (CONFIG.LIVE.MAX_INSTANCE_LIVES !== -1) { | ||
73 | const totalInstanceLives = await VideoModel.countLocalLives() | ||
74 | |||
75 | if (totalInstanceLives >= CONFIG.LIVE.MAX_INSTANCE_LIVES) { | ||
76 | cleanUpReqFiles(req) | ||
77 | |||
78 | return res.status(403) | ||
79 | .json({ | ||
80 | code: ServerErrorCode.MAX_INSTANCE_LIVES_LIMIT_REACHED, | ||
81 | error: 'Cannot create this live because the max instance lives limit is reached.' | ||
82 | }) | ||
83 | } | ||
84 | } | ||
85 | |||
86 | if (CONFIG.LIVE.MAX_USER_LIVES !== -1) { | ||
87 | const totalUserLives = await VideoModel.countLivesOfAccount(user.Account.id) | ||
88 | |||
89 | if (totalUserLives >= CONFIG.LIVE.MAX_USER_LIVES) { | ||
90 | cleanUpReqFiles(req) | ||
91 | |||
92 | return res.status(403) | ||
93 | .json({ | ||
94 | code: ServerErrorCode.MAX_USER_LIVES_LIMIT_REACHED, | ||
95 | error: 'Cannot create this live because the max user lives limit is reached.' | ||
96 | }) | ||
97 | } | ||
98 | } | ||
99 | |||
67 | return next() | 100 | return next() |
68 | } | 101 | } |
69 | ]) | 102 | ]) |
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 78fec5585..d094f19b0 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -1142,6 +1142,37 @@ export class VideoModel extends Model<VideoModel> { | |||
1142 | return VideoModel.getAvailableForApi(queryOptions) | 1142 | return VideoModel.getAvailableForApi(queryOptions) |
1143 | } | 1143 | } |
1144 | 1144 | ||
1145 | static countLocalLives () { | ||
1146 | const options = { | ||
1147 | where: { | ||
1148 | remote: false, | ||
1149 | isLive: true | ||
1150 | } | ||
1151 | } | ||
1152 | |||
1153 | return VideoModel.count(options) | ||
1154 | } | ||
1155 | |||
1156 | static countLivesOfAccount (accountId: number) { | ||
1157 | const options = { | ||
1158 | where: { | ||
1159 | remote: false, | ||
1160 | isLive: true | ||
1161 | }, | ||
1162 | include: [ | ||
1163 | { | ||
1164 | required: true, | ||
1165 | model: VideoChannelModel.unscoped(), | ||
1166 | where: { | ||
1167 | accountId | ||
1168 | } | ||
1169 | } | ||
1170 | ] | ||
1171 | } | ||
1172 | |||
1173 | return VideoModel.count(options) | ||
1174 | } | ||
1175 | |||
1145 | static load (id: number | string, t?: Transaction): Bluebird<MVideoThumbnail> { | 1176 | static load (id: number | string, t?: Transaction): Bluebird<MVideoThumbnail> { |
1146 | const where = buildWhereIdOrUUID(id) | 1177 | const where = buildWhereIdOrUUID(id) |
1147 | const options = { | 1178 | const options = { |
diff --git a/server/tests/api/check-params/config.ts b/server/tests/api/check-params/config.ts index 2882ceb7c..42ac5e1f9 100644 --- a/server/tests/api/check-params/config.ts +++ b/server/tests/api/check-params/config.ts | |||
@@ -105,6 +105,8 @@ describe('Test config API validators', function () { | |||
105 | 105 | ||
106 | allowReplay: false, | 106 | allowReplay: false, |
107 | maxDuration: null, | 107 | maxDuration: null, |
108 | maxInstanceLives: -1, | ||
109 | maxUserLives: 50, | ||
108 | 110 | ||
109 | transcoding: { | 111 | transcoding: { |
110 | enabled: true, | 112 | enabled: true, |
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts index a7f035362..6c37be113 100644 --- a/server/tests/api/server/config.ts +++ b/server/tests/api/server/config.ts | |||
@@ -81,6 +81,8 @@ function checkInitialConfig (server: ServerInfo, data: CustomConfig) { | |||
81 | expect(data.live.enabled).to.be.false | 81 | expect(data.live.enabled).to.be.false |
82 | expect(data.live.allowReplay).to.be.true | 82 | expect(data.live.allowReplay).to.be.true |
83 | expect(data.live.maxDuration).to.equal(1000 * 3600 * 5) | 83 | expect(data.live.maxDuration).to.equal(1000 * 3600 * 5) |
84 | expect(data.live.maxInstanceLives).to.equal(20) | ||
85 | expect(data.live.maxUserLives).to.equal(3) | ||
84 | expect(data.live.transcoding.enabled).to.be.false | 86 | expect(data.live.transcoding.enabled).to.be.false |
85 | expect(data.live.transcoding.threads).to.equal(2) | 87 | expect(data.live.transcoding.threads).to.equal(2) |
86 | expect(data.live.transcoding.resolutions['240p']).to.be.false | 88 | expect(data.live.transcoding.resolutions['240p']).to.be.false |
@@ -166,6 +168,8 @@ function checkUpdatedConfig (data: CustomConfig) { | |||
166 | expect(data.live.enabled).to.be.true | 168 | expect(data.live.enabled).to.be.true |
167 | expect(data.live.allowReplay).to.be.false | 169 | expect(data.live.allowReplay).to.be.false |
168 | expect(data.live.maxDuration).to.equal(5000) | 170 | expect(data.live.maxDuration).to.equal(5000) |
171 | expect(data.live.maxInstanceLives).to.equal(-1) | ||
172 | expect(data.live.maxUserLives).to.equal(10) | ||
169 | expect(data.live.transcoding.enabled).to.be.true | 173 | expect(data.live.transcoding.enabled).to.be.true |
170 | expect(data.live.transcoding.threads).to.equal(4) | 174 | expect(data.live.transcoding.threads).to.equal(4) |
171 | expect(data.live.transcoding.resolutions['240p']).to.be.true | 175 | expect(data.live.transcoding.resolutions['240p']).to.be.true |
@@ -330,6 +334,8 @@ describe('Test config', function () { | |||
330 | enabled: true, | 334 | enabled: true, |
331 | allowReplay: false, | 335 | allowReplay: false, |
332 | maxDuration: 5000, | 336 | maxDuration: 5000, |
337 | maxInstanceLives: -1, | ||
338 | maxUserLives: 10, | ||
333 | transcoding: { | 339 | transcoding: { |
334 | enabled: true, | 340 | enabled: true, |
335 | threads: 4, | 341 | threads: 4, |
diff --git a/shared/extra-utils/server/config.ts b/shared/extra-utils/server/config.ts index bb7e23d54..7c1ad0a75 100644 --- a/shared/extra-utils/server/config.ts +++ b/shared/extra-utils/server/config.ts | |||
@@ -130,6 +130,8 @@ function updateCustomSubConfig (url: string, token: string, newConfig: DeepParti | |||
130 | enabled: true, | 130 | enabled: true, |
131 | allowReplay: false, | 131 | allowReplay: false, |
132 | maxDuration: null, | 132 | maxDuration: null, |
133 | maxInstanceLives: -1, | ||
134 | maxUserLives: 50, | ||
133 | transcoding: { | 135 | transcoding: { |
134 | enabled: true, | 136 | enabled: true, |
135 | threads: 4, | 137 | threads: 4, |
diff --git a/shared/models/server/custom-config.model.ts b/shared/models/server/custom-config.model.ts index 11b2ef2eb..67e05e23f 100644 --- a/shared/models/server/custom-config.model.ts +++ b/shared/models/server/custom-config.model.ts | |||
@@ -99,7 +99,10 @@ export interface CustomConfig { | |||
99 | enabled: boolean | 99 | enabled: boolean |
100 | 100 | ||
101 | allowReplay: boolean | 101 | allowReplay: boolean |
102 | |||
102 | maxDuration: number | 103 | maxDuration: number |
104 | maxInstanceLives: number | ||
105 | maxUserLives: number | ||
103 | 106 | ||
104 | transcoding: { | 107 | transcoding: { |
105 | enabled: boolean | 108 | enabled: boolean |
diff --git a/shared/models/server/server-config.model.ts b/shared/models/server/server-config.model.ts index 1563d848e..a01fcbe41 100644 --- a/shared/models/server/server-config.model.ts +++ b/shared/models/server/server-config.model.ts | |||
@@ -102,6 +102,8 @@ export interface ServerConfig { | |||
102 | enabled: boolean | 102 | enabled: boolean |
103 | 103 | ||
104 | maxDuration: number | 104 | maxDuration: number |
105 | maxInstanceLives: number | ||
106 | maxUserLives: number | ||
105 | allowReplay: boolean | 107 | allowReplay: boolean |
106 | 108 | ||
107 | transcoding: { | 109 | transcoding: { |
diff --git a/shared/models/server/server-error-code.enum.ts b/shared/models/server/server-error-code.enum.ts index 0bfb2c470..c02b0e6c7 100644 --- a/shared/models/server/server-error-code.enum.ts +++ b/shared/models/server/server-error-code.enum.ts | |||
@@ -1,3 +1,5 @@ | |||
1 | export const enum ServerErrorCode { | 1 | export const enum ServerErrorCode { |
2 | DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS = 1 | 2 | DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS = 1, |
3 | MAX_INSTANCE_LIVES_LIMIT_REACHED = 2, | ||
4 | MAX_USER_LIVES_LIMIT_REACHED = 3, | ||
3 | } | 5 | } |