fix: local user profile url cannot be resolved with ap/show

This commit is contained in:
anatawa12 2025-08-30 23:15:36 +09:00
parent d127d82c5b
commit e00e6c5eb4
No known key found for this signature in database
GPG Key ID: 9CA909848B8E4EA6
1 changed files with 32 additions and 1 deletions

View File

@ -21,6 +21,10 @@ import { bindThis } from '@/decorators.js';
import { ApiError } from '../../error.js'; import { ApiError } from '../../error.js';
import { IdentifiableError } from '@/misc/identifiable-error.js'; import { IdentifiableError } from '@/misc/identifiable-error.js';
import { FetchAllowSoftFailMask } from '@/core/activitypub/misc/check-against-url.js'; import { FetchAllowSoftFailMask } from '@/core/activitypub/misc/check-against-url.js';
import * as Acct from '@/misc/acct.js';
import { IsNull } from 'typeorm';
import { DI } from '@/di-symbols.js';
import type { NotesRepository, UsersRepository } from '@/models/_.js';
export const meta = { export const meta = {
tags: ['federation'], tags: ['federation'],
@ -116,6 +120,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private apDbResolverService: ApDbResolverService, private apDbResolverService: ApDbResolverService,
private apPersonService: ApPersonService, private apPersonService: ApPersonService,
private apNoteService: ApNoteService, private apNoteService: ApNoteService,
@Inject(DI.usersRepository)
private usersRepository: UsersRepository,
) { ) {
super(meta, paramDef, async (ps, me) => { super(meta, paramDef, async (ps, me) => {
const object = await this.fetchAny(ps.uri, me); const object = await this.fetchAny(ps.uri, me);
@ -137,7 +144,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
} }
let local = await this.mergePack(me, ...await Promise.all([ let local = await this.mergePack(me, ...await Promise.all([
this.apDbResolverService.getUserFromApId(uri), this.apDbResolverService.getUserFromApId(uri).then(async x => x ?? await this.getUserFromProfileUrl(uri)),
this.apDbResolverService.getNoteFromApId(uri), this.apDbResolverService.getNoteFromApId(uri),
])); ]));
if (local != null) return local; if (local != null) return local;
@ -200,6 +207,30 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
); );
} }
// To keep consistency with ap/show from external server,
// this function will handle `https://local.instance/@user`
// profile url to resolve user.
@bindThis
private async getUserFromProfileUrl(url: string): Promise<MiUser | null | undefined> {
if (!this.utilityService.isUriLocal(url)) {
return null;
}
const uri = new URL(url);
const pathComponents = uri.pathname.split('/').filter(Boolean);
if (pathComponents.length === 1 && pathComponents[0].startsWith('@')) {
const acct = Acct.parse(pathComponents[0]);
return await this.usersRepository.findOneBy({
usernameLower: acct.username.toLowerCase(),
host: acct.host ?? IsNull(),
isSuspended: false,
});
}
return null;
}
@bindThis @bindThis
private async mergePack(me: MiLocalUser | null | undefined, user: MiUser | null | undefined, note: MiNote | null | undefined): Promise<SchemaType<typeof meta.res> | null> { private async mergePack(me: MiLocalUser | null | undefined, user: MiUser | null | undefined, note: MiNote | null | undefined): Promise<SchemaType<typeof meta.res> | null> {
if (user != null) { if (user != null) {