Deliver update person when new key generated (not tested)

https://github.com/misskey-dev/misskey/pull/13464#issuecomment-1977049061
This commit is contained in:
tamaina 2024-03-04 18:47:07 +00:00
parent 1af1bc87bd
commit 7d77c7044e
7 changed files with 53 additions and 17 deletions

View File

@ -27,15 +27,22 @@ export class AccountUpdateService {
} }
@bindThis @bindThis
public async publishToFollowers(userId: MiUser['id']) { /**
*
* @param userId ID
* @param isKeyUpdation Ed25519キーの作成など公開鍵のアップデートによる呼び出しか trueにするとメインキーを使うようになる
*/
public async publishToFollowers(userId: MiUser['id'], isKeyUpdation: boolean = false) {
const user = await this.usersRepository.findOneBy({ id: userId }); const user = await this.usersRepository.findOneBy({ id: userId });
if (user == null) throw new Error('user not found'); if (user == null) throw new Error('user not found');
// フォロワーがリモートユーザーかつ投稿者がローカルユーザーならUpdateを配信 // フォロワーがリモートユーザーかつ投稿者がローカルユーザーならUpdateを配信
if (this.userEntityService.isLocalUser(user)) { if (this.userEntityService.isLocalUser(user)) {
const content = this.apRendererService.addContext(this.apRendererService.renderUpdate(await this.apRendererService.renderPerson(user), user)); const content = this.apRendererService.addContext(this.apRendererService.renderUpdate(await this.apRendererService.renderPerson(user), user));
this.apDeliverManagerService.deliverToFollowers(user, content); await Promise.allSettled([
this.relayService.deliverToRelays(user, content); this.apDeliverManagerService.deliverToFollowers(user, content, isKeyUpdation),
this.relayService.deliverToRelays(user, content, isKeyUpdation),
]);
} }
} }
} }

View File

@ -70,7 +70,7 @@ export class QueueService {
} }
@bindThis @bindThis
public async deliver(user: ThinUser, content: IActivity | null, to: string | null, isSharedInbox: boolean) { public async deliver(user: ThinUser, content: IActivity | null, to: string | null, isSharedInbox: boolean, forceMainKey?: boolean) {
if (content == null) return null; if (content == null) return null;
if (to == null) return null; if (to == null) return null;
@ -84,6 +84,7 @@ export class QueueService {
digest: await genRFC3230DigestHeader(contentBody, 'SHA-256'), digest: await genRFC3230DigestHeader(contentBody, 'SHA-256'),
to, to,
isSharedInbox, isSharedInbox,
forceMainKey,
}; };
return this.deliverQueue.add(to, data, { return this.deliverQueue.add(to, data, {
@ -101,10 +102,11 @@ export class QueueService {
* @param user `{ id: string; }` ThinUserに変換しないので前もって変換してください * @param user `{ id: string; }` ThinUserに変換しないので前もって変換してください
* @param content IActivity | null * @param content IActivity | null
* @param inboxes `Map<string, boolean>` / key: to (inbox url), value: isSharedInbox (whether it is sharedInbox) * @param inboxes `Map<string, boolean>` / key: to (inbox url), value: isSharedInbox (whether it is sharedInbox)
* @param forceMainKey boolean | undefined, force to use main (rsa) key
* @returns void * @returns void
*/ */
@bindThis @bindThis
public async deliverMany(user: ThinUser, content: IActivity | null, inboxes: Map<string, boolean>) { public async deliverMany(user: ThinUser, content: IActivity | null, inboxes: Map<string, boolean>, forceMainKey?: boolean) {
if (content == null) return null; if (content == null) return null;
const contentBody = JSON.stringify(content); const contentBody = JSON.stringify(content);
@ -124,6 +126,7 @@ export class QueueService {
content: contentBody, content: contentBody,
to: d[0], to: d[0],
isSharedInbox: d[1], isSharedInbox: d[1],
forceMainKey,
} as DeliverJobData, } as DeliverJobData,
opts, opts,
}))); })));

View File

@ -111,7 +111,7 @@ export class RelayService {
} }
@bindThis @bindThis
public async deliverToRelays(user: { id: MiUser['id']; host: null; }, activity: any): Promise<void> { public async deliverToRelays(user: { id: MiUser['id']; host: null; }, activity: any, forceMainKey?: boolean): Promise<void> {
if (activity == null) return; if (activity == null) return;
const relays = await this.relaysCache.fetch(() => this.relaysRepository.findBy({ const relays = await this.relaysCache.fetch(() => this.relaysRepository.findBy({
@ -125,7 +125,7 @@ export class RelayService {
const signed = await this.apRendererService.attachLdSignature(copy, user); const signed = await this.apRendererService.attachLdSignature(copy, user);
for (const relay of relays) { for (const relay of relays) {
this.queueService.deliver(user, signed, relay.inbox, false); this.queueService.deliver(user, signed, relay.inbox, false, forceMainKey);
} }
} }
} }

View File

@ -13,6 +13,7 @@ import { bindThis } from '@/decorators.js';
import type { IActivity } from '@/core/activitypub/type.js'; import type { IActivity } from '@/core/activitypub/type.js';
import { ThinUser } from '@/queue/types.js'; import { ThinUser } from '@/queue/types.js';
import { UserKeypairService } from '../UserKeypairService.js'; import { UserKeypairService } from '../UserKeypairService.js';
import { AccountUpdateService } from '@/core/AccountUpdateService.js';
interface IRecipe { interface IRecipe {
type: string; type: string;
@ -50,6 +51,7 @@ class DeliverManager {
private userKeypairService: UserKeypairService, private userKeypairService: UserKeypairService,
private followingsRepository: FollowingsRepository, private followingsRepository: FollowingsRepository,
private queueService: QueueService, private queueService: QueueService,
private accountUpdateService: AccountUpdateService,
actor: { id: MiUser['id']; host: null; }, actor: { id: MiUser['id']; host: null; },
activity: IActivity | null, activity: IActivity | null,
@ -104,12 +106,16 @@ class DeliverManager {
* Execute delivers * Execute delivers
*/ */
@bindThis @bindThis
public async execute(): Promise<void> { public async execute(opts?: { forceMainKey?: boolean }): Promise<void> {
//#region MIGRATION //#region MIGRATION
/** if (opts?.forceMainKey !== true) {
* ed25519の署名がなければ追加する /**
*/ * ed25519の署名がなければ追加する
await this.userKeypairService.refreshAndprepareEd25519KeyPair(this.actor.id); */
await this.userKeypairService.refreshAndprepareEd25519KeyPair(this.actor.id);
// リモートに配信
await this.accountUpdateService.publishToFollowers(this.actor.id, true);
}
//#endregion //#endregion
// The value flags whether it is shared or not. // The value flags whether it is shared or not.
@ -163,6 +169,7 @@ export class ApDeliverManagerService {
private userKeypairService: UserKeypairService, private userKeypairService: UserKeypairService,
private queueService: QueueService, private queueService: QueueService,
private accountUpdateService: AccountUpdateService,
) { ) {
} }
@ -170,18 +177,20 @@ export class ApDeliverManagerService {
* Deliver activity to followers * Deliver activity to followers
* @param actor * @param actor
* @param activity Activity * @param activity Activity
* @param forceMainKey Force to use main (rsa) key
*/ */
@bindThis @bindThis
public async deliverToFollowers(actor: { id: MiLocalUser['id']; host: null; }, activity: IActivity): Promise<void> { public async deliverToFollowers(actor: { id: MiLocalUser['id']; host: null; }, activity: IActivity, forceMainKey?: boolean): Promise<void> {
const manager = new DeliverManager( const manager = new DeliverManager(
this.userKeypairService, this.userKeypairService,
this.followingsRepository, this.followingsRepository,
this.queueService, this.queueService,
this.accountUpdateService,
actor, actor,
activity, activity,
); );
manager.addFollowersRecipe(); manager.addFollowersRecipe();
await manager.execute(); await manager.execute({ forceMainKey });
} }
/** /**
@ -196,6 +205,7 @@ export class ApDeliverManagerService {
this.userKeypairService, this.userKeypairService,
this.followingsRepository, this.followingsRepository,
this.queueService, this.queueService,
this.accountUpdateService,
actor, actor,
activity, activity,
); );
@ -209,7 +219,7 @@ export class ApDeliverManagerService {
this.userKeypairService, this.userKeypairService,
this.followingsRepository, this.followingsRepository,
this.queueService, this.queueService,
this.accountUpdateService,
actor, actor,
activity, activity,
); );

View File

@ -91,11 +91,16 @@ export class ApRequestService {
this.logger = this.loggerService?.getLogger('ap-request'); // なぜか TypeError: Cannot read properties of undefined (reading 'getLogger') と言われる this.logger = this.loggerService?.getLogger('ap-request'); // なぜか TypeError: Cannot read properties of undefined (reading 'getLogger') と言われる
} }
/**
* Get private key by user id and implementation level
* @param userId User id
* @param level Implementation level
*/
@bindThis @bindThis
private async getPrivateKey(userId: MiUser['id'], level: string): Promise<PrivateKey> { private async getPrivateKey(userId: MiUser['id'], level: string): Promise<PrivateKey> {
const keypair = await this.userKeypairService.getUserKeypair(userId); const keypair = await this.userKeypairService.getUserKeypair(userId);
return (level !== '00' && keypair.ed25519PrivateKey) ? { return (level !== '00' && level !== '10' && keypair.ed25519PrivateKey) ? {
privateKeyPem: keypair.ed25519PrivateKey, privateKeyPem: keypair.ed25519PrivateKey,
keyId: `${this.config.url}/users/${userId}#ed25519-key`, keyId: `${this.config.url}/users/${userId}#ed25519-key`,
} : { } : {

View File

@ -76,7 +76,16 @@ export class DeliverProcessorService {
await this.fetchInstanceMetadataService.fetchInstanceMetadata(_server).then(() => {}); await this.fetchInstanceMetadataService.fetchInstanceMetadata(_server).then(() => {});
const server = await this.federatedInstanceService.fetch(host); const server = await this.federatedInstanceService.fetch(host);
await this.apRequestService.signedPost(job.data.user, job.data.to, job.data.content, server.httpMessageSignaturesImplementationLevel, job.data.digest); /**
* RSAキーを強制するかでレベルを変える
*/
const level = job.data.forceMainKey ?
server.httpMessageSignaturesImplementationLevel === '11' ?
'10' :
'00'
: server.httpMessageSignaturesImplementationLevel;
await this.apRequestService.signedPost(job.data.user, job.data.to, job.data.content, level, job.data.digest);
// Update stats // Update stats
if (server.isNotResponding) { if (server.isNotResponding) {

View File

@ -38,6 +38,8 @@ export type DeliverJobData = {
to: string; to: string;
/** whether it is sharedInbox */ /** whether it is sharedInbox */
isSharedInbox: boolean; isSharedInbox: boolean;
/** force to use main (rsa) key */
forceMainKey?: boolean;
}; };
export type InboxJobData = { export type InboxJobData = {