convert Authorized Fetch to a setting and add support for hybrid mode (essential metadata only)

This commit is contained in:
Hazelnoot 2025-02-21 22:04:36 -05:00
parent e3d949ced6
commit a35c2f214b
28 changed files with 517 additions and 103 deletions

View file

@ -22,13 +22,16 @@ import { CoreModule } from '@/core/CoreModule.js';
import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
import { LoggerService } from '@/core/LoggerService.js';
import type { IActor, IApDocument, ICollection, IObject, IPost } from '@/core/activitypub/type.js';
import { MiMeta, MiNote, MiUser, UserProfilesRepository, UserPublickeysRepository } from '@/models/_.js';
import { MiMeta, MiNote, MiUser, MiUserKeypair, UserProfilesRepository, UserPublickeysRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js';
import { secureRndstr } from '@/misc/secure-rndstr.js';
import { DownloadService } from '@/core/DownloadService.js';
import type { MiRemoteUser } from '@/models/User.js';
import type { MiLocalUser, MiRemoteUser } from '@/models/User.js';
import { genAidx } from '@/misc/id/aidx.js';
import { MockResolver } from '../misc/mock-resolver.js';
import { UserKeypairService } from '@/core/UserKeypairService.js';
import { MemoryKVCache, RedisKVCache } from '@/misc/cache.js';
import { generateKeyPair } from 'crypto';
const host = 'https://host1.test';
@ -97,6 +100,7 @@ describe('ActivityPub', () => {
let resolver: MockResolver;
let idService: IdService;
let userPublickeysRepository: UserPublickeysRepository;
let userKeypairService: UserKeypairService;
const metaInitial = {
cacheRemoteFiles: true,
@ -146,6 +150,7 @@ describe('ActivityPub', () => {
resolver = new MockResolver(await app.resolve<LoggerService>(LoggerService));
idService = app.get<IdService>(IdService);
userPublickeysRepository = app.get<UserPublickeysRepository>(DI.userPublickeysRepository);
userKeypairService = app.get<UserKeypairService>(UserKeypairService);
// Prevent ApPersonService from fetching instance, as it causes Jest import-after-test error
const federatedInstanceService = app.get<FederatedInstanceService>(FederatedInstanceService);
@ -486,15 +491,57 @@ describe('ActivityPub', () => {
describe(ApRendererService, () => {
let note: MiNote;
let author: MiUser;
let author: MiLocalUser;
let keypair: MiUserKeypair;
beforeEach(() => {
beforeEach(async () => {
author = new MiUser({
id: idService.gen(),
host: null,
uri: null,
username: 'testAuthor',
usernameLower: 'testauthor',
name: 'Test Author',
isCat: true,
requireSigninToViewContents: true,
makeNotesFollowersOnlyBefore: new Date(2025, 2, 20).valueOf(),
makeNotesHiddenBefore: new Date(2025, 2, 21).valueOf(),
isLocked: true,
isExplorable: true,
hideOnlineStatus: true,
noindex: true,
enableRss: true,
}) as MiLocalUser;
const [publicKey, privateKey] = await new Promise<[string, string]>((res, rej) =>
generateKeyPair('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem',
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
cipher: undefined,
passphrase: undefined,
},
}, (err, publicKey, privateKey) =>
err ? rej(err) : res([publicKey, privateKey]),
));
keypair = new MiUserKeypair({
userId: author.id,
user: author,
publicKey,
privateKey,
});
((userKeypairService as unknown as { cache: RedisKVCache<MiUserKeypair> }).cache as unknown as { memoryCache: MemoryKVCache<MiUserKeypair> }).memoryCache.set(author.id, keypair);
note = new MiNote({
id: idService.gen(),
userId: author.id,
user: author,
visibility: 'public',
localOnly: false,
text: 'Note text',
@ -621,6 +668,35 @@ describe('ActivityPub', () => {
});
});
});
describe('renderPersonRedacted', () => {
it('should include minimal properties', async () => {
const result = await rendererService.renderPersonRedacted(author);
expect(result.type).toBe('Person');
expect(result.id).toBeTruthy();
expect(result.inbox).toBeTruthy();
expect(result.sharedInbox).toBeTruthy();
expect(result.endpoints.sharedInbox).toBeTruthy();
expect(result.url).toBeTruthy();
expect(result.preferredUsername).toBe(author.username);
expect(result.publicKey.owner).toBe(result.id);
expect(result._misskey_requireSigninToViewContents).toBe(author.requireSigninToViewContents);
expect(result._misskey_makeNotesFollowersOnlyBefore).toBe(author.makeNotesFollowersOnlyBefore);
expect(result._misskey_makeNotesHiddenBefore).toBe(author.makeNotesHiddenBefore);
expect(result.discoverable).toBe(author.isExplorable);
expect(result.hideOnlineStatus).toBe(author.hideOnlineStatus);
expect(result.noindex).toBe(author.noindex);
expect(result.indexable).toBe(!author.noindex);
expect(result.enableRss).toBe(author.enableRss);
});
it('should not include sensitive properties', async () => {
const result = await rendererService.renderPersonRedacted(author) as IActor;
expect(result.name).toBeUndefined();
});
});
});
describe(ApPersonService, () => {