diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2017-11-16 11:08:25 +0100 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2017-11-27 19:40:52 +0100 |
commit | efc32059d980c51793e8e9ac0fb6a885a8026f94 (patch) | |
tree | c272e63fd57a9625b53dc26ceb1b46aee35d21d3 /server/helpers | |
parent | d846501818c2d29e66e6fd141789cb04fd55a437 (diff) | |
download | PeerTube-efc32059d980c51793e8e9ac0fb6a885a8026f94.tar.gz PeerTube-efc32059d980c51793e8e9ac0fb6a885a8026f94.tar.zst PeerTube-efc32059d980c51793e8e9ac0fb6a885a8026f94.zip |
Send server announce when users upload a video
Diffstat (limited to 'server/helpers')
-rw-r--r-- | server/helpers/activitypub.ts | 30 | ||||
-rw-r--r-- | server/helpers/core-utils.ts | 9 | ||||
-rw-r--r-- | server/helpers/custom-validators/activitypub/videos.ts | 15 | ||||
-rw-r--r-- | server/helpers/peertube-crypto.ts | 10 | ||||
-rw-r--r-- | server/helpers/utils.ts | 18 |
5 files changed, 55 insertions, 27 deletions
diff --git a/server/helpers/activitypub.ts b/server/helpers/activitypub.ts index de20ba55d..b376b8ca2 100644 --- a/server/helpers/activitypub.ts +++ b/server/helpers/activitypub.ts | |||
@@ -1,15 +1,19 @@ | |||
1 | import { join } from 'path' | 1 | import { join } from 'path' |
2 | import * as request from 'request' | 2 | import * as request from 'request' |
3 | import * as Sequelize from 'sequelize' | ||
3 | import * as url from 'url' | 4 | import * as url from 'url' |
4 | import { ActivityIconObject } from '../../shared/index' | 5 | import { ActivityIconObject } from '../../shared/index' |
5 | import { ActivityPubActor } from '../../shared/models/activitypub/activitypub-actor' | 6 | import { ActivityPubActor } from '../../shared/models/activitypub/activitypub-actor' |
6 | import { ResultList } from '../../shared/models/result-list.model' | 7 | import { ResultList } from '../../shared/models/result-list.model' |
7 | import { database as db, REMOTE_SCHEME } from '../initializers' | 8 | import { database as db, REMOTE_SCHEME } from '../initializers' |
8 | import { ACTIVITY_PUB_ACCEPT_HEADER, CONFIG, STATIC_PATHS } from '../initializers/constants' | 9 | import { ACTIVITY_PUB_ACCEPT_HEADER, CONFIG, STATIC_PATHS } from '../initializers/constants' |
10 | import { sendAnnounce } from '../lib/activitypub/send-request' | ||
11 | import { VideoChannelInstance } from '../models/video/video-channel-interface' | ||
9 | import { VideoInstance } from '../models/video/video-interface' | 12 | import { VideoInstance } from '../models/video/video-interface' |
10 | import { isRemoteAccountValid } from './custom-validators' | 13 | import { isRemoteAccountValid } from './custom-validators' |
11 | import { logger } from './logger' | 14 | import { logger } from './logger' |
12 | import { doRequest, doRequestAndSaveToFile } from './requests' | 15 | import { doRequest, doRequestAndSaveToFile } from './requests' |
16 | import { getServerAccount } from './utils' | ||
13 | 17 | ||
14 | function generateThumbnailFromUrl (video: VideoInstance, icon: ActivityIconObject) { | 18 | function generateThumbnailFromUrl (video: VideoInstance, icon: ActivityIconObject) { |
15 | const thumbnailName = video.getThumbnailName() | 19 | const thumbnailName = video.getThumbnailName() |
@@ -22,6 +26,28 @@ function generateThumbnailFromUrl (video: VideoInstance, icon: ActivityIconObjec | |||
22 | return doRequestAndSaveToFile(options, thumbnailPath) | 26 | return doRequestAndSaveToFile(options, thumbnailPath) |
23 | } | 27 | } |
24 | 28 | ||
29 | async function shareVideoChannelByServer (videoChannel: VideoChannelInstance, t: Sequelize.Transaction) { | ||
30 | const serverAccount = await getServerAccount() | ||
31 | |||
32 | await db.VideoChannelShare.create({ | ||
33 | accountId: serverAccount.id, | ||
34 | videoChannelId: videoChannel.id | ||
35 | }, { transaction: t }) | ||
36 | |||
37 | return sendAnnounce(serverAccount, videoChannel, t) | ||
38 | } | ||
39 | |||
40 | async function shareVideoByServer (video: VideoInstance, t: Sequelize.Transaction) { | ||
41 | const serverAccount = await getServerAccount() | ||
42 | |||
43 | await db.VideoShare.create({ | ||
44 | accountId: serverAccount.id, | ||
45 | videoId: video.id | ||
46 | }, { transaction: t }) | ||
47 | |||
48 | return sendAnnounce(serverAccount, video, t) | ||
49 | } | ||
50 | |||
25 | function getActivityPubUrl (type: 'video' | 'videoChannel' | 'account' | 'videoAbuse', id: string) { | 51 | function getActivityPubUrl (type: 'video' | 'videoChannel' | 'account' | 'videoAbuse', id: string) { |
26 | if (type === 'video') return CONFIG.WEBSERVER.URL + '/videos/watch/' + id | 52 | if (type === 'video') return CONFIG.WEBSERVER.URL + '/videos/watch/' + id |
27 | else if (type === 'videoChannel') return CONFIG.WEBSERVER.URL + '/video-channels/' + id | 53 | else if (type === 'videoChannel') return CONFIG.WEBSERVER.URL + '/video-channels/' + id |
@@ -172,7 +198,9 @@ export { | |||
172 | generateThumbnailFromUrl, | 198 | generateThumbnailFromUrl, |
173 | getOrCreateAccount, | 199 | getOrCreateAccount, |
174 | fetchRemoteVideoPreview, | 200 | fetchRemoteVideoPreview, |
175 | fetchRemoteVideoDescription | 201 | fetchRemoteVideoDescription, |
202 | shareVideoChannelByServer, | ||
203 | shareVideoByServer | ||
176 | } | 204 | } |
177 | 205 | ||
178 | // --------------------------------------------------------------------------- | 206 | // --------------------------------------------------------------------------- |
diff --git a/server/helpers/core-utils.ts b/server/helpers/core-utils.ts index d8748e1d7..4ff07848c 100644 --- a/server/helpers/core-utils.ts +++ b/server/helpers/core-utils.ts | |||
@@ -20,9 +20,6 @@ import * as bcrypt from 'bcrypt' | |||
20 | import * as createTorrent from 'create-torrent' | 20 | import * as createTorrent from 'create-torrent' |
21 | import * as rimraf from 'rimraf' | 21 | import * as rimraf from 'rimraf' |
22 | import * as pem from 'pem' | 22 | import * as pem from 'pem' |
23 | import * as jsonld from 'jsonld' | ||
24 | import * as jsig from 'jsonld-signatures' | ||
25 | jsig.use('jsonld', jsonld) | ||
26 | 23 | ||
27 | function isTestInstance () { | 24 | function isTestInstance () { |
28 | return process.env.NODE_ENV === 'test' | 25 | return process.env.NODE_ENV === 'test' |
@@ -120,8 +117,6 @@ const bcryptHashPromise = promisify2<any, string | number, string>(bcrypt.hash) | |||
120 | const createTorrentPromise = promisify2<string, any, any>(createTorrent) | 117 | const createTorrentPromise = promisify2<string, any, any>(createTorrent) |
121 | const rimrafPromise = promisify1WithVoid<string>(rimraf) | 118 | const rimrafPromise = promisify1WithVoid<string>(rimraf) |
122 | const statPromise = promisify1<string, Stats>(stat) | 119 | const statPromise = promisify1<string, Stats>(stat) |
123 | const jsonldSignPromise = promisify2<object, { privateKeyPem: string, creator: string }, object>(jsig.sign) | ||
124 | const jsonldVerifyPromise = promisify2<object, object, object>(jsig.verify) | ||
125 | 120 | ||
126 | // --------------------------------------------------------------------------- | 121 | // --------------------------------------------------------------------------- |
127 | 122 | ||
@@ -150,7 +145,5 @@ export { | |||
150 | bcryptHashPromise, | 145 | bcryptHashPromise, |
151 | createTorrentPromise, | 146 | createTorrentPromise, |
152 | rimrafPromise, | 147 | rimrafPromise, |
153 | statPromise, | 148 | statPromise |
154 | jsonldSignPromise, | ||
155 | jsonldVerifyPromise | ||
156 | } | 149 | } |
diff --git a/server/helpers/custom-validators/activitypub/videos.ts b/server/helpers/custom-validators/activitypub/videos.ts index 9ddacd601..89c49b0df 100644 --- a/server/helpers/custom-validators/activitypub/videos.ts +++ b/server/helpers/custom-validators/activitypub/videos.ts | |||
@@ -34,7 +34,7 @@ function isActivityPubVideoDurationValid (value: string) { | |||
34 | typeof value === 'string' && | 34 | typeof value === 'string' && |
35 | value.startsWith('PT') && | 35 | value.startsWith('PT') && |
36 | value.endsWith('S') && | 36 | value.endsWith('S') && |
37 | isVideoDurationValid(value.replace(/[^0-9]+/, '')) | 37 | isVideoDurationValid(value.replace(/[^0-9]+/g, '')) |
38 | } | 38 | } |
39 | 39 | ||
40 | function isVideoTorrentObjectValid (video: any) { | 40 | function isVideoTorrentObjectValid (video: any) { |
@@ -46,13 +46,14 @@ function isVideoTorrentObjectValid (video: any) { | |||
46 | isRemoteIdentifierValid(video.category) && | 46 | isRemoteIdentifierValid(video.category) && |
47 | isRemoteIdentifierValid(video.licence) && | 47 | isRemoteIdentifierValid(video.licence) && |
48 | isRemoteIdentifierValid(video.language) && | 48 | isRemoteIdentifierValid(video.language) && |
49 | isVideoViewsValid(video.video) && | 49 | isVideoViewsValid(video.views) && |
50 | isVideoNSFWValid(video.nsfw) && | 50 | isVideoNSFWValid(video.nsfw) && |
51 | isDateValid(video.published) && | 51 | isDateValid(video.published) && |
52 | isDateValid(video.updated) && | 52 | isDateValid(video.updated) && |
53 | isRemoteVideoContentValid(video.mediaType, video.content) && | 53 | isRemoteVideoContentValid(video.mediaType, video.content) && |
54 | isRemoteVideoIconValid(video.icon) && | 54 | isRemoteVideoIconValid(video.icon) && |
55 | setValidRemoteVideoUrls(video.url) | 55 | setValidRemoteVideoUrls(video) && |
56 | video.url.length !== 0 | ||
56 | } | 57 | } |
57 | 58 | ||
58 | function isVideoFlagValid (activity: any) { | 59 | function isVideoFlagValid (activity: any) { |
@@ -132,8 +133,8 @@ function isRemoteVideoIconValid (icon: any) { | |||
132 | return icon.type === 'Image' && | 133 | return icon.type === 'Image' && |
133 | isVideoUrlValid(icon.url) && | 134 | isVideoUrlValid(icon.url) && |
134 | icon.mediaType === 'image/jpeg' && | 135 | icon.mediaType === 'image/jpeg' && |
135 | validator.isInt(icon.width, { min: 0 }) && | 136 | validator.isInt(icon.width + '', { min: 0 }) && |
136 | validator.isInt(icon.height, { min: 0 }) | 137 | validator.isInt(icon.height + '', { min: 0 }) |
137 | } | 138 | } |
138 | 139 | ||
139 | function setValidRemoteVideoUrls (video: any) { | 140 | function setValidRemoteVideoUrls (video: any) { |
@@ -149,6 +150,6 @@ function isRemoteVideoUrlValid (url: any) { | |||
149 | return url.type === 'Link' && | 150 | return url.type === 'Link' && |
150 | ACTIVITY_PUB.VIDEO_URL_MIME_TYPES.indexOf(url.mimeType) !== -1 && | 151 | ACTIVITY_PUB.VIDEO_URL_MIME_TYPES.indexOf(url.mimeType) !== -1 && |
151 | isVideoUrlValid(url.url) && | 152 | isVideoUrlValid(url.url) && |
152 | validator.isInt(url.width, { min: 0 }) && | 153 | validator.isInt(url.width + '', { min: 0 }) && |
153 | validator.isInt(url.size, { min: 0 }) | 154 | validator.isInt(url.size + '', { min: 0 }) |
154 | } | 155 | } |
diff --git a/server/helpers/peertube-crypto.ts b/server/helpers/peertube-crypto.ts index 6d50e446f..04a8d5681 100644 --- a/server/helpers/peertube-crypto.ts +++ b/server/helpers/peertube-crypto.ts | |||
@@ -1,4 +1,6 @@ | |||
1 | import * as jsonld from 'jsonld' | ||
1 | import * as jsig from 'jsonld-signatures' | 2 | import * as jsig from 'jsonld-signatures' |
3 | jsig.use('jsonld', jsonld) | ||
2 | 4 | ||
3 | import { | 5 | import { |
4 | PRIVATE_RSA_KEY_SIZE, | 6 | PRIVATE_RSA_KEY_SIZE, |
@@ -9,9 +11,7 @@ import { | |||
9 | bcryptGenSaltPromise, | 11 | bcryptGenSaltPromise, |
10 | bcryptHashPromise, | 12 | bcryptHashPromise, |
11 | createPrivateKey, | 13 | createPrivateKey, |
12 | getPublicKey, | 14 | getPublicKey |
13 | jsonldSignPromise, | ||
14 | jsonldVerifyPromise | ||
15 | } from './core-utils' | 15 | } from './core-utils' |
16 | import { logger } from './logger' | 16 | import { logger } from './logger' |
17 | import { AccountInstance } from '../models/account/account-interface' | 17 | import { AccountInstance } from '../models/account/account-interface' |
@@ -45,7 +45,7 @@ function isSignatureVerified (fromAccount: AccountInstance, signedDocument: obje | |||
45 | publicKeyOwner: publicKeyOwnerObject | 45 | publicKeyOwner: publicKeyOwnerObject |
46 | } | 46 | } |
47 | 47 | ||
48 | return jsonldVerifyPromise(signedDocument, options) | 48 | return jsig.promises.verify(signedDocument, options) |
49 | .catch(err => { | 49 | .catch(err => { |
50 | logger.error('Cannot check signature.', err) | 50 | logger.error('Cannot check signature.', err) |
51 | return false | 51 | return false |
@@ -58,7 +58,7 @@ function signObject (byAccount: AccountInstance, data: any) { | |||
58 | creator: byAccount.url | 58 | creator: byAccount.url |
59 | } | 59 | } |
60 | 60 | ||
61 | return jsonldSignPromise(data, options) | 61 | return jsig.promises.sign(data, options) |
62 | } | 62 | } |
63 | 63 | ||
64 | function comparePassword (plainPassword: string, hashPassword: string) { | 64 | function comparePassword (plainPassword: string, hashPassword: string) { |
diff --git a/server/helpers/utils.ts b/server/helpers/utils.ts index 39957c90f..3af14a68a 100644 --- a/server/helpers/utils.ts +++ b/server/helpers/utils.ts | |||
@@ -6,6 +6,7 @@ import { CONFIG, database as db } from '../initializers' | |||
6 | import { ResultList } from '../../shared' | 6 | import { ResultList } from '../../shared' |
7 | import { VideoResolution } from '../../shared/models/videos/video-resolution.enum' | 7 | import { VideoResolution } from '../../shared/models/videos/video-resolution.enum' |
8 | import { AccountInstance } from '../models/account/account-interface' | 8 | import { AccountInstance } from '../models/account/account-interface' |
9 | import { logger } from './logger' | ||
9 | 10 | ||
10 | function badRequest (req: express.Request, res: express.Response, next: express.NextFunction) { | 11 | function badRequest (req: express.Request, res: express.Response, next: express.NextFunction) { |
11 | return res.type('json').status(400).end() | 12 | return res.type('json').status(400).end() |
@@ -79,13 +80,18 @@ function resetSequelizeInstance (instance: Sequelize.Instance<any>, savedFields: | |||
79 | }) | 80 | }) |
80 | } | 81 | } |
81 | 82 | ||
82 | let applicationAccount: AccountInstance | 83 | let serverAccount: AccountInstance |
83 | async function getApplicationAccount () { | 84 | async function getServerAccount () { |
84 | if (applicationAccount === undefined) { | 85 | if (serverAccount === undefined) { |
85 | applicationAccount = await db.Account.loadApplication() | 86 | serverAccount = await db.Account.loadApplication() |
86 | } | 87 | } |
87 | 88 | ||
88 | return Promise.resolve(applicationAccount) | 89 | if (!serverAccount) { |
90 | logger.error('Cannot load server account.') | ||
91 | process.exit(0) | ||
92 | } | ||
93 | |||
94 | return Promise.resolve(serverAccount) | ||
89 | } | 95 | } |
90 | 96 | ||
91 | type SortType = { sortModel: any, sortValue: string } | 97 | type SortType = { sortModel: any, sortValue: string } |
@@ -99,6 +105,6 @@ export { | |||
99 | isSignupAllowed, | 105 | isSignupAllowed, |
100 | computeResolutionsToTranscode, | 106 | computeResolutionsToTranscode, |
101 | resetSequelizeInstance, | 107 | resetSequelizeInstance, |
102 | getApplicationAccount, | 108 | getServerAccount, |
103 | SortType | 109 | SortType |
104 | } | 110 | } |