aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html5
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts7
-rw-r--r--client/src/app/core/server/server.service.ts3
-rw-r--r--client/src/app/videos/+video-edit/video-add.component.scss1
-rw-r--r--client/src/app/videos/+video-edit/video-add.component.ts2
-rw-r--r--config/default.yaml2
-rw-r--r--config/production.yaml.example2
-rw-r--r--config/test.yaml2
-rw-r--r--server/controllers/api/config.ts8
-rw-r--r--server/controllers/api/users.ts2
-rw-r--r--server/controllers/api/videos/import.ts10
-rw-r--r--server/initializers/constants.ts5
-rw-r--r--server/initializers/migrations/0245-import-magnet.ts42
-rw-r--r--server/lib/job-queue/handlers/video-import.ts9
-rw-r--r--server/middlewares/validators/config.ts1
-rw-r--r--server/middlewares/validators/video-imports.ts15
-rw-r--r--server/models/account/user.ts2
-rw-r--r--server/models/video/video-import.ts83
-rw-r--r--server/tests/api/check-params/config.ts3
-rw-r--r--server/tests/api/server/config.ts5
-rw-r--r--server/tests/utils/server/config.ts3
-rw-r--r--shared/models/server/custom-config.model.ts3
-rw-r--r--shared/models/server/server-config.model.ts3
23 files changed, 112 insertions, 106 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 13b43306b..0a032df12 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
@@ -108,6 +108,11 @@
108 i18n-labelText labelText="Video import with HTTP enabled" 108 i18n-labelText labelText="Video import with HTTP enabled"
109 ></my-peertube-checkbox> 109 ></my-peertube-checkbox>
110 110
111 <my-peertube-checkbox
112 inputName="importVideosTorrentEnabled" formControlName="importVideosTorrentEnabled"
113 i18n-labelText labelText="Video import with a torrent file or a magnet URI enabled"
114 ></my-peertube-checkbox>
115
111 <div i18n class="inner-form-title">Administrator</div> 116 <div i18n class="inner-form-title">Administrator</div>
112 117
113 <div class="form-group"> 118 <div class="form-group">
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 bc5ce6e5d..fd6784415 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
@@ -72,6 +72,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
72 signupEnabled: null, 72 signupEnabled: null,
73 signupLimit: this.customConfigValidatorsService.SIGNUP_LIMIT, 73 signupLimit: this.customConfigValidatorsService.SIGNUP_LIMIT,
74 importVideosHttpEnabled: null, 74 importVideosHttpEnabled: null,
75 importVideosTorrentEnabled: null,
75 adminEmail: this.customConfigValidatorsService.ADMIN_EMAIL, 76 adminEmail: this.customConfigValidatorsService.ADMIN_EMAIL,
76 userVideoQuota: this.userValidatorsService.USER_VIDEO_QUOTA, 77 userVideoQuota: this.userValidatorsService.USER_VIDEO_QUOTA,
77 transcodingThreads: this.customConfigValidatorsService.TRANSCODING_THREADS, 78 transcodingThreads: this.customConfigValidatorsService.TRANSCODING_THREADS,
@@ -189,6 +190,9 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
189 videos: { 190 videos: {
190 http: { 191 http: {
191 enabled: this.form.value['importVideosHttpEnabled'] 192 enabled: this.form.value['importVideosHttpEnabled']
193 },
194 torrent: {
195 enabled: this.form.value['importVideosTorrentEnabled']
192 } 196 }
193 } 197 }
194 } 198 }
@@ -231,7 +235,8 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
231 transcodingEnabled: this.customConfig.transcoding.enabled, 235 transcodingEnabled: this.customConfig.transcoding.enabled,
232 customizationJavascript: this.customConfig.instance.customizations.javascript, 236 customizationJavascript: this.customConfig.instance.customizations.javascript,
233 customizationCSS: this.customConfig.instance.customizations.css, 237 customizationCSS: this.customConfig.instance.customizations.css,
234 importVideosHttpEnabled: this.customConfig.import.videos.http.enabled 238 importVideosHttpEnabled: this.customConfig.import.videos.http.enabled,
239 importVideosTorrentEnabled: this.customConfig.import.videos.torrent.enabled
235 } 240 }
236 241
237 for (const resolution of this.resolutions) { 242 for (const resolution of this.resolutions) {
diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts
index ab317f0aa..52b50cbe8 100644
--- a/client/src/app/core/server/server.service.ts
+++ b/client/src/app/core/server/server.service.ts
@@ -73,6 +73,9 @@ export class ServerService {
73 videos: { 73 videos: {
74 http: { 74 http: {
75 enabled: false 75 enabled: false
76 },
77 torrent: {
78 enabled: false
76 } 79 }
77 } 80 }
78 } 81 }
diff --git a/client/src/app/videos/+video-edit/video-add.component.scss b/client/src/app/videos/+video-edit/video-add.component.scss
index 443361f50..c1f96cc37 100644
--- a/client/src/app/videos/+video-edit/video-add.component.scss
+++ b/client/src/app/videos/+video-edit/video-add.component.scss
@@ -50,6 +50,7 @@ $background-color: #F7F7F7;
50 border-radius: 3px; 50 border-radius: 3px;
51 width: 100%; 51 width: 100%;
52 min-height: 440px; 52 min-height: 440px;
53 padding-bottom: 20px;
53 display: flex; 54 display: flex;
54 justify-content: center; 55 justify-content: center;
55 align-items: center; 56 align-items: center;
diff --git a/client/src/app/videos/+video-edit/video-add.component.ts b/client/src/app/videos/+video-edit/video-add.component.ts
index 7d360598d..1a9247dbe 100644
--- a/client/src/app/videos/+video-edit/video-add.component.ts
+++ b/client/src/app/videos/+video-edit/video-add.component.ts
@@ -40,6 +40,6 @@ export class VideoAddComponent implements CanComponentDeactivate {
40 } 40 }
41 41
42 isVideoImportTorrentEnabled () { 42 isVideoImportTorrentEnabled () {
43 return this.serverService.getConfig().import.videos.http.enabled 43 return this.serverService.getConfig().import.videos.torrent.enabled
44 } 44 }
45} 45}
diff --git a/config/default.yaml b/config/default.yaml
index 5fa7e5945..60da192b4 100644
--- a/config/default.yaml
+++ b/config/default.yaml
@@ -97,6 +97,8 @@ import:
97 videos: 97 videos:
98 http: # Classic HTTP or all sites supported by youtube-dl https://rg3.github.io/youtube-dl/supportedsites.html 98 http: # Classic HTTP or all sites supported by youtube-dl https://rg3.github.io/youtube-dl/supportedsites.html
99 enabled: false 99 enabled: false
100 torrent: # Magnet URI or torrent file (use classic TCP/UDP/WebSeed to download the file)
101 enabled: false
100 102
101instance: 103instance:
102 name: 'PeerTube' 104 name: 'PeerTube'
diff --git a/config/production.yaml.example b/config/production.yaml.example
index 635a41e9e..9e8b57829 100644
--- a/config/production.yaml.example
+++ b/config/production.yaml.example
@@ -111,6 +111,8 @@ import:
111 videos: 111 videos:
112 http: # Classic HTTP or all sites supported by youtube-dl https://rg3.github.io/youtube-dl/supportedsites.html 112 http: # Classic HTTP or all sites supported by youtube-dl https://rg3.github.io/youtube-dl/supportedsites.html
113 enabled: false 113 enabled: false
114 torrent: # Magnet URI or torrent file (use classic TCP/UDP/WebSeed to download the file)
115 enabled: false
114 116
115# Instance settings 117# Instance settings
116instance: 118instance:
diff --git a/config/test.yaml b/config/test.yaml
index 3c51785f2..879b6bdd4 100644
--- a/config/test.yaml
+++ b/config/test.yaml
@@ -44,6 +44,8 @@ import:
44 videos: 44 videos:
45 http: 45 http:
46 enabled: true 46 enabled: true
47 torrent:
48 enabled: true
47 49
48instance: 50instance:
49 default_nsfw_policy: 'display' \ No newline at end of file 51 default_nsfw_policy: 'display' \ No newline at end of file
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts
index 950a1498e..6f05c33db 100644
--- a/server/controllers/api/config.ts
+++ b/server/controllers/api/config.ts
@@ -9,7 +9,7 @@ import { CONFIG, CONSTRAINTS_FIELDS, reloadConfig } from '../../initializers'
9import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares' 9import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares'
10import { customConfigUpdateValidator } from '../../middlewares/validators/config' 10import { customConfigUpdateValidator } from '../../middlewares/validators/config'
11import { ClientHtml } from '../../lib/client-html' 11import { ClientHtml } from '../../lib/client-html'
12import { CustomConfigAuditView, auditLoggerFactory } from '../../helpers/audit-logger' 12import { auditLoggerFactory, CustomConfigAuditView } from '../../helpers/audit-logger'
13 13
14const packageJSON = require('../../../../package.json') 14const packageJSON = require('../../../../package.json')
15const configRouter = express.Router() 15const configRouter = express.Router()
@@ -69,6 +69,9 @@ async function getConfig (req: express.Request, res: express.Response, next: exp
69 videos: { 69 videos: {
70 http: { 70 http: {
71 enabled: CONFIG.IMPORT.VIDEOS.HTTP.ENABLED 71 enabled: CONFIG.IMPORT.VIDEOS.HTTP.ENABLED
72 },
73 torrent: {
74 enabled: CONFIG.IMPORT.VIDEOS.TORRENT.ENABLED
72 } 75 }
73 } 76 }
74 }, 77 },
@@ -237,6 +240,9 @@ function customConfig (): CustomConfig {
237 videos: { 240 videos: {
238 http: { 241 http: {
239 enabled: CONFIG.IMPORT.VIDEOS.HTTP.ENABLED 242 enabled: CONFIG.IMPORT.VIDEOS.HTTP.ENABLED
243 },
244 torrent: {
245 enabled: CONFIG.IMPORT.VIDEOS.TORRENT.ENABLED
240 } 246 }
241 } 247 }
242 } 248 }
diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts
index 879ba3f91..36bf0e0fe 100644
--- a/server/controllers/api/users.ts
+++ b/server/controllers/api/users.ts
@@ -196,7 +196,7 @@ async function getUserVideos (req: express.Request, res: express.Response, next:
196async function getUserVideoImports (req: express.Request, res: express.Response, next: express.NextFunction) { 196async function getUserVideoImports (req: express.Request, res: express.Response, next: express.NextFunction) {
197 const user = res.locals.oauth.token.User as UserModel 197 const user = res.locals.oauth.token.User as UserModel
198 const resultList = await VideoImportModel.listUserVideoImportsForApi( 198 const resultList = await VideoImportModel.listUserVideoImportsForApi(
199 user.Account.id, 199 user.id,
200 req.query.start as number, 200 req.query.start as number,
201 req.query.count as number, 201 req.query.count as number,
202 req.query.sort 202 req.query.sort
diff --git a/server/controllers/api/videos/import.ts b/server/controllers/api/videos/import.ts
index df151e79d..94dafcdbd 100644
--- a/server/controllers/api/videos/import.ts
+++ b/server/controllers/api/videos/import.ts
@@ -61,12 +61,13 @@ export {
61function addVideoImport (req: express.Request, res: express.Response) { 61function addVideoImport (req: express.Request, res: express.Response) {
62 if (req.body.targetUrl) return addYoutubeDLImport(req, res) 62 if (req.body.targetUrl) return addYoutubeDLImport(req, res)
63 63
64 const file = req.files['torrentfile'][0] 64 const file = req.files && req.files['torrentfile'] ? req.files['torrentfile'][0] : undefined
65 if (req.body.magnetUri || file) return addTorrentImport(req, res, file) 65 if (req.body.magnetUri || file) return addTorrentImport(req, res, file)
66} 66}
67 67
68async function addTorrentImport (req: express.Request, res: express.Response, torrentfile: Express.Multer.File) { 68async function addTorrentImport (req: express.Request, res: express.Response, torrentfile: Express.Multer.File) {
69 const body: VideoImportCreate = req.body 69 const body: VideoImportCreate = req.body
70 const user = res.locals.oauth.token.User
70 71
71 let videoName: string 72 let videoName: string
72 let torrentName: string 73 let torrentName: string
@@ -100,7 +101,8 @@ async function addTorrentImport (req: express.Request, res: express.Response, to
100 const videoImportAttributes = { 101 const videoImportAttributes = {
101 magnetUri, 102 magnetUri,
102 torrentName, 103 torrentName,
103 state: VideoImportState.PENDING 104 state: VideoImportState.PENDING,
105 userId: user.id
104 } 106 }
105 const videoImport: VideoImportModel = await insertIntoDB(video, res.locals.videoChannel, tags, videoImportAttributes) 107 const videoImport: VideoImportModel = await insertIntoDB(video, res.locals.videoChannel, tags, videoImportAttributes)
106 108
@@ -120,6 +122,7 @@ async function addTorrentImport (req: express.Request, res: express.Response, to
120async function addYoutubeDLImport (req: express.Request, res: express.Response) { 122async function addYoutubeDLImport (req: express.Request, res: express.Response) {
121 const body: VideoImportCreate = req.body 123 const body: VideoImportCreate = req.body
122 const targetUrl = body.targetUrl 124 const targetUrl = body.targetUrl
125 const user = res.locals.oauth.token.User
123 126
124 let youtubeDLInfo: YoutubeDLInfo 127 let youtubeDLInfo: YoutubeDLInfo
125 try { 128 try {
@@ -140,7 +143,8 @@ async function addYoutubeDLImport (req: express.Request, res: express.Response)
140 const tags = body.tags || youtubeDLInfo.tags 143 const tags = body.tags || youtubeDLInfo.tags
141 const videoImportAttributes = { 144 const videoImportAttributes = {
142 targetUrl, 145 targetUrl,
143 state: VideoImportState.PENDING 146 state: VideoImportState.PENDING,
147 userId: user.id
144 } 148 }
145 const videoImport: VideoImportModel = await insertIntoDB(video, res.locals.videoChannel, tags, videoImportAttributes) 149 const videoImport: VideoImportModel = await insertIntoDB(video, res.locals.videoChannel, tags, videoImportAttributes)
146 150
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts
index cf7cd3d74..80eb3f1e7 100644
--- a/server/initializers/constants.ts
+++ b/server/initializers/constants.ts
@@ -15,7 +15,7 @@ let config: IConfig = require('config')
15 15
16// --------------------------------------------------------------------------- 16// ---------------------------------------------------------------------------
17 17
18const LAST_MIGRATION_VERSION = 245 18const LAST_MIGRATION_VERSION = 240
19 19
20// --------------------------------------------------------------------------- 20// ---------------------------------------------------------------------------
21 21
@@ -211,6 +211,9 @@ const CONFIG = {
211 VIDEOS: { 211 VIDEOS: {
212 HTTP: { 212 HTTP: {
213 get ENABLED () { return config.get<boolean>('import.videos.http.enabled') } 213 get ENABLED () { return config.get<boolean>('import.videos.http.enabled') }
214 },
215 TORRENT: {
216 get ENABLED () { return config.get<boolean>('import.videos.torrent.enabled') }
214 } 217 }
215 } 218 }
216 }, 219 },
diff --git a/server/initializers/migrations/0245-import-magnet.ts b/server/initializers/migrations/0245-import-magnet.ts
deleted file mode 100644
index 87603b006..000000000
--- a/server/initializers/migrations/0245-import-magnet.ts
+++ /dev/null
@@ -1,42 +0,0 @@
1import * as Sequelize from 'sequelize'
2import { Migration } from '../../models/migrations'
3import { CONSTRAINTS_FIELDS } from '../index'
4
5async function up (utils: {
6 transaction: Sequelize.Transaction
7 queryInterface: Sequelize.QueryInterface
8 sequelize: Sequelize.Sequelize
9}): Promise<any> {
10 {
11 const data = {
12 type: Sequelize.STRING,
13 allowNull: true,
14 defaultValue: null
15 } as Migration.String
16 await utils.queryInterface.changeColumn('videoImport', 'targetUrl', data)
17 }
18
19 {
20 const data = {
21 type: Sequelize.STRING(CONSTRAINTS_FIELDS.VIDEO_IMPORTS.URL.max),
22 allowNull: true,
23 defaultValue: null
24 }
25 await utils.queryInterface.addColumn('videoImport', 'magnetUri', data)
26 }
27
28 {
29 const data = {
30 type: Sequelize.STRING(CONSTRAINTS_FIELDS.VIDEO_IMPORTS.TORRENT_NAME.max),
31 allowNull: true,
32 defaultValue: null
33 }
34 await utils.queryInterface.addColumn('videoImport', 'torrentName', data)
35 }
36}
37
38function down (options) {
39 throw new Error('Not implemented.')
40}
41
42export { up, down }
diff --git a/server/lib/job-queue/handlers/video-import.ts b/server/lib/job-queue/handlers/video-import.ts
index fd61aecad..28a03d19e 100644
--- a/server/lib/job-queue/handlers/video-import.ts
+++ b/server/lib/job-queue/handlers/video-import.ts
@@ -114,16 +114,21 @@ async function processFile (downloader: () => Promise<string>, videoImport: Vide
114 tempVideoPath = await downloader() 114 tempVideoPath = await downloader()
115 115
116 // Get information about this video 116 // Get information about this video
117 const { size } = await statPromise(tempVideoPath)
118 const isAble = await videoImport.User.isAbleToUploadVideo({ size })
119 if (isAble === false) {
120 throw new Error('The user video quota is exceeded with this video to import.')
121 }
122
117 const { videoFileResolution } = await getVideoFileResolution(tempVideoPath) 123 const { videoFileResolution } = await getVideoFileResolution(tempVideoPath)
118 const fps = await getVideoFileFPS(tempVideoPath) 124 const fps = await getVideoFileFPS(tempVideoPath)
119 const stats = await statPromise(tempVideoPath)
120 const duration = await getDurationFromVideoFile(tempVideoPath) 125 const duration = await getDurationFromVideoFile(tempVideoPath)
121 126
122 // Create video file object in database 127 // Create video file object in database
123 const videoFileData = { 128 const videoFileData = {
124 extname: extname(tempVideoPath), 129 extname: extname(tempVideoPath),
125 resolution: videoFileResolution, 130 resolution: videoFileResolution,
126 size: stats.size, 131 size,
127 fps, 132 fps,
128 videoId: videoImport.videoId 133 videoId: videoImport.videoId
129 } 134 }
diff --git a/server/middlewares/validators/config.ts b/server/middlewares/validators/config.ts
index 9d303eee2..f3f257d57 100644
--- a/server/middlewares/validators/config.ts
+++ b/server/middlewares/validators/config.ts
@@ -25,6 +25,7 @@ const customConfigUpdateValidator = [
25 body('transcoding.resolutions.720p').isBoolean().withMessage('Should have a valid transcoding 720p resolution enabled boolean'), 25 body('transcoding.resolutions.720p').isBoolean().withMessage('Should have a valid transcoding 720p resolution enabled boolean'),
26 body('transcoding.resolutions.1080p').isBoolean().withMessage('Should have a valid transcoding 1080p resolution enabled boolean'), 26 body('transcoding.resolutions.1080p').isBoolean().withMessage('Should have a valid transcoding 1080p resolution enabled boolean'),
27 body('import.videos.http.enabled').isBoolean().withMessage('Should have a valid import video http enabled boolean'), 27 body('import.videos.http.enabled').isBoolean().withMessage('Should have a valid import video http enabled boolean'),
28 body('import.videos.torrent.enabled').isBoolean().withMessage('Should have a valid import video torrent enabled boolean'),
28 29
29 async (req: express.Request, res: express.Response, next: express.NextFunction) => { 30 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
30 logger.debug('Checking customConfigUpdateValidator parameters', { parameters: req.body }) 31 logger.debug('Checking customConfigUpdateValidator parameters', { parameters: req.body })
diff --git a/server/middlewares/validators/video-imports.ts b/server/middlewares/validators/video-imports.ts
index c03cf2e4d..9ac739101 100644
--- a/server/middlewares/validators/video-imports.ts
+++ b/server/middlewares/validators/video-imports.ts
@@ -33,21 +33,28 @@ const videoImportAddValidator = getCommonVideoAttributes().concat([
33 logger.debug('Checking videoImportAddValidator parameters', { parameters: req.body }) 33 logger.debug('Checking videoImportAddValidator parameters', { parameters: req.body })
34 34
35 const user = res.locals.oauth.token.User 35 const user = res.locals.oauth.token.User
36 const torrentFile = req.files && req.files['torrentfile'] ? req.files['torrentfile'][0] : undefined
36 37
37 if (areValidationErrors(req, res)) return cleanUpReqFiles(req) 38 if (areValidationErrors(req, res)) return cleanUpReqFiles(req)
38 39
39 if (CONFIG.IMPORT.VIDEOS.HTTP.ENABLED !== true) { 40 if (req.body.targetUrl && CONFIG.IMPORT.VIDEOS.HTTP.ENABLED !== true) {
40 cleanUpReqFiles(req) 41 cleanUpReqFiles(req)
41 return res.status(409) 42 return res.status(409)
42 .json({ error: 'Import is not enabled on this instance.' }) 43 .json({ error: 'HTTP import is not enabled on this instance.' })
43 .end() 44 .end()
44 } 45 }
45 46
47 if (CONFIG.IMPORT.VIDEOS.TORRENT.ENABLED !== true && (req.body.magnetUri || torrentFile)) {
48 cleanUpReqFiles(req)
49 return res.status(409)
50 .json({ error: 'Torrent/magnet URI import is not enabled on this instance.' })
51 .end()
52 }
53
46 if (!await isVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req) 54 if (!await isVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req)
47 55
48 // Check we have at least 1 required param 56 // Check we have at least 1 required param
49 const file = req.files['torrentfile'][0] 57 if (!req.body.targetUrl && !req.body.magnetUri && !torrentFile) {
50 if (!req.body.targetUrl && !req.body.magnetUri && !file) {
51 cleanUpReqFiles(req) 58 cleanUpReqFiles(req)
52 59
53 return res.status(400) 60 return res.status(400)
diff --git a/server/models/account/user.ts b/server/models/account/user.ts
index 1165285ea..1b1fc5ee8 100644
--- a/server/models/account/user.ts
+++ b/server/models/account/user.ts
@@ -295,7 +295,7 @@ export class UserModel extends Model<UserModel> {
295 return json 295 return json
296 } 296 }
297 297
298 isAbleToUploadVideo (videoFile: Express.Multer.File) { 298 isAbleToUploadVideo (videoFile: { size: number }) {
299 if (this.videoQuota === -1) return Promise.resolve(true) 299 if (this.videoQuota === -1) return Promise.resolve(true)
300 300
301 return UserModel.getOriginalVideoFileTotalFromUser(this) 301 return UserModel.getOriginalVideoFileTotalFromUser(this)
diff --git a/server/models/video/video-import.ts b/server/models/video/video-import.ts
index d6c02e5ac..b794d8324 100644
--- a/server/models/video/video-import.ts
+++ b/server/models/video/video-import.ts
@@ -15,34 +15,21 @@ import {
15} from 'sequelize-typescript' 15} from 'sequelize-typescript'
16import { CONSTRAINTS_FIELDS, VIDEO_IMPORT_STATES } from '../../initializers' 16import { CONSTRAINTS_FIELDS, VIDEO_IMPORT_STATES } from '../../initializers'
17import { getSort, throwIfNotValid } from '../utils' 17import { getSort, throwIfNotValid } from '../utils'
18import { VideoModel } from './video' 18import { ScopeNames as VideoModelScopeNames, VideoModel } from './video'
19import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports' 19import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports'
20import { VideoImport, VideoImportState } from '../../../shared' 20import { VideoImport, VideoImportState } from '../../../shared'
21import { VideoChannelModel } from './video-channel'
22import { AccountModel } from '../account/account'
23import { TagModel } from './tag'
24import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos' 21import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos'
22import { UserModel } from '../account/user'
25 23
26@DefaultScope({ 24@DefaultScope({
27 include: [ 25 include: [
28 { 26 {
29 model: () => VideoModel, 27 model: () => UserModel.unscoped(),
30 required: false, 28 required: true
31 include: [ 29 },
32 { 30 {
33 model: () => VideoChannelModel, 31 model: () => VideoModel.scope([ VideoModelScopeNames.WITH_ACCOUNT_DETAILS, VideoModelScopeNames.WITH_TAGS]),
34 required: true, 32 required: false
35 include: [
36 {
37 model: () => AccountModel,
38 required: true
39 }
40 ]
41 },
42 {
43 model: () => TagModel
44 }
45 ]
46 } 33 }
47 ] 34 ]
48}) 35})
@@ -53,6 +40,9 @@ import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos'
53 { 40 {
54 fields: [ 'videoId' ], 41 fields: [ 'videoId' ],
55 unique: true 42 unique: true
43 },
44 {
45 fields: [ 'userId' ]
56 } 46 }
57 ] 47 ]
58}) 48})
@@ -91,6 +81,18 @@ export class VideoImportModel extends Model<VideoImportModel> {
91 @Column(DataType.TEXT) 81 @Column(DataType.TEXT)
92 error: string 82 error: string
93 83
84 @ForeignKey(() => UserModel)
85 @Column
86 userId: number
87
88 @BelongsTo(() => UserModel, {
89 foreignKey: {
90 allowNull: false
91 },
92 onDelete: 'cascade'
93 })
94 User: UserModel
95
94 @ForeignKey(() => VideoModel) 96 @ForeignKey(() => VideoModel)
95 @Column 97 @Column
96 videoId: number 98 videoId: number
@@ -116,41 +118,24 @@ export class VideoImportModel extends Model<VideoImportModel> {
116 return VideoImportModel.findById(id) 118 return VideoImportModel.findById(id)
117 } 119 }
118 120
119 static listUserVideoImportsForApi (accountId: number, start: number, count: number, sort: string) { 121 static listUserVideoImportsForApi (userId: number, start: number, count: number, sort: string) {
120 const query = { 122 const query = {
121 distinct: true, 123 distinct: true,
122 offset: start,
123 limit: count,
124 order: getSort(sort),
125 include: [ 124 include: [
126 { 125 {
127 model: VideoModel, 126 model: UserModel.unscoped(), // FIXME: Without this, sequelize try to COUNT(DISTINCT(*)) which is an invalid SQL query
128 required: false, 127 required: true
129 include: [
130 {
131 model: VideoChannelModel,
132 required: true,
133 include: [
134 {
135 model: AccountModel,
136 required: true,
137 where: {
138 id: accountId
139 }
140 }
141 ]
142 },
143 {
144 model: TagModel,
145 required: false
146 }
147 ]
148 } 128 }
149 ] 129 ],
130 offset: start,
131 limit: count,
132 order: getSort(sort),
133 where: {
134 userId
135 }
150 } 136 }
151 137
152 return VideoImportModel.unscoped() 138 return VideoImportModel.findAndCountAll(query)
153 .findAndCountAll(query)
154 .then(({ rows, count }) => { 139 .then(({ rows, count }) => {
155 return { 140 return {
156 data: rows, 141 data: rows,
diff --git a/server/tests/api/check-params/config.ts b/server/tests/api/check-params/config.ts
index 2742e26de..b26dfa252 100644
--- a/server/tests/api/check-params/config.ts
+++ b/server/tests/api/check-params/config.ts
@@ -65,6 +65,9 @@ describe('Test config API validators', function () {
65 videos: { 65 videos: {
66 http: { 66 http: {
67 enabled: false 67 enabled: false
68 },
69 torrent: {
70 enabled: false
68 } 71 }
69 } 72 }
70 } 73 }
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts
index b65061a5d..f9805b6ea 100644
--- a/server/tests/api/server/config.ts
+++ b/server/tests/api/server/config.ts
@@ -45,6 +45,7 @@ function checkInitialConfig (data: CustomConfig) {
45 expect(data.transcoding.resolutions['720p']).to.be.true 45 expect(data.transcoding.resolutions['720p']).to.be.true
46 expect(data.transcoding.resolutions['1080p']).to.be.true 46 expect(data.transcoding.resolutions['1080p']).to.be.true
47 expect(data.import.videos.http.enabled).to.be.true 47 expect(data.import.videos.http.enabled).to.be.true
48 expect(data.import.videos.torrent.enabled).to.be.true
48} 49}
49 50
50function checkUpdatedConfig (data: CustomConfig) { 51function checkUpdatedConfig (data: CustomConfig) {
@@ -72,6 +73,7 @@ function checkUpdatedConfig (data: CustomConfig) {
72 expect(data.transcoding.resolutions['720p']).to.be.false 73 expect(data.transcoding.resolutions['720p']).to.be.false
73 expect(data.transcoding.resolutions['1080p']).to.be.false 74 expect(data.transcoding.resolutions['1080p']).to.be.false
74 expect(data.import.videos.http.enabled).to.be.false 75 expect(data.import.videos.http.enabled).to.be.false
76 expect(data.import.videos.torrent.enabled).to.be.false
75} 77}
76 78
77describe('Test config', function () { 79describe('Test config', function () {
@@ -167,6 +169,9 @@ describe('Test config', function () {
167 videos: { 169 videos: {
168 http: { 170 http: {
169 enabled: false 171 enabled: false
172 },
173 torrent: {
174 enabled: false
170 } 175 }
171 } 176 }
172 } 177 }
diff --git a/server/tests/utils/server/config.ts b/server/tests/utils/server/config.ts
index e21614282..d6ac3ef8a 100644
--- a/server/tests/utils/server/config.ts
+++ b/server/tests/utils/server/config.ts
@@ -97,6 +97,9 @@ function updateCustomSubConfig (url: string, token: string, newConfig: any) {
97 videos: { 97 videos: {
98 http: { 98 http: {
99 enabled: false 99 enabled: false
100 },
101 torrent: {
102 enabled: false
100 } 103 }
101 } 104 }
102 } 105 }
diff --git a/shared/models/server/custom-config.model.ts b/shared/models/server/custom-config.model.ts
index 46320435d..d70c757b6 100644
--- a/shared/models/server/custom-config.model.ts
+++ b/shared/models/server/custom-config.model.ts
@@ -60,6 +60,9 @@ export interface CustomConfig {
60 videos: { 60 videos: {
61 http: { 61 http: {
62 enabled: boolean 62 enabled: boolean
63 },
64 torrent: {
65 enabled: boolean
63 } 66 }
64 } 67 }
65 } 68 }
diff --git a/shared/models/server/server-config.model.ts b/shared/models/server/server-config.model.ts
index 2cafedbbc..8cb087234 100644
--- a/shared/models/server/server-config.model.ts
+++ b/shared/models/server/server-config.model.ts
@@ -28,6 +28,9 @@ export interface ServerConfig {
28 http: { 28 http: {
29 enabled: boolean 29 enabled: boolean
30 } 30 }
31 torrent: {
32 enabled: boolean
33 }
31 } 34 }
32 } 35 }
33 36