Merge branch 'develop'
This commit is contained in:
commit
929982117f
20 changed files with 209 additions and 134 deletions
|
@ -141,7 +141,7 @@ export const mfmLanguage = P.createLanguage({
|
|||
},
|
||||
hashtag: () => P((input, i) => {
|
||||
const text = input.substr(i);
|
||||
const match = text.match(/^#([^\s\.,!\?'"#:\/\[\]]+)/i);
|
||||
const match = text.match(/^#([^\s\.,!\?'"#:\/\[\]【】]+)/i);
|
||||
if (!match) return P.makeFailure(i, 'not a hashtag');
|
||||
let hashtag = match[1];
|
||||
hashtag = removeOrphanedBrackets(hashtag);
|
||||
|
|
|
@ -182,6 +182,7 @@ export class NoteRepository extends Repository<Note> {
|
|||
files: DriveFiles.packMany(note.fileIds),
|
||||
replyId: note.replyId,
|
||||
renoteId: note.renoteId,
|
||||
mentions: note.mentions.length > 0 ? note.mentions : undefined,
|
||||
uri: note.uri || undefined,
|
||||
|
||||
...(opts.detail ? {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as Bull from 'bull';
|
||||
import * as httpSignature from 'http-signature';
|
||||
import parseAcct from '../../misc/acct/parse';
|
||||
import { IRemoteUser } from '../../models/entities/user';
|
||||
import perform from '../../remote/activitypub/perform';
|
||||
import { resolvePerson, updatePerson } from '../../remote/activitypub/models/person';
|
||||
|
@ -12,7 +11,7 @@ import { Instances, Users, UserPublickeys } from '../../models';
|
|||
import { instanceChart } from '../../services/chart';
|
||||
import { UserPublickey } from '../../models/entities/user-publickey';
|
||||
import fetchMeta from '../../misc/fetch-meta';
|
||||
import { toPuny, toPunyNullable } from '../../misc/convert-host';
|
||||
import { toPuny } from '../../misc/convert-host';
|
||||
import { validActor } from '../../remote/activitypub/type';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
|
||||
|
@ -35,68 +34,49 @@ export default async (job: Bull.Job): Promise<void> => {
|
|||
let key: UserPublickey;
|
||||
|
||||
if (keyIdLower.startsWith('acct:')) {
|
||||
const acct = parseAcct(keyIdLower.slice('acct:'.length));
|
||||
const host = toPunyNullable(acct.host);
|
||||
const username = toPuny(acct.username);
|
||||
logger.warn(`Old keyId is no longer supported. ${keyIdLower}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (host === null) {
|
||||
logger.warn(`request was made by local user: @${username}`);
|
||||
return;
|
||||
// アクティビティ内のホストの検証
|
||||
const host = toPuny(new URL(signature.keyId).hostname);
|
||||
try {
|
||||
ValidateActivity(activity, host);
|
||||
} catch (e) {
|
||||
logger.warn(e.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// ブロックしてたら中断
|
||||
// TODO: いちいちデータベースにアクセスするのはコスト高そうなのでどっかにキャッシュしておく
|
||||
const meta = await fetchMeta();
|
||||
if (meta.blockedHosts.includes(host)) {
|
||||
logger.info(`Blocked request: ${host}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const _key = await UserPublickeys.findOne({
|
||||
keyId: signature.keyId
|
||||
});
|
||||
|
||||
if (_key) {
|
||||
// 登録済みユーザー
|
||||
user = await Users.findOne(_key.userId) as IRemoteUser;
|
||||
key = _key;
|
||||
} else {
|
||||
// 未登録ユーザーの場合はリモート解決
|
||||
user = await resolvePerson(activity.actor) as IRemoteUser;
|
||||
if (user == null) {
|
||||
throw new Error('failed to resolve user');
|
||||
}
|
||||
|
||||
// アクティビティ内のホストの検証
|
||||
try {
|
||||
ValidateActivity(activity, host);
|
||||
} catch (e) {
|
||||
logger.warn(e.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// ブロックしてたら中断
|
||||
// TODO: いちいちデータベースにアクセスするのはコスト高そうなのでどっかにキャッシュしておく
|
||||
const meta = await fetchMeta();
|
||||
if (meta.blockedHosts.includes(host)) {
|
||||
logger.info(`Blocked request: ${host}`);
|
||||
return;
|
||||
}
|
||||
|
||||
user = await Users.findOne({
|
||||
usernameLower: username.toLowerCase(),
|
||||
host: host
|
||||
}) as IRemoteUser;
|
||||
|
||||
key = await UserPublickeys.findOne(user.id).then(ensure);
|
||||
} else {
|
||||
// アクティビティ内のホストの検証
|
||||
const host = toPuny(new URL(signature.keyId).hostname);
|
||||
try {
|
||||
ValidateActivity(activity, host);
|
||||
} catch (e) {
|
||||
logger.warn(e.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// ブロックしてたら中断
|
||||
// TODO: いちいちデータベースにアクセスするのはコスト高そうなのでどっかにキャッシュしておく
|
||||
const meta = await fetchMeta();
|
||||
if (meta.blockedHosts.includes(host)) {
|
||||
logger.info(`Blocked request: ${host}`);
|
||||
return;
|
||||
}
|
||||
|
||||
key = await UserPublickeys.findOne({
|
||||
keyId: signature.keyId
|
||||
}).then(ensure);
|
||||
|
||||
user = await Users.findOne(key.userId) as IRemoteUser;
|
||||
}
|
||||
|
||||
// Update Person activityの場合は、ここで署名検証/更新処理まで実施して終了
|
||||
if (activity.type === 'Update') {
|
||||
if (activity.object && validActor.includes(activity.object.type)) {
|
||||
if (user == null) {
|
||||
logger.warn('Update activity received, but user not registed.');
|
||||
} else if (!httpSignature.verifySignature(signature, key.keyPem)) {
|
||||
if (!httpSignature.verifySignature(signature, key.keyPem)) {
|
||||
logger.warn('Update activity received, but signature verification failed.');
|
||||
} else {
|
||||
updatePerson(activity.actor, null, activity.object);
|
||||
|
@ -105,15 +85,6 @@ export default async (job: Bull.Job): Promise<void> => {
|
|||
}
|
||||
}
|
||||
|
||||
// アクティビティを送信してきたユーザーがまだMisskeyサーバーに登録されていなかったら登録する
|
||||
if (user == null) {
|
||||
user = await resolvePerson(activity.actor) as IRemoteUser;
|
||||
}
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('failed to resolve user');
|
||||
}
|
||||
|
||||
if (!httpSignature.verifySignature(signature, key.keyPem)) {
|
||||
logger.error('signature verification failed');
|
||||
return;
|
||||
|
|
|
@ -20,21 +20,21 @@ export default async (actor: IRemoteUser, activity: IDelete): Promise<void> => {
|
|||
const uri = (object as any).id;
|
||||
|
||||
switch (object.type) {
|
||||
case 'Note':
|
||||
case 'Question':
|
||||
case 'Article':
|
||||
deleteNote(actor, uri);
|
||||
break;
|
||||
|
||||
case 'Tombstone':
|
||||
const note = await Notes.findOne({ uri });
|
||||
if (note != null) {
|
||||
case 'Note':
|
||||
case 'Question':
|
||||
case 'Article':
|
||||
deleteNote(actor, uri);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
apLogger.warn(`Unknown type: ${object.type}`);
|
||||
break;
|
||||
case 'Tombstone':
|
||||
const note = await Notes.findOne({ uri });
|
||||
if (note != null) {
|
||||
deleteNote(actor, uri);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
apLogger.warn(`Unknown type: ${object.type}`);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@ import { IRemoteUser } from '../../../models/entities/user';
|
|||
import { ILike } from '../type';
|
||||
import create from '../../../services/note/reaction/create';
|
||||
import { Notes } from '../../../models';
|
||||
import { apLogger } from '../logger';
|
||||
|
||||
export default async (actor: IRemoteUser, activity: ILike) => {
|
||||
const id = typeof activity.object == 'string' ? activity.object : activity.object.id;
|
||||
|
@ -14,7 +15,8 @@ export default async (actor: IRemoteUser, activity: ILike) => {
|
|||
|
||||
const note = await Notes.findOne(noteId);
|
||||
if (note == null) {
|
||||
throw new Error();
|
||||
apLogger.warn(`Like activity recivied, but no such note: ${id}`, { id });
|
||||
return;
|
||||
}
|
||||
|
||||
await create(actor, note, activity._misskey_reaction);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue