149 lines
4.9 KiB
JavaScript
149 lines
4.9 KiB
JavaScript
import config from "../../config/index.js";
|
|
import { Notes, Users, UserPublickeys, MessagingMessages } from "../../models/index.js";
|
|
import { Cache } from "../../misc/cache.js";
|
|
import { uriPersonCache, userByIdCache } from "../../services/user-cache.js";
|
|
import { getApId } from "./type.js";
|
|
import { resolvePerson, updatePerson } from "./models/person.js";
|
|
import { subscriber } from "../../db/redis.js";
|
|
import { toPuny } from "../../misc/convert-host.js";
|
|
const publicKeyCache = new Cache("publicKey", 60 * 30);
|
|
const publicKeyByUserIdCache = new Cache("publicKeyByUserId", 60 * 30);
|
|
export function parseUri(value) {
|
|
const uri = getApId(value);
|
|
const parsed = new URL(uri);
|
|
if (toPuny(parsed.host) === toPuny(config.host)) {
|
|
const localRegex = new RegExp(`^.*?/(\\w+)/(\\w+)(?:/(.+))?`);
|
|
const matchLocal = uri.match(localRegex);
|
|
if (matchLocal == null) {
|
|
throw new Error(`Failed to parse local URI: ${uri}`);
|
|
}
|
|
return {
|
|
local: true,
|
|
type: matchLocal[1],
|
|
id: matchLocal[2],
|
|
rest: matchLocal[3]
|
|
};
|
|
} else {
|
|
return {
|
|
local: false,
|
|
uri
|
|
};
|
|
}
|
|
}
|
|
export default class DbResolver {
|
|
/**
|
|
* AP Note => Misskey Note in DB
|
|
*/ async getNoteFromApId(value) {
|
|
const parsed = parseUri(value);
|
|
if (parsed.local) {
|
|
if (parsed.type !== "notes") return null;
|
|
return await Notes.findOneBy({
|
|
id: parsed.id
|
|
});
|
|
} else {
|
|
return await Notes.findOne({
|
|
where: [
|
|
{
|
|
uri: parsed.uri
|
|
},
|
|
{
|
|
url: parsed.uri
|
|
}
|
|
]
|
|
});
|
|
}
|
|
}
|
|
async getMessageFromApId(value) {
|
|
const parsed = parseUri(value);
|
|
if (parsed.local) {
|
|
if (parsed.type !== "notes") return null;
|
|
return await MessagingMessages.findOneBy({
|
|
id: parsed.id
|
|
});
|
|
} else {
|
|
return await MessagingMessages.findOneBy({
|
|
uri: parsed.uri
|
|
});
|
|
}
|
|
}
|
|
/**
|
|
* AP Person => Misskey User in DB
|
|
*/ async getUserFromApId(value) {
|
|
const parsed = parseUri(value);
|
|
if (parsed.local) {
|
|
if (parsed.type !== "users") return null;
|
|
return await userByIdCache.fetchMaybe(parsed.id, ()=>Users.findOneBy({
|
|
id: parsed.id
|
|
}).then((x)=>x ?? undefined), true) ?? null;
|
|
} else {
|
|
return await uriPersonCache.fetch(parsed.uri, ()=>Users.findOneBy({
|
|
uri: parsed.uri
|
|
}), true);
|
|
}
|
|
}
|
|
/**
|
|
* AP KeyId => Misskey User and Key
|
|
*/ async getAuthUserFromKeyId(keyId) {
|
|
const key = await publicKeyCache.fetch(keyId, async ()=>{
|
|
const key = await UserPublickeys.findOneBy({
|
|
keyId
|
|
});
|
|
if (key == null) return null;
|
|
return key;
|
|
}, true, (key)=>key != null);
|
|
if (key == null) return null;
|
|
return {
|
|
user: await userByIdCache.fetch(key.userId, ()=>Users.findOneByOrFail({
|
|
id: key.userId
|
|
}), true),
|
|
key
|
|
};
|
|
}
|
|
/**
|
|
* AP Actor id => Misskey User and Key
|
|
*/ async getAuthUserFromApId(uri) {
|
|
const user = await resolvePerson(uri);
|
|
if (user == null) return null;
|
|
const key = await publicKeyByUserIdCache.fetch(user.id, ()=>UserPublickeys.findOneBy({
|
|
userId: user.id
|
|
}), true, (v)=>v != null);
|
|
return {
|
|
user,
|
|
key
|
|
};
|
|
}
|
|
async refetchPublicKeyForApId(user) {
|
|
try {
|
|
await updatePerson(user.uri, undefined, undefined, user);
|
|
let key = await UserPublickeys.findOneBy({
|
|
userId: user.id
|
|
});
|
|
if (key != null) {
|
|
await publicKeyByUserIdCache.set(user.id, key);
|
|
}
|
|
return key;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
subscriber.on("message", async (_, data)=>{
|
|
const obj = JSON.parse(data);
|
|
if (obj.channel === "internal") {
|
|
const { type, body } = obj.message;
|
|
switch(type){
|
|
case "remoteUserDeleted":
|
|
case "localUserDeleted":
|
|
{
|
|
const toDelete = Array.from(await publicKeyByUserIdCache.getAll()).filter((v)=>v[1]?.userId === body.id).map((v)=>v[0]);
|
|
const toDeleteKey = Array.from(await publicKeyCache.getAll()).filter((v)=>v[1]?.userId === body.id).map((v)=>v[0]);
|
|
await publicKeyByUserIdCache.delete(...toDelete);
|
|
await publicKeyCache.delete(...toDeleteKey);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
});
|