aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--server/initializers/migrations/0120-video-null.ts46
-rw-r--r--server/middlewares/validators/videos.ts6
-rw-r--r--server/models/video/video.ts16
-rw-r--r--server/tests/api/check-params/videos.ts24
-rw-r--r--server/tests/api/single-server.ts82
5 files changed, 117 insertions, 57 deletions
diff --git a/server/initializers/migrations/0120-video-null.ts b/server/initializers/migrations/0120-video-null.ts
new file mode 100644
index 000000000..3506a5046
--- /dev/null
+++ b/server/initializers/migrations/0120-video-null.ts
@@ -0,0 +1,46 @@
1import * as Sequelize from 'sequelize'
2import { PeerTubeDatabase } from '../database'
3
4async function up (utils: {
5 transaction: Sequelize.Transaction,
6 queryInterface: Sequelize.QueryInterface,
7 sequelize: Sequelize.Sequelize,
8 db: PeerTubeDatabase
9}): Promise<void> {
10
11 {
12 const data = {
13 type: Sequelize.INTEGER,
14 allowNull: true,
15 defaultValue: null
16 }
17 await utils.queryInterface.changeColumn('Videos', 'licence', data)
18 }
19
20 {
21 const data = {
22 type: Sequelize.INTEGER,
23 allowNull: true,
24 defaultValue: null
25 }
26 await utils.queryInterface.changeColumn('Videos', 'category', data)
27 }
28
29 {
30 const data = {
31 type: Sequelize.INTEGER,
32 allowNull: true,
33 defaultValue: null
34 }
35 await utils.queryInterface.changeColumn('Videos', 'description', data)
36 }
37}
38
39function down (options) {
40 throw new Error('Not implemented.')
41}
42
43export {
44 up,
45 down
46}
diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts
index ee2ac50c8..10625e41d 100644
--- a/server/middlewares/validators/videos.ts
+++ b/server/middlewares/validators/videos.ts
@@ -31,11 +31,11 @@ const videosAddValidator = [
31 + CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ') 31 + CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ')
32 ), 32 ),
33 body('name').custom(isVideoNameValid).withMessage('Should have a valid name'), 33 body('name').custom(isVideoNameValid).withMessage('Should have a valid name'),
34 body('category').custom(isVideoCategoryValid).withMessage('Should have a valid category'), 34 body('category').optional().custom(isVideoCategoryValid).withMessage('Should have a valid category'),
35 body('licence').custom(isVideoLicenceValid).withMessage('Should have a valid licence'), 35 body('licence').optional().custom(isVideoLicenceValid).withMessage('Should have a valid licence'),
36 body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'), 36 body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'),
37 body('nsfw').custom(isVideoNSFWValid).withMessage('Should have a valid NSFW attribute'), 37 body('nsfw').custom(isVideoNSFWValid).withMessage('Should have a valid NSFW attribute'),
38 body('description').custom(isVideoDescriptionValid).withMessage('Should have a valid description'), 38 body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'),
39 body('channelId').custom(isIdValid).withMessage('Should have correct video channel id'), 39 body('channelId').custom(isIdValid).withMessage('Should have correct video channel id'),
40 body('privacy').custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), 40 body('privacy').custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'),
41 body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), 41 body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'),
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index 60023bc8c..8b1eb1f96 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -104,7 +104,8 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
104 }, 104 },
105 category: { 105 category: {
106 type: DataTypes.INTEGER, 106 type: DataTypes.INTEGER,
107 allowNull: false, 107 allowNull: true,
108 defaultValue: null,
108 validate: { 109 validate: {
109 categoryValid: value => { 110 categoryValid: value => {
110 const res = isVideoCategoryValid(value) 111 const res = isVideoCategoryValid(value)
@@ -114,7 +115,7 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
114 }, 115 },
115 licence: { 116 licence: {
116 type: DataTypes.INTEGER, 117 type: DataTypes.INTEGER,
117 allowNull: false, 118 allowNull: true,
118 defaultValue: null, 119 defaultValue: null,
119 validate: { 120 validate: {
120 licenceValid: value => { 121 licenceValid: value => {
@@ -126,6 +127,7 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
126 language: { 127 language: {
127 type: DataTypes.INTEGER, 128 type: DataTypes.INTEGER,
128 allowNull: true, 129 allowNull: true,
130 defaultValue: null,
129 validate: { 131 validate: {
130 languageValid: value => { 132 languageValid: value => {
131 const res = isVideoLanguageValid(value) 133 const res = isVideoLanguageValid(value)
@@ -155,7 +157,8 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
155 }, 157 },
156 description: { 158 description: {
157 type: DataTypes.STRING(CONSTRAINTS_FIELDS.VIDEOS.DESCRIPTION.max), 159 type: DataTypes.STRING(CONSTRAINTS_FIELDS.VIDEOS.DESCRIPTION.max),
158 allowNull: false, 160 allowNull: true,
161 defaultValue: null,
159 validate: { 162 validate: {
160 descriptionValid: value => { 163 descriptionValid: value => {
161 const res = isVideoDescriptionValid(value) 164 const res = isVideoDescriptionValid(value)
@@ -664,6 +667,8 @@ toActivityPubObject = function (this: VideoInstance) {
664} 667}
665 668
666getTruncatedDescription = function (this: VideoInstance) { 669getTruncatedDescription = function (this: VideoInstance) {
670 if (!this.description) return null
671
667 const options = { 672 const options = {
668 length: CONSTRAINTS_FIELDS.VIDEOS.TRUNCATED_DESCRIPTION.max 673 length: CONSTRAINTS_FIELDS.VIDEOS.TRUNCATED_DESCRIPTION.max
669 } 674 }
@@ -754,8 +759,6 @@ getDescriptionPath = function (this: VideoInstance) {
754 759
755getCategoryLabel = function (this: VideoInstance) { 760getCategoryLabel = function (this: VideoInstance) {
756 let categoryLabel = VIDEO_CATEGORIES[this.category] 761 let categoryLabel = VIDEO_CATEGORIES[this.category]
757
758 // Maybe our server is not up to date and there are new categories since our version
759 if (!categoryLabel) categoryLabel = 'Misc' 762 if (!categoryLabel) categoryLabel = 'Misc'
760 763
761 return categoryLabel 764 return categoryLabel
@@ -763,15 +766,12 @@ getCategoryLabel = function (this: VideoInstance) {
763 766
764getLicenceLabel = function (this: VideoInstance) { 767getLicenceLabel = function (this: VideoInstance) {
765 let licenceLabel = VIDEO_LICENCES[this.licence] 768 let licenceLabel = VIDEO_LICENCES[this.licence]
766
767 // Maybe our server is not up to date and there are new licences since our version
768 if (!licenceLabel) licenceLabel = 'Unknown' 769 if (!licenceLabel) licenceLabel = 'Unknown'
769 770
770 return licenceLabel 771 return licenceLabel
771} 772}
772 773
773getLanguageLabel = function (this: VideoInstance) { 774getLanguageLabel = function (this: VideoInstance) {
774 // Language is an optional attribute
775 let languageLabel = VIDEO_LANGUAGES[this.language] 775 let languageLabel = VIDEO_LANGUAGES[this.language]
776 if (!languageLabel) languageLabel = 'Unknown' 776 if (!languageLabel) languageLabel = 'Unknown'
777 777
diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts
index 2962f5640..00a209665 100644
--- a/server/tests/api/check-params/videos.ts
+++ b/server/tests/api/check-params/videos.ts
@@ -189,14 +189,6 @@ describe('Test videos API validator', function () {
189 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 189 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
190 }) 190 })
191 191
192 it('Should fail without a category', async function () {
193 const fields = getCompleteVideoUploadAttributes()
194 delete fields.category
195
196 const attaches = getVideoUploadAttaches
197 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
198 })
199
200 it('Should fail with a bad category', async function () { 192 it('Should fail with a bad category', async function () {
201 const fields = getCompleteVideoUploadAttributes() 193 const fields = getCompleteVideoUploadAttributes()
202 fields.category = 125 194 fields.category = 125
@@ -205,14 +197,6 @@ describe('Test videos API validator', function () {
205 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 197 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
206 }) 198 })
207 199
208 it('Should fail without a licence', async function () {
209 const fields = getCompleteVideoUploadAttributes()
210 delete fields.licence
211
212 const attaches = getVideoUploadAttaches()
213 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
214 })
215
216 it('Should fail with a bad licence', async function () { 200 it('Should fail with a bad licence', async function () {
217 const fields = getCompleteVideoUploadAttributes() 201 const fields = getCompleteVideoUploadAttributes()
218 fields.licence = 125 202 fields.licence = 125
@@ -245,14 +229,6 @@ describe('Test videos API validator', function () {
245 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 229 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
246 }) 230 })
247 231
248 it('Should fail without description', async function () {
249 const fields = getCompleteVideoUploadAttributes()
250 delete fields.description
251
252 const attaches = getVideoUploadAttaches()
253 await makePostUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
254 })
255
256 it('Should fail with a long description', async function () { 232 it('Should fail with a long description', async function () {
257 const fields = getCompleteVideoUploadAttributes() 233 const fields = getCompleteVideoUploadAttributes()
258 fields.description = 'my super description which is very very very very very very very very very very very very long'.repeat(35) 234 fields.description = 'my super description which is very very very very very very very very very very very very long'.repeat(35)
diff --git a/server/tests/api/single-server.ts b/server/tests/api/single-server.ts
index d7e9ad41f..fbb2dd1fb 100644
--- a/server/tests/api/single-server.ts
+++ b/server/tests/api/single-server.ts
@@ -1,40 +1,41 @@
1/* tslint:disable:no-unused-expression */ 1/* tslint:disable:no-unused-expression */
2 2
3import * as chai from 'chai'
3import { keyBy } from 'lodash' 4import { keyBy } from 'lodash'
4import { join } from 'path'
5import 'mocha' 5import 'mocha'
6import * as chai from 'chai' 6import { join } from 'path'
7const expect = chai.expect 7import * as request from 'supertest'
8
9import { 8import {
10 ServerInfo,
11 flushTests,
12 runServer,
13 uploadVideo,
14 getVideosList,
15 rateVideo,
16 removeVideo,
17 wait,
18 setAccessTokensToServers,
19 searchVideo,
20 killallServers,
21 dateIsValid, 9 dateIsValid,
10 flushTests,
11 getVideo,
22 getVideoCategories, 12 getVideoCategories,
23 getVideoLicences,
24 getVideoLanguages, 13 getVideoLanguages,
14 getVideoLicences,
25 getVideoPrivacies, 15 getVideoPrivacies,
26 testVideoImage, 16 getVideosList,
27 webtorrentAdd,
28 getVideo,
29 readdirPromise,
30 getVideosListPagination, 17 getVideosListPagination,
31 searchVideoWithPagination,
32 getVideosListSort, 18 getVideosListSort,
19 killallServers,
20 rateVideo,
21 readdirPromise,
22 removeVideo,
23 runServer,
24 searchVideo,
25 searchVideoWithPagination,
33 searchVideoWithSort, 26 searchVideoWithSort,
34 updateVideo 27 ServerInfo,
28 setAccessTokensToServers,
29 testVideoImage,
30 updateVideo,
31 uploadVideo,
32 wait,
33 webtorrentAdd
35} from '../utils' 34} from '../utils'
36import { viewVideo } from '../utils/videos' 35import { viewVideo } from '../utils/videos'
37 36
37const expect = chai.expect
38
38describe('Test a single server', function () { 39describe('Test a single server', function () {
39 let server: ServerInfo = null 40 let server: ServerInfo = null
40 let videoId = -1 41 let videoId = -1
@@ -693,6 +694,43 @@ describe('Test a single server', function () {
693 expect(video.dislikes).to.equal(1) 694 expect(video.dislikes).to.equal(1)
694 }) 695 })
695 696
697 it('Should upload a video with minimum parameters', async function () {
698 const path = '/api/v1/videos/upload'
699
700 const req = request(server.url)
701 .post(path)
702 .set('Accept', 'application/json')
703 .set('Authorization', 'Bearer ' + server.accessToken)
704 .field('name', 'minimum parameters')
705 .field('privacy', '1')
706 .field('nsfw', 'false')
707 .field('channelId', '1')
708
709 const filePath = join(__dirname, '..', 'api', 'fixtures', 'video_short.webm')
710
711 await req.attach('videofile', filePath)
712 .expect(204)
713
714 const res = await getVideosList(server.url)
715 const video = res.body.data.find(v => v.name === 'minimum parameters')
716
717 expect(video.name).to.equal('minimum parameters')
718 expect(video.category).to.equal(null)
719 expect(video.categoryLabel).to.equal('Misc')
720 expect(video.licence).to.equal(null)
721 expect(video.licenceLabel).to.equal('Unknown')
722 expect(video.language).to.equal(null)
723 expect(video.languageLabel).to.equal('Unknown')
724 expect(video.nsfw).to.not.be.ok
725 expect(video.description).to.equal(null)
726 expect(video.serverHost).to.equal('localhost:9001')
727 expect(video.accountName).to.equal('root')
728 expect(video.isLocal).to.be.true
729 expect(video.tags).to.deep.equal([ ])
730 expect(dateIsValid(video.createdAt)).to.be.true
731 expect(dateIsValid(video.updatedAt)).to.be.true
732 })
733
696 after(async function () { 734 after(async function () {
697 killallServers([ server ]) 735 killallServers([ server ])
698 736