export migration URIs in addition to resolved user IDs, and move alsoKnownAs to MeDetailed for privacy

This commit is contained in:
Hazelnoot 2025-09-14 20:52:51 -04:00
parent 756e99e9c4
commit ba77e606f8
2 changed files with 67 additions and 11 deletions

View file

@ -409,6 +409,30 @@ export class UserEntityService implements OnModuleInit {
);
}
@bindThis
public async resolveAlsoKnownAs(user: MiUser): Promise<{ uri: string, id: string | null }[] | null> {
if (!user.alsoKnownAs) {
return null;
}
const alsoKnownAs: { uri: string, id: string | null }[] = [];
for (const uri of new Set(user.alsoKnownAs)) {
try {
const resolved = await this.apPersonService.resolvePerson(uri);
alsoKnownAs.push({ uri, id: resolved.id });
} catch {
// ignore errors - we expect some users to be deleted or unavailable
alsoKnownAs.push({ uri, id: null });
}
}
if (alsoKnownAs.length < 1) {
return null;
}
return alsoKnownAs;
}
@bindThis
public getIdenticonUrl(user: MiUser): string {
if ((user.host == null || user.host === this.config.host) && user.username.includes('.') && this.meta.iconUrl) { // ローカルのシステムアカウントの場合
@ -551,6 +575,10 @@ export class UserEntityService implements OnModuleInit {
let fetchPoliciesPromise: Promise<RolePolicies> | null = null;
const fetchPolicies = () => fetchPoliciesPromise ??= this.roleService.getUserPolicies(user);
// This has a cache so it's fine to await here
const alsoKnownAs = await this.resolveAlsoKnownAs(user);
const alsoKnownAsIds = alsoKnownAs?.map(aka => aka.id).filter(id => id != null) ?? null;
const bypassSilence = isMe || (myFollowings ? myFollowings.has(user.id) : false);
const packed = {
@ -617,10 +645,8 @@ export class UserEntityService implements OnModuleInit {
url: profile!.url,
uri: user.uri,
movedTo: user.movedToUri ? Promise.resolve(opts.userIdsByUri?.get(user.movedToUri) ?? this.apPersonService.resolvePerson(user.movedToUri).then(user => user.id).catch(() => null)) : null,
alsoKnownAs: user.alsoKnownAs
? Promise.all(user.alsoKnownAs.map(uri => Promise.resolve(opts.userIdsByUri?.get(uri) ?? this.apPersonService.fetchPerson(uri).then(user => user?.id).catch(() => null))))
.then(xs => xs.length === 0 ? null : xs.filter(x => x != null))
: null,
movedToUri: user.movedToUri,
// alsoKnownAs moved from packedUserDetailedNotMeOnly for privacy
bannerUrl: user.bannerId == null ? null : user.bannerUrl,
bannerBlurhash: user.bannerId == null ? null : user.bannerBlurhash,
backgroundUrl: user.backgroundId == null ? null : user.backgroundUrl,
@ -711,6 +737,9 @@ export class UserEntityService implements OnModuleInit {
defaultCW: profile!.defaultCW,
defaultCWPriority: profile!.defaultCWPriority,
allowUnsignedFetch: user.allowUnsignedFetch,
// alsoKnownAs moved from packedUserDetailedNotMeOnly for privacy
alsoKnownAs: alsoKnownAsIds,
skAlsoKnownAs: alsoKnownAs,
} : {}),
...(opts.includeSecrets ? {

View file

@ -313,15 +313,12 @@ export const packedUserDetailedNotMeOnlySchema = {
format: 'id',
nullable: true, optional: false,
},
alsoKnownAs: {
type: 'array',
movedToUri: {
type: 'string',
format: 'uri',
nullable: true, optional: false,
items: {
type: 'string',
format: 'id',
nullable: false, optional: false,
},
},
// alsoKnownAs moved to packedUserDetailedNotMeOnly for privacy
bannerUrl: {
type: 'string',
format: 'url',
@ -814,6 +811,36 @@ export const packedMeDetailedOnlySchema = {
enum: userUnsignedFetchOptions,
nullable: false, optional: false,
},
// alsoKnownAs moved from packedUserDetailedNotMeOnly for privacy
alsoKnownAs: {
type: 'array',
nullable: true, optional: false,
items: {
type: 'string',
format: 'id',
nullable: false, optional: false,
},
},
skAlsoKnownAs: {
type: 'array',
nullable: true, optional: false,
items: {
type: 'object',
nullable: false, optional: false,
properties: {
uri: {
type: 'string',
format: 'uri',
nullable: false, optional: false,
},
id: {
type: 'string',
format: 'id',
nullable: true, optional: false,
},
},
},
},
},
} as const;