Compare commits
18 Commits
13.0.0-bet
...
12.119.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5a74f4434 | ||
|
|
993110d114 | ||
|
|
fccd9c32e8 | ||
|
|
58a3a0b7d4 | ||
|
|
a2a1636c10 | ||
|
|
46ec0303b7 | ||
|
|
3b1669fb6b | ||
|
|
09591fa4ae | ||
|
|
85ce00adc0 | ||
|
|
f25518af91 | ||
|
|
b796aacf7f | ||
|
|
ff24811676 | ||
|
|
4c8a1867f0 | ||
|
|
bce48dfee9 | ||
|
|
c20311b8a7 | ||
|
|
fb14ac50b8 | ||
|
|
84d984bd31 | ||
|
|
1bc856c451 |
@@ -9,6 +9,14 @@
|
|||||||
You should also include the user name that made the change.
|
You should also include the user name that made the change.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
## 12.119.2 (2022/12/04)
|
||||||
|
### Bugfixes
|
||||||
|
- Server: Backported versions mitigate isn't working @mei23
|
||||||
|
|
||||||
|
## 12.119.1 (2022/12/03)
|
||||||
|
### Bugfixes
|
||||||
|
- Server: Mitigate AP reference chain DoS vector @skehmatics
|
||||||
|
|
||||||
## 12.119.0 (2022/09/10)
|
## 12.119.0 (2022/09/10)
|
||||||
|
|
||||||
### Improvements
|
### Improvements
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"version": "12.119.0",
|
"version": "12.119.2",
|
||||||
"codename": "indigo",
|
"codename": "indigo",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { updatePerson } from '../../models/person.js';
|
|||||||
*/
|
*/
|
||||||
export default async (actor: CacheableRemoteUser, activity: IUpdate): Promise<string> => {
|
export default async (actor: CacheableRemoteUser, activity: IUpdate): Promise<string> => {
|
||||||
if ('actor' in activity && actor.uri !== activity.actor) {
|
if ('actor' in activity && actor.uri !== activity.actor) {
|
||||||
return `skip: invalid actor`;
|
return 'skip: invalid actor';
|
||||||
}
|
}
|
||||||
|
|
||||||
apLogger.debug('Update');
|
apLogger.debug('Update');
|
||||||
@@ -24,10 +24,10 @@ export default async (actor: CacheableRemoteUser, activity: IUpdate): Promise<st
|
|||||||
|
|
||||||
if (isActor(object)) {
|
if (isActor(object)) {
|
||||||
await updatePerson(actor.uri!, resolver, object);
|
await updatePerson(actor.uri!, resolver, object);
|
||||||
return `ok: Person updated`;
|
return 'ok: Person updated';
|
||||||
} else if (getApType(object) === 'Question') {
|
} else if (getApType(object) === 'Question') {
|
||||||
await updateQuestion(object).catch(e => console.log(e));
|
await updateQuestion(object, resolver).catch(e => console.log(e));
|
||||||
return `ok: Question updated`;
|
return 'ok: Question updated';
|
||||||
} else {
|
} else {
|
||||||
return `skip: Unknown type: ${getApType(object)}`;
|
return `skip: Unknown type: ${getApType(object)}`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,9 @@ import { IObject, isMention, IApMention } from '../type.js';
|
|||||||
import Resolver from '../resolver.js';
|
import Resolver from '../resolver.js';
|
||||||
import { resolvePerson } from './person.js';
|
import { resolvePerson } from './person.js';
|
||||||
|
|
||||||
export async function extractApMentions(tags: IObject | IObject[] | null | undefined) {
|
export async function extractApMentions(tags: IObject | IObject[] | null | undefined, resolver: Resolver) {
|
||||||
const hrefs = unique(extractApMentionObjects(tags).map(x => x.href as string));
|
const hrefs = unique(extractApMentionObjects(tags).map(x => x.href as string));
|
||||||
|
|
||||||
const resolver = new Resolver();
|
|
||||||
|
|
||||||
const limit = promiseLimit<CacheableUser | null>(2);
|
const limit = promiseLimit<CacheableUser | null>(2);
|
||||||
const mentionedUsers = (await Promise.all(
|
const mentionedUsers = (await Promise.all(
|
||||||
hrefs.map(x => limit(() => resolvePerson(x, resolver).catch(() => null))),
|
hrefs.map(x => limit(() => resolvePerson(x, resolver).catch(() => null))),
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s
|
|||||||
throw new Error('actor has been suspended');
|
throw new Error('actor has been suspended');
|
||||||
}
|
}
|
||||||
|
|
||||||
const noteAudience = await parseAudience(actor, note.to, note.cc);
|
const noteAudience = await parseAudience(actor, note.to, note.cc, resolver);
|
||||||
let visibility = noteAudience.visibility;
|
let visibility = noteAudience.visibility;
|
||||||
const visibleUsers = noteAudience.visibleUsers;
|
const visibleUsers = noteAudience.visibleUsers;
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s
|
|||||||
|
|
||||||
let isTalk = note._misskey_talk && visibility === 'specified';
|
let isTalk = note._misskey_talk && visibility === 'specified';
|
||||||
|
|
||||||
const apMentions = await extractApMentions(note.tag);
|
const apMentions = await extractApMentions(note.tag, resolver);
|
||||||
const apHashtags = await extractApHashtags(note.tag);
|
const apHashtags = await extractApHashtags(note.tag);
|
||||||
|
|
||||||
// 添付ファイル
|
// 添付ファイル
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
|
|||||||
});
|
});
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
await updateFeatured(user!.id).catch(err => logger.error(err));
|
await updateFeatured(user!.id, resolver).catch(err => logger.error(err));
|
||||||
|
|
||||||
return user!;
|
return user!;
|
||||||
}
|
}
|
||||||
@@ -384,7 +384,7 @@ export async function updatePerson(uri: string, resolver?: Resolver | null, hint
|
|||||||
followerSharedInbox: person.sharedInbox || (person.endpoints ? person.endpoints.sharedInbox : undefined),
|
followerSharedInbox: person.sharedInbox || (person.endpoints ? person.endpoints.sharedInbox : undefined),
|
||||||
});
|
});
|
||||||
|
|
||||||
await updateFeatured(exist.id).catch(err => logger.error(err));
|
await updateFeatured(exist.id, resolver).catch(err => logger.error(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -462,14 +462,14 @@ export function analyzeAttachments(attachments: IObject | IObject[] | undefined)
|
|||||||
return { fields, services };
|
return { fields, services };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateFeatured(userId: User['id']) {
|
export async function updateFeatured(userId: User['id'], resolver?: Resolver) {
|
||||||
const user = await Users.findOneByOrFail({ id: userId });
|
const user = await Users.findOneByOrFail({ id: userId });
|
||||||
if (!Users.isRemoteUser(user)) return;
|
if (!Users.isRemoteUser(user)) return;
|
||||||
if (!user.featured) return;
|
if (!user.featured) return;
|
||||||
|
|
||||||
logger.info(`Updating the featured: ${user.uri}`);
|
logger.info(`Updating the featured: ${user.uri}`);
|
||||||
|
|
||||||
const resolver = new Resolver();
|
if (resolver == null) resolver = new Resolver();
|
||||||
|
|
||||||
// Resolve to (Ordered)Collection Object
|
// Resolve to (Ordered)Collection Object
|
||||||
const collection = await resolver.resolveCollection(user.featured);
|
const collection = await resolver.resolveCollection(user.featured);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import config from '@/config/index.js';
|
import config from '@/config/index.js';
|
||||||
|
import { Notes, Polls } from '@/models/index.js';
|
||||||
|
import { IPoll } from '@/models/entities/poll.js';
|
||||||
import Resolver from '../resolver.js';
|
import Resolver from '../resolver.js';
|
||||||
import { IObject, IQuestion, isQuestion } from '../type.js';
|
import { IObject, IQuestion, isQuestion } from '../type.js';
|
||||||
import { apLogger } from '../logger.js';
|
import { apLogger } from '../logger.js';
|
||||||
import { Notes, Polls } from '@/models/index.js';
|
|
||||||
import { IPoll } from '@/models/entities/poll.js';
|
|
||||||
|
|
||||||
export async function extractPollFromQuestion(source: string | IObject, resolver?: Resolver): Promise<IPoll> {
|
export async function extractPollFromQuestion(source: string | IObject, resolver?: Resolver): Promise<IPoll> {
|
||||||
if (resolver == null) resolver = new Resolver();
|
if (resolver == null) resolver = new Resolver();
|
||||||
@@ -40,7 +40,7 @@ export async function extractPollFromQuestion(source: string | IObject, resolver
|
|||||||
* @param uri URI of AP Question object
|
* @param uri URI of AP Question object
|
||||||
* @returns true if updated
|
* @returns true if updated
|
||||||
*/
|
*/
|
||||||
export async function updateQuestion(value: any) {
|
export async function updateQuestion(value: any, resolver?: Resolver) {
|
||||||
const uri = typeof value === 'string' ? value : value.id;
|
const uri = typeof value === 'string' ? value : value.id;
|
||||||
|
|
||||||
// URIがこのサーバーを指しているならスキップ
|
// URIがこのサーバーを指しているならスキップ
|
||||||
@@ -55,7 +55,7 @@ export async function updateQuestion(value: any) {
|
|||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
// resolve new Question object
|
// resolve new Question object
|
||||||
const resolver = new Resolver();
|
if (resolver == null) resolver = new Resolver();
|
||||||
const question = await resolver.resolve(value) as IQuestion;
|
const question = await resolver.resolve(value) as IQuestion;
|
||||||
apLogger.debug(`fetched question: ${JSON.stringify(question, null, 2)}`);
|
apLogger.debug(`fetched question: ${JSON.stringify(question, null, 2)}`);
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,7 @@ import { ILocalUser } from '@/models/entities/user.js';
|
|||||||
import { getInstanceActor } from '@/services/instance-actor.js';
|
import { getInstanceActor } from '@/services/instance-actor.js';
|
||||||
import { fetchMeta } from '@/misc/fetch-meta.js';
|
import { fetchMeta } from '@/misc/fetch-meta.js';
|
||||||
import { extractDbHost, isSelfHost } from '@/misc/convert-host.js';
|
import { extractDbHost, isSelfHost } from '@/misc/convert-host.js';
|
||||||
import { signedGet } from './request.js';
|
|
||||||
import { IObject, isCollectionOrOrderedCollection, ICollection, IOrderedCollection } from './type.js';
|
|
||||||
import { FollowRequests, Notes, NoteReactions, Polls, Users } from '@/models/index.js';
|
import { FollowRequests, Notes, NoteReactions, Polls, Users } from '@/models/index.js';
|
||||||
import { parseUri } from './db-resolver.js';
|
|
||||||
import renderNote from '@/remote/activitypub/renderer/note.js';
|
import renderNote from '@/remote/activitypub/renderer/note.js';
|
||||||
import { renderLike } from '@/remote/activitypub/renderer/like.js';
|
import { renderLike } from '@/remote/activitypub/renderer/like.js';
|
||||||
import { renderPerson } from '@/remote/activitypub/renderer/person.js';
|
import { renderPerson } from '@/remote/activitypub/renderer/person.js';
|
||||||
@@ -15,13 +12,18 @@ import renderQuestion from '@/remote/activitypub/renderer/question.js';
|
|||||||
import renderCreate from '@/remote/activitypub/renderer/create.js';
|
import renderCreate from '@/remote/activitypub/renderer/create.js';
|
||||||
import { renderActivity } from '@/remote/activitypub/renderer/index.js';
|
import { renderActivity } from '@/remote/activitypub/renderer/index.js';
|
||||||
import renderFollow from '@/remote/activitypub/renderer/follow.js';
|
import renderFollow from '@/remote/activitypub/renderer/follow.js';
|
||||||
|
import { parseUri } from './db-resolver.js';
|
||||||
|
import { IObject, isCollectionOrOrderedCollection, ICollection, IOrderedCollection } from './type.js';
|
||||||
|
import { signedGet } from './request.js';
|
||||||
|
|
||||||
export default class Resolver {
|
export default class Resolver {
|
||||||
private history: Set<string>;
|
private history: Set<string>;
|
||||||
private user?: ILocalUser;
|
private user?: ILocalUser;
|
||||||
|
private recursionLimit?: number;
|
||||||
|
|
||||||
constructor() {
|
constructor(recursionLimit = 100) {
|
||||||
this.history = new Set();
|
this.history = new Set();
|
||||||
|
this.recursionLimit = recursionLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getHistory(): string[] {
|
public getHistory(): string[] {
|
||||||
@@ -60,6 +62,10 @@ export default class Resolver {
|
|||||||
throw new Error('cannot resolve already resolved one');
|
throw new Error('cannot resolve already resolved one');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.recursionLimit && this.history.size > this.recursionLimit) {
|
||||||
|
throw new Error('hit recursion limit');
|
||||||
|
}
|
||||||
|
|
||||||
this.history.add(value);
|
this.history.add(value);
|
||||||
|
|
||||||
const host = extractDbHost(value);
|
const host = extractDbHost(value);
|
||||||
@@ -123,7 +129,7 @@ export default class Resolver {
|
|||||||
if (parsed.rest == null || !/^\w+$/.test(parsed.rest)) throw new Error('resolveLocal: invalid follow URI');
|
if (parsed.rest == null || !/^\w+$/.test(parsed.rest)) throw new Error('resolveLocal: invalid follow URI');
|
||||||
|
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
[parsed.id, parsed.rest].map(id => Users.findOneByOrFail({ id }))
|
[parsed.id, parsed.rest].map(id => Users.findOneByOrFail({ id })),
|
||||||
)
|
)
|
||||||
.then(([follower, followee]) => renderActivity(renderFollow(follower, followee, url)));
|
.then(([follower, followee]) => renderActivity(renderFollow(follower, followee, url)));
|
||||||
default:
|
default:
|
||||||
|
|||||||
Reference in New Issue
Block a user