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. | ||||
| --> | ||||
|  | ||||
| ## 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) | ||||
|  | ||||
| ### Improvements | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
| 	"name": "misskey", | ||||
| 	"version": "12.119.0", | ||||
| 	"version": "12.119.2", | ||||
| 	"codename": "indigo", | ||||
| 	"repository": { | ||||
| 		"type": "git", | ||||
|   | ||||
| @@ -10,7 +10,7 @@ import { updatePerson } from '../../models/person.js'; | ||||
|  */ | ||||
| export default async (actor: CacheableRemoteUser, activity: IUpdate): Promise<string> => { | ||||
| 	if ('actor' in activity && actor.uri !== activity.actor) { | ||||
| 		return `skip: invalid actor`; | ||||
| 		return 'skip: invalid actor'; | ||||
| 	} | ||||
|  | ||||
| 	apLogger.debug('Update'); | ||||
| @@ -24,10 +24,10 @@ export default async (actor: CacheableRemoteUser, activity: IUpdate): Promise<st | ||||
|  | ||||
| 	if (isActor(object)) { | ||||
| 		await updatePerson(actor.uri!, resolver, object); | ||||
| 		return `ok: Person updated`; | ||||
| 		return 'ok: Person updated'; | ||||
| 	} else if (getApType(object) === 'Question') { | ||||
| 		await updateQuestion(object).catch(e => console.log(e)); | ||||
| 		return `ok: Question updated`; | ||||
| 		await updateQuestion(object, resolver).catch(e => console.log(e)); | ||||
| 		return 'ok: Question updated'; | ||||
| 	} else { | ||||
| 		return `skip: Unknown type: ${getApType(object)}`; | ||||
| 	} | ||||
|   | ||||
| @@ -5,11 +5,9 @@ import { IObject, isMention, IApMention } from '../type.js'; | ||||
| import Resolver from '../resolver.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 resolver = new Resolver(); | ||||
|  | ||||
| 	const limit = promiseLimit<CacheableUser | null>(2); | ||||
| 	const mentionedUsers = (await Promise.all( | ||||
| 		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'); | ||||
| 	} | ||||
|  | ||||
| 	const noteAudience = await parseAudience(actor, note.to, note.cc); | ||||
| 	const noteAudience = await parseAudience(actor, note.to, note.cc, resolver); | ||||
| 	let visibility = noteAudience.visibility; | ||||
| 	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'; | ||||
|  | ||||
| 	const apMentions = await extractApMentions(note.tag); | ||||
| 	const apMentions = await extractApMentions(note.tag, resolver); | ||||
| 	const apHashtags = await extractApHashtags(note.tag); | ||||
|  | ||||
| 	// 添付ファイル | ||||
|   | ||||
| @@ -271,7 +271,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us | ||||
| 	}); | ||||
| 	//#endregion | ||||
|  | ||||
| 	await updateFeatured(user!.id).catch(err => logger.error(err)); | ||||
| 	await updateFeatured(user!.id, resolver).catch(err => logger.error(err)); | ||||
|  | ||||
| 	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), | ||||
| 	}); | ||||
|  | ||||
| 	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 }; | ||||
| } | ||||
|  | ||||
| export async function updateFeatured(userId: User['id']) { | ||||
| export async function updateFeatured(userId: User['id'], resolver?: Resolver) { | ||||
| 	const user = await Users.findOneByOrFail({ id: userId }); | ||||
| 	if (!Users.isRemoteUser(user)) return; | ||||
| 	if (!user.featured) return; | ||||
|  | ||||
| 	logger.info(`Updating the featured: ${user.uri}`); | ||||
|  | ||||
| 	const resolver = new Resolver(); | ||||
| 	if (resolver == null) resolver = new Resolver(); | ||||
|  | ||||
| 	// Resolve to (Ordered)Collection Object | ||||
| 	const collection = await resolver.resolveCollection(user.featured); | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| 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 { IObject, IQuestion, isQuestion } from '../type.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> { | ||||
| 	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 | ||||
|  * @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; | ||||
|  | ||||
| 	// URIがこのサーバーを指しているならスキップ | ||||
| @@ -55,7 +55,7 @@ export async function updateQuestion(value: any) { | ||||
| 	//#endregion | ||||
|  | ||||
| 	// resolve new Question object | ||||
| 	const resolver = new Resolver(); | ||||
| 	if (resolver == null) resolver = new Resolver(); | ||||
| 	const question = await resolver.resolve(value) as IQuestion; | ||||
| 	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 { fetchMeta } from '@/misc/fetch-meta.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 { parseUri } from './db-resolver.js'; | ||||
| import renderNote from '@/remote/activitypub/renderer/note.js'; | ||||
| import { renderLike } from '@/remote/activitypub/renderer/like.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 { renderActivity } from '@/remote/activitypub/renderer/index.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 { | ||||
| 	private history: Set<string>; | ||||
| 	private user?: ILocalUser; | ||||
| 	private recursionLimit?: number; | ||||
|  | ||||
| 	constructor() { | ||||
| 	constructor(recursionLimit = 100) { | ||||
| 		this.history = new Set(); | ||||
| 		this.recursionLimit = recursionLimit; | ||||
| 	} | ||||
|  | ||||
| 	public getHistory(): string[] { | ||||
| @@ -60,6 +62,10 @@ export default class Resolver { | ||||
| 			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); | ||||
|  | ||||
| 		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'); | ||||
|  | ||||
| 				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))); | ||||
| 			default: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user