diff options
Diffstat (limited to 'server/helpers')
-rw-r--r-- | server/helpers/activitypub.ts | 6 | ||||
-rw-r--r-- | server/helpers/custom-validators/activitypub/activity.ts | 19 | ||||
-rw-r--r-- | server/helpers/custom-validators/activitypub/actor.ts | 61 | ||||
-rw-r--r-- | server/helpers/custom-validators/activitypub/announce.ts | 6 | ||||
-rw-r--r-- | server/helpers/custom-validators/activitypub/misc.ts | 20 | ||||
-rw-r--r-- | server/helpers/custom-validators/activitypub/undo.ts | 4 | ||||
-rw-r--r-- | server/helpers/custom-validators/activitypub/video-channels.ts | 6 | ||||
-rw-r--r-- | server/helpers/custom-validators/activitypub/videos.ts | 14 | ||||
-rw-r--r-- | server/helpers/custom-validators/webfinger.ts | 8 | ||||
-rw-r--r-- | server/helpers/peertube-crypto.ts | 18 | ||||
-rw-r--r-- | server/helpers/utils.ts | 20 | ||||
-rw-r--r-- | server/helpers/webfinger.ts | 33 |
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 @@ | |||
1 | import { ResultList } from '../../shared/models' | 1 | import { ResultList } from '../../shared/models' |
2 | import { Activity } from '../../shared/models/activitypub' | 2 | import { Activity } from '../../shared/models/activitypub' |
3 | import { ACTIVITY_PUB } from '../initializers' | 3 | import { ACTIVITY_PUB } from '../initializers' |
4 | import { AccountModel } from '../models/account/account' | 4 | import { ActorModel } from '../models/activitypub/actor' |
5 | import { signObject } from './peertube-crypto' | 5 | import { signObject } from './peertube-crypto' |
6 | 6 | ||
7 | function activityPubContextify <T> (data: T) { | 7 | function 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 | ||
74 | function buildSignedActivity (byAccount: AccountModel, data: Object) { | 74 | function 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 @@ | |||
1 | import * as validator from 'validator' | 1 | import * as validator from 'validator' |
2 | import { Activity, ActivityType } from '../../../../shared/models/activitypub' | 2 | import { Activity, ActivityType } from '../../../../shared/models/activitypub' |
3 | import { isAccountAcceptActivityValid, isAccountDeleteActivityValid, isAccountFollowActivityValid } from './actor' | 3 | import { isActorAcceptActivityValid, isActorDeleteActivityValid, isActorFollowActivityValid } from './actor' |
4 | import { isAnnounceActivityValid } from './announce' | 4 | import { isAnnounceActivityValid } from './announce' |
5 | import { isActivityPubUrlValid } from './misc' | 5 | import { isActivityPubUrlValid } from './misc' |
6 | import { isDislikeActivityValid, isLikeActivityValid } from './rate' | 6 | import { isDislikeActivityValid, isLikeActivityValid } from './rate' |
7 | import { isUndoActivityValid } from './undo' | 7 | import { isUndoActivityValid } from './undo' |
8 | import { isVideoChannelCreateActivityValid, isVideoChannelDeleteActivityValid, isVideoChannelUpdateActivityValid } from './video-channels' | 8 | import { isVideoChannelDeleteActivityValid, isVideoChannelUpdateActivityValid } from './video-channels' |
9 | import { | 9 | import { |
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 | ||
30 | const activityCheckers: { [ P in ActivityType ]: (activity: Activity) => boolean } = { | 30 | const 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 { | |||
59 | function checkCreateActivity (activity: any) { | 58 | function 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 | ||
66 | function checkAddActivity (activity: any) { | ||
67 | return isVideoTorrentAddActivityValid(activity) | ||
68 | } | ||
69 | |||
70 | function checkUpdateActivity (activity: any) { | 65 | function 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) { | |||
75 | function checkDeleteActivity (activity: any) { | 70 | function 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 | ||
81 | function checkFollowActivity (activity: any) { | 76 | function checkFollowActivity (activity: any) { |
82 | return isAccountFollowActivityValid(activity) | 77 | return isActorFollowActivityValid(activity) |
83 | } | 78 | } |
84 | 79 | ||
85 | function checkAcceptActivity (activity: any) { | 80 | function checkAcceptActivity (activity: any) { |
86 | return isAccountAcceptActivityValid(activity) | 81 | return isActorAcceptActivityValid(activity) |
87 | } | 82 | } |
88 | 83 | ||
89 | function checkAnnounceActivity (activity: any) { | 84 | function 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 @@ | |||
1 | import * as Bluebird from 'bluebird' | ||
2 | import { Response } from 'express' | ||
1 | import * as validator from 'validator' | 3 | import * as validator from 'validator' |
2 | import { CONSTRAINTS_FIELDS } from '../../../initializers' | 4 | import { CONSTRAINTS_FIELDS } from '../../../initializers' |
5 | import { ActorModel } from '../../../models/activitypub/actor' | ||
3 | import { isAccountNameValid } from '../accounts' | 6 | import { isAccountNameValid } from '../accounts' |
4 | import { exists, isUUIDValid } from '../misc' | 7 | import { exists, isUUIDValid } from '../misc' |
5 | import { isActivityPubUrlValid, isBaseActivityValid } from './misc' | 8 | import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../video-channels' |
9 | import { isActivityPubUrlValid, isBaseActivityValid, setValidAttributedTo } from './misc' | ||
6 | 10 | ||
7 | function isActorEndpointsObjectValid (endpointObject: any) { | 11 | function 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 | ||
29 | function isActorPreferredUsernameValid (preferredUsername: string) { | 33 | function isActorPreferredUsernameValid (preferredUsername: string) { |
30 | return isAccountNameValid(preferredUsername) | 34 | return isAccountNameValid(preferredUsername) || isVideoChannelNameValid(preferredUsername) |
35 | } | ||
36 | |||
37 | const actorNameRegExp = new RegExp('[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_]+') | ||
38 | function isActorNameValid (name: string) { | ||
39 | return exists(name) && validator.matches(name, actorNameRegExp) | ||
31 | } | 40 | } |
32 | 41 | ||
33 | function isActorPrivateKeyValid (privateKey: string) { | 42 | function 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 | ||
55 | function isActorFollowingCountValid (value: string) { | 70 | function 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 | ||
91 | function 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 | |||
103 | function isLocalActorNameExist (name: string, res: Response) { | ||
104 | const promise = ActorModel.loadLocalByName(name) | ||
105 | |||
106 | return isActorExist(promise, res) | ||
107 | } | ||
108 | |||
109 | async 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 | ||
78 | export { | 127 | export { |
@@ -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 @@ | |||
1 | import { isBaseActivityValid } from './misc' | 1 | import { isBaseActivityValid } from './misc' |
2 | import { isVideoTorrentAddActivityValid } from './videos' | 2 | import { isVideoTorrentCreateActivityValid } from './videos' |
3 | import { isVideoChannelCreateActivityValid } from './video-channels' | ||
4 | 3 | ||
5 | function isAnnounceActivityValid (activity: any) { | 4 | function 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 | ||
23 | function isBaseActivityValid (activity: any, type: string) { | 23 | function isBaseActivityValid (activity: any, type: string) { |
@@ -35,7 +35,23 @@ function isBaseActivityValid (activity: any, type: string) { | |||
35 | ) | 35 | ) |
36 | } | 36 | } |
37 | 37 | ||
38 | function 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 | |||
38 | export { | 53 | export { |
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 @@ | |||
1 | import { isAccountFollowActivityValid } from './actor' | 1 | import { isActorFollowActivityValid } from './actor' |
2 | import { isBaseActivityValid } from './misc' | 2 | import { isBaseActivityValid } from './misc' |
3 | import { isDislikeActivityValid, isLikeActivityValid } from './rate' | 3 | import { isDislikeActivityValid, isLikeActivityValid } from './rate' |
4 | 4 | ||
5 | function isUndoActivityValid (activity: any) { | 5 | function 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' | |||
2 | import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../video-channels' | 2 | import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../video-channels' |
3 | import { isActivityPubUrlValid, isBaseActivityValid } from './misc' | 3 | import { isActivityPubUrlValid, isBaseActivityValid } from './misc' |
4 | 4 | ||
5 | function isVideoChannelCreateActivityValid (activity: any) { | ||
6 | return isBaseActivityValid(activity, 'Create') && | ||
7 | isVideoChannelObjectValid(activity.object) | ||
8 | } | ||
9 | |||
10 | function isVideoChannelUpdateActivityValid (activity: any) { | 5 | function 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 | ||
31 | export { | 26 | export { |
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' |
13 | import { isActivityPubUrlValid, isBaseActivityValid } from './misc' | 13 | import { isActivityPubUrlValid, isBaseActivityValid, setValidAttributedTo } from './misc' |
14 | 14 | ||
15 | function isVideoTorrentAddActivityValid (activity: any) { | 15 | function 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 | ||
45 | function isVideoTorrentObjectValid (video: any) { | 45 | function 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 | ||
67 | export { | 71 | export { |
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 @@ | |||
1 | import { BCRYPT_SALT_SIZE, PRIVATE_RSA_KEY_SIZE } from '../initializers' | 1 | import { BCRYPT_SALT_SIZE, PRIVATE_RSA_KEY_SIZE } from '../initializers' |
2 | import { AccountModel } from '../models/account/account' | 2 | import { ActorModel } from '../models/activitypub/actor' |
3 | import { bcryptComparePromise, bcryptGenSaltPromise, bcryptHashPromise, createPrivateKey, getPublicKey } from './core-utils' | 3 | import { bcryptComparePromise, bcryptGenSaltPromise, bcryptHashPromise, createPrivateKey, getPublicKey } from './core-utils' |
4 | import { jsig } from './custom-jsonld-signature' | 4 | import { jsig } from './custom-jsonld-signature' |
5 | import { logger } from './logger' | 5 | import { logger } from './logger' |
@@ -13,18 +13,18 @@ async function createPrivateAndPublicKeys () { | |||
13 | return { privateKey: key, publicKey } | 13 | return { privateKey: key, publicKey } |
14 | } | 14 | } |
15 | 15 | ||
16 | function isSignatureVerified (fromAccount: AccountModel, signedDocument: object) { | 16 | function 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 | ||
43 | function signObject (byAccount: AccountModel, data: any) { | 43 | function 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' | |||
3 | import { ResultList } from '../../shared' | 3 | import { ResultList } from '../../shared' |
4 | import { VideoResolution } from '../../shared/models/videos' | 4 | import { VideoResolution } from '../../shared/models/videos' |
5 | import { CONFIG } from '../initializers' | 5 | import { CONFIG } from '../initializers' |
6 | import { AccountModel } from '../models/account/account' | ||
7 | import { UserModel } from '../models/account/user' | 6 | import { UserModel } from '../models/account/user' |
7 | import { ActorModel } from '../models/activitypub/actor' | ||
8 | import { ApplicationModel } from '../models/application/application' | ||
8 | import { pseudoRandomBytesPromise } from './core-utils' | 9 | import { pseudoRandomBytesPromise } from './core-utils' |
9 | import { logger } from './logger' | 10 | import { logger } from './logger' |
10 | 11 | ||
@@ -80,18 +81,19 @@ function resetSequelizeInstance (instance: Model<any>, savedFields: object) { | |||
80 | }) | 81 | }) |
81 | } | 82 | } |
82 | 83 | ||
83 | let serverAccount: AccountModel | 84 | let serverActor: ActorModel |
84 | async function getServerAccount () { | 85 | async 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 | ||
97 | type SortType = { sortModel: any, sortValue: string } | 99 | type 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 @@ | |||
1 | import * as WebFinger from 'webfinger.js' | 1 | import * as WebFinger from 'webfinger.js' |
2 | import { WebFingerData } from '../../shared' | 2 | import { WebFingerData } from '../../shared' |
3 | import { fetchRemoteAccount } from '../lib/activitypub' | 3 | import { ActorModel } from '../models/activitypub/actor' |
4 | import { isTestInstance } from './core-utils' | 4 | import { isTestInstance } from './core-utils' |
5 | import { isActivityPubUrlValid } from './custom-validators/activitypub' | 5 | import { 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 | ||
14 | async function getAccountFromWebfinger (nameWithHost: string) { | 14 | async 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 | ||
32 | export { | 24 | export { |
33 | getAccountFromWebfinger | 25 | loadActorUrlOrGetFromWebfinger |
34 | } | 26 | } |
35 | 27 | ||
36 | // --------------------------------------------------------------------------- | 28 | // --------------------------------------------------------------------------- |
37 | 29 | ||
30 | function 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 | |||
38 | function webfingerLookup (nameWithHost: string) { | 41 | function 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) => { |