1c67c26bd8
* wip * wip * wip * Update following.ts * wip * wip * wip * Update resolve-user.ts * maxQueryExecutionTime * wip * wip
151 lines
3.5 KiB
TypeScript
151 lines
3.5 KiB
TypeScript
import escapeRegexp from 'escape-regexp';
|
|
import config from '@/config/index.js';
|
|
import { Note } from '@/models/entities/note.js';
|
|
import { User, IRemoteUser, CacheableRemoteUser } from '@/models/entities/user.js';
|
|
import { UserPublickey } from '@/models/entities/user-publickey.js';
|
|
import { MessagingMessage } from '@/models/entities/messaging-message.js';
|
|
import { Notes, Users, UserPublickeys, MessagingMessages } from '@/models/index.js';
|
|
import { IObject, getApId } from './type.js';
|
|
import { resolvePerson } from './models/person.js';
|
|
import { Cache } from '@/misc/cache.js';
|
|
import { userByIdCache } from '@/services/user-cache.js';
|
|
|
|
const publicKeyCache = new Cache<UserPublickey | null>(Infinity);
|
|
const publicKeyByUserIdCache = new Cache<UserPublickey | null>(Infinity);
|
|
|
|
export default class DbResolver {
|
|
constructor() {
|
|
}
|
|
|
|
/**
|
|
* AP Note => Misskey Note in DB
|
|
*/
|
|
public async getNoteFromApId(value: string | IObject): Promise<Note | null> {
|
|
const parsed = this.parseUri(value);
|
|
|
|
if (parsed.id) {
|
|
return (await Notes.findOneBy({
|
|
id: parsed.id,
|
|
})) || null;
|
|
}
|
|
|
|
if (parsed.uri) {
|
|
return (await Notes.findOneBy({
|
|
uri: parsed.uri,
|
|
})) || null;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public async getMessageFromApId(value: string | IObject): Promise<MessagingMessage | null> {
|
|
const parsed = this.parseUri(value);
|
|
|
|
if (parsed.id) {
|
|
return (await MessagingMessages.findOneBy({
|
|
id: parsed.id,
|
|
})) || null;
|
|
}
|
|
|
|
if (parsed.uri) {
|
|
return (await MessagingMessages.findOneBy({
|
|
uri: parsed.uri,
|
|
})) || null;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* AP Person => Misskey User in DB
|
|
*/
|
|
public async getUserFromApId(value: string | IObject): Promise<User | null> {
|
|
const parsed = this.parseUri(value);
|
|
|
|
if (parsed.id) {
|
|
return (await Users.findOneBy({
|
|
id: parsed.id,
|
|
})) || null;
|
|
}
|
|
|
|
if (parsed.uri) {
|
|
return (await Users.findOneBy({
|
|
uri: parsed.uri,
|
|
})) || null;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* AP KeyId => Misskey User and Key
|
|
*/
|
|
public async getAuthUserFromKeyId(keyId: string): Promise<{
|
|
user: CacheableRemoteUser;
|
|
key: UserPublickey;
|
|
} | null> {
|
|
const key = await publicKeyCache.fetch(keyId, async () => {
|
|
const key = await UserPublickeys.findOneBy({
|
|
keyId,
|
|
});
|
|
|
|
if (key == null) return null;
|
|
|
|
return key;
|
|
}, key => key != null);
|
|
|
|
if (key == null) return null;
|
|
|
|
return {
|
|
user: await userByIdCache.fetch(key.userId, () => Users.findOneByOrFail({ id: key.userId })) as CacheableRemoteUser,
|
|
key,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* AP Actor id => Misskey User and Key
|
|
*/
|
|
public async getAuthUserFromApId(uri: string): Promise<{
|
|
user: CacheableRemoteUser;
|
|
key: UserPublickey | null;
|
|
} | null> {
|
|
const user = await resolvePerson(uri) as CacheableRemoteUser;
|
|
|
|
if (user == null) return null;
|
|
|
|
const key = await publicKeyByUserIdCache.fetch(user.id, () => UserPublickeys.findOneBy({ userId: user.id }), v => v != null);
|
|
|
|
return {
|
|
user,
|
|
key,
|
|
};
|
|
}
|
|
|
|
public parseUri(value: string | IObject): UriParseResult {
|
|
const uri = getApId(value);
|
|
|
|
const localRegex = new RegExp('^' + escapeRegexp(config.url) + '/' + '(\\w+)' + '/' + '(\\w+)');
|
|
const matchLocal = uri.match(localRegex);
|
|
|
|
if (matchLocal) {
|
|
return {
|
|
type: matchLocal[1],
|
|
id: matchLocal[2],
|
|
};
|
|
} else {
|
|
return {
|
|
uri,
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
type UriParseResult = {
|
|
/** id in DB (local object only) */
|
|
id?: string;
|
|
/** uri in DB (remote object only) */
|
|
uri?: string;
|
|
/** hint of type (local object only, ex: notes, users) */
|
|
type?: string
|
|
};
|