fix: primitives 25-33: proper local instance checks

This commit is contained in:
Julia Johannesen 2024-11-14 22:01:22 -05:00
parent 74565f67f7
commit 5764fa55cb
No known key found for this signature in database
GPG key ID: 4A1377AF3E7FBC46
6 changed files with 20 additions and 10 deletions

View file

@ -54,9 +54,9 @@ export class RemoteUserResolveService {
}) as MiLocalUser; }) as MiLocalUser;
} }
host = this.utilityService.toPuny(host); host = this.utilityService.punyHost(host);
if (this.config.host === host) { if (host === this.utilityService.toPuny(this.config.host)) {
this.logger.info(`return local user: ${usernameLower}`); this.logger.info(`return local user: ${usernameLower}`);
return await this.usersRepository.findOneBy({ usernameLower, host: IsNull() }).then(u => { return await this.usersRepository.findOneBy({ usernameLower, host: IsNull() }).then(u => {
if (u == null) { if (u == null) {

View file

@ -34,6 +34,11 @@ export class UtilityService {
return this.toPuny(this.config.host) === this.toPuny(host); return this.toPuny(this.config.host) === this.toPuny(host);
} }
@bindThis
public isUriLocal(uri: string): boolean {
return this.punyHost(uri) === this.toPuny(this.config.host);
}
@bindThis @bindThis
public isBlockedHost(blockedHosts: string[], host: string | null): boolean { public isBlockedHost(blockedHosts: string[], host: string | null): boolean {
if (host == null) return false; if (host == null) return false;

View file

@ -10,6 +10,7 @@ import type { Config } from '@/config.js';
import { MemoryKVCache } from '@/misc/cache.js'; import { MemoryKVCache } from '@/misc/cache.js';
import type { MiUserPublickey } from '@/models/UserPublickey.js'; import type { MiUserPublickey } from '@/models/UserPublickey.js';
import { CacheService } from '@/core/CacheService.js'; import { CacheService } from '@/core/CacheService.js';
import { UtilityService } from '@/core/UtilityService.js';
import type { MiNote } from '@/models/Note.js'; import type { MiNote } from '@/models/Note.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import type { MiLocalUser, MiRemoteUser } from '@/models/User.js'; import type { MiLocalUser, MiRemoteUser } from '@/models/User.js';
@ -55,6 +56,7 @@ export class ApDbResolverService implements OnApplicationShutdown {
private cacheService: CacheService, private cacheService: CacheService,
private apPersonService: ApPersonService, private apPersonService: ApPersonService,
private apLoggerService: ApLoggerService, private apLoggerService: ApLoggerService,
private utilityService: UtilityService,
) { ) {
this.publicKeyCache = new MemoryKVCache<MiUserPublickey | null>(1000 * 60 * 60 * 12); // 12h this.publicKeyCache = new MemoryKVCache<MiUserPublickey | null>(1000 * 60 * 60 * 12); // 12h
this.publicKeyByUserIdCache = new MemoryKVCache<MiUserPublickey | null>(1000 * 60 * 60 * 12); // 12h this.publicKeyByUserIdCache = new MemoryKVCache<MiUserPublickey | null>(1000 * 60 * 60 * 12); // 12h
@ -65,7 +67,9 @@ export class ApDbResolverService implements OnApplicationShutdown {
const separator = '/'; const separator = '/';
const uri = new URL(getApId(value)); const uri = new URL(getApId(value));
if (uri.origin !== this.config.url) return { local: false, uri: uri.href }; if (this.utilityService.toPuny(uri.host) !== this.utilityService.toPuny(this.config.host)) {
return { local: false, uri: uri.href };
}
const [, type, id, ...rest] = uri.pathname.split(separator); const [, type, id, ...rest] = uri.pathname.split(separator);
return { return {

View file

@ -621,7 +621,7 @@ export class ApNoteService {
if (exist) return exist; if (exist) return exist;
//#endregion //#endregion
if (uri.startsWith(this.config.url)) { if (this.utilityService.isUriLocal(uri)) {
throw new StatusError('cannot resolve local note', 400, 'cannot resolve local note'); throw new StatusError('cannot resolve local note', 400, 'cannot resolve local note');
} }

View file

@ -296,7 +296,8 @@ export class ApPersonService implements OnModuleInit {
public async createPerson(uri: string, resolver?: Resolver): Promise<MiRemoteUser> { public async createPerson(uri: string, resolver?: Resolver): Promise<MiRemoteUser> {
if (typeof uri !== 'string') throw new Error('uri is not string'); if (typeof uri !== 'string') throw new Error('uri is not string');
if (uri.startsWith(this.config.url)) { const host = this.utilityService.punyHost(uri);
if (host === this.utilityService.toPuny(this.config.host)) {
throw new StatusError('cannot resolve local user', 400, 'cannot resolve local user'); throw new StatusError('cannot resolve local user', 400, 'cannot resolve local user');
} }
@ -310,8 +311,6 @@ export class ApPersonService implements OnModuleInit {
this.logger.info(`Creating the Person: ${person.id}`); this.logger.info(`Creating the Person: ${person.id}`);
const host = this.utilityService.punyHost(object.id);
const fields = this.analyzeAttachments(person.attachment ?? []); const fields = this.analyzeAttachments(person.attachment ?? []);
const tags = extractApHashtags(person.tag).map(normalizeForSearch).splice(0, 32); const tags = extractApHashtags(person.tag).map(normalizeForSearch).splice(0, 32);
@ -500,7 +499,7 @@ export class ApPersonService implements OnModuleInit {
if (typeof uri !== 'string') throw new Error('uri is not string'); if (typeof uri !== 'string') throw new Error('uri is not string');
// URIがこのサーバーを指しているならスキップ // URIがこのサーバーを指しているならスキップ
if (uri.startsWith(`${this.config.url}/`)) return; if (this.utilityService.isUriLocal(uri)) return;
//#region このサーバーに既に登録されているか //#region このサーバーに既に登録されているか
const exist = await this.fetchPerson(uri) as MiRemoteUser | null; const exist = await this.fetchPerson(uri) as MiRemoteUser | null;
@ -777,7 +776,7 @@ export class ApPersonService implements OnModuleInit {
await this.updatePerson(src.movedToUri, undefined, undefined, [...movePreventUris, src.uri]); await this.updatePerson(src.movedToUri, undefined, undefined, [...movePreventUris, src.uri]);
dst = await this.fetchPerson(src.movedToUri) ?? dst; dst = await this.fetchPerson(src.movedToUri) ?? dst;
} else { } else {
if (src.movedToUri.startsWith(`${this.config.url}/`)) { if (this.utilityService.isUriLocal(src.movedToUri)) {
// ローカルユーザーっぽいのにfetchPersonで見つからないということはmovedToUriが間違っている // ローカルユーザーっぽいのにfetchPersonで見つからないということはmovedToUriが間違っている
return 'failed: movedTo is local but not found'; return 'failed: movedTo is local but not found';
} }

View file

@ -11,6 +11,7 @@ import type { IPoll } from '@/models/Poll.js';
import type { MiRemoteUser } from '@/models/User.js'; import type { MiRemoteUser } from '@/models/User.js';
import type Logger from '@/logger.js'; import type Logger from '@/logger.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { UtilityService } from '@/core/UtilityService.js';
import { getOneApId, isQuestion } from '../type.js'; import { getOneApId, isQuestion } from '../type.js';
import { ApLoggerService } from '../ApLoggerService.js'; import { ApLoggerService } from '../ApLoggerService.js';
import { ApResolverService } from '../ApResolverService.js'; import { ApResolverService } from '../ApResolverService.js';
@ -36,6 +37,7 @@ export class ApQuestionService {
private apResolverService: ApResolverService, private apResolverService: ApResolverService,
private apLoggerService: ApLoggerService, private apLoggerService: ApLoggerService,
private utilityService: UtilityService,
) { ) {
this.logger = this.apLoggerService.logger; this.logger = this.apLoggerService.logger;
} }
@ -74,7 +76,7 @@ export class ApQuestionService {
if (uri == null) throw new Error('uri is null'); if (uri == null) throw new Error('uri is null');
// URIがこのサーバーを指しているならスキップ // URIがこのサーバーを指しているならスキップ
if (uri.startsWith(this.config.url + '/')) throw new Error('uri points local'); if (this.utilityService.isUriLocal(uri)) throw new Error('uri points local');
//#region このサーバーに既に登録されているか //#region このサーバーに既に登録されているか
const note = await this.notesRepository.findOneBy({ uri }); const note = await this.notesRepository.findOneBy({ uri });