diff options
author | Chocobozzz <me@florianbigard.com> | 2018-03-22 18:40:33 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2018-03-22 18:40:56 +0100 |
commit | 6be84cbcea99518e8eca58c76259effd0dd992fd (patch) | |
tree | c2b4b22c8b60528025b172013d72c12f8ba06192 | |
parent | 9e841674da612b68bf84a427a8710a44347083f5 (diff) | |
download | PeerTube-6be84cbcea99518e8eca58c76259effd0dd992fd.tar.gz PeerTube-6be84cbcea99518e8eca58c76259effd0dd992fd.tar.zst PeerTube-6be84cbcea99518e8eca58c76259effd0dd992fd.zip |
Improve activity pub actors implementation
-rw-r--r-- | server/helpers/activitypub.ts | 9 | ||||
-rw-r--r-- | server/helpers/custom-validators/activitypub/activity.ts | 2 | ||||
-rw-r--r-- | server/helpers/custom-validators/activitypub/misc.ts | 2 | ||||
-rw-r--r-- | server/lib/activitypub/actor.ts | 5 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-accept.ts | 4 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-reject.ts | 4 | ||||
-rw-r--r-- | server/lib/activitypub/process/process-undo.ts | 9 | ||||
-rw-r--r-- | server/lib/activitypub/process/process.ts | 7 | ||||
-rw-r--r-- | shared/models/activitypub/activity.ts | 2 |
9 files changed, 32 insertions, 12 deletions
diff --git a/server/helpers/activitypub.ts b/server/helpers/activitypub.ts index d64a6dd78..1934fa0f0 100644 --- a/server/helpers/activitypub.ts +++ b/server/helpers/activitypub.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import { ResultList } from '../../shared/models' | 1 | import { ResultList } from '../../shared/models' |
2 | import { Activity } from '../../shared/models/activitypub' | 2 | import { Activity, ActivityPubActor } from '../../shared/models/activitypub' |
3 | import { ACTIVITY_PUB } from '../initializers' | 3 | import { ACTIVITY_PUB } from '../initializers' |
4 | import { ActorModel } from '../models/activitypub/actor' | 4 | import { ActorModel } from '../models/activitypub/actor' |
5 | import { signObject } from './peertube-crypto' | 5 | import { signObject } from './peertube-crypto' |
@@ -98,9 +98,16 @@ function buildSignedActivity (byActor: ActorModel, data: Object) { | |||
98 | return signObject(byActor, activity) as Promise<Activity> | 98 | return signObject(byActor, activity) as Promise<Activity> |
99 | } | 99 | } |
100 | 100 | ||
101 | function getActorUrl (activityActor: string | ActivityPubActor) { | ||
102 | if (typeof activityActor === 'string') return activityActor | ||
103 | |||
104 | return activityActor.id | ||
105 | } | ||
106 | |||
101 | // --------------------------------------------------------------------------- | 107 | // --------------------------------------------------------------------------- |
102 | 108 | ||
103 | export { | 109 | export { |
110 | getActorUrl, | ||
104 | activityPubContextify, | 111 | activityPubContextify, |
105 | activityPubCollectionPagination, | 112 | activityPubCollectionPagination, |
106 | activityPubCollection, | 113 | activityPubCollection, |
diff --git a/server/helpers/custom-validators/activitypub/activity.ts b/server/helpers/custom-validators/activitypub/activity.ts index 632f14223..7e4dccefb 100644 --- a/server/helpers/custom-validators/activitypub/activity.ts +++ b/server/helpers/custom-validators/activitypub/activity.ts | |||
@@ -26,7 +26,7 @@ function isRootActivityValid (activity: any) { | |||
26 | ) || | 26 | ) || |
27 | ( | 27 | ( |
28 | isActivityPubUrlValid(activity.id) && | 28 | isActivityPubUrlValid(activity.id) && |
29 | isActivityPubUrlValid(activity.actor) | 29 | (isActivityPubUrlValid(activity.actor) || isActivityPubUrlValid(activity.actor.id)) |
30 | ) | 30 | ) |
31 | } | 31 | } |
32 | 32 | ||
diff --git a/server/helpers/custom-validators/activitypub/misc.ts b/server/helpers/custom-validators/activitypub/misc.ts index 75d308e9d..2dac8e1ad 100644 --- a/server/helpers/custom-validators/activitypub/misc.ts +++ b/server/helpers/custom-validators/activitypub/misc.ts | |||
@@ -24,7 +24,7 @@ function isBaseActivityValid (activity: any, type: string) { | |||
24 | return (activity['@context'] === undefined || Array.isArray(activity['@context'])) && | 24 | return (activity['@context'] === undefined || Array.isArray(activity['@context'])) && |
25 | activity.type === type && | 25 | activity.type === type && |
26 | isActivityPubUrlValid(activity.id) && | 26 | isActivityPubUrlValid(activity.id) && |
27 | isActivityPubUrlValid(activity.actor) && | 27 | (isActivityPubUrlValid(activity.actor) || isActivityPubUrlValid(activity.actor.id)) && |
28 | ( | 28 | ( |
29 | activity.to === undefined || | 29 | activity.to === undefined || |
30 | (Array.isArray(activity.to) && activity.to.every(t => isActivityPubUrlValid(t))) | 30 | (Array.isArray(activity.to) && activity.to.every(t => isActivityPubUrlValid(t))) |
diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts index b7114bbee..fa31e71c7 100644 --- a/server/lib/activitypub/actor.ts +++ b/server/lib/activitypub/actor.ts | |||
@@ -5,6 +5,7 @@ import * as url from 'url' | |||
5 | import * as uuidv4 from 'uuid/v4' | 5 | import * as uuidv4 from 'uuid/v4' |
6 | import { ActivityPubActor, ActivityPubActorType } from '../../../shared/models/activitypub' | 6 | import { ActivityPubActor, ActivityPubActorType } from '../../../shared/models/activitypub' |
7 | import { ActivityPubAttributedTo } from '../../../shared/models/activitypub/objects' | 7 | import { ActivityPubAttributedTo } from '../../../shared/models/activitypub/objects' |
8 | import { getActorUrl } from '../../helpers/activitypub' | ||
8 | import { isActorObjectValid } from '../../helpers/custom-validators/activitypub/actor' | 9 | import { isActorObjectValid } from '../../helpers/custom-validators/activitypub/actor' |
9 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 10 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
10 | import { retryTransactionWrapper, updateInstanceWithAnother } from '../../helpers/database-utils' | 11 | import { retryTransactionWrapper, updateInstanceWithAnother } from '../../helpers/database-utils' |
@@ -34,7 +35,9 @@ function setAsyncActorKeys (actor: ActorModel) { | |||
34 | }) | 35 | }) |
35 | } | 36 | } |
36 | 37 | ||
37 | async function getOrCreateActorAndServerAndModel (actorUrl: string, recurseIfNeeded = true) { | 38 | async function getOrCreateActorAndServerAndModel (activityActor: string | ActivityPubActor, recurseIfNeeded = true) { |
39 | const actorUrl = getActorUrl(activityActor) | ||
40 | |||
38 | let actor = await ActorModel.loadByUrl(actorUrl) | 41 | let actor = await ActorModel.loadByUrl(actorUrl) |
39 | 42 | ||
40 | // We don't have this actor in our database, fetch it on remote | 43 | // We don't have this actor in our database, fetch it on remote |
diff --git a/server/lib/activitypub/process/process-accept.ts b/server/lib/activitypub/process/process-accept.ts index 7db2f8ff0..c55b57820 100644 --- a/server/lib/activitypub/process/process-accept.ts +++ b/server/lib/activitypub/process/process-accept.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { ActivityAccept } from '../../../../shared/models/activitypub' | 1 | import { ActivityAccept } from '../../../../shared/models/activitypub' |
2 | import { getActorUrl } from '../../../helpers/activitypub' | ||
2 | import { ActorModel } from '../../../models/activitypub/actor' | 3 | import { ActorModel } from '../../../models/activitypub/actor' |
3 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' | 4 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' |
4 | import { addFetchOutboxJob } from '../fetch' | 5 | import { addFetchOutboxJob } from '../fetch' |
@@ -6,7 +7,8 @@ import { addFetchOutboxJob } from '../fetch' | |||
6 | async function processAcceptActivity (activity: ActivityAccept, inboxActor?: ActorModel) { | 7 | async function processAcceptActivity (activity: ActivityAccept, inboxActor?: ActorModel) { |
7 | if (inboxActor === undefined) throw new Error('Need to accept on explicit inbox.') | 8 | if (inboxActor === undefined) throw new Error('Need to accept on explicit inbox.') |
8 | 9 | ||
9 | const targetActor = await ActorModel.loadByUrl(activity.actor) | 10 | const actorUrl = getActorUrl(activity.actor) |
11 | const targetActor = await ActorModel.loadByUrl(actorUrl) | ||
10 | 12 | ||
11 | return processAccept(inboxActor, targetActor) | 13 | return processAccept(inboxActor, targetActor) |
12 | } | 14 | } |
diff --git a/server/lib/activitypub/process/process-reject.ts b/server/lib/activitypub/process/process-reject.ts index b2de28d79..f06b03772 100644 --- a/server/lib/activitypub/process/process-reject.ts +++ b/server/lib/activitypub/process/process-reject.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { ActivityReject } from '../../../../shared/models/activitypub/activity' | 1 | import { ActivityReject } from '../../../../shared/models/activitypub/activity' |
2 | import { getActorUrl } from '../../../helpers/activitypub' | ||
2 | import { sequelizeTypescript } from '../../../initializers' | 3 | import { sequelizeTypescript } from '../../../initializers' |
3 | import { ActorModel } from '../../../models/activitypub/actor' | 4 | import { ActorModel } from '../../../models/activitypub/actor' |
4 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' | 5 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' |
@@ -6,7 +7,8 @@ import { ActorFollowModel } from '../../../models/activitypub/actor-follow' | |||
6 | async function processRejectActivity (activity: ActivityReject, inboxActor?: ActorModel) { | 7 | async function processRejectActivity (activity: ActivityReject, inboxActor?: ActorModel) { |
7 | if (inboxActor === undefined) throw new Error('Need to reject on explicit inbox.') | 8 | if (inboxActor === undefined) throw new Error('Need to reject on explicit inbox.') |
8 | 9 | ||
9 | const targetActor = await ActorModel.loadByUrl(activity.actor) | 10 | const actorUrl = getActorUrl(activity.actor) |
11 | const targetActor = await ActorModel.loadByUrl(actorUrl) | ||
10 | 12 | ||
11 | return processReject(inboxActor, targetActor) | 13 | return processReject(inboxActor, targetActor) |
12 | } | 14 | } |
diff --git a/server/lib/activitypub/process/process-undo.ts b/server/lib/activitypub/process/process-undo.ts index 5a770bb97..565e70289 100644 --- a/server/lib/activitypub/process/process-undo.ts +++ b/server/lib/activitypub/process/process-undo.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { ActivityFollow, ActivityLike, ActivityUndo } from '../../../../shared/models/activitypub' | 1 | import { ActivityFollow, ActivityLike, ActivityUndo } from '../../../../shared/models/activitypub' |
2 | import { DislikeObject } from '../../../../shared/models/activitypub/objects' | 2 | import { DislikeObject } from '../../../../shared/models/activitypub/objects' |
3 | import { getActorUrl } from '../../../helpers/activitypub' | ||
3 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | 4 | import { retryTransactionWrapper } from '../../../helpers/database-utils' |
4 | import { logger } from '../../../helpers/logger' | 5 | import { logger } from '../../../helpers/logger' |
5 | import { sequelizeTypescript } from '../../../initializers' | 6 | import { sequelizeTypescript } from '../../../initializers' |
@@ -13,12 +14,14 @@ import { getOrCreateAccountAndVideoAndChannel } from '../videos' | |||
13 | async function processUndoActivity (activity: ActivityUndo) { | 14 | async function processUndoActivity (activity: ActivityUndo) { |
14 | const activityToUndo = activity.object | 15 | const activityToUndo = activity.object |
15 | 16 | ||
17 | const actorUrl = getActorUrl(activity.actor) | ||
18 | |||
16 | if (activityToUndo.type === 'Like') { | 19 | if (activityToUndo.type === 'Like') { |
17 | return processUndoLike(activity.actor, activity) | 20 | return processUndoLike(actorUrl, activity) |
18 | } else if (activityToUndo.type === 'Create' && activityToUndo.object.type === 'Dislike') { | 21 | } else if (activityToUndo.type === 'Create' && activityToUndo.object.type === 'Dislike') { |
19 | return processUndoDislike(activity.actor, activity) | 22 | return processUndoDislike(actorUrl, activity) |
20 | } else if (activityToUndo.type === 'Follow') { | 23 | } else if (activityToUndo.type === 'Follow') { |
21 | return processUndoFollow(activity.actor, activityToUndo) | 24 | return processUndoFollow(actorUrl, activityToUndo) |
22 | } | 25 | } |
23 | 26 | ||
24 | logger.warn('Unknown activity object type %s -> %s when undo activity.', activityToUndo.type, { activity: activity.id }) | 27 | logger.warn('Unknown activity object type %s -> %s when undo activity.', activityToUndo.type, { activity: activity.id }) |
diff --git a/server/lib/activitypub/process/process.ts b/server/lib/activitypub/process/process.ts index 094219489..10d8ba189 100644 --- a/server/lib/activitypub/process/process.ts +++ b/server/lib/activitypub/process/process.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { Activity, ActivityType } from '../../../../shared/models/activitypub' | 1 | import { Activity, ActivityType } from '../../../../shared/models/activitypub' |
2 | import { getActorUrl } from '../../../helpers/activitypub' | ||
2 | import { logger } from '../../../helpers/logger' | 3 | import { logger } from '../../../helpers/logger' |
3 | import { ActorModel } from '../../../models/activitypub/actor' | 4 | import { ActorModel } from '../../../models/activitypub/actor' |
4 | import { processAcceptActivity } from './process-accept' | 5 | import { processAcceptActivity } from './process-accept' |
@@ -25,9 +26,11 @@ const processActivity: { [ P in ActivityType ]: (activity: Activity, inboxActor? | |||
25 | 26 | ||
26 | async function processActivities (activities: Activity[], signatureActor?: ActorModel, inboxActor?: ActorModel) { | 27 | async function processActivities (activities: Activity[], signatureActor?: ActorModel, inboxActor?: ActorModel) { |
27 | for (const activity of activities) { | 28 | for (const activity of activities) { |
29 | const actorUrl = getActorUrl(activity.actor) | ||
30 | |||
28 | // When we fetch remote data, we don't have signature | 31 | // When we fetch remote data, we don't have signature |
29 | if (signatureActor && activity.actor !== signatureActor.url) { | 32 | if (signatureActor && actorUrl !== signatureActor.url) { |
30 | logger.warn('Signature mismatch between %s and %s.', activity.actor, signatureActor.url) | 33 | logger.warn('Signature mismatch between %s and %s.', actorUrl, signatureActor.url) |
31 | continue | 34 | continue |
32 | } | 35 | } |
33 | 36 | ||
diff --git a/shared/models/activitypub/activity.ts b/shared/models/activitypub/activity.ts index a28260ffd..f555f0118 100644 --- a/shared/models/activitypub/activity.ts +++ b/shared/models/activitypub/activity.ts | |||
@@ -22,7 +22,7 @@ export interface BaseActivity { | |||
22 | id: string | 22 | id: string |
23 | to?: string[] | 23 | to?: string[] |
24 | cc?: string[] | 24 | cc?: string[] |
25 | actor: string | 25 | actor: string | ActivityPubActor |
26 | type: ActivityType | 26 | type: ActivityType |
27 | signature?: ActivityPubSignature | 27 | signature?: ActivityPubSignature |
28 | } | 28 | } |