kopia lustrzana https://github.com/cloudflare/wildebeest
getAndCache Actor of any types
Closes https://github.com/cloudflare/wildebeest/issues/178pull/179/head
rodzic
a122cb99af
commit
646b83cf93
|
@ -188,7 +188,7 @@ export async function handle(
|
|||
continue
|
||||
}
|
||||
|
||||
const person = await actors.getPersonById(db, actorURL(domain, handle.localPart))
|
||||
const person = await actors.getActorById(db, actorURL(domain, handle.localPart))
|
||||
if (person === null) {
|
||||
console.warn(`person ${recipients[i]} not found`)
|
||||
continue
|
||||
|
@ -210,7 +210,7 @@ export async function handle(
|
|||
requireComplexObject()
|
||||
const actorId = getActorAsId()
|
||||
|
||||
const actor = await actors.getPersonById(db, activity.object.actor)
|
||||
const actor = await actors.getActorById(db, activity.object.actor)
|
||||
if (actor !== null) {
|
||||
const follower = await actors.getAndCache(new URL(actorId), db)
|
||||
await acceptFollowing(db, actor, follower)
|
||||
|
@ -226,7 +226,7 @@ export async function handle(
|
|||
const objectId = getObjectAsId()
|
||||
const actorId = getActorAsId()
|
||||
|
||||
const receiver = await actors.getPersonById(db, objectId)
|
||||
const receiver = await actors.getActorById(db, objectId)
|
||||
if (receiver !== null) {
|
||||
const originalActor = await actors.getAndCache(new URL(actorId), db)
|
||||
const receiverAcct = `${receiver.preferredUsername}@${domain}`
|
||||
|
@ -279,7 +279,7 @@ export async function handle(
|
|||
const fromActor = await actors.getAndCache(actorId, db)
|
||||
|
||||
// notify the user
|
||||
const targetActor = await actors.getPersonById(db, new URL(obj[originalActorIdSymbol]))
|
||||
const targetActor = await actors.getActorById(db, new URL(obj[originalActorIdSymbol]))
|
||||
if (targetActor === null) {
|
||||
console.warn('object actor not found')
|
||||
break
|
||||
|
@ -307,7 +307,7 @@ export async function handle(
|
|||
}
|
||||
|
||||
const fromActor = await actors.getAndCache(actorId, db)
|
||||
const targetActor = await actors.getPersonById(db, new URL(obj[originalActorIdSymbol]))
|
||||
const targetActor = await actors.getActorById(db, new URL(obj[originalActorIdSymbol]))
|
||||
if (targetActor === null) {
|
||||
console.warn('object actor not found')
|
||||
break
|
||||
|
|
|
@ -88,10 +88,13 @@ export async function get(url: string | URL): Promise<Actor> {
|
|||
return actor
|
||||
}
|
||||
|
||||
// Get and cache the Actor locally
|
||||
export async function getAndCache(url: URL, db: D1Database): Promise<Actor> {
|
||||
const person = await getPersonById(db, url)
|
||||
if (person !== null) {
|
||||
return person
|
||||
{
|
||||
const actor = await getActorById(db, url)
|
||||
if (actor !== null) {
|
||||
return actor
|
||||
}
|
||||
}
|
||||
|
||||
const actor = await get(url)
|
||||
|
@ -197,8 +200,8 @@ export async function updateActorProperty(db: D1Database, actorId: URL, key: str
|
|||
}
|
||||
}
|
||||
|
||||
export async function getPersonById(db: D1Database, id: URL): Promise<Person | null> {
|
||||
const stmt = db.prepare('SELECT * FROM actors WHERE id=? AND type=?').bind(id.toString(), PERSON)
|
||||
export async function getActorById(db: D1Database, id: URL): Promise<Actor | null> {
|
||||
const stmt = db.prepare('SELECT * FROM actors WHERE id=?').bind(id.toString())
|
||||
const { results } = await stmt.all()
|
||||
if (!results || results.length === 0) {
|
||||
return null
|
||||
|
|
|
@ -9,6 +9,7 @@ export const mastodonIdSymbol = Symbol()
|
|||
export interface APObject {
|
||||
type: string
|
||||
// ObjectId, URL used for federation. Called `uri` in Mastodon APIs.
|
||||
// https://www.w3.org/TR/activitypub/#obj-id
|
||||
id: URL
|
||||
// Link to the HTML representation of the object
|
||||
url: URL
|
||||
|
|
|
@ -4,7 +4,7 @@ import * as actors from 'wildebeest/backend/src/activitypub/actors'
|
|||
import { urlToHandle } from 'wildebeest/backend/src/utils/handle'
|
||||
import { loadExternalMastodonAccount } from 'wildebeest/backend/src/mastodon/account'
|
||||
import { generateWebPushMessage } from 'wildebeest/backend/src/webpush'
|
||||
import { getPersonById } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { getActorById } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import type { WebPushInfos, WebPushMessage } from 'wildebeest/backend/src/webpush/webpushinfos'
|
||||
import { WebPushResult } from 'wildebeest/backend/src/webpush/webpushinfos'
|
||||
import type { Actor } from 'wildebeest/backend/src/activitypub/actors'
|
||||
|
@ -206,7 +206,7 @@ export async function getNotifications(db: D1Database, actor: Actor, domain: str
|
|||
const properties = JSON.parse(result.properties)
|
||||
const notifFromActorId = new URL(result.notif_from_actor_id)
|
||||
|
||||
const notifFromActor = await getPersonById(db, notifFromActorId)
|
||||
const notifFromActor = await getActorById(db, notifFromActorId)
|
||||
if (!notifFromActor) {
|
||||
console.warn('unknown actor')
|
||||
continue
|
||||
|
|
|
@ -159,6 +159,56 @@ describe('ActivityPub', () => {
|
|||
assert.equal(results.length, 1)
|
||||
assert.equal(results[0].domain, 'example.com')
|
||||
})
|
||||
|
||||
test('getAndCache supports any Actor types', async () => {
|
||||
// While Actor ObjectID MUST be globally unique, the Object can
|
||||
// change type and Mastodon uses this behavior as a feature.
|
||||
// We need to make sure our caching works with Actor that change
|
||||
// types.
|
||||
|
||||
const actorId = new URL('https://example.com/user/foo')
|
||||
|
||||
globalThis.fetch = async (input: RequestInfo) => {
|
||||
if (input.toString() === actorId.toString()) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
id: actorId,
|
||||
type: 'Service',
|
||||
preferredUsername: 'sven',
|
||||
name: 'sven ssss',
|
||||
|
||||
icon: { url: 'icon.jpg' },
|
||||
image: { url: 'image.jpg' },
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
if (input.toString() === actorId.toString()) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
id: actorId,
|
||||
type: 'Person',
|
||||
preferredUsername: 'sven',
|
||||
name: 'sven ssss',
|
||||
|
||||
icon: { url: 'icon.jpg' },
|
||||
image: { url: 'image.jpg' },
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
throw new Error(`unexpected request to "${input}"`)
|
||||
}
|
||||
|
||||
const db = await makeDB()
|
||||
|
||||
await actors.getAndCache(actorId, db)
|
||||
|
||||
const { results } = (await db.prepare('SELECT * FROM actors').all()) as any
|
||||
assert.equal(results.length, 1)
|
||||
assert.equal(results[0].id, actorId.toString())
|
||||
assert.equal(results[0].type, 'Service')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Objects', () => {
|
||||
|
|
|
@ -15,7 +15,7 @@ import * as accounts_get from 'wildebeest/functions/api/v1/accounts/[id]'
|
|||
import { isUUID, isUrlValid, makeDB, assertCORS, assertJSON, makeQueue } from '../utils'
|
||||
import * as accounts_verify_creds from 'wildebeest/functions/api/v1/accounts/verify_credentials'
|
||||
import * as accounts_update_creds from 'wildebeest/functions/api/v1/accounts/update_credentials'
|
||||
import { createPerson, getPersonById } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { createPerson, getActorById } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { addFollowing, acceptFollowing } from 'wildebeest/backend/src/mastodon/follow'
|
||||
import { insertLike } from 'wildebeest/backend/src/mastodon/like'
|
||||
import { insertReblog } from 'wildebeest/backend/src/mastodon/reblog'
|
||||
|
@ -125,7 +125,7 @@ describe('Mastodon APIs', () => {
|
|||
assert.equal(data.display_name, 'newsven')
|
||||
assert.equal(data.note, 'hein')
|
||||
|
||||
const updatedActor: any = await getPersonById(db, connectedActor.id)
|
||||
const updatedActor: any = await getActorById(db, connectedActor.id)
|
||||
assert(updatedActor)
|
||||
assert.equal(updatedActor.name, 'newsven')
|
||||
assert.equal(updatedActor.summary, 'hein')
|
||||
|
|
|
@ -18,7 +18,7 @@ export type Env = {
|
|||
export default {
|
||||
async queue(batch: MessageBatch<MessageBody>, env: Env, ctx: ExecutionContext) {
|
||||
for (const message of batch.messages) {
|
||||
const actor = await actors.getPersonById(env.DATABASE, new URL(message.body.actorId))
|
||||
const actor = await actors.getActorById(env.DATABASE, new URL(message.body.actorId))
|
||||
if (actor === null) {
|
||||
console.warn(`actor ${message.body.actorId} is missing`)
|
||||
return
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// https://www.rfc-editor.org/rfc/rfc7033
|
||||
|
||||
import { parseHandle } from '../../backend/src/utils/parse'
|
||||
import { getPersonById, actorURL } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { getActorById, actorURL } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import type { Env } from '../../backend/src/types/env'
|
||||
import type { WebFingerResponse } from '../../backend/src/webfinger'
|
||||
|
||||
|
@ -36,12 +36,12 @@ export async function handleRequest(request: Request, db: D1Database): Promise<R
|
|||
return new Response('', { status: 403 })
|
||||
}
|
||||
|
||||
const person = await getPersonById(db, actorURL(domain, handle.localPart))
|
||||
if (person === null) {
|
||||
const actor = await getActorById(db, actorURL(domain, handle.localPart))
|
||||
if (actor === null) {
|
||||
return new Response('', { status: 404 })
|
||||
}
|
||||
|
||||
const jsonLink = person.id.toString()
|
||||
const jsonLink = actor.id.toString()
|
||||
|
||||
const res: WebFingerResponse = {
|
||||
subject: `acct:${handle.localPart}@${handle.domain}`,
|
||||
|
|
|
@ -22,7 +22,7 @@ export async function handleRequest(domain: string, db: D1Database, id: string):
|
|||
return new Response('', { status: 403 })
|
||||
}
|
||||
|
||||
const person = await actors.getPersonById(db, actorURL(domain, handle.localPart))
|
||||
const person = await actors.getActorById(db, actorURL(domain, handle.localPart))
|
||||
if (person === null) {
|
||||
return new Response('', { status: 404 })
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ export async function handleRequest(domain: string, db: D1Database, id: string):
|
|||
}
|
||||
|
||||
const actorId = actorURL(domain, handle.localPart)
|
||||
const actor = await actors.getPersonById(db, actorId)
|
||||
const actor = await actors.getActorById(db, actorId)
|
||||
if (actor === null) {
|
||||
return new Response('', { status: 404 })
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { parseHandle } from 'wildebeest/backend/src/utils/parse'
|
||||
import { getFollowers } from 'wildebeest/backend/src/mastodon/follow'
|
||||
import { getPersonById } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { getActorById } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { actorURL } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import type { ContextData } from 'wildebeest/backend/src/types/context'
|
||||
import type { Env } from 'wildebeest/backend/src/types/env'
|
||||
|
@ -22,7 +22,7 @@ export async function handleRequest(domain: string, db: D1Database, id: string):
|
|||
}
|
||||
|
||||
const actorId = actorURL(domain, handle.localPart)
|
||||
const actor = await getPersonById(db, actorId)
|
||||
const actor = await getActorById(db, actorId)
|
||||
if (actor === null) {
|
||||
return new Response('', { status: 404 })
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ export async function handleRequest(domain: string, db: D1Database, id: string):
|
|||
}
|
||||
|
||||
const actorId = actorURL(domain, handle.localPart)
|
||||
const actor = await actors.getPersonById(db, actorId)
|
||||
const actor = await actors.getActorById(db, actorId)
|
||||
if (actor === null) {
|
||||
return new Response('', { status: 404 })
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { parseHandle } from 'wildebeest/backend/src/utils/parse'
|
||||
import { getFollowingId } from 'wildebeest/backend/src/mastodon/follow'
|
||||
import { getPersonById } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { getActorById } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { actorURL } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import type { ContextData } from 'wildebeest/backend/src/types/context'
|
||||
import type { Env } from 'wildebeest/backend/src/types/env'
|
||||
|
@ -22,7 +22,7 @@ export async function handleRequest(domain: string, db: D1Database, id: string):
|
|||
}
|
||||
|
||||
const actorId = actorURL(domain, handle.localPart)
|
||||
const actor = await getPersonById(db, actorId)
|
||||
const actor = await getActorById(db, actorId)
|
||||
if (actor === null) {
|
||||
return new Response('', { status: 404 })
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ export async function handleRequest(
|
|||
}
|
||||
const actorId = actorURL(domain, handle.localPart)
|
||||
|
||||
const actor = await actors.getPersonById(db, actorId)
|
||||
const actor = await actors.getActorById(db, actorId)
|
||||
if (actor === null) {
|
||||
return new Response('', { status: 404 })
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { parseHandle } from 'wildebeest/backend/src/utils/parse'
|
||||
import { getPersonById } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { getActorById } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { actorURL } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import type { ContextData } from 'wildebeest/backend/src/types/context'
|
||||
import type { Env } from 'wildebeest/backend/src/types/env'
|
||||
|
@ -22,7 +22,7 @@ export async function handleRequest(domain: string, db: D1Database, id: string,
|
|||
}
|
||||
|
||||
const actorId = actorURL(domain, handle.localPart)
|
||||
const actor = await getPersonById(db, actorId)
|
||||
const actor = await getActorById(db, actorId)
|
||||
if (actor === null) {
|
||||
return new Response('', { status: 404 })
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { parseHandle } from 'wildebeest/backend/src/utils/parse'
|
|||
import { cors } from 'wildebeest/backend/src/utils/cors'
|
||||
import * as objects from 'wildebeest/backend/src/activitypub/objects'
|
||||
import type { Activity } from 'wildebeest/backend/src/activitypub/activities'
|
||||
import { getPersonById } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { getActorById } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { actorURL } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import type { ContextData } from 'wildebeest/backend/src/types/context'
|
||||
import type { Env } from 'wildebeest/backend/src/types/env'
|
||||
|
@ -30,7 +30,7 @@ export async function handleRequest(domain: string, db: D1Database, id: string):
|
|||
}
|
||||
|
||||
const actorId = actorURL(domain, handle.localPart)
|
||||
const actor = await getPersonById(db, actorId)
|
||||
const actor = await getActorById(db, actorId)
|
||||
if (actor === null) {
|
||||
return new Response('', { status: 404 })
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { cors } from 'wildebeest/backend/src/utils/cors'
|
||||
import { actorURL } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { getPersonById } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { getActorById } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import type { ContextData } from 'wildebeest/backend/src/types/context'
|
||||
import type { Env } from 'wildebeest/backend/src/types/env'
|
||||
import { parseHandle } from 'wildebeest/backend/src/utils/parse'
|
||||
|
@ -51,7 +51,7 @@ async function getRemoteAccount(handle: Handle, acct: string): Promise<Response>
|
|||
async function getLocalAccount(domain: string, db: D1Database, handle: Handle): Promise<Response> {
|
||||
const actorId = actorURL(domain, handle.localPart)
|
||||
|
||||
const actor = await getPersonById(db, actorId)
|
||||
const actor = await getActorById(db, actorId)
|
||||
if (actor === null) {
|
||||
return new Response('', { status: 404 })
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ export async function handleRequest(
|
|||
|
||||
// reload the current user and sent back updated infos
|
||||
{
|
||||
const actor = await actors.getPersonById(db, connectedActor.id)
|
||||
const actor = await actors.getActorById(db, connectedActor.id)
|
||||
if (actor === null) {
|
||||
return errors.notAuthorized('user not found')
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import type { Notification, NotificationsQueryResult } from 'wildebeest/backend/src/types/notification'
|
||||
import { urlToHandle } from 'wildebeest/backend/src/utils/handle'
|
||||
import { getPersonById } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { getActorById } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { loadExternalMastodonAccount } from 'wildebeest/backend/src/mastodon/account'
|
||||
import type { Person } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import type { Env } from 'wildebeest/backend/src/types/env'
|
||||
|
@ -39,7 +39,7 @@ export async function handleRequest(
|
|||
const row = await db.prepare(query).bind(id, connectedActor.id.toString()).first<NotificationsQueryResult>()
|
||||
|
||||
const from_actor_id = new URL(row.from_actor_id)
|
||||
const fromActor = await getPersonById(db, from_actor_id)
|
||||
const fromActor = await getActorById(db, from_actor_id)
|
||||
if (!fromActor) {
|
||||
throw new Error('unknown from actor')
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue