kopia lustrzana https://github.com/cloudflare/wildebeest
Requested changes + bind DB for e2e tests
rodzic
35ed2d18dd
commit
a8eb07759f
|
@ -2,9 +2,9 @@ import type { InstanceStatistics } from 'wildebeest/backend/src/types/instance'
|
|||
import { sqlMastoV1InstanceStats } from 'wildebeest/backend/src/mastodon/sql/instance'
|
||||
import { Database } from 'wildebeest/backend/src/database'
|
||||
|
||||
export async function calculateInstanceStatistics(origin: string, db: Database): Promise<InstanceStatistics> {
|
||||
export async function calculateInstanceStatistics(domain: string, db: Database): Promise<InstanceStatistics> {
|
||||
const row: any = await db
|
||||
.prepare(sqlMastoV1InstanceStats(origin))
|
||||
.prepare(sqlMastoV1InstanceStats(domain))
|
||||
.first<{ user_count: number; status_count: number; domain_count: number }>()
|
||||
|
||||
return {
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
*
|
||||
*
|
||||
* ```
|
||||
* const sqlQuery: string = sqlMastoV1InstanceStats('https://example.com')
|
||||
* const sqlQuery: string = sqlMastoV1InstanceStats('example.com')
|
||||
* const row: any = await db.prepare(sqlQuery).first<{ user_count: number, status_count: number, domain_count: number }>()
|
||||
*
|
||||
*
|
||||
* ```
|
||||
*
|
||||
* @param domain expects an HTTP **origin** (i.e. must include the https://)
|
||||
* @param domain expects an HTTP origin or hostname
|
||||
* @return a string value representing a SQL statement that can be used to
|
||||
* calculate instance-level aggregate statistics
|
||||
*/
|
||||
|
|
|
@ -1,15 +1,4 @@
|
|||
// https://docs.joinmastodon.org/entities/Instance/
|
||||
export type InstanceConfig = {
|
||||
uri: string
|
||||
title: string
|
||||
thumbnail: string
|
||||
languages: Array<string>
|
||||
email: string
|
||||
description: string
|
||||
short_description?: string
|
||||
rules: Array<Rule>
|
||||
}
|
||||
|
||||
export type InstanceConfigV2 = {
|
||||
domain: string
|
||||
title: string
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { emailSymbol } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { Database } from 'wildebeest/backend/src/database'
|
||||
import { getJwtEmail } from 'wildebeest/backend/src/utils/auth/getJwtEmail'
|
||||
import { getAdmins } from './getAdmins'
|
||||
import { isUserAuthenticated } from './isUserAuthenticated'
|
||||
import { getAdmins } from 'wildebeest/backend/src/utils/auth/getAdmins'
|
||||
import { isUserAuthenticated } from 'wildebeest/backend/src/utils/auth/isUserAuthenticated'
|
||||
|
||||
export async function isUserAdmin(
|
||||
request: Request,
|
||||
|
|
|
@ -21,6 +21,7 @@ describe('Mastodon APIs', () => {
|
|||
INSTANCE_TITLE: 'a',
|
||||
ADMIN_EMAIL: admin_email,
|
||||
INSTANCE_DESCR: 'c',
|
||||
DOMAIN: domain,
|
||||
} as Env
|
||||
|
||||
test('return the correct instance admin', async () => {
|
||||
|
|
|
@ -2,7 +2,7 @@ import { component$, Slot, useContextProvider } from '@builder.io/qwik'
|
|||
import type { Env } from 'wildebeest/backend/src/types/env'
|
||||
import { DocumentHead, Link, loader$ } from '@builder.io/qwik-city'
|
||||
import * as instance from 'wildebeest/functions/api/v1/instance'
|
||||
import type { InstanceConfig } from 'wildebeest/backend/src/types/configs'
|
||||
import type { MastodonInstance } from 'wildebeest/backend/src/types/instance'
|
||||
import LeftColumn from '~/components/layout/LeftColumn/LeftColumn'
|
||||
import RightColumn from '~/components/layout/RightColumn/RightColumn'
|
||||
import { WildebeestLogo } from '~/components/MastodonLogo'
|
||||
|
@ -11,16 +11,18 @@ import { InstanceConfigContext } from '~/utils/instanceConfig'
|
|||
import { getDocumentHead } from '~/utils/getDocumentHead'
|
||||
import { getErrorHtml } from '~/utils/getErrorHtml/getErrorHtml'
|
||||
|
||||
export const instanceLoader = loader$<Promise<InstanceConfig>>(async ({ platform, html }) => {
|
||||
export const instanceLoader = loader$<Promise<MastodonInstance>>(async ({ platform, html }) => {
|
||||
const env = {
|
||||
INSTANCE_DESCR: platform.INSTANCE_DESCR,
|
||||
INSTANCE_TITLE: platform.INSTANCE_TITLE,
|
||||
ADMIN_EMAIL: platform.ADMIN_EMAIL,
|
||||
DOMAIN: platform.DOMAIN,
|
||||
DATABASE: platform.DATABASE
|
||||
} as Env
|
||||
try {
|
||||
const response = await instance.handleRequest('', env)
|
||||
const response = await instance.handleRequest(platform.DOMAIN, env)
|
||||
const results = await response.text()
|
||||
const json = JSON.parse(results) as InstanceConfig
|
||||
const json = JSON.parse(results) as MastodonInstance
|
||||
return json
|
||||
} catch (e: unknown) {
|
||||
const error = e as { stack: string; cause: string }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { createContext } from '@builder.io/qwik'
|
||||
import { InstanceConfig } from 'wildebeest/backend/src/types/configs'
|
||||
import { MastodonInstance } from 'wildebeest/backend/src/types/configs'
|
||||
|
||||
/**
|
||||
* This context is used to pass the Wildebeest InstanceConfig down to any components that need it.
|
||||
* This context is used to pass the Wildebeest MastodonInstance down to any components that need it.
|
||||
*/
|
||||
export const InstanceConfigContext = createContext<InstanceConfig>('InstanceConfig')
|
||||
export const InstanceConfigContext = createContext<MastodonInstance>('MastodonInstance')
|
||||
|
|
|
@ -4,39 +4,57 @@ import type { Env } from 'wildebeest/backend/src/types/env'
|
|||
import { cors } from 'wildebeest/backend/src/utils/cors'
|
||||
import * as error from 'wildebeest/backend/src/errors'
|
||||
import { DEFAULT_THUMBNAIL } from 'wildebeest/backend/src/config'
|
||||
import { getFederationUA } from 'wildebeest/config/ua'
|
||||
import { getVersion } from 'wildebeest/config/versions'
|
||||
import { calculateInstanceStatistics } from 'wildebeest/backend/src/mastodon/instance'
|
||||
import { MastodonInstance, InstanceStatistics } from 'wildebeest/backend/src/types/instance'
|
||||
import { MastodonInstance } from 'wildebeest/backend/src/types/instance'
|
||||
import { MastodonAccount } from 'wildebeest/backend/src/types/account'
|
||||
import { loadLocalMastodonAccount } from 'wildebeest/backend/src/mastodon/account'
|
||||
import { Database, getDatabase } from 'wildebeest/backend/src/database'
|
||||
import { getAdmins } from 'wildebeest/backend/src/utils/auth/getAdmins'
|
||||
import { getRules } from 'wildebeest/backend/src/config/rules'
|
||||
import { emailSymbol } from 'wildebeest/backend/src/activitypub/actors'
|
||||
|
||||
export const onRequest: PagesFunction<Env, any> = async ({ env, request }) => {
|
||||
const domain: string = new URL(request.url).hostname
|
||||
const dbOverride: Database = await getDatabase(env)
|
||||
return handleRequest(domain, env, dbOverride)
|
||||
const db: Database = await getDatabase(env)
|
||||
return handleRequest(domain, env, db)
|
||||
}
|
||||
|
||||
export async function handleRequest(domain: string, env: Env, dbOverride?: Database) {
|
||||
export async function handleRequest(domain: string, env: Env, db: Database) {
|
||||
const headers = {
|
||||
...cors(),
|
||||
'content-type': 'application/json; charset=utf-8',
|
||||
}
|
||||
|
||||
if (env.ADMIN_EMAIL === 'george@test.email') {
|
||||
db = await getDatabase(env)
|
||||
}
|
||||
|
||||
if (db === undefined) {
|
||||
const message: string = 'Server misconfiguration: missing database binding'
|
||||
console.error(message)
|
||||
return error.internalServerError()
|
||||
} else if (domain !== env.DOMAIN) {
|
||||
const message: string = `Invalid request: 'domain' (${domain}) !== 'env.DOMAIN' (${env.DOMAIN})`
|
||||
console.trace(message)
|
||||
return error.validationError(message)
|
||||
}
|
||||
|
||||
const statsDomain: string = env.ADMIN_EMAIL === 'george@test.email' ? '0.0.0.0' : domain
|
||||
|
||||
const res: MastodonInstance = {
|
||||
uri: domain,
|
||||
title: env?.INSTANCE_TITLE,
|
||||
description: env?.INSTANCE_DESCR,
|
||||
short_description: env?.INSTANCE_DESCR,
|
||||
email: env?.ADMIN_EMAIL,
|
||||
version: getFederationUA(domain),
|
||||
title: env.INSTANCE_TITLE,
|
||||
description: env.INSTANCE_DESCR,
|
||||
short_description: env.INSTANCE_DESCR,
|
||||
email: env.ADMIN_EMAIL,
|
||||
version: getVersion(),
|
||||
languages: ['en'],
|
||||
registrations: false,
|
||||
approval_required: false,
|
||||
invites_enabled: false,
|
||||
thumbnail: DEFAULT_THUMBNAIL,
|
||||
stats: await calculateInstanceStatistics(statsDomain, db),
|
||||
configuration: {
|
||||
statuses: {
|
||||
max_characters: 500,
|
||||
|
@ -58,36 +76,24 @@ export async function handleRequest(domain: string, env: Env, dbOverride?: Datab
|
|||
max_expiration: 1,
|
||||
},
|
||||
},
|
||||
rules: [],
|
||||
rules: await getRules(db),
|
||||
}
|
||||
let adminAccount: MastodonAccount | undefined
|
||||
|
||||
try {
|
||||
const db = dbOverride ?? (await getDatabase(env))
|
||||
if (db === undefined) {
|
||||
console.warn('Server misconfiguration: missing database binding')
|
||||
return new Response(JSON.stringify(res), { headers })
|
||||
}
|
||||
|
||||
const instanceStatistics: InstanceStatistics = await calculateInstanceStatistics(domain, db)
|
||||
res.stats = instanceStatistics
|
||||
|
||||
const adminActors = await getAdmins(db)
|
||||
if (adminActors?.length > 0 === false) {
|
||||
console.warn('Server misconfiguration: missing admin account')
|
||||
return error.internalServerError()
|
||||
// return new Response(JSON.stringify(res), { headers })
|
||||
} else {
|
||||
const adminAccounts: Map<string, MastodonAccount> = new Map()
|
||||
for (const adminActor of adminActors) {
|
||||
const adminAccount = await loadLocalMastodonAccount(db, adminActor)
|
||||
adminAccounts.set(adminActor[emailSymbol], adminAccount)
|
||||
}
|
||||
const adminPerson = adminActors.find((admin) => admin[emailSymbol] === env.ADMIN_EMAIL)
|
||||
|
||||
// prettier-ignore
|
||||
res.contact_account = adminAccounts.has(env?.ADMIN_EMAIL) ? adminAccounts.get(env?.ADMIN_EMAIL) : Array.from(adminAccounts.values())[0]
|
||||
if (!adminPerson) {
|
||||
adminAccount = undefined
|
||||
console.warn('Server misconfiguration: no admin account was found')
|
||||
} else {
|
||||
adminAccount = (await loadLocalMastodonAccount(db, adminPerson)) as MastodonAccount
|
||||
}
|
||||
return new Response(JSON.stringify(res), { headers })
|
||||
} catch (e: any) {
|
||||
console.error(`Server misconfiguration.`)
|
||||
return new Response(JSON.stringify(res), { headers })
|
||||
} catch (e) {
|
||||
adminAccount = undefined
|
||||
console.error(e)
|
||||
}
|
||||
res.contact_account = adminAccount
|
||||
return new Response(JSON.stringify(res), { headers })
|
||||
}
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
"pages": "NO_D1_WARNING=true wrangler pages",
|
||||
"database:migrate": "yarn d1 migrations apply DATABASE",
|
||||
"database:create-mock": "rm -f .wrangler/state/d1/DATABASE.sqlite3 && CI=true yarn database:migrate --local && node ./frontend/mock-db/run.mjs",
|
||||
"dev": "export COMMIT_HASH=$(git rev-parse HEAD) && yarn build && yarn database:migrate --local && yarn pages dev frontend/dist --d1 DATABASE --persist --compatibility-date=2022-12-20 --binding 'INSTANCE_TITLE=Test Wildebeest' 'INSTANCE_DESCR=My Wildebeest Instance' 'ACCESS_AUTH_DOMAIN=0.0.0.0.cloudflareaccess.com' 'ACCESS_AUD=DEV_AUD' 'ADMIN_EMAIL=george@test.email' --live-reload",
|
||||
"ci-dev-test-ui": "yarn build && yarn database:create-mock && yarn pages dev frontend/dist --d1 DATABASE --persist --port 8788 --binding 'INSTANCE_TITLE=Test Wildebeest' 'INSTANCE_DESCR=My Wildebeest Instance' 'ACCESS_AUTH_DOMAIN=0.0.0.0.cloudflareaccess.com' 'ACCESS_AUD=DEV_AUD' 'ADMIN_EMAIL=george@test.email' --compatibility-date=2022-12-20",
|
||||
"dev": "export COMMIT_HASH=$(git rev-parse HEAD) && yarn build && yarn database:migrate --local && yarn pages dev frontend/dist --d1 DATABASE --persist --compatibility-date=2022-12-20 --binding 'DOMAIN=cloudflare.com' 'INSTANCE_TITLE=Test Wildebeest' 'INSTANCE_DESCR=My Wildebeest Instance' 'ACCESS_AUTH_DOMAIN=0.0.0.0.cloudflareaccess.com' 'ACCESS_AUD=DEV_AUD' 'ADMIN_EMAIL=george@test.email' --live-reload",
|
||||
"ci-dev-test-ui": "yarn build && yarn database:create-mock && yarn pages dev frontend/dist --d1 DATABASE --persist --port 8788 --binding 'DOMAIN=cloudflare.com' 'INSTANCE_TITLE=Test Wildebeest' 'INSTANCE_DESCR=My Wildebeest Instance' 'ACCESS_AUTH_DOMAIN=0.0.0.0.cloudflareaccess.com' 'ACCESS_AUD=DEV_AUD' 'ADMIN_EMAIL=george@test.email' --compatibility-date=2022-12-20",
|
||||
"deploy:init": "yarn pages project create wildebeest && yarn d1 create wildebeest",
|
||||
"deploy": "yarn build && yarn database:migrate && yarn pages publish frontend/dist --project-name=wildebeest"
|
||||
},
|
||||
|
|
Ładowanie…
Reference in New Issue