aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/helpers
diff options
context:
space:
mode:
Diffstat (limited to 'server/helpers')
-rw-r--r--server/helpers/activitypub.ts6
-rw-r--r--server/helpers/custom-validators/activitypub/activity.ts19
-rw-r--r--server/helpers/custom-validators/activitypub/actor.ts61
-rw-r--r--server/helpers/custom-validators/activitypub/announce.ts6
-rw-r--r--server/helpers/custom-validators/activitypub/misc.ts20
-rw-r--r--server/helpers/custom-validators/activitypub/undo.ts4
-rw-r--r--server/helpers/custom-validators/activitypub/video-channels.ts6
-rw-r--r--server/helpers/custom-validators/activitypub/videos.ts14
-rw-r--r--server/helpers/custom-validators/webfinger.ts8
-rw-r--r--server/helpers/peertube-crypto.ts18
-rw-r--r--server/helpers/utils.ts20
-rw-r--r--server/helpers/webfinger.ts33
12 files changed, 140 insertions, 75 deletions
diff --git a/server/helpers/activitypub.ts b/server/helpers/activitypub.ts
index 43907b596..5850fc19f 100644
--- a/server/helpers/activitypub.ts
+++ b/server/helpers/activitypub.ts
@@ -1,7 +1,7 @@
1import { ResultList } from '../../shared/models' 1import { ResultList } from '../../shared/models'
2import { Activity } from '../../shared/models/activitypub' 2import { Activity } from '../../shared/models/activitypub'
3import { ACTIVITY_PUB } from '../initializers' 3import { ACTIVITY_PUB } from '../initializers'
4import { AccountModel } from '../models/account/account' 4import { ActorModel } from '../models/activitypub/actor'
5import { signObject } from './peertube-crypto' 5import { signObject } from './peertube-crypto'
6 6
7function activityPubContextify <T> (data: T) { 7function activityPubContextify <T> (data: T) {
@@ -71,10 +71,10 @@ function activityPubCollectionPagination (url: string, page: any, result: Result
71 return orderedCollectionPagination 71 return orderedCollectionPagination
72} 72}
73 73
74function buildSignedActivity (byAccount: AccountModel, data: Object) { 74function buildSignedActivity (byActor: ActorModel, data: Object) {
75 const activity = activityPubContextify(data) 75 const activity = activityPubContextify(data)
76 76
77 return signObject(byAccount, activity) as Promise<Activity> 77 return signObject(byActor, activity) as Promise<Activity>
78} 78}
79 79
80// --------------------------------------------------------------------------- 80// ---------------------------------------------------------------------------
diff --git a/server/helpers/custom-validators/activitypub/activity.ts b/server/helpers/custom-validators/activitypub/activity.ts
index ae7732194..c402800a4 100644
--- a/server/helpers/custom-validators/activitypub/activity.ts
+++ b/server/helpers/custom-validators/activitypub/activity.ts
@@ -1,14 +1,14 @@
1import * as validator from 'validator' 1import * as validator from 'validator'
2import { Activity, ActivityType } from '../../../../shared/models/activitypub' 2import { Activity, ActivityType } from '../../../../shared/models/activitypub'
3import { isAccountAcceptActivityValid, isAccountDeleteActivityValid, isAccountFollowActivityValid } from './actor' 3import { isActorAcceptActivityValid, isActorDeleteActivityValid, isActorFollowActivityValid } from './actor'
4import { isAnnounceActivityValid } from './announce' 4import { isAnnounceActivityValid } from './announce'
5import { isActivityPubUrlValid } from './misc' 5import { isActivityPubUrlValid } from './misc'
6import { isDislikeActivityValid, isLikeActivityValid } from './rate' 6import { isDislikeActivityValid, isLikeActivityValid } from './rate'
7import { isUndoActivityValid } from './undo' 7import { isUndoActivityValid } from './undo'
8import { isVideoChannelCreateActivityValid, isVideoChannelDeleteActivityValid, isVideoChannelUpdateActivityValid } from './video-channels' 8import { isVideoChannelDeleteActivityValid, isVideoChannelUpdateActivityValid } from './video-channels'
9import { 9import {
10 isVideoFlagValid, 10 isVideoFlagValid,
11 isVideoTorrentAddActivityValid, 11 isVideoTorrentCreateActivityValid,
12 isVideoTorrentDeleteActivityValid, 12 isVideoTorrentDeleteActivityValid,
13 isVideoTorrentUpdateActivityValid 13 isVideoTorrentUpdateActivityValid
14} from './videos' 14} from './videos'
@@ -29,7 +29,6 @@ function isRootActivityValid (activity: any) {
29 29
30const activityCheckers: { [ P in ActivityType ]: (activity: Activity) => boolean } = { 30const activityCheckers: { [ P in ActivityType ]: (activity: Activity) => boolean } = {
31 Create: checkCreateActivity, 31 Create: checkCreateActivity,
32 Add: checkAddActivity,
33 Update: checkUpdateActivity, 32 Update: checkUpdateActivity,
34 Delete: checkDeleteActivity, 33 Delete: checkDeleteActivity,
35 Follow: checkFollowActivity, 34 Follow: checkFollowActivity,
@@ -59,14 +58,10 @@ export {
59function checkCreateActivity (activity: any) { 58function checkCreateActivity (activity: any) {
60 return isViewActivityValid(activity) || 59 return isViewActivityValid(activity) ||
61 isDislikeActivityValid(activity) || 60 isDislikeActivityValid(activity) ||
62 isVideoChannelCreateActivityValid(activity) || 61 isVideoTorrentCreateActivityValid(activity) ||
63 isVideoFlagValid(activity) 62 isVideoFlagValid(activity)
64} 63}
65 64
66function checkAddActivity (activity: any) {
67 return isVideoTorrentAddActivityValid(activity)
68}
69
70function checkUpdateActivity (activity: any) { 65function checkUpdateActivity (activity: any) {
71 return isVideoTorrentUpdateActivityValid(activity) || 66 return isVideoTorrentUpdateActivityValid(activity) ||
72 isVideoChannelUpdateActivityValid(activity) 67 isVideoChannelUpdateActivityValid(activity)
@@ -75,15 +70,15 @@ function checkUpdateActivity (activity: any) {
75function checkDeleteActivity (activity: any) { 70function checkDeleteActivity (activity: any) {
76 return isVideoTorrentDeleteActivityValid(activity) || 71 return isVideoTorrentDeleteActivityValid(activity) ||
77 isVideoChannelDeleteActivityValid(activity) || 72 isVideoChannelDeleteActivityValid(activity) ||
78 isAccountDeleteActivityValid(activity) 73 isActorDeleteActivityValid(activity)
79} 74}
80 75
81function checkFollowActivity (activity: any) { 76function checkFollowActivity (activity: any) {
82 return isAccountFollowActivityValid(activity) 77 return isActorFollowActivityValid(activity)
83} 78}
84 79
85function checkAcceptActivity (activity: any) { 80function checkAcceptActivity (activity: any) {
86 return isAccountAcceptActivityValid(activity) 81 return isActorAcceptActivityValid(activity)
87} 82}
88 83
89function checkAnnounceActivity (activity: any) { 84function checkAnnounceActivity (activity: any) {
diff --git a/server/helpers/custom-validators/activitypub/actor.ts b/server/helpers/custom-validators/activitypub/actor.ts
index 28551c96c..bf42757c5 100644
--- a/server/helpers/custom-validators/activitypub/actor.ts
+++ b/server/helpers/custom-validators/activitypub/actor.ts
@@ -1,8 +1,12 @@
1import * as Bluebird from 'bluebird'
2import { Response } from 'express'
1import * as validator from 'validator' 3import * as validator from 'validator'
2import { CONSTRAINTS_FIELDS } from '../../../initializers' 4import { CONSTRAINTS_FIELDS } from '../../../initializers'
5import { ActorModel } from '../../../models/activitypub/actor'
3import { isAccountNameValid } from '../accounts' 6import { isAccountNameValid } from '../accounts'
4import { exists, isUUIDValid } from '../misc' 7import { exists, isUUIDValid } from '../misc'
5import { isActivityPubUrlValid, isBaseActivityValid } from './misc' 8import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../video-channels'
9import { isActivityPubUrlValid, isBaseActivityValid, setValidAttributedTo } from './misc'
6 10
7function isActorEndpointsObjectValid (endpointObject: any) { 11function isActorEndpointsObjectValid (endpointObject: any) {
8 return isActivityPubUrlValid(endpointObject.sharedInbox) 12 return isActivityPubUrlValid(endpointObject.sharedInbox)
@@ -27,7 +31,12 @@ function isActorPublicKeyValid (publicKey: string) {
27} 31}
28 32
29function isActorPreferredUsernameValid (preferredUsername: string) { 33function isActorPreferredUsernameValid (preferredUsername: string) {
30 return isAccountNameValid(preferredUsername) 34 return isAccountNameValid(preferredUsername) || isVideoChannelNameValid(preferredUsername)
35}
36
37const actorNameRegExp = new RegExp('[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_]+')
38function isActorNameValid (name: string) {
39 return exists(name) && validator.matches(name, actorNameRegExp)
31} 40}
32 41
33function isActorPrivateKeyValid (privateKey: string) { 42function isActorPrivateKeyValid (privateKey: string) {
@@ -46,10 +55,16 @@ function isRemoteActorValid (remoteActor: any) {
46 isActivityPubUrlValid(remoteActor.followers) && 55 isActivityPubUrlValid(remoteActor.followers) &&
47 isActivityPubUrlValid(remoteActor.inbox) && 56 isActivityPubUrlValid(remoteActor.inbox) &&
48 isActivityPubUrlValid(remoteActor.outbox) && 57 isActivityPubUrlValid(remoteActor.outbox) &&
58 isActorNameValid(remoteActor.name) &&
49 isActorPreferredUsernameValid(remoteActor.preferredUsername) && 59 isActorPreferredUsernameValid(remoteActor.preferredUsername) &&
50 isActivityPubUrlValid(remoteActor.url) && 60 isActivityPubUrlValid(remoteActor.url) &&
51 isActorPublicKeyObjectValid(remoteActor.publicKey) && 61 isActorPublicKeyObjectValid(remoteActor.publicKey) &&
52 isActorEndpointsObjectValid(remoteActor.endpoints) 62 isActorEndpointsObjectValid(remoteActor.endpoints) &&
63 (!remoteActor.summary || isVideoChannelDescriptionValid(remoteActor.summary)) &&
64 setValidAttributedTo(remoteActor) &&
65 // If this is not an account, it should be attributed to an account
66 // In PeerTube we use this to attach a video channel to a specific account
67 (remoteActor.type === 'Person' || remoteActor.attributedTo.length !== 0)
53} 68}
54 69
55function isActorFollowingCountValid (value: string) { 70function isActorFollowingCountValid (value: string) {
@@ -73,6 +88,40 @@ function isActorAcceptActivityValid (activity: any) {
73 return isBaseActivityValid(activity, 'Accept') 88 return isBaseActivityValid(activity, 'Accept')
74} 89}
75 90
91function isActorIdExist (id: number | string, res: Response) {
92 let promise: Bluebird<ActorModel>
93
94 if (validator.isInt('' + id)) {
95 promise = ActorModel.load(+id)
96 } else { // UUID
97 promise = ActorModel.loadByUUID('' + id)
98 }
99
100 return isActorExist(promise, res)
101}
102
103function isLocalActorNameExist (name: string, res: Response) {
104 const promise = ActorModel.loadLocalByName(name)
105
106 return isActorExist(promise, res)
107}
108
109async function isActorExist (p: Bluebird<ActorModel>, res: Response) {
110 const actor = await p
111
112 if (!actor) {
113 res.status(404)
114 .send({ error: 'Actor not found' })
115 .end()
116
117 return false
118 }
119
120 res.locals.actor = actor
121
122 return true
123}
124
76// --------------------------------------------------------------------------- 125// ---------------------------------------------------------------------------
77 126
78export { 127export {
@@ -87,5 +136,9 @@ export {
87 isActorFollowersCountValid, 136 isActorFollowersCountValid,
88 isActorFollowActivityValid, 137 isActorFollowActivityValid,
89 isActorAcceptActivityValid, 138 isActorAcceptActivityValid,
90 isActorDeleteActivityValid 139 isActorDeleteActivityValid,
140 isActorIdExist,
141 isLocalActorNameExist,
142 isActorNameValid,
143 isActorExist
91} 144}
diff --git a/server/helpers/custom-validators/activitypub/announce.ts b/server/helpers/custom-validators/activitypub/announce.ts
index 45f6b05a0..80511129c 100644
--- a/server/helpers/custom-validators/activitypub/announce.ts
+++ b/server/helpers/custom-validators/activitypub/announce.ts
@@ -1,12 +1,10 @@
1import { isBaseActivityValid } from './misc' 1import { isBaseActivityValid } from './misc'
2import { isVideoTorrentAddActivityValid } from './videos' 2import { isVideoTorrentCreateActivityValid } from './videos'
3import { isVideoChannelCreateActivityValid } from './video-channels'
4 3
5function isAnnounceActivityValid (activity: any) { 4function isAnnounceActivityValid (activity: any) {
6 return isBaseActivityValid(activity, 'Announce') && 5 return isBaseActivityValid(activity, 'Announce') &&
7 ( 6 (
8 isVideoChannelCreateActivityValid(activity.object) || 7 isVideoTorrentCreateActivityValid(activity.object)
9 isVideoTorrentAddActivityValid(activity.object)
10 ) 8 )
11} 9}
12 10
diff --git a/server/helpers/custom-validators/activitypub/misc.ts b/server/helpers/custom-validators/activitypub/misc.ts
index 65f5ca809..3ca4e4ff4 100644
--- a/server/helpers/custom-validators/activitypub/misc.ts
+++ b/server/helpers/custom-validators/activitypub/misc.ts
@@ -17,7 +17,7 @@ function isActivityPubUrlValid (url: string) {
17 isURLOptions.require_tld = false 17 isURLOptions.require_tld = false
18 } 18 }
19 19
20 return exists(url) && validator.isURL(url, isURLOptions) && validator.isLength(url, CONSTRAINTS_FIELDS.ACCOUNTS.URL) 20 return exists(url) && validator.isURL(url, isURLOptions) && validator.isLength(url, CONSTRAINTS_FIELDS.ACTOR.URL)
21} 21}
22 22
23function isBaseActivityValid (activity: any, type: string) { 23function isBaseActivityValid (activity: any, type: string) {
@@ -35,7 +35,23 @@ function isBaseActivityValid (activity: any, type: string) {
35 ) 35 )
36} 36}
37 37
38function setValidAttributedTo (obj: any) {
39 if (Array.isArray(obj.attributedTo) === false) {
40 obj.attributedTo = []
41 return true
42 }
43
44 const newAttributesTo = obj.attributedTo.filter(a => {
45 return (a.type === 'Group' || a.type === 'Person') && isActivityPubUrlValid(a.id)
46 })
47
48 obj.attributedTo = newAttributesTo
49
50 return true
51}
52
38export { 53export {
39 isActivityPubUrlValid, 54 isActivityPubUrlValid,
40 isBaseActivityValid 55 isBaseActivityValid,
56 setValidAttributedTo
41} 57}
diff --git a/server/helpers/custom-validators/activitypub/undo.ts b/server/helpers/custom-validators/activitypub/undo.ts
index d07bbf6b7..a2831b0bf 100644
--- a/server/helpers/custom-validators/activitypub/undo.ts
+++ b/server/helpers/custom-validators/activitypub/undo.ts
@@ -1,11 +1,11 @@
1import { isAccountFollowActivityValid } from './actor' 1import { isActorFollowActivityValid } from './actor'
2import { isBaseActivityValid } from './misc' 2import { isBaseActivityValid } from './misc'
3import { isDislikeActivityValid, isLikeActivityValid } from './rate' 3import { isDislikeActivityValid, isLikeActivityValid } from './rate'
4 4
5function isUndoActivityValid (activity: any) { 5function isUndoActivityValid (activity: any) {
6 return isBaseActivityValid(activity, 'Undo') && 6 return isBaseActivityValid(activity, 'Undo') &&
7 ( 7 (
8 isAccountFollowActivityValid(activity.object) || 8 isActorFollowActivityValid(activity.object) ||
9 isLikeActivityValid(activity.object) || 9 isLikeActivityValid(activity.object) ||
10 isDislikeActivityValid(activity.object) 10 isDislikeActivityValid(activity.object)
11 ) 11 )
diff --git a/server/helpers/custom-validators/activitypub/video-channels.ts b/server/helpers/custom-validators/activitypub/video-channels.ts
index 9fd3bb149..eb45c6372 100644
--- a/server/helpers/custom-validators/activitypub/video-channels.ts
+++ b/server/helpers/custom-validators/activitypub/video-channels.ts
@@ -2,11 +2,6 @@ import { isDateValid, isUUIDValid } from '../misc'
2import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../video-channels' 2import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../video-channels'
3import { isActivityPubUrlValid, isBaseActivityValid } from './misc' 3import { isActivityPubUrlValid, isBaseActivityValid } from './misc'
4 4
5function isVideoChannelCreateActivityValid (activity: any) {
6 return isBaseActivityValid(activity, 'Create') &&
7 isVideoChannelObjectValid(activity.object)
8}
9
10function isVideoChannelUpdateActivityValid (activity: any) { 5function isVideoChannelUpdateActivityValid (activity: any) {
11 return isBaseActivityValid(activity, 'Update') && 6 return isBaseActivityValid(activity, 'Update') &&
12 isVideoChannelObjectValid(activity.object) 7 isVideoChannelObjectValid(activity.object)
@@ -29,7 +24,6 @@ function isVideoChannelObjectValid (videoChannel: any) {
29// --------------------------------------------------------------------------- 24// ---------------------------------------------------------------------------
30 25
31export { 26export {
32 isVideoChannelCreateActivityValid,
33 isVideoChannelUpdateActivityValid, 27 isVideoChannelUpdateActivityValid,
34 isVideoChannelDeleteActivityValid, 28 isVideoChannelDeleteActivityValid,
35 isVideoChannelObjectValid 29 isVideoChannelObjectValid
diff --git a/server/helpers/custom-validators/activitypub/videos.ts b/server/helpers/custom-validators/activitypub/videos.ts
index 2ed2988f5..b485e5fcf 100644
--- a/server/helpers/custom-validators/activitypub/videos.ts
+++ b/server/helpers/custom-validators/activitypub/videos.ts
@@ -10,10 +10,10 @@ import {
10 isVideoTruncatedDescriptionValid, 10 isVideoTruncatedDescriptionValid,
11 isVideoViewsValid 11 isVideoViewsValid
12} from '../videos' 12} from '../videos'
13import { isActivityPubUrlValid, isBaseActivityValid } from './misc' 13import { isActivityPubUrlValid, isBaseActivityValid, setValidAttributedTo } from './misc'
14 14
15function isVideoTorrentAddActivityValid (activity: any) { 15function isVideoTorrentCreateActivityValid (activity: any) {
16 return isBaseActivityValid(activity, 'Add') && 16 return isBaseActivityValid(activity, 'Create') &&
17 isVideoTorrentObjectValid(activity.object) 17 isVideoTorrentObjectValid(activity.object)
18} 18}
19 19
@@ -43,6 +43,8 @@ function isActivityPubVideoDurationValid (value: string) {
43} 43}
44 44
45function isVideoTorrentObjectValid (video: any) { 45function isVideoTorrentObjectValid (video: any) {
46 console.log(video)
47
46 return video.type === 'Video' && 48 return video.type === 'Video' &&
47 isActivityPubUrlValid(video.id) && 49 isActivityPubUrlValid(video.id) &&
48 isVideoNameValid(video.name) && 50 isVideoNameValid(video.name) &&
@@ -59,13 +61,15 @@ function isVideoTorrentObjectValid (video: any) {
59 (!video.content || isRemoteVideoContentValid(video.mediaType, video.content)) && 61 (!video.content || isRemoteVideoContentValid(video.mediaType, video.content)) &&
60 isRemoteVideoIconValid(video.icon) && 62 isRemoteVideoIconValid(video.icon) &&
61 setValidRemoteVideoUrls(video) && 63 setValidRemoteVideoUrls(video) &&
62 video.url.length !== 0 64 video.url.length !== 0 &&
65 setValidAttributedTo(video) &&
66 video.attributedTo.length !== 0
63} 67}
64 68
65// --------------------------------------------------------------------------- 69// ---------------------------------------------------------------------------
66 70
67export { 71export {
68 isVideoTorrentAddActivityValid, 72 isVideoTorrentCreateActivityValid,
69 isVideoTorrentUpdateActivityValid, 73 isVideoTorrentUpdateActivityValid,
70 isVideoTorrentDeleteActivityValid, 74 isVideoTorrentDeleteActivityValid,
71 isVideoFlagValid 75 isVideoFlagValid
diff --git a/server/helpers/custom-validators/webfinger.ts b/server/helpers/custom-validators/webfinger.ts
index 38f6b938d..c53db4027 100644
--- a/server/helpers/custom-validators/webfinger.ts
+++ b/server/helpers/custom-validators/webfinger.ts
@@ -5,11 +5,11 @@ function isWebfingerResourceValid (value: string) {
5 if (!exists(value)) return false 5 if (!exists(value)) return false
6 if (value.startsWith('acct:') === false) return false 6 if (value.startsWith('acct:') === false) return false
7 7
8 const accountWithHost = value.substr(5) 8 const actorWithHost = value.substr(5)
9 const accountParts = accountWithHost.split('@') 9 const actorParts = actorWithHost.split('@')
10 if (accountParts.length !== 2) return false 10 if (actorParts.length !== 2) return false
11 11
12 const host = accountParts[1] 12 const host = actorParts[1]
13 13
14 return host === CONFIG.WEBSERVER.HOST 14 return host === CONFIG.WEBSERVER.HOST
15} 15}
diff --git a/server/helpers/peertube-crypto.ts b/server/helpers/peertube-crypto.ts
index c4c735cb8..a0c9112b9 100644
--- a/server/helpers/peertube-crypto.ts
+++ b/server/helpers/peertube-crypto.ts
@@ -1,5 +1,5 @@
1import { BCRYPT_SALT_SIZE, PRIVATE_RSA_KEY_SIZE } from '../initializers' 1import { BCRYPT_SALT_SIZE, PRIVATE_RSA_KEY_SIZE } from '../initializers'
2import { AccountModel } from '../models/account/account' 2import { ActorModel } from '../models/activitypub/actor'
3import { bcryptComparePromise, bcryptGenSaltPromise, bcryptHashPromise, createPrivateKey, getPublicKey } from './core-utils' 3import { bcryptComparePromise, bcryptGenSaltPromise, bcryptHashPromise, createPrivateKey, getPublicKey } from './core-utils'
4import { jsig } from './custom-jsonld-signature' 4import { jsig } from './custom-jsonld-signature'
5import { logger } from './logger' 5import { logger } from './logger'
@@ -13,18 +13,18 @@ async function createPrivateAndPublicKeys () {
13 return { privateKey: key, publicKey } 13 return { privateKey: key, publicKey }
14} 14}
15 15
16function isSignatureVerified (fromAccount: AccountModel, signedDocument: object) { 16function isSignatureVerified (fromActor: ActorModel, signedDocument: object) {
17 const publicKeyObject = { 17 const publicKeyObject = {
18 '@context': jsig.SECURITY_CONTEXT_URL, 18 '@context': jsig.SECURITY_CONTEXT_URL,
19 '@id': fromAccount.url, 19 '@id': fromActor.url,
20 '@type': 'CryptographicKey', 20 '@type': 'CryptographicKey',
21 owner: fromAccount.url, 21 owner: fromActor.url,
22 publicKeyPem: fromAccount.publicKey 22 publicKeyPem: fromActor.publicKey
23 } 23 }
24 24
25 const publicKeyOwnerObject = { 25 const publicKeyOwnerObject = {
26 '@context': jsig.SECURITY_CONTEXT_URL, 26 '@context': jsig.SECURITY_CONTEXT_URL,
27 '@id': fromAccount.url, 27 '@id': fromActor.url,
28 publicKey: [ publicKeyObject ] 28 publicKey: [ publicKeyObject ]
29 } 29 }
30 30
@@ -40,10 +40,10 @@ function isSignatureVerified (fromAccount: AccountModel, signedDocument: object)
40 }) 40 })
41} 41}
42 42
43function signObject (byAccount: AccountModel, data: any) { 43function signObject (byActor: ActorModel, data: any) {
44 const options = { 44 const options = {
45 privateKeyPem: byAccount.privateKey, 45 privateKeyPem: byActor.privateKey,
46 creator: byAccount.url 46 creator: byActor.url
47 } 47 }
48 48
49 return jsig.promises.sign(data, options) 49 return jsig.promises.sign(data, options)
diff --git a/server/helpers/utils.ts b/server/helpers/utils.ts
index cb5e536b8..ef6a878cf 100644
--- a/server/helpers/utils.ts
+++ b/server/helpers/utils.ts
@@ -3,8 +3,9 @@ import { Model } from 'sequelize-typescript'
3import { ResultList } from '../../shared' 3import { ResultList } from '../../shared'
4import { VideoResolution } from '../../shared/models/videos' 4import { VideoResolution } from '../../shared/models/videos'
5import { CONFIG } from '../initializers' 5import { CONFIG } from '../initializers'
6import { AccountModel } from '../models/account/account'
7import { UserModel } from '../models/account/user' 6import { UserModel } from '../models/account/user'
7import { ActorModel } from '../models/activitypub/actor'
8import { ApplicationModel } from '../models/application/application'
8import { pseudoRandomBytesPromise } from './core-utils' 9import { pseudoRandomBytesPromise } from './core-utils'
9import { logger } from './logger' 10import { logger } from './logger'
10 11
@@ -80,18 +81,19 @@ function resetSequelizeInstance (instance: Model<any>, savedFields: object) {
80 }) 81 })
81} 82}
82 83
83let serverAccount: AccountModel 84let serverActor: ActorModel
84async function getServerAccount () { 85async function getServerActor () {
85 if (serverAccount === undefined) { 86 if (serverActor === undefined) {
86 serverAccount = await AccountModel.loadApplication() 87 const application = await ApplicationModel.load()
88 serverActor = application.Account.Actor
87 } 89 }
88 90
89 if (!serverAccount) { 91 if (!serverActor) {
90 logger.error('Cannot load server account.') 92 logger.error('Cannot load server actor.')
91 process.exit(0) 93 process.exit(0)
92 } 94 }
93 95
94 return Promise.resolve(serverAccount) 96 return Promise.resolve(serverActor)
95} 97}
96 98
97type SortType = { sortModel: any, sortValue: string } 99type SortType = { sortModel: any, sortValue: string }
@@ -105,6 +107,6 @@ export {
105 isSignupAllowed, 107 isSignupAllowed,
106 computeResolutionsToTranscode, 108 computeResolutionsToTranscode,
107 resetSequelizeInstance, 109 resetSequelizeInstance,
108 getServerAccount, 110 getServerActor,
109 SortType 111 SortType
110} 112}
diff --git a/server/helpers/webfinger.ts b/server/helpers/webfinger.ts
index d98068cd7..76444fbe3 100644
--- a/server/helpers/webfinger.ts
+++ b/server/helpers/webfinger.ts
@@ -1,6 +1,6 @@
1import * as WebFinger from 'webfinger.js' 1import * as WebFinger from 'webfinger.js'
2import { WebFingerData } from '../../shared' 2import { WebFingerData } from '../../shared'
3import { fetchRemoteAccount } from '../lib/activitypub' 3import { ActorModel } from '../models/activitypub/actor'
4import { isTestInstance } from './core-utils' 4import { isTestInstance } from './core-utils'
5import { isActivityPubUrlValid } from './custom-validators/activitypub' 5import { isActivityPubUrlValid } from './custom-validators/activitypub'
6 6
@@ -11,30 +11,33 @@ const webfinger = new WebFinger({
11 request_timeout: 3000 11 request_timeout: 3000
12}) 12})
13 13
14async function getAccountFromWebfinger (nameWithHost: string) { 14async function loadActorUrlOrGetFromWebfinger (name: string, host: string) {
15 const webfingerData: WebFingerData = await webfingerLookup(nameWithHost) 15 const actor = await ActorModel.loadByNameAndHost(name, host)
16 if (actor) return actor.url
16 17
17 if (Array.isArray(webfingerData.links) === false) throw new Error('WebFinger links is not an array.') 18 const webfingerData: WebFingerData = await webfingerLookup(name + '@' + host)
18 19 return getLinkOrThrow(webfingerData)
19 const selfLink = webfingerData.links.find(l => l.rel === 'self')
20 if (selfLink === undefined || isActivityPubUrlValid(selfLink.href) === false) {
21 throw new Error('Cannot find self link or href is not a valid URL.')
22 }
23
24 const account = await fetchRemoteAccount(selfLink.href)
25 if (account === undefined) throw new Error('Cannot fetch remote account ' + selfLink.href)
26
27 return account
28} 20}
29 21
30// --------------------------------------------------------------------------- 22// ---------------------------------------------------------------------------
31 23
32export { 24export {
33 getAccountFromWebfinger 25 loadActorUrlOrGetFromWebfinger
34} 26}
35 27
36// --------------------------------------------------------------------------- 28// ---------------------------------------------------------------------------
37 29
30function getLinkOrThrow (webfingerData: WebFingerData) {
31 if (Array.isArray(webfingerData.links) === false) throw new Error('WebFinger links is not an array.')
32
33 const selfLink = webfingerData.links.find(l => l.rel === 'self')
34 if (selfLink === undefined || isActivityPubUrlValid(selfLink.href) === false) {
35 throw new Error('Cannot find self link or href is not a valid URL.')
36 }
37
38 return selfLink.href
39}
40
38function webfingerLookup (nameWithHost: string) { 41function webfingerLookup (nameWithHost: string) {
39 return new Promise<WebFingerData>((res, rej) => { 42 return new Promise<WebFingerData>((res, rej) => {
40 webfinger.lookup(nameWithHost, (err, p) => { 43 webfinger.lookup(nameWithHost, (err, p) => {