Fix federation issues caused by Delete actor activities
This commit is contained in:
parent
b44a37de5a
commit
4743d69f95
|
@ -24,7 +24,7 @@ function createActivity(article: Article): Create {
|
||||||
return createObject;
|
return createObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getActor(url: string, db: Database, forceUpdate: boolean = false): Promise<Actor> {
|
export async function getActor(url: string, db: Database, forceUpdate: boolean = false): Promise<Actor | null> {
|
||||||
if (!forceUpdate) {
|
if (!forceUpdate) {
|
||||||
try {
|
try {
|
||||||
const cached = await getCachedActor(url, db);
|
const cached = await getCachedActor(url, db);
|
||||||
|
@ -34,7 +34,7 @@ export async function getActor(url: string, db: Database, forceUpdate: boolean =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const remote = await fetchActor(url);
|
const remote = await fetchActor(url);
|
||||||
cacheActor(remote, db);
|
if (remote) cacheActor(remote, db);
|
||||||
return remote;
|
return remote;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ async function cacheActor(actor: Actor, db: Database) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchActor(url: string): Promise<Actor> {
|
async function fetchActor(url: string): Promise<Actor | null> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
request({
|
request({
|
||||||
url,
|
url,
|
||||||
|
@ -91,7 +91,7 @@ async function fetchActor(url: string): Promise<Actor> {
|
||||||
json: true
|
json: true
|
||||||
}, (err, res) => {
|
}, (err, res) => {
|
||||||
if (err) reject(err);
|
if (err) reject(err);
|
||||||
else resolve(res.body as Actor);
|
else resolve(res.body ? res.body as Actor : null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,11 @@ async function handleFollow(activity: Activity, req: Request, res: Response) {
|
||||||
}
|
}
|
||||||
const db = req.app.get("db") as Database;
|
const db = req.app.get("db") as Database;
|
||||||
const actor = await getActor(follow.actor, db, true); // always force re-fetch the actor on follow
|
const actor = await getActor(follow.actor, db, true); // always force re-fetch the actor on follow
|
||||||
|
if (!actor) {
|
||||||
|
// if the actor ceases existing between the time the Follow is sent and when receive it, ignore it and end the request
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
const acceptObject = <Accept>{
|
const acceptObject = <Accept>{
|
||||||
"@context": [
|
"@context": [
|
||||||
"https://www.w3.org/ns/activitystreams",
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
|
|
@ -11,16 +11,28 @@ export = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
}
|
}
|
||||||
const db = req.app.get("db") as Database;
|
const db = req.app.get("db") as Database;
|
||||||
const actor = await getActor(req.body.actor as string, db);
|
const actor = await getActor(req.body.actor as string, db);
|
||||||
if (validate(req, actor.publicKey.publicKeyPem)) {
|
if (actor && validate(req, actor.publicKey.publicKeyPem)) {
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
// if the first check fails, force re-fetch the actor and try again
|
// if the first check fails, force re-fetch the actor and try again
|
||||||
const actor = await getActor(req.body.actor as string, db, true);
|
const actor = await getActor(req.body.actor as string, db, true);
|
||||||
if (validate(req, actor.publicKey.publicKeyPem)) {
|
if (!actor) {
|
||||||
next();
|
// probably caused by Delete activity for an actor
|
||||||
} else {
|
if (req.body.type === "Delete") {
|
||||||
|
// if we don't have a cached copy of the key, we have had no interaction with actor
|
||||||
|
// so the Delete can be safely ignored
|
||||||
|
// we still send a 200 OK status, so that the originating instances knows it has successfully
|
||||||
|
// delivered the Delete (we just can't act on it)
|
||||||
|
res.status(200).end();
|
||||||
|
} else {
|
||||||
|
console.log(`Could not retrieve actor ${req.body.actor} to validate HTTP signature for`, req.body);
|
||||||
|
res.status(401).end("Could not retrieve actor to validate HTTP signature");
|
||||||
|
}
|
||||||
|
} else if (!validate(req, actor.publicKey.publicKeyPem)) {
|
||||||
console.log(`Could not validate HTTP signature for ${req.body.actor}`);
|
console.log(`Could not validate HTTP signature for ${req.body.actor}`);
|
||||||
res.status(401).end("Could not validate HTTP signature");
|
res.status(401).end("Could not validate HTTP signature");
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue