]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Add notification settings migration
authorChocobozzz <me@florianbigard.com>
Fri, 28 Dec 2018 12:47:17 +0000 (13:47 +0100)
committerChocobozzz <chocobozzz@cpy.re>
Wed, 9 Jan 2019 10:15:15 +0000 (11:15 +0100)
server/controllers/api/videos/index.ts
server/initializers/constants.ts
server/initializers/migrations/0315-user-notifications.ts [new file with mode: 0644]
server/lib/activitypub/videos.ts
server/lib/job-queue/handlers/video-file.ts
server/lib/job-queue/handlers/video-import.ts
server/tests/api/users/user-notifications.ts

index 94ed08fedb4ea2d6af1db4f5a2fd5a34029bda90..33521a8c1386eb67e6bfe157338c69d553133895 100644 (file)
@@ -264,7 +264,6 @@ async function addVideo (req: express.Request, res: express.Response) {
     }
 
     await federateVideoIfNeeded(video, true, t)
-    Notifier.Instance.notifyOnNewVideo(video)
 
     auditLogger.create(getAuditIdFromRes(res), new VideoAuditView(videoCreated.toFormattedDetailsJSON()))
     logger.info('Video with name %s and uuid %s created.', videoInfo.name, videoCreated.uuid)
@@ -272,6 +271,8 @@ async function addVideo (req: express.Request, res: express.Response) {
     return videoCreated
   })
 
+  Notifier.Instance.notifyOnNewVideo(videoCreated)
+
   if (video.state === VideoState.TO_TRANSCODE) {
     // Put uuid because we don't have id auto incremented for now
     const dataInput = {
@@ -311,10 +312,8 @@ async function updateVideo (req: express.Request, res: express.Response) {
   }
 
   try {
-    await sequelizeTypescript.transaction(async t => {
-      const sequelizeOptions = {
-        transaction: t
-      }
+    const videoInstanceUpdated = await sequelizeTypescript.transaction(async t => {
+      const sequelizeOptions = { transaction: t }
       const oldVideoChannel = videoInstance.VideoChannel
 
       if (videoInfoToUpdate.name !== undefined) videoInstance.set('name', videoInfoToUpdate.name)
@@ -367,17 +366,19 @@ async function updateVideo (req: express.Request, res: express.Response) {
       const isNewVideo = wasPrivateVideo && videoInstanceUpdated.privacy !== VideoPrivacy.PRIVATE
       await federateVideoIfNeeded(videoInstanceUpdated, isNewVideo, t)
 
-      if (wasUnlistedVideo || wasPrivateVideo) {
-        Notifier.Instance.notifyOnNewVideo(videoInstanceUpdated)
-      }
-
       auditLogger.update(
         getAuditIdFromRes(res),
         new VideoAuditView(videoInstanceUpdated.toFormattedDetailsJSON()),
         oldVideoAuditView
       )
       logger.info('Video with name %s and uuid %s updated.', videoInstance.name, videoInstance.uuid)
+
+      return videoInstanceUpdated
     })
+
+    if (wasUnlistedVideo || wasPrivateVideo) {
+      Notifier.Instance.notifyOnNewVideo(videoInstanceUpdated)
+    }
   } catch (err) {
     // Force fields we want to update
     // If the transaction is retried, sequelize will think the object has not changed
index fcfaf71a01e2ae8ee28555b1cb853726065e3aac..91e74f6c71cde8a5a9868950b888ba22903e184e 100644 (file)
@@ -16,7 +16,7 @@ let config: IConfig = require('config')
 
 // ---------------------------------------------------------------------------
 
-const LAST_MIGRATION_VERSION = 310
+const LAST_MIGRATION_VERSION = 315
 
 // ---------------------------------------------------------------------------
 
diff --git a/server/initializers/migrations/0315-user-notifications.ts b/server/initializers/migrations/0315-user-notifications.ts
new file mode 100644 (file)
index 0000000..2bd9c65
--- /dev/null
@@ -0,0 +1,41 @@
+import * as Sequelize from 'sequelize'
+
+async function up (utils: {
+  transaction: Sequelize.Transaction,
+  queryInterface: Sequelize.QueryInterface,
+  sequelize: Sequelize.Sequelize
+}): Promise<void> {
+
+  {
+    const query = `
+CREATE TABLE IF NOT EXISTS "userNotificationSetting" ("id" SERIAL,
+"newVideoFromSubscription" INTEGER NOT NULL DEFAULT NULL,
+"newCommentOnMyVideo" INTEGER NOT NULL DEFAULT NULL,
+"videoAbuseAsModerator" INTEGER NOT NULL DEFAULT NULL,
+"blacklistOnMyVideo" INTEGER NOT NULL DEFAULT NULL,
+"userId" INTEGER REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
+"createdAt" TIMESTAMP WITH TIME ZONE NOT NULL,
+"updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL,
+PRIMARY KEY ("id"))
+`
+    await utils.sequelize.query(query)
+  }
+
+  {
+    const query = 'INSERT INTO "userNotificationSetting" ' +
+      '("newVideoFromSubscription", "newCommentOnMyVideo", "videoAbuseAsModerator", "blacklistOnMyVideo", ' +
+      '"userId", "createdAt", "updatedAt") ' +
+      '(SELECT 2, 2, 4, 4, id, NOW(), NOW() FROM "user")'
+
+    await utils.sequelize.query(query)
+  }
+}
+
+function down (options) {
+  throw new Error('Not implemented.')
+}
+
+export {
+  up,
+  down
+}
index 5794988a516e826f11cf68383c75d9b9434ec351..893768769d39840e6ffbedf252412db806617b46 100644 (file)
@@ -204,19 +204,17 @@ async function updateVideoFromAP (options: {
   overrideTo?: string[]
 }) {
   logger.debug('Updating remote video "%s".', options.videoObject.uuid)
+
   let videoFieldsSave: any
+  const wasPrivateVideo = options.video.privacy === VideoPrivacy.PRIVATE
+  const wasUnlistedVideo = options.video.privacy === VideoPrivacy.UNLISTED
 
   try {
     await sequelizeTypescript.transaction(async t => {
-      const sequelizeOptions = {
-        transaction: t
-      }
+      const sequelizeOptions = { transaction: t }
 
       videoFieldsSave = options.video.toJSON()
 
-      const wasPrivateVideo = options.video.privacy === VideoPrivacy.PRIVATE
-      const wasUnlistedVideo = options.video.privacy === VideoPrivacy.UNLISTED
-
       // Check actor has the right to update the video
       const videoChannel = options.video.VideoChannel
       if (videoChannel.Account.id !== options.account.id) {
@@ -281,15 +279,13 @@ async function updateVideoFromAP (options: {
         })
         options.video.VideoCaptions = await Promise.all(videoCaptionsPromises)
       }
-
-      {
-        // Notify our users?
-        if (wasPrivateVideo || wasUnlistedVideo) {
-          Notifier.Instance.notifyOnNewVideo(options.video)
-        }
-      }
     })
 
+    // Notify our users?
+    if (wasPrivateVideo || wasUnlistedVideo) {
+      Notifier.Instance.notifyOnNewVideo(options.video)
+    }
+
     logger.info('Remote video with uuid %s updated', options.videoObject.uuid)
   } catch (err) {
     if (options.video !== undefined && videoFieldsSave !== undefined) {
index 959cc04fa0b3b69849027ba4b425dc37f0f04fb5..480d324dc290dae43a2fa4cb54147c096dc3fe3d 100644 (file)
@@ -1,5 +1,5 @@
 import * as Bull from 'bull'
-import { VideoResolution, VideoState, Job } from '../../../../shared'
+import { VideoResolution, VideoState } from '../../../../shared'
 import { logger } from '../../../helpers/logger'
 import { VideoModel } from '../../../models/video/video'
 import { JobQueue } from '../job-queue'
@@ -8,7 +8,7 @@ import { retryTransactionWrapper } from '../../../helpers/database-utils'
 import { sequelizeTypescript } from '../../../initializers'
 import * as Bluebird from 'bluebird'
 import { computeResolutionsToTranscode } from '../../../helpers/ffmpeg-utils'
-import { importVideoFile, transcodeOriginalVideofile, optimizeVideofile } from '../../video-transcoding'
+import { importVideoFile, optimizeVideofile, transcodeOriginalVideofile } from '../../video-transcoding'
 import { Notifier } from '../../notifier'
 
 export type VideoFilePayload = {
@@ -68,7 +68,7 @@ async function processVideoFile (job: Bull.Job) {
 async function onVideoFileTranscoderOrImportSuccess (video: VideoModel) {
   if (video === undefined) return undefined
 
-  return sequelizeTypescript.transaction(async t => {
+  const { videoDatabase, isNewVideo } = await sequelizeTypescript.transaction(async t => {
     // Maybe the video changed in database, refresh it
     let videoDatabase = await VideoModel.loadAndPopulateAccountAndServerAndTags(video.uuid, t)
     // Video does not exist anymore
@@ -87,10 +87,11 @@ async function onVideoFileTranscoderOrImportSuccess (video: VideoModel) {
 
     // If the video was not published, we consider it is a new one for other instances
     await federateVideoIfNeeded(videoDatabase, isNewVideo, t)
-    if (isNewVideo) Notifier.Instance.notifyOnNewVideo(video)
 
-    return undefined
+    return { videoDatabase, isNewVideo }
   })
+
+  if (isNewVideo) Notifier.Instance.notifyOnNewVideo(videoDatabase)
 }
 
 async function onVideoFileOptimizerSuccess (videoArg: VideoModel, isNewVideo: boolean) {
@@ -99,7 +100,7 @@ async function onVideoFileOptimizerSuccess (videoArg: VideoModel, isNewVideo: bo
   // Outside the transaction (IO on disk)
   const { videoFileResolution } = await videoArg.getOriginalFileResolution()
 
-  return sequelizeTypescript.transaction(async t => {
+  const videoDatabase = await sequelizeTypescript.transaction(async t => {
     // Maybe the video changed in database, refresh it
     let videoDatabase = await VideoModel.loadAndPopulateAccountAndServerAndTags(videoArg.uuid, t)
     // Video does not exist anymore
@@ -137,8 +138,11 @@ async function onVideoFileOptimizerSuccess (videoArg: VideoModel, isNewVideo: bo
     }
 
     await federateVideoIfNeeded(videoDatabase, isNewVideo, t)
-    if (isNewVideo) Notifier.Instance.notifyOnNewVideo(videoDatabase)
+
+    return videoDatabase
   })
+
+  if (isNewVideo) Notifier.Instance.notifyOnNewVideo(videoDatabase)
 }
 
 // ---------------------------------------------------------------------------
index 82edb8d5c0001476efeaa1fed41f2959ef42ac69..29cd1198c7fedcddeabac4a2b0b21c1f782ca892 100644 (file)
@@ -180,12 +180,11 @@ async function processFile (downloader: () => Promise<string>, videoImport: Vide
       // Update video DB object
       video.duration = duration
       video.state = CONFIG.TRANSCODING.ENABLED ? VideoState.TO_TRANSCODE : VideoState.PUBLISHED
-      const videoUpdated = await video.save({ transaction: t })
+      await video.save({ transaction: t })
 
       // Now we can federate the video (reload from database, we need more attributes)
       const videoForFederation = await VideoModel.loadAndPopulateAccountAndServerAndTags(video.uuid, t)
       await federateVideoIfNeeded(videoForFederation, true, t)
-      Notifier.Instance.notifyOnNewVideo(videoForFederation)
 
       // Update video import object
       videoImport.state = VideoImportState.SUCCESS
@@ -193,10 +192,12 @@ async function processFile (downloader: () => Promise<string>, videoImport: Vide
 
       logger.info('Video %s imported.', video.uuid)
 
-      videoImportUpdated.Video = videoUpdated
+      videoImportUpdated.Video = videoForFederation
       return videoImportUpdated
     })
 
+    Notifier.Instance.notifyOnNewVideo(videoImportUpdated.Video)
+
     // Create transcoding jobs?
     if (videoImportUpdated.Video.state === VideoState.TO_TRANSCODE) {
       // Put uuid because we don't have id auto incremented for now
index ea35e63902e8ec3f473a3249edf9a7b9629ce80f..09c0479fdf79c45fda9530490ce00926a64b5a59 100644 (file)
@@ -152,6 +152,8 @@ describe('Test users notifications', function () {
       const videoName = 'remote video ' + videoNameId
 
       const uuid = await uploadVideoByRemoteAccount(servers, videoNameId)
+      await waitJobs(servers)
+
       await checkNewVideoFromSubscription(baseParams, videoName, uuid, 'presence')
     })
 
@@ -194,6 +196,7 @@ describe('Test users notifications', function () {
         }
       }
       const uuid = await uploadVideoByRemoteAccount(servers, videoNameId, data)
+      await waitJobs(servers)
 
       await wait(6000)
       await checkNewVideoFromSubscription(baseParams, videoName, uuid, 'presence')
@@ -245,6 +248,7 @@ describe('Test users notifications', function () {
 
       const data = { privacy: VideoPrivacy.PRIVATE }
       const uuid = await uploadVideoByRemoteAccount(servers, videoNameId, data)
+      await waitJobs(servers)
 
       await checkNewVideoFromSubscription(baseParams, videoName, uuid, 'absence')
 
@@ -276,6 +280,7 @@ describe('Test users notifications', function () {
 
       const data = { privacy: VideoPrivacy.PRIVATE }
       const uuid = await uploadVideoByRemoteAccount(servers, videoNameId, data)
+      await waitJobs(servers)
 
       await updateVideo(servers[1].url, servers[1].accessToken, uuid, { privacy: VideoPrivacy.UNLISTED })