Fix updating video tags to empty field

This commit is contained in:
Chocobozzz 2018-05-16 09:28:18 +02:00
parent 17c49e60b3
commit 2efd32f697
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
8 changed files with 62 additions and 40 deletions

View File

@ -66,6 +66,11 @@ function objectToFormData (obj: any, form?: FormData, namespace?: string) {
if (obj[key] === undefined) continue if (obj[key] === undefined) continue
if (Array.isArray(obj[key]) && obj[key].length === 0) {
fd.append(key, null)
continue
}
if (obj[key] !== null && typeof obj[ key ] === 'object' && !(obj[ key ] instanceof File)) { if (obj[key] !== null && typeof obj[ key ] === 'object' && !(obj[ key ] instanceof File)) {
objectToFormData(obj[ key ], fd, key) objectToFormData(obj[ key ], fd, key)
} else { } else {

View File

@ -80,7 +80,7 @@ export class VideoEditComponent implements OnInit {
this.form.addControl('licence', new FormControl('', VIDEO_LICENCE.VALIDATORS)) this.form.addControl('licence', new FormControl('', VIDEO_LICENCE.VALIDATORS))
this.form.addControl('language', new FormControl('', VIDEO_LANGUAGE.VALIDATORS)) this.form.addControl('language', new FormControl('', VIDEO_LANGUAGE.VALIDATORS))
this.form.addControl('description', new FormControl('', VIDEO_DESCRIPTION.VALIDATORS)) this.form.addControl('description', new FormControl('', VIDEO_DESCRIPTION.VALIDATORS))
this.form.addControl('tags', new FormControl('')) this.form.addControl('tags', new FormControl([]))
this.form.addControl('thumbnailfile', new FormControl('')) this.form.addControl('thumbnailfile', new FormControl(''))
this.form.addControl('previewfile', new FormControl('')) this.form.addControl('previewfile', new FormControl(''))
this.form.addControl('support', new FormControl('', VIDEO_SUPPORT.VALIDATORS)) this.form.addControl('support', new FormControl('', VIDEO_SUPPORT.VALIDATORS))

View File

@ -155,17 +155,17 @@ export class PeertubeChunkStore extends EventEmitter {
this.cleanerInterval = null this.cleanerInterval = null
} }
if (this.db) {
await this.db.close()
await this.dropDatabase(this.databaseName)
}
if (this.expirationDB) { if (this.expirationDB) {
await this.expirationDB.close() await this.expirationDB.close()
this.expirationDB = null this.expirationDB = null
} }
if (this.db) {
console.log('Destroying IndexDB database %s.', this.databaseName)
await this.db.close()
await this.db.delete()
}
return cb() return cb()
} catch (err) { } catch (err) {
console.error('Cannot destroy peertube chunk store.', err) console.error('Cannot destroy peertube chunk store.', err)
@ -181,31 +181,42 @@ export class PeertubeChunkStore extends EventEmitter {
}, PeertubeChunkStore.CLEANER_INTERVAL_MS) }, PeertubeChunkStore.CLEANER_INTERVAL_MS)
} }
private checkExpiration () { private async checkExpiration () {
this.expirationDB.transaction('rw', this.expirationDB.databases, async () => { let databasesToDeleteInfo: { name: string }[] = []
// Update our database expiration since we are alive
await this.expirationDB.databases.put({ try {
name: this.databaseName, await this.expirationDB.transaction('rw', this.expirationDB.databases, async () => {
expiration: new Date().getTime() + PeertubeChunkStore.CLEANER_EXPIRATION_MS // Update our database expiration since we are alive
await this.expirationDB.databases.put({
name: this.databaseName,
expiration: new Date().getTime() + PeertubeChunkStore.CLEANER_EXPIRATION_MS
})
const now = new Date().getTime()
databasesToDeleteInfo = await this.expirationDB.databases.where('expiration').below(now).toArray()
}) })
} catch (err) {
console.error('Cannot update expiration of fetch expired databases.', err)
}
const now = new Date().getTime() for (const databaseToDeleteInfo of databasesToDeleteInfo) {
const databasesToDeleteInfo = await this.expirationDB.databases.where('expiration').below(now).toArray() await this.dropDatabase(databaseToDeleteInfo.name)
}
for (const databaseToDeleteInfo of databasesToDeleteInfo) {
await this.dropDatabase(databaseToDeleteInfo.name)
await this.expirationDB.databases.where({ name: databaseToDeleteInfo.name }).delete()
}
}).catch(err => console.error('Cannot check expiration.', err))
} }
private dropDatabase (databaseName: string) { private async dropDatabase (databaseName: string) {
const dbToDelete = new ChunkDatabase(databaseName) const dbToDelete = new ChunkDatabase(databaseName)
console.log('Destroying IndexDB database %s.', databaseName)
console.log('Deleting %s.', databaseName) try {
return dbToDelete.delete() await dbToDelete.delete()
.catch(err => console.error('Cannot delete %s.', databaseName))
await this.expirationDB.transaction('rw', this.expirationDB.databases, () => {
return this.expirationDB.databases.where({ name: databaseName }).delete()
})
} catch (err) {
console.error('Cannot delete %s.', databaseName, err)
}
} }
private nextTick (cb, err, val?) { private nextTick (cb, err, val?) {

View File

@ -244,7 +244,7 @@ async function addVideo (req: express.Request, res: express.Response, videoPhysi
video.VideoFiles = [ videoFile ] video.VideoFiles = [ videoFile ]
if (videoInfo.tags) { if (videoInfo.tags !== undefined) {
const tagInstances = await TagModel.findOrCreateTags(videoInfo.tags, t) const tagInstances = await TagModel.findOrCreateTags(videoInfo.tags, t)
await video.$set('Tags', tagInstances, sequelizeOptions) await video.$set('Tags', tagInstances, sequelizeOptions)
@ -332,7 +332,7 @@ async function updateVideo (req: express.Request, res: express.Response) {
const videoInstanceUpdated = await videoInstance.save(sequelizeOptions) const videoInstanceUpdated = await videoInstance.save(sequelizeOptions)
// Video tags update? // Video tags update?
if (videoInfoToUpdate.tags) { if (videoInfoToUpdate.tags !== undefined) {
const tagInstances = await TagModel.findOrCreateTags(videoInfoToUpdate.tags, t) const tagInstances = await TagModel.findOrCreateTags(videoInfoToUpdate.tags, t)
await videoInstanceUpdated.$set('Tags', tagInstances, sequelizeOptions) await videoInstanceUpdated.$set('Tags', tagInstances, sequelizeOptions)

View File

@ -35,7 +35,7 @@ function toIntOrNull (value: string) {
return validator.toInt(value) return validator.toInt(value)
} }
function toStringOrNull (value: string) { function toValueOrNull (value: string) {
if (value === 'null') return null if (value === 'null') return null
return value return value
@ -73,7 +73,7 @@ export {
isUUIDValid, isUUIDValid,
isIdOrUUIDValid, isIdOrUUIDValid,
isDateValid, isDateValid,
toStringOrNull, toValueOrNull,
isBooleanValid, isBooleanValid,
toIntOrNull, toIntOrNull,
isFileValid isFileValid

View File

@ -57,9 +57,11 @@ function isVideoTagValid (tag: string) {
} }
function isVideoTagsValid (tags: string[]) { function isVideoTagsValid (tags: string[]) {
return isArray(tags) && return tags === null || (
validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) && isArray(tags) &&
tags.every(tag => isVideoTagValid(tag)) validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
tags.every(tag => isVideoTagValid(tag))
)
} }
function isVideoAbuseReasonValid (value: string) { function isVideoAbuseReasonValid (value: string) {

View File

@ -2,7 +2,7 @@ import * as express from 'express'
import 'express-validator' import 'express-validator'
import { body, param, query } from 'express-validator/check' import { body, param, query } from 'express-validator/check'
import { UserRight, VideoPrivacy } from '../../../shared' import { UserRight, VideoPrivacy } from '../../../shared'
import { isBooleanValid, isIdOrUUIDValid, isIdValid, isUUIDValid, toIntOrNull, toStringOrNull } from '../../helpers/custom-validators/misc' import { isBooleanValid, isIdOrUUIDValid, isIdValid, isUUIDValid, toIntOrNull, toValueOrNull } from '../../helpers/custom-validators/misc'
import { import {
isVideoAbuseReasonValid, isVideoAbuseReasonValid,
isVideoCategoryValid, isVideoCategoryValid,
@ -52,21 +52,22 @@ const videosAddValidator = [
.custom(isVideoLicenceValid).withMessage('Should have a valid licence'), .custom(isVideoLicenceValid).withMessage('Should have a valid licence'),
body('language') body('language')
.optional() .optional()
.customSanitizer(toStringOrNull) .customSanitizer(toValueOrNull)
.custom(isVideoLanguageValid).withMessage('Should have a valid language'), .custom(isVideoLanguageValid).withMessage('Should have a valid language'),
body('nsfw') body('nsfw')
.toBoolean() .toBoolean()
.custom(isBooleanValid).withMessage('Should have a valid NSFW attribute'), .custom(isBooleanValid).withMessage('Should have a valid NSFW attribute'),
body('description') body('description')
.optional() .optional()
.customSanitizer(toStringOrNull) .customSanitizer(toValueOrNull)
.custom(isVideoDescriptionValid).withMessage('Should have a valid description'), .custom(isVideoDescriptionValid).withMessage('Should have a valid description'),
body('support') body('support')
.optional() .optional()
.customSanitizer(toStringOrNull) .customSanitizer(toValueOrNull)
.custom(isVideoSupportValid).withMessage('Should have a valid support text'), .custom(isVideoSupportValid).withMessage('Should have a valid support text'),
body('tags') body('tags')
.optional() .optional()
.customSanitizer(toValueOrNull)
.custom(isVideoTagsValid).withMessage('Should have correct tags'), .custom(isVideoTagsValid).withMessage('Should have correct tags'),
body('commentsEnabled') body('commentsEnabled')
.toBoolean() .toBoolean()
@ -142,7 +143,7 @@ const videosUpdateValidator = [
.custom(isVideoLicenceValid).withMessage('Should have a valid licence'), .custom(isVideoLicenceValid).withMessage('Should have a valid licence'),
body('language') body('language')
.optional() .optional()
.customSanitizer(toStringOrNull) .customSanitizer(toValueOrNull)
.custom(isVideoLanguageValid).withMessage('Should have a valid language'), .custom(isVideoLanguageValid).withMessage('Should have a valid language'),
body('nsfw') body('nsfw')
.optional() .optional()
@ -154,14 +155,15 @@ const videosUpdateValidator = [
.custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), .custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'),
body('description') body('description')
.optional() .optional()
.customSanitizer(toStringOrNull) .customSanitizer(toValueOrNull)
.custom(isVideoDescriptionValid).withMessage('Should have a valid description'), .custom(isVideoDescriptionValid).withMessage('Should have a valid description'),
body('support') body('support')
.optional() .optional()
.customSanitizer(toStringOrNull) .customSanitizer(toValueOrNull)
.custom(isVideoSupportValid).withMessage('Should have a valid support text'), .custom(isVideoSupportValid).withMessage('Should have a valid support text'),
body('tags') body('tags')
.optional() .optional()
.customSanitizer(toValueOrNull)
.custom(isVideoTagsValid).withMessage('Should have correct tags'), .custom(isVideoTagsValid).withMessage('Should have correct tags'),
body('commentsEnabled') body('commentsEnabled')
.optional() .optional()

View File

@ -37,6 +37,8 @@ export class TagModel extends Model<TagModel> {
Videos: VideoModel[] Videos: VideoModel[]
static findOrCreateTags (tags: string[], transaction: Transaction) { static findOrCreateTags (tags: string[], transaction: Transaction) {
if (tags === null) return []
const tasks: Bluebird<TagModel>[] = [] const tasks: Bluebird<TagModel>[] = []
tags.forEach(tag => { tags.forEach(tag => {
const query = { const query = {