Deliver update person when new key generated (not tested)
https://github.com/misskey-dev/misskey/pull/13464#issuecomment-1977049061
This commit is contained in:
parent
1af1bc87bd
commit
7d77c7044e
|
@ -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),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
})));
|
})));
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
|
|
|
@ -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`,
|
||||||
} : {
|
} : {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
Loading…
Reference in New Issue