From 2efd32f697549c59337db5177a93749af8e605d8 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 16 May 2018 09:28:18 +0200 Subject: [PATCH] Fix updating video tags to empty field --- client/src/app/shared/misc/utils.ts | 5 ++ .../shared/video-edit.component.ts | 2 +- .../src/assets/player/peertube-chunk-store.ts | 61 +++++++++++-------- server/controllers/api/videos/index.ts | 4 +- server/helpers/custom-validators/misc.ts | 4 +- server/helpers/custom-validators/videos.ts | 8 ++- server/middlewares/validators/videos.ts | 16 ++--- server/models/video/tag.ts | 2 + 8 files changed, 62 insertions(+), 40 deletions(-) diff --git a/client/src/app/shared/misc/utils.ts b/client/src/app/shared/misc/utils.ts index b5bf99be2..b9aa223cf 100644 --- a/client/src/app/shared/misc/utils.ts +++ b/client/src/app/shared/misc/utils.ts @@ -66,6 +66,11 @@ function objectToFormData (obj: any, form?: FormData, namespace?: string) { 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)) { objectToFormData(obj[ key ], fd, key) } else { diff --git a/client/src/app/videos/+video-edit/shared/video-edit.component.ts b/client/src/app/videos/+video-edit/shared/video-edit.component.ts index af4438bd2..d4567e26c 100644 --- a/client/src/app/videos/+video-edit/shared/video-edit.component.ts +++ b/client/src/app/videos/+video-edit/shared/video-edit.component.ts @@ -80,7 +80,7 @@ export class VideoEditComponent implements OnInit { this.form.addControl('licence', new FormControl('', VIDEO_LICENCE.VALIDATORS)) this.form.addControl('language', new FormControl('', VIDEO_LANGUAGE.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('previewfile', new FormControl('')) this.form.addControl('support', new FormControl('', VIDEO_SUPPORT.VALIDATORS)) diff --git a/client/src/assets/player/peertube-chunk-store.ts b/client/src/assets/player/peertube-chunk-store.ts index 84fbaf146..e14e31c04 100644 --- a/client/src/assets/player/peertube-chunk-store.ts +++ b/client/src/assets/player/peertube-chunk-store.ts @@ -155,17 +155,17 @@ export class PeertubeChunkStore extends EventEmitter { this.cleanerInterval = null } + if (this.db) { + await this.db.close() + + await this.dropDatabase(this.databaseName) + } + if (this.expirationDB) { await this.expirationDB.close() this.expirationDB = null } - if (this.db) { - console.log('Destroying IndexDB database %s.', this.databaseName) - await this.db.close() - await this.db.delete() - } - return cb() } catch (err) { console.error('Cannot destroy peertube chunk store.', err) @@ -181,31 +181,42 @@ export class PeertubeChunkStore extends EventEmitter { }, PeertubeChunkStore.CLEANER_INTERVAL_MS) } - private checkExpiration () { - this.expirationDB.transaction('rw', this.expirationDB.databases, async () => { - // Update our database expiration since we are alive - await this.expirationDB.databases.put({ - name: this.databaseName, - expiration: new Date().getTime() + PeertubeChunkStore.CLEANER_EXPIRATION_MS + private async checkExpiration () { + let databasesToDeleteInfo: { name: string }[] = [] + + try { + await this.expirationDB.transaction('rw', this.expirationDB.databases, async () => { + // 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() - const databasesToDeleteInfo = await this.expirationDB.databases.where('expiration').below(now).toArray() - - 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)) + for (const databaseToDeleteInfo of databasesToDeleteInfo) { + await this.dropDatabase(databaseToDeleteInfo.name) + } } - private dropDatabase (databaseName: string) { + private async dropDatabase (databaseName: string) { const dbToDelete = new ChunkDatabase(databaseName) + console.log('Destroying IndexDB database %s.', databaseName) - console.log('Deleting %s.', databaseName) - return dbToDelete.delete() - .catch(err => console.error('Cannot delete %s.', databaseName)) + try { + await dbToDelete.delete() + + 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?) { diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index c07430e6c..bcf1eaee6 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts @@ -244,7 +244,7 @@ async function addVideo (req: express.Request, res: express.Response, videoPhysi video.VideoFiles = [ videoFile ] - if (videoInfo.tags) { + if (videoInfo.tags !== undefined) { const tagInstances = await TagModel.findOrCreateTags(videoInfo.tags, t) 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) // Video tags update? - if (videoInfoToUpdate.tags) { + if (videoInfoToUpdate.tags !== undefined) { const tagInstances = await TagModel.findOrCreateTags(videoInfoToUpdate.tags, t) await videoInstanceUpdated.$set('Tags', tagInstances, sequelizeOptions) diff --git a/server/helpers/custom-validators/misc.ts b/server/helpers/custom-validators/misc.ts index 275482fa1..254b4db6c 100644 --- a/server/helpers/custom-validators/misc.ts +++ b/server/helpers/custom-validators/misc.ts @@ -35,7 +35,7 @@ function toIntOrNull (value: string) { return validator.toInt(value) } -function toStringOrNull (value: string) { +function toValueOrNull (value: string) { if (value === 'null') return null return value @@ -73,7 +73,7 @@ export { isUUIDValid, isIdOrUUIDValid, isDateValid, - toStringOrNull, + toValueOrNull, isBooleanValid, toIntOrNull, isFileValid diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts index c35db49ac..002324fe0 100644 --- a/server/helpers/custom-validators/videos.ts +++ b/server/helpers/custom-validators/videos.ts @@ -57,9 +57,11 @@ function isVideoTagValid (tag: string) { } function isVideoTagsValid (tags: string[]) { - return isArray(tags) && - validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) && - tags.every(tag => isVideoTagValid(tag)) + return tags === null || ( + isArray(tags) && + validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) && + tags.every(tag => isVideoTagValid(tag)) + ) } function isVideoAbuseReasonValid (value: string) { diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts index aa2afb068..dd0246a63 100644 --- a/server/middlewares/validators/videos.ts +++ b/server/middlewares/validators/videos.ts @@ -2,7 +2,7 @@ import * as express from 'express' import 'express-validator' import { body, param, query } from 'express-validator/check' 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 { isVideoAbuseReasonValid, isVideoCategoryValid, @@ -52,21 +52,22 @@ const videosAddValidator = [ .custom(isVideoLicenceValid).withMessage('Should have a valid licence'), body('language') .optional() - .customSanitizer(toStringOrNull) + .customSanitizer(toValueOrNull) .custom(isVideoLanguageValid).withMessage('Should have a valid language'), body('nsfw') .toBoolean() .custom(isBooleanValid).withMessage('Should have a valid NSFW attribute'), body('description') .optional() - .customSanitizer(toStringOrNull) + .customSanitizer(toValueOrNull) .custom(isVideoDescriptionValid).withMessage('Should have a valid description'), body('support') .optional() - .customSanitizer(toStringOrNull) + .customSanitizer(toValueOrNull) .custom(isVideoSupportValid).withMessage('Should have a valid support text'), body('tags') .optional() + .customSanitizer(toValueOrNull) .custom(isVideoTagsValid).withMessage('Should have correct tags'), body('commentsEnabled') .toBoolean() @@ -142,7 +143,7 @@ const videosUpdateValidator = [ .custom(isVideoLicenceValid).withMessage('Should have a valid licence'), body('language') .optional() - .customSanitizer(toStringOrNull) + .customSanitizer(toValueOrNull) .custom(isVideoLanguageValid).withMessage('Should have a valid language'), body('nsfw') .optional() @@ -154,14 +155,15 @@ const videosUpdateValidator = [ .custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), body('description') .optional() - .customSanitizer(toStringOrNull) + .customSanitizer(toValueOrNull) .custom(isVideoDescriptionValid).withMessage('Should have a valid description'), body('support') .optional() - .customSanitizer(toStringOrNull) + .customSanitizer(toValueOrNull) .custom(isVideoSupportValid).withMessage('Should have a valid support text'), body('tags') .optional() + .customSanitizer(toValueOrNull) .custom(isVideoTagsValid).withMessage('Should have correct tags'), body('commentsEnabled') .optional() diff --git a/server/models/video/tag.ts b/server/models/video/tag.ts index 0ae74d808..6d79a5575 100644 --- a/server/models/video/tag.ts +++ b/server/models/video/tag.ts @@ -37,6 +37,8 @@ export class TagModel extends Model { Videos: VideoModel[] static findOrCreateTags (tags: string[], transaction: Transaction) { + if (tags === null) return [] + const tasks: Bluebird[] = [] tags.forEach(tag => { const query = {