aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2020-01-08 15:11:38 +0100
committerChocobozzz <me@florianbigard.com>2020-01-08 15:44:41 +0100
commite612209767ebe1deb0af7688c96b7f979bb52b44 (patch)
treec5be9241e41a098f5452fe3cd187e2305d8047e3
parent440d39c52d4efb878b6a2e21584d6b8f52072f27 (diff)
downloadPeerTube-e612209767ebe1deb0af7688c96b7f979bb52b44.tar.gz
PeerTube-e612209767ebe1deb0af7688c96b7f979bb52b44.tar.zst
PeerTube-e612209767ebe1deb0af7688c96b7f979bb52b44.zip
Try to fix subscriptions inconsistencies
-rw-r--r--client/src/app/shared/video/abstract-video-list.html2
-rw-r--r--server/lib/activitypub/send/send-update.ts2
-rw-r--r--server/lib/activitypub/videos.ts2
-rw-r--r--server/lib/video-transcoding.ts2
-rw-r--r--server/models/account/account.ts2
-rw-r--r--server/models/activitypub/actor-follow.ts13
-rw-r--r--server/models/activitypub/actor.ts27
-rw-r--r--server/models/video/video-caption.ts2
-rw-r--r--server/models/video/video-channel.ts2
-rw-r--r--server/models/video/video.ts2
-rw-r--r--server/tests/api/activitypub/helpers.ts7
-rw-r--r--server/tests/api/server/follows.ts2
12 files changed, 37 insertions, 28 deletions
diff --git a/client/src/app/shared/video/abstract-video-list.html b/client/src/app/shared/video/abstract-video-list.html
index 3abc4312f..c8bb4270b 100644
--- a/client/src/app/shared/video/abstract-video-list.html
+++ b/client/src/app/shared/video/abstract-video-list.html
@@ -25,7 +25,7 @@
25 </div> 25 </div>
26 </div> 26 </div>
27 27
28 <div class="no-results" i18n *ngIf="pagination.totalItems === 0">No results.</div> 28 <div class="no-results" i18n *ngIf="hasDoneFirstQuery && videos.length === 0">No results.</div>
29 <div 29 <div
30 myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" [dataObservable]="onDataSubject.asObservable()" 30 myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" [dataObservable]="onDataSubject.asObservable()"
31 class="videos" 31 class="videos"
diff --git a/server/lib/activitypub/send/send-update.ts b/server/lib/activitypub/send/send-update.ts
index cb14b8dbf..9c76671b5 100644
--- a/server/lib/activitypub/send/send-update.ts
+++ b/server/lib/activitypub/send/send-update.ts
@@ -35,7 +35,7 @@ async function sendUpdateVideo (videoArg: MVideoAPWithoutCaption, t: Transaction
35 35
36 // Needed to build the AP object 36 // Needed to build the AP object
37 if (!video.VideoCaptions) { 37 if (!video.VideoCaptions) {
38 video.VideoCaptions = await video.$get('VideoCaptions', { transaction: t }) as VideoCaptionModel[] 38 video.VideoCaptions = await video.$get('VideoCaptions', { transaction: t })
39 } 39 }
40 40
41 const videoObject = video.toActivityPubObject() 41 const videoObject = video.toActivityPubObject()
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts
index 2fb1f8d49..ade93150f 100644
--- a/server/lib/activitypub/videos.ts
+++ b/server/lib/activitypub/videos.ts
@@ -86,7 +86,7 @@ async function federateVideoIfNeeded (videoArg: MVideoAPWithoutCaption, isNewVid
86 video.VideoCaptions = await video.$get('VideoCaptions', { 86 video.VideoCaptions = await video.$get('VideoCaptions', {
87 attributes: [ 'language' ], 87 attributes: [ 'language' ],
88 transaction 88 transaction
89 }) as VideoCaptionModel[] 89 })
90 } 90 }
91 91
92 if (isNewVideo) { 92 if (isNewVideo) {
diff --git a/server/lib/video-transcoding.ts b/server/lib/video-transcoding.ts
index 4fd1d62a9..0d5b3ae39 100644
--- a/server/lib/video-transcoding.ts
+++ b/server/lib/video-transcoding.ts
@@ -206,7 +206,7 @@ async function generateHlsPlaylist (video: MVideoWithFile, resolution: VideoReso
206 await createTorrentAndSetInfoHash(videoStreamingPlaylist, newVideoFile) 206 await createTorrentAndSetInfoHash(videoStreamingPlaylist, newVideoFile)
207 207
208 await newVideoFile.save() 208 await newVideoFile.save()
209 videoStreamingPlaylist.VideoFiles = await videoStreamingPlaylist.$get('VideoFiles') as VideoFileModel[] 209 videoStreamingPlaylist.VideoFiles = await videoStreamingPlaylist.$get('VideoFiles')
210 210
211 video.setHLSPlaylist(videoStreamingPlaylist) 211 video.setHLSPlaylist(videoStreamingPlaylist)
212 212
diff --git a/server/models/account/account.ts b/server/models/account/account.ts
index a757b7203..8a0ffeb63 100644
--- a/server/models/account/account.ts
+++ b/server/models/account/account.ts
@@ -223,7 +223,7 @@ export class AccountModel extends Model<AccountModel> {
223 @BeforeDestroy 223 @BeforeDestroy
224 static async sendDeleteIfOwned (instance: AccountModel, options) { 224 static async sendDeleteIfOwned (instance: AccountModel, options) {
225 if (!instance.Actor) { 225 if (!instance.Actor) {
226 instance.Actor = await instance.$get('Actor', { transaction: options.transaction }) as ActorModel 226 instance.Actor = await instance.$get('Actor', { transaction: options.transaction })
227 } 227 }
228 228
229 await ActorFollowModel.removeFollowsOf(instance.Actor.id, options.transaction) 229 await ActorFollowModel.removeFollowsOf(instance.Actor.id, options.transaction)
diff --git a/server/models/activitypub/actor-follow.ts b/server/models/activitypub/actor-follow.ts
index c65b975d2..f21d2b8a2 100644
--- a/server/models/activitypub/actor-follow.ts
+++ b/server/models/activitypub/actor-follow.ts
@@ -36,6 +36,7 @@ import {
36 MActorFollowSubscriptions 36 MActorFollowSubscriptions
37} from '@server/typings/models' 37} from '@server/typings/models'
38import { ActivityPubActorType } from '@shared/models' 38import { ActivityPubActorType } from '@shared/models'
39import { afterCommitIfTransaction } from '@server/helpers/database-utils'
39 40
40@Table({ 41@Table({
41 tableName: 'actorFollow', 42 tableName: 'actorFollow',
@@ -104,20 +105,20 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
104 105
105 @AfterCreate 106 @AfterCreate
106 @AfterUpdate 107 @AfterUpdate
107 static incrementFollowerAndFollowingCount (instance: ActorFollowModel) { 108 static incrementFollowerAndFollowingCount (instance: ActorFollowModel, options: any) {
108 if (instance.state !== 'accepted') return undefined 109 if (instance.state !== 'accepted') return undefined
109 110
110 return Promise.all([ 111 return Promise.all([
111 ActorModel.incrementFollows(instance.actorId, 'followingCount', 1), 112 ActorModel.rebuildFollowsCount(instance.actorId, 'following', options.transaction),
112 ActorModel.incrementFollows(instance.targetActorId, 'followersCount', 1) 113 ActorModel.rebuildFollowsCount(instance.targetActorId, 'followers', options.transaction)
113 ]) 114 ])
114 } 115 }
115 116
116 @AfterDestroy 117 @AfterDestroy
117 static decrementFollowerAndFollowingCount (instance: ActorFollowModel) { 118 static decrementFollowerAndFollowingCount (instance: ActorFollowModel, options: any) {
118 return Promise.all([ 119 return Promise.all([
119 ActorModel.incrementFollows(instance.actorId, 'followingCount',-1), 120 ActorModel.rebuildFollowsCount(instance.actorId, 'following', options.transaction),
120 ActorModel.incrementFollows(instance.targetActorId, 'followersCount', -1) 121 ActorModel.rebuildFollowsCount(instance.targetActorId, 'followers', options.transaction)
121 ]) 122 ])
122 } 123 }
123 124
diff --git a/server/models/activitypub/actor.ts b/server/models/activitypub/actor.ts
index 58b52ffb1..007647ced 100644
--- a/server/models/activitypub/actor.ts
+++ b/server/models/activitypub/actor.ts
@@ -47,7 +47,7 @@ import {
47 MActorWithInboxes 47 MActorWithInboxes
48} from '../../typings/models' 48} from '../../typings/models'
49import * as Bluebird from 'bluebird' 49import * as Bluebird from 'bluebird'
50import { Op, Transaction } from 'sequelize' 50import { Op, Transaction, literal } from 'sequelize'
51 51
52enum ScopeNames { 52enum ScopeNames {
53 FULL = 'FULL' 53 FULL = 'FULL'
@@ -421,13 +421,24 @@ export class ActorModel extends Model<ActorModel> {
421 return ActorModel.scope(ScopeNames.FULL).findOne(query) 421 return ActorModel.scope(ScopeNames.FULL).findOne(query)
422 } 422 }
423 423
424 static incrementFollows (id: number, column: 'followersCount' | 'followingCount', by: number) { 424 static rebuildFollowsCount (ofId: number, type: 'followers' | 'following', transaction?: Transaction) {
425 return ActorModel.increment(column, { 425 const sanitizedOfId = parseInt(ofId + '', 10)
426 by, 426 const where = { id: sanitizedOfId }
427 where: { 427
428 id 428 let columnToUpdate: string
429 } 429 let columnOfCount: string
430 }) 430
431 if (type === 'followers') {
432 columnToUpdate = 'followersCount'
433 columnOfCount = 'targetActorId'
434 } else {
435 columnToUpdate = 'followingCount'
436 columnOfCount = 'actorId'
437 }
438
439 return ActorModel.update({
440 [columnToUpdate]: literal(`(SELECT COUNT(*) FROM "actorFollow" WHERE "${columnOfCount}" = ${sanitizedOfId})`)
441 }, { where, transaction })
431 } 442 }
432 443
433 getSharedInbox (this: MActorWithInboxes) { 444 getSharedInbox (this: MActorWithInboxes) {
diff --git a/server/models/video/video-caption.ts b/server/models/video/video-caption.ts
index ad5801768..eeb2a4afd 100644
--- a/server/models/video/video-caption.ts
+++ b/server/models/video/video-caption.ts
@@ -79,7 +79,7 @@ export class VideoCaptionModel extends Model<VideoCaptionModel> {
79 @BeforeDestroy 79 @BeforeDestroy
80 static async removeFiles (instance: VideoCaptionModel) { 80 static async removeFiles (instance: VideoCaptionModel) {
81 if (!instance.Video) { 81 if (!instance.Video) {
82 instance.Video = await instance.$get('Video') as VideoModel 82 instance.Video = await instance.$get('Video')
83 } 83 }
84 84
85 if (instance.isOwned()) { 85 if (instance.isOwned()) {
diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts
index 05545bd9d..e10adcb3a 100644
--- a/server/models/video/video-channel.ts
+++ b/server/models/video/video-channel.ts
@@ -249,7 +249,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
249 @BeforeDestroy 249 @BeforeDestroy
250 static async sendDeleteIfOwned (instance: VideoChannelModel, options) { 250 static async sendDeleteIfOwned (instance: VideoChannelModel, options) {
251 if (!instance.Actor) { 251 if (!instance.Actor) {
252 instance.Actor = await instance.$get('Actor', { transaction: options.transaction }) as ActorModel 252 instance.Actor = await instance.$get('Actor', { transaction: options.transaction })
253 } 253 }
254 254
255 if (instance.Actor.isOwned()) { 255 if (instance.Actor.isOwned()) {
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index cd3245ee4..ac8c81ddf 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -1061,7 +1061,7 @@ export class VideoModel extends Model<VideoModel> {
1061 1061
1062 if (instance.isOwned()) { 1062 if (instance.isOwned()) {
1063 if (!Array.isArray(instance.VideoFiles)) { 1063 if (!Array.isArray(instance.VideoFiles)) {
1064 instance.VideoFiles = await instance.$get('VideoFiles') as VideoFileModel[] 1064 instance.VideoFiles = await instance.$get('VideoFiles')
1065 } 1065 }
1066 1066
1067 // Remove physical files and torrents 1067 // Remove physical files and torrents
diff --git a/server/tests/api/activitypub/helpers.ts b/server/tests/api/activitypub/helpers.ts
index 0d1f154fe..8c00ba3d6 100644
--- a/server/tests/api/activitypub/helpers.ts
+++ b/server/tests/api/activitypub/helpers.ts
@@ -76,7 +76,6 @@ describe('Test activity pub helpers', function () {
76 const mastodonObject = cloneDeep(require('./json/mastodon/bad-http-signature.json')) 76 const mastodonObject = cloneDeep(require('./json/mastodon/bad-http-signature.json'))
77 req.body = mastodonObject.body 77 req.body = mastodonObject.body
78 req.headers = mastodonObject.headers 78 req.headers = mastodonObject.headers
79 req.headers.signature = 'Signature ' + req.headers.signature
80 79
81 const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10) 80 const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10)
82 const publicKey = require('./json/mastodon/public-key.json').publicKey 81 const publicKey = require('./json/mastodon/public-key.json').publicKey
@@ -95,7 +94,6 @@ describe('Test activity pub helpers', function () {
95 const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json')) 94 const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json'))
96 req.body = mastodonObject.body 95 req.body = mastodonObject.body
97 req.headers = mastodonObject.headers 96 req.headers = mastodonObject.headers
98 req.headers.signature = 'Signature ' + req.headers.signature
99 97
100 const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10) 98 const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10)
101 const publicKey = require('./json/mastodon/bad-public-key.json').publicKey 99 const publicKey = require('./json/mastodon/bad-public-key.json').publicKey
@@ -114,7 +112,6 @@ describe('Test activity pub helpers', function () {
114 const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json')) 112 const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json'))
115 req.body = mastodonObject.body 113 req.body = mastodonObject.body
116 req.headers = mastodonObject.headers 114 req.headers = mastodonObject.headers
117 req.headers.signature = 'Signature ' + req.headers.signature
118 115
119 let errored = false 116 let errored = false
120 try { 117 try {
@@ -126,7 +123,7 @@ describe('Test activity pub helpers', function () {
126 expect(errored).to.be.true 123 expect(errored).to.be.true
127 }) 124 })
128 125
129 it('Should fail without scheme', async function () { 126 it('Should with a scheme', async function () {
130 const req = buildRequestStub() 127 const req = buildRequestStub()
131 req.method = 'POST' 128 req.method = 'POST'
132 req.url = '/accounts/ronan/inbox' 129 req.url = '/accounts/ronan/inbox'
@@ -134,6 +131,7 @@ describe('Test activity pub helpers', function () {
134 const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json')) 131 const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json'))
135 req.body = mastodonObject.body 132 req.body = mastodonObject.body
136 req.headers = mastodonObject.headers 133 req.headers = mastodonObject.headers
134 req.headers = 'Signature ' + mastodonObject.headers
137 135
138 let errored = false 136 let errored = false
139 try { 137 try {
@@ -153,7 +151,6 @@ describe('Test activity pub helpers', function () {
153 const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json')) 151 const mastodonObject = cloneDeep(require('./json/mastodon/http-signature.json'))
154 req.body = mastodonObject.body 152 req.body = mastodonObject.body
155 req.headers = mastodonObject.headers 153 req.headers = mastodonObject.headers
156 req.headers.signature = 'Signature ' + req.headers.signature
157 154
158 const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10) 155 const parsed = parseHTTPSignature(req, 3600 * 1000 * 365 * 10)
159 const publicKey = require('./json/mastodon/public-key.json').publicKey 156 const publicKey = require('./json/mastodon/public-key.json').publicKey
diff --git a/server/tests/api/server/follows.ts b/server/tests/api/server/follows.ts
index 60dbe2e6d..4ffa9e791 100644
--- a/server/tests/api/server/follows.ts
+++ b/server/tests/api/server/follows.ts
@@ -419,7 +419,7 @@ describe('Test follows', function () {
419 await expectAccountFollows(servers[1].url, 'peertube@localhost:' + servers[0].port, 0, 1) 419 await expectAccountFollows(servers[1].url, 'peertube@localhost:' + servers[0].port, 0, 1)
420 await expectAccountFollows(servers[1].url, 'peertube@localhost:' + servers[1].port, 1, 0) 420 await expectAccountFollows(servers[1].url, 'peertube@localhost:' + servers[1].port, 1, 0)
421 421
422 await expectAccountFollows(servers[2].url, 'peertube@localhost:' + servers[0].port, 0, 2) 422 await expectAccountFollows(servers[2].url, 'peertube@localhost:' + servers[0].port, 0, 1)
423 await expectAccountFollows(servers[2].url, 'peertube@localhost:' + servers[2].port, 1, 0) 423 await expectAccountFollows(servers[2].url, 'peertube@localhost:' + servers[2].port, 1, 0)
424 }) 424 })
425 425