activitypub: simplify some URI/id related checks

followup on previous commit
This commit is contained in:
Johann150 2022-12-15 00:31:23 +01:00
parent 3582fd8260
commit ef53ec276a
Signed by untrusted user: Johann150
GPG key ID: 9EE6577A2A06F8F1
3 changed files with 32 additions and 25 deletions

View file

@ -1,5 +1,5 @@
import { CacheableRemoteUser } from '@/models/entities/user.js';
import { getApType, IUpdate, isActor } from '@/remote/activitypub/type.js';
import { getApId, getApType, IUpdate, isActor } from '@/remote/activitypub/type.js';
import { apLogger } from '@/remote/activitypub/logger.js';
import { updateQuestion } from '@/remote/activitypub/models/question.js';
import { Resolver } from '@/remote/activitypub/resolver.js';
@ -21,7 +21,11 @@ export default async (actor: CacheableRemoteUser, activity: IUpdate, resolver: R
});
if (isActor(object)) {
await updatePerson(actor.uri!, resolver, object);
if (actor.uri !== getApId(object)) {
return 'skip: actor id !== updated actor id';
}
await updatePerson(object, resolver);
return 'ok: Person updated';
} else if (getApType(object) === 'Question') {
await updateQuestion(object, resolver).catch(e => console.log(e));

View file

@ -28,9 +28,7 @@ import { extractApHashtags } from './tag.js';
import { extractPollFromQuestion } from './question.js';
import { extractApMentions } from './mention.js';
export function validateNote(object: any, uri: string): Error | null {
const expectHost = extractDbHost(uri);
export function validateNote(object: IObject): Error | null {
if (object == null) {
return new Error('invalid Note: object is null');
}
@ -39,12 +37,20 @@ export function validateNote(object: any, uri: string): Error | null {
return new Error(`invalid Note: invalid object type ${getApType(object)}`);
}
if (object.id && extractDbHost(object.id) !== expectHost) {
return new Error(`invalid Note: id has different host. expected: ${expectHost}, actual: ${extractDbHost(object.id)}`);
const id = getApId(object);
if (id == null) {
// Only transient objects or anonymous objects may not have an id or an id that is explicitly null.
// We consider all Notes as not transient and not anonymous so require ids for them.
return new Error(`invalid Note: id required but not present`);
}
if (object.attributedTo && extractDbHost(getOneApId(object.attributedTo)) !== expectHost) {
return new Error(`invalid Note: attributedTo has different host. expected: ${expectHost}, actual: ${extractDbHost(object.attributedTo)}`);
// Check that the server is authorized to act on behalf of this author.
const expectHost = extractDbHost(id);
const attributedToHost = object.attributedTo
? extractDbHost(getOneApId(object.attributedTo))
: null;
if (attributedToHost !== expectHost) {
return new Error(`invalid Note: attributedTo has different host. expected: ${expectHost}, actual: ${attributedToHost}`);
}
return null;
@ -64,10 +70,9 @@ export async function fetchNote(object: string | IObject): Promise<Note | null>
* Noteを作成します
*/
export async function createNote(value: string | IObject, resolver: Resolver, silent = false): Promise<Note | null> {
const object: any = await resolver.resolve(value);
const object: IObject = await resolver.resolve(value);
const entryUri = getApId(value);
const err = validateNote(object, entryUri);
const err = validateNote(object);
if (err) {
apLogger.error(`${err.message}`, {
resolver: {

View file

@ -39,8 +39,7 @@ const summaryLength = 2048;
* @param x Fetched object
* @param uri Fetch target URI
*/
function validateActor(x: IObject, uri: string): IActor {
const expectHost = toPuny(new URL(uri).hostname);
function validateActor(x: IObject): IActor {
if (x == null) {
throw new Error('invalid Actor: object is null');
@ -50,7 +49,10 @@ function validateActor(x: IObject, uri: string): IActor {
throw new Error(`invalid Actor type '${x.type}'`);
}
if (!(typeof x.id === 'string' && x.id.length > 0)) {
const uri = getApId(x);
if (uri == null) {
// Only transient objects or anonymous objects may not have an id or an id that is explicitly null.
// We consider all actors as not transient and not anonymous so require ids for them.
throw new Error('invalid Actor: wrong id');
}
@ -78,16 +80,12 @@ function validateActor(x: IObject, uri: string): IActor {
x.summary = truncate(x.summary, summaryLength);
}
const idHost = toPuny(new URL(x.id!).hostname);
if (idHost !== expectHost) {
throw new Error('invalid Actor: id has different host');
}
if (x.publicKey) {
if (typeof x.publicKey.id !== 'string') {
throw new Error('invalid Actor: publicKey.id is not a string');
}
const expectHost = extractDbHost(uri);
const publicKeyIdHost = toPuny(new URL(x.publicKey.id).hostname);
if (publicKeyIdHost !== expectHost) {
throw new Error('invalid Actor: publicKey.id has different host');
@ -140,7 +138,7 @@ export async function createPerson(uri: string, resolver: Resolver): Promise<Use
const object = await resolver.resolve(uri) as any;
const person = validateActor(object, uri);
const person = validateActor(object);
apLogger.info(`Creating the Person: ${person.id}`);
@ -278,8 +276,8 @@ export async function createPerson(uri: string, resolver: Resolver): Promise<Use
* @param resolver Resolver
* @param hint Hint of Person object (If this value is a valid Person, it is used for updating without Remote resolve.)
*/
export async function updatePerson(uri: string, resolver: Resolver, hint?: IObject): Promise<void> {
if (typeof uri !== 'string') throw new Error('uri is not string');
export async function updatePerson(value: IObject | string, resolver: Resolver): Promise<void> {
const uri = getApId(value);
// URIがこのサーバーを指しているならスキップ
if (uri.startsWith(config.url + '/')) {
@ -294,9 +292,9 @@ export async function updatePerson(uri: string, resolver: Resolver, hint?: IObje
}
//#endregion
const object = hint || await resolver.resolve(uri);
const object = await resolver.resolve(value);
const person = validateActor(object, uri);
const person = validateActor(object);
apLogger.info(`Updating the Person: ${person.id}`);