Some progress towards accepting and rejecting follows #3
15 changed files with 315 additions and 133 deletions
18
.vscode/launch.json
vendored
18
.vscode/launch.json
vendored
|
@ -6,9 +6,9 @@
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Dev Server",
|
"name": "Reinitialize database",
|
||||||
"type": "node",
|
"type": "node",
|
||||||
"program": "${workspaceFolder}/main.ts",
|
"program": "${workspaceFolder}/src/entry/dbInit.ts",
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"envFile": "${workspaceFolder}/local.env",
|
"envFile": "${workspaceFolder}/local.env",
|
||||||
"runtimeExecutable": "/usr/bin/deno",
|
"runtimeExecutable": "/usr/bin/deno",
|
||||||
|
@ -17,28 +17,26 @@
|
||||||
"--watch",
|
"--watch",
|
||||||
"--no-prompt",
|
"--no-prompt",
|
||||||
"--allow-all",
|
"--allow-all",
|
||||||
"--inspect-wait",
|
"--inspect-wait"
|
||||||
"src/main.ts"
|
|
||||||
],
|
],
|
||||||
"attachSimplePort": 9229
|
"attachSimplePort": 9229
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Init database",
|
"name": "Dev Server",
|
||||||
"type": "node",
|
"type": "node",
|
||||||
"program": "${workspaceFolder}/main.ts",
|
"program": "${workspaceFolder}/src/entry/server.ts",
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"envFile": "${workspaceFolder}/local.env",
|
"envFile": "${workspaceFolder}/local.env",
|
||||||
"runtimeExecutable": "/usr/bin/deno",
|
"runtimeExecutable": "/usr/bin/deno",
|
||||||
"runtimeArgs": [
|
"runtimeArgs": [
|
||||||
"run",
|
"run",
|
||||||
|
"--watch",
|
||||||
"--no-prompt",
|
"--no-prompt",
|
||||||
"--allow-all",
|
"--allow-all",
|
||||||
"--inspect-wait",
|
"--inspect-wait"
|
||||||
"src/database/init/index.ts"
|
|
||||||
],
|
],
|
||||||
"attachSimplePort": 9229
|
"attachSimplePort": 9229
|
||||||
},
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
176
src/database/index.ts
Normal file
176
src/database/index.ts
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
import Postgres from "@@npm/postgres"
|
||||||
|
import { getLogger } from "@logtape/logtape"
|
||||||
|
import { exportJwk, generateCryptoKeyPair, KvStore } from "@fedify/fedify"
|
||||||
|
import { PostgresKvStore } from "@fedify/postgres/kv"
|
||||||
|
|
||||||
|
|
||||||
|
const l = getLogger(["dotino-veloce", "database", "postgres"])
|
||||||
|
|
||||||
|
|
||||||
|
export type DbActor = {
|
||||||
|
handle: string,
|
||||||
|
public_rsa: JsonWebKey,
|
||||||
|
public_ed: JsonWebKey,
|
||||||
|
private_rsa: JsonWebKey,
|
||||||
|
private_ed: JsonWebKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DbActorService = DbActor
|
||||||
|
|
||||||
|
export type DbActorPlayer = DbActor & {
|
||||||
|
steam_id: bigint,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DbActorGuild = DbActor & {
|
||||||
|
guild_id: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class Database {
|
||||||
|
sql: Postgres.Sql
|
||||||
|
|
||||||
|
constructor(connString: string) {
|
||||||
|
l.info`Creating Postgres object with string: ${connString}`
|
||||||
|
this.sql = Postgres(connString)
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromEnv() {
|
||||||
|
l.debug`Getting connection string from environment variable DOTINO_POSTGRES_STRING...`
|
||||||
|
const connString = Deno.env.get("DOTINO_POSTGRES_STRING")
|
||||||
|
if(!connString) {
|
||||||
|
l.error`DOTINO_POSTGRES_STRING is unset.`
|
||||||
|
throw new Error("DOTINO_POSTGRES_STRING is unset.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Database(connString)
|
||||||
|
}
|
||||||
|
|
||||||
|
useAsKvStore(): KvStore {
|
||||||
|
l.info`Creating Postgres key-value store...`
|
||||||
|
return new PostgresKvStore(this.sql, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
async #doQueryFile<T>(path: string, variables: Postgres.ParameterOrJSON<any>[] = []): Promise<Postgres.RowList<T[]>> {
|
||||||
|
try {
|
||||||
|
l.debug`Running query at ${path}...`
|
||||||
|
var results = await this.sql.file<T[]>(path, variables, undefined)
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
l.error`Query at ${path} errored out with: ${e}`
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
l.debug`Query was successful, results are: ${results}`
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
async reinitializeDev() {
|
||||||
|
l.warn`Re-initializing database from scratch for development!!!`
|
||||||
|
|
||||||
|
l.info`01/XX Dropping public schema from database...`
|
||||||
|
await this.#doQueryFile("src/database/init/01-drop-schema.sql")
|
||||||
|
|
||||||
|
l.info`02/XX Recreating public schema...`
|
||||||
|
await this.#doQueryFile("src/database/init/02-create-schema.sql")
|
||||||
|
|
||||||
|
l.info`03/XX Creating applied migrations table...`
|
||||||
|
await this.#doQueryFile("src/database/init/03-create-migration_applied.sql")
|
||||||
|
|
||||||
|
l.info`04/XX Creating actor table...`
|
||||||
|
await this.#doQueryFile("src/database/init/04-create-actor.sql")
|
||||||
|
|
||||||
|
l.info`05/XX Creating service table...`
|
||||||
|
await this.#doQueryFile("src/database/init/05-create-actor_service.sql")
|
||||||
|
|
||||||
|
l.info`06/XX Creating player table...`
|
||||||
|
await this.#doQueryFile("src/database/init/06-create-actor_player.sql")
|
||||||
|
|
||||||
|
l.info`07/XX Creating guild table...`
|
||||||
|
await this.#doQueryFile("src/database/init/07-create-actor_guild.sql")
|
||||||
|
|
||||||
|
l.info`08/XX Creating service actor...`
|
||||||
|
l.debug`Creating RSA key pair...`
|
||||||
|
const {publicKey: publicRsa, privateKey: privateRsa} = await generateCryptoKeyPair("RSASSA-PKCS1-v1_5")
|
||||||
|
l.debug`Creating elliptic curve key pair...`
|
||||||
|
const {publicKey: publicEd, privateKey: privateEd} = await generateCryptoKeyPair("Ed25519")
|
||||||
|
l.debug`Exporting to JWK format...`
|
||||||
|
const publicRsaJwk = await exportJwk(publicRsa)
|
||||||
|
const publicEdJwk = await exportJwk(publicEd)
|
||||||
|
const privateRsaJwk = await exportJwk(privateRsa)
|
||||||
|
const privateEdJwk = await exportJwk(privateEd)
|
||||||
|
l.debug`Running SQL query...`
|
||||||
|
await this.#doQueryFile<DbActorService>(
|
||||||
|
"src/database/init/08-insert-actor_service.sql",
|
||||||
|
[
|
||||||
|
publicRsaJwk,
|
||||||
|
publicEdJwk,
|
||||||
|
privateRsaJwk,
|
||||||
|
privateEdJwk,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
l.info("Done!")
|
||||||
|
}
|
||||||
|
|
||||||
|
async getActorService(): Promise<DbActorService> {
|
||||||
|
l.info`Getting service actor entity...`
|
||||||
|
|
||||||
|
const results = await this.#doQueryFile<DbActorService>("src/database/query/get-actor_service.sql")
|
||||||
|
|
||||||
|
if(results.count == 0) {
|
||||||
|
l.error`No service actor entity exists.`
|
||||||
|
throw new Error("No service actor entity exists.")
|
||||||
|
}
|
||||||
|
else if(results.count > 1) {
|
||||||
|
l.error`Multiple service actor entities exist.`
|
||||||
|
throw new Error("Multiple service actor entities exist.")
|
||||||
|
}
|
||||||
|
|
||||||
|
l.debug`Attempting to get only result...`
|
||||||
|
const result = results[0]
|
||||||
|
l.debug`Filtered down to result: ${result}`
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
async getActorPlayer(steamId: number): Promise<DbActorPlayer | null> {
|
||||||
|
l.info`Getting player actor entity with id: ${steamId}`
|
||||||
|
|
||||||
|
const results = await this.#doQueryFile<DbActorPlayer>("src/database/query/get-actor_player.sql", [steamId])
|
||||||
|
|
||||||
|
if(results.count == 0) {
|
||||||
|
l.debug`No such player actor entity exists.`
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
else if(results.count > 1) {
|
||||||
|
l.error`Multiple player actor entities having the same SteamID exist.`
|
||||||
|
throw new Error("Multiple player actor entities having the same SteamID exist.")
|
||||||
|
}
|
||||||
|
|
||||||
|
l.debug`Attempting to get only result...`
|
||||||
|
const result = results[0]
|
||||||
|
l.debug`Filtered down to result: ${result}`
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
async getActorGuild(guildId: number): Promise<DbActorGuild | null> {
|
||||||
|
l.info`Getting guild actor entity with id: ${guildId}`
|
||||||
|
|
||||||
|
const results = await this.#doQueryFile<DbActorGuild>("src/database/query/get-actor_guild.sql", [guildId])
|
||||||
|
|
||||||
|
if(results.count == 0) {
|
||||||
|
l.debug`No such guild actor entity exists.`
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
else if(results.count > 1) {
|
||||||
|
l.error`Multiple guild actor entities having the same Guild ID exist.`
|
||||||
|
throw new Error("Multiple guild actor entities having the same Guild ID exist.")
|
||||||
|
}
|
||||||
|
|
||||||
|
l.debug`Attempting to get only result...`
|
||||||
|
const result = results[0]
|
||||||
|
l.debug`Filtered down to result: ${result}`
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,3 @@
|
||||||
CREATE TABLE actor (
|
CREATE TABLE actor (
|
||||||
handle VARCHAR PRIMARY KEY,
|
handle VARCHAR PRIMARY KEY
|
||||||
|
|
||||||
public_rsassa BYTEA NOT NULL,
|
|
||||||
private_rsassa BYTEA NOT NULL,
|
|
||||||
|
|
||||||
public_jwk BYTEA NOT NULL,
|
|
||||||
private_jwk BYTEA NOT NULL
|
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
CREATE TABLE actor_service (
|
CREATE TABLE actor_service (
|
||||||
service_id SERIAL UNIQUE NOT NULL
|
public_rsa JSON NOT NULL,
|
||||||
|
public_ed JSON NOT NULL,
|
||||||
|
private_rsa JSON NOT NULL,
|
||||||
|
private_ed JSON NOT NULL
|
||||||
) INHERITS (
|
) INHERITS (
|
||||||
actor
|
actor
|
||||||
);
|
);
|
||||||
|
|
13
src/database/init/08-insert-actor_service.sql
Normal file
13
src/database/init/08-insert-actor_service.sql
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
INSERT INTO actor_service (
|
||||||
|
handle,
|
||||||
|
public_rsa,
|
||||||
|
public_ed,
|
||||||
|
private_rsa,
|
||||||
|
private_ed
|
||||||
|
) VALUES (
|
||||||
|
'service',
|
||||||
|
$1,
|
||||||
|
$2,
|
||||||
|
$3,
|
||||||
|
$4
|
||||||
|
);
|
|
@ -1,41 +0,0 @@
|
||||||
import { getLogger } from "https://jsr.io/@logtape/logtape/0.6.3/logtape/logger.ts"
|
|
||||||
import { createPostgresFromEnv } from "../postgres.ts"
|
|
||||||
import { initLogging } from "../../deno/logging.ts"
|
|
||||||
|
|
||||||
|
|
||||||
const l = getLogger(["dotino-veloce", "database", "init"])
|
|
||||||
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
await initLogging()
|
|
||||||
|
|
||||||
l.debug`Creating Postgres instance...`
|
|
||||||
const postgres = createPostgresFromEnv()
|
|
||||||
|
|
||||||
l.info`01/XX Dropping public schema from database...`
|
|
||||||
await postgres.file("src/database/init/01-drop-schema.sql")
|
|
||||||
|
|
||||||
l.info`02/XX Recreating public schema...`
|
|
||||||
await postgres.file("src/database/init/02-create-schema.sql")
|
|
||||||
|
|
||||||
l.info`03/XX Creating applied migrations table...`
|
|
||||||
await postgres.file("src/database/init/03-create-migration_applied.sql")
|
|
||||||
|
|
||||||
l.info`04/XX Creating actor table...`
|
|
||||||
await postgres.file("src/database/init/04-create-actor.sql")
|
|
||||||
|
|
||||||
l.info`05/XX Creating service table...`
|
|
||||||
await postgres.file("src/database/init/05-create-actor_service.sql")
|
|
||||||
|
|
||||||
l.info`06/XX Creating player table...`
|
|
||||||
await postgres.file("src/database/init/06-create-actor_player.sql")
|
|
||||||
|
|
||||||
l.info`07/XX Creating guild table...`
|
|
||||||
await postgres.file("src/database/init/07-create-actor_guild.sql")
|
|
||||||
|
|
||||||
l.info("Done!")
|
|
||||||
Deno.exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
await main()
|
|
|
@ -1,12 +0,0 @@
|
||||||
import { PostgresKvStore } from "@fedify/postgres/kv"
|
|
||||||
import { getLogger } from "@logtape/logtape"
|
|
||||||
import Postgres from "@@npm/postgres"
|
|
||||||
|
|
||||||
|
|
||||||
const l = getLogger(["dotino-veloce", "database", "kv"])
|
|
||||||
|
|
||||||
|
|
||||||
export function createPostgresKvStore(postgres: Postgres.Sql): PostgresKvStore {
|
|
||||||
l.info`Creating Postgres key-value store...`
|
|
||||||
return new PostgresKvStore(postgres, {})
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
import Postgres from "@@npm/postgres"
|
|
||||||
import { getLogger } from "@logtape/logtape"
|
|
||||||
|
|
||||||
|
|
||||||
const l = getLogger(["dotino-veloce", "database", "postgres"])
|
|
||||||
|
|
||||||
|
|
||||||
export function createPostgres(connString: string): Postgres.Sql {
|
|
||||||
l.info`Creating Postgres object with string: ${connString}`
|
|
||||||
return Postgres(connString)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createPostgresFromEnv(): Postgres.Sql {
|
|
||||||
l.debug`Getting connection string from environment variable DOTINO_POSTGRES_STRING...`
|
|
||||||
const connString = Deno.env.get("DOTINO_POSTGRES_STRING")
|
|
||||||
if(!connString) {
|
|
||||||
l.error`DOTINO_POSTGRES_STRING is unset.`
|
|
||||||
throw new Error("DOTINO_POSTGRES_STRING is unset.")
|
|
||||||
}
|
|
||||||
|
|
||||||
return createPostgres(connString)
|
|
||||||
}
|
|
12
src/database/query/get-actor_guild.sql
Normal file
12
src/database/query/get-actor_guild.sql
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
SELECT
|
||||||
|
actor_guild.handle,
|
||||||
|
actor_guild.guild_id,
|
||||||
|
actor_service.public_rsa,
|
||||||
|
actor_service.public_ed,
|
||||||
|
actor_service.private_rsa,
|
||||||
|
actor_service.private_ed
|
||||||
|
FROM
|
||||||
|
actor_guild,
|
||||||
|
actor_service
|
||||||
|
WHERE
|
||||||
|
actor_guild.steam_id = $1;
|
12
src/database/query/get-actor_player.sql
Normal file
12
src/database/query/get-actor_player.sql
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
SELECT
|
||||||
|
actor_player.handle,
|
||||||
|
actor_player.steam_id,
|
||||||
|
actor_service.public_rsa,
|
||||||
|
actor_service.public_ed,
|
||||||
|
actor_service.private_rsa,
|
||||||
|
actor_service.private_ed
|
||||||
|
FROM
|
||||||
|
actor_player,
|
||||||
|
actor_service
|
||||||
|
WHERE
|
||||||
|
actor_player.steam_id = $1;
|
8
src/database/query/get-actor_service.sql
Normal file
8
src/database/query/get-actor_service.sql
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
SELECT
|
||||||
|
actor_service.handle,
|
||||||
|
actor_service.public_rsa,
|
||||||
|
actor_service.public_ed,
|
||||||
|
actor_service.private_rsa,
|
||||||
|
actor_service.private_ed
|
||||||
|
FROM
|
||||||
|
actor_service;
|
|
@ -1,8 +1,9 @@
|
||||||
// deno-lint-ignore-file require-await
|
// deno-lint-ignore-file require-await
|
||||||
import { createFederation, Person, Application, Image, PropertyValue, Organization, Federation, KvStore, Context, Actor, Follow, Endpoints } from "@fedify/fedify"
|
import { createFederation, Person, Application, Image, PropertyValue, Organization, Federation, KvStore, Context, Actor, Follow, Endpoints, importSpki, importJwk } from "@fedify/fedify"
|
||||||
import { getLogger } from "https://jsr.io/@logtape/logtape/0.6.3/logtape/logger.ts"
|
import { getLogger } from "https://jsr.io/@logtape/logtape/0.6.3/logtape/logger.ts"
|
||||||
import { escapeHtml } from "@@x/escape"
|
import { escapeHtml } from "@@x/escape"
|
||||||
import { StratzAPI } from "../stratz/api.ts"
|
import { StratzAPI } from "../stratz/api.ts"
|
||||||
|
import { Database } from "../database/index.ts"
|
||||||
|
|
||||||
|
|
||||||
const l = getLogger(["dotino-veloce", "ap", "federation"])
|
const l = getLogger(["dotino-veloce", "ap", "federation"])
|
||||||
|
@ -12,39 +13,39 @@ type ContextData = undefined
|
||||||
|
|
||||||
|
|
||||||
export class DotinoVeloce {
|
export class DotinoVeloce {
|
||||||
|
db: Database
|
||||||
stratz: StratzAPI
|
stratz: StratzAPI
|
||||||
federation: Federation<ContextData>
|
federation: Federation<ContextData>
|
||||||
|
|
||||||
constructor(kv: KvStore, stratz: StratzAPI) {
|
constructor(db: Database, stratz: StratzAPI) {
|
||||||
|
this.db = db
|
||||||
this.stratz = stratz
|
this.stratz = stratz
|
||||||
|
|
||||||
this.federation = createFederation<ContextData>({ kv })
|
this.federation = createFederation<ContextData>({ kv: db.useAsKvStore() })
|
||||||
|
|
||||||
this.federation
|
this.federation
|
||||||
.setActorDispatcher("/users/{identifier}", this.#actorHandler.bind(this))
|
.setActorDispatcher("/users/{identifier}", this.#actorHandler.bind(this))
|
||||||
|
.setKeyPairsDispatcher(this.#actorKeys.bind(this))
|
||||||
.mapHandle(this.#actorMapper.bind(this))
|
.mapHandle(this.#actorMapper.bind(this))
|
||||||
// .setKeyPairsDispatcher(this.#actorKeys.bind(this))
|
|
||||||
|
|
||||||
this.federation
|
this.federation
|
||||||
.setInboxListeners("/inbox/{identifier}", "/inbox")
|
.setInboxListeners("/inbox/{identifier}", "/inbox")
|
||||||
.on(Follow, this.#followHandler.bind(this))
|
.on(Follow, this.#followHandler.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
#commonActorProperties(ctx: Context<ContextData>, handle: string): Partial<Actor> {
|
async #commonActorProperties(ctx: Context<ContextData>, handle: string): Promise<Partial<Actor>> {
|
||||||
l.debug`Generating common actor properties for ${handle}...`
|
l.debug`Generating common actor properties for ${handle}...`
|
||||||
const properties = {
|
const properties = {
|
||||||
|
preferredUsername: handle,
|
||||||
id: ctx.getActorUri(handle),
|
id: ctx.getActorUri(handle),
|
||||||
|
publicKeys: (await ctx.getActorKeyPairs(handle)).map(keyPair => keyPair.cryptographicKey),
|
||||||
|
assertionMethods: (await ctx.getActorKeyPairs(handle)).map(keyPair => keyPair.multikey),
|
||||||
|
// Akkoma requires inboxes to be setup to display profiles
|
||||||
|
// https://akkoma.dev/AkkomaGang/akkoma/src/commit/f1018867097e6f293d8b2b5b6935f0a7ebf99bd0/lib/pleroma/web/activity_pub/object_validators/user_validator.ex#L72
|
||||||
inbox: ctx.getInboxUri(handle),
|
inbox: ctx.getInboxUri(handle),
|
||||||
endpoints: new Endpoints({
|
endpoints: new Endpoints({
|
||||||
sharedInbox: ctx.getInboxUri(),
|
sharedInbox: ctx.getInboxUri(),
|
||||||
}),
|
}),
|
||||||
preferredUsername: handle,
|
|
||||||
// Akkoma expects URL to be equal to ID
|
|
||||||
// Or does it? This makes no sense to me...
|
|
||||||
// https://akkoma.dev/AkkomaGang/akkoma/src/commit/f1018867097e6f293d8b2b5b6935f0a7ebf99bd0/lib/pleroma/object/fetcher.ex#L287
|
|
||||||
// url: id,
|
|
||||||
// Akkoma requires inboxes to be setup to display profiles
|
|
||||||
// https://akkoma.dev/AkkomaGang/akkoma/src/commit/f1018867097e6f293d8b2b5b6935f0a7ebf99bd0/lib/pleroma/web/activity_pub/object_validators/user_validator.ex#L72
|
|
||||||
}
|
}
|
||||||
l.debug`Generated common actor properties for ${handle}: ${properties}`
|
l.debug`Generated common actor properties for ${handle}: ${properties}`
|
||||||
return properties
|
return properties
|
||||||
|
@ -79,7 +80,7 @@ export class DotinoVeloce {
|
||||||
|
|
||||||
l.debug`Generating ActivityPub actor for player ${steamId}...`
|
l.debug`Generating ActivityPub actor for player ${steamId}...`
|
||||||
const actor = new Person({
|
const actor = new Person({
|
||||||
...this.#commonActorProperties(ctx, handle),
|
...(await this.#commonActorProperties(ctx, handle)),
|
||||||
|
|
||||||
name: `[TEST] ${escapeHtml(player.name)}`,
|
name: `[TEST] ${escapeHtml(player.name)}`,
|
||||||
icon: new Image({
|
icon: new Image({
|
||||||
|
@ -140,7 +141,7 @@ export class DotinoVeloce {
|
||||||
|
|
||||||
l.debug`Generating ActivityPub actor for guild ${guildId}...`
|
l.debug`Generating ActivityPub actor for guild ${guildId}...`
|
||||||
const actor = new Organization({
|
const actor = new Organization({
|
||||||
...this.#commonActorProperties(ctx, handle),
|
...(await this.#commonActorProperties(ctx, handle)),
|
||||||
|
|
||||||
name: `[TEST] ${escapeHtml(guild.name)}`,
|
name: `[TEST] ${escapeHtml(guild.name)}`,
|
||||||
summary: escapeHtml(guild.description),
|
summary: escapeHtml(guild.description),
|
||||||
|
@ -181,7 +182,7 @@ export class DotinoVeloce {
|
||||||
|
|
||||||
l.debug`Generating ActivityPub actor for service...`
|
l.debug`Generating ActivityPub actor for service...`
|
||||||
const actor = new Application({
|
const actor = new Application({
|
||||||
...this.#commonActorProperties(ctx, handle),
|
...(await this.#commonActorProperties(ctx, handle)),
|
||||||
|
|
||||||
name: "[TEST] Dotino Veloce",
|
name: "[TEST] Dotino Veloce",
|
||||||
summary: "Service account of a Dotino Veloce instance.",
|
summary: "Service account of a Dotino Veloce instance.",
|
||||||
|
@ -210,11 +211,41 @@ export class DotinoVeloce {
|
||||||
}
|
}
|
||||||
|
|
||||||
async #actorMapper(_ctx: Context<ContextData>, handle: string): Promise<string> {
|
async #actorMapper(_ctx: Context<ContextData>, handle: string): Promise<string> {
|
||||||
|
l.debug`Getting handle mapping for: ${handle}`
|
||||||
return handle
|
return handle
|
||||||
}
|
}
|
||||||
|
|
||||||
async #actorKeys(ctx: Context<ContextData>, handle: string): Promise<CryptoKeyPair[]> {
|
async #actorKeys(_ctx: Context<ContextData>, handle: string): Promise<CryptoKeyPair[]> {
|
||||||
throw "TODO: Not implemented"
|
l.debug`Getting keys for: ${handle}`
|
||||||
|
|
||||||
|
l.debug`Requesting keys from the database...`
|
||||||
|
const {
|
||||||
|
public_rsa: publicRsaJwk,
|
||||||
|
public_ed: publicEdJwk,
|
||||||
|
private_rsa: privateRsaJwk,
|
||||||
|
private_ed: privateEdJwk,
|
||||||
|
} = await this.db.getActorService()
|
||||||
|
|
||||||
|
l.debug`Importing keys from JWK format...`
|
||||||
|
const publicRsa = await importJwk(publicRsaJwk, "public")
|
||||||
|
const publicEd = await importJwk(publicEdJwk, "public")
|
||||||
|
const privateRsa = await importJwk(privateRsaJwk, "private")
|
||||||
|
const privateEd = await importJwk(privateEdJwk, "private")
|
||||||
|
|
||||||
|
l.debug`Bundling keys...`
|
||||||
|
const result = [
|
||||||
|
{
|
||||||
|
publicKey: publicRsa,
|
||||||
|
privateKey: privateRsa,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
publicKey: publicEd,
|
||||||
|
privateKey: privateEd,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
l.debug`Bundled keys are: ${result}`
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async #followHandler(ctx: Context<ContextData>, follow: Follow) {
|
async #followHandler(ctx: Context<ContextData>, follow: Follow) {
|
||||||
|
|
12
src/entry/dbInit.ts
Normal file
12
src/entry/dbInit.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { Database } from "../database/index.ts"
|
||||||
|
import { initLogging } from "../deno/logging.ts"
|
||||||
|
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
await initLogging()
|
||||||
|
const db = Database.fromEnv()
|
||||||
|
await db.reinitializeDev()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
21
src/entry/server.ts
Normal file
21
src/entry/server.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { doServe } from "../deno/server.ts"
|
||||||
|
import { initLogging } from "../deno/logging.ts"
|
||||||
|
import { StratzAPI } from "../stratz/api.ts"
|
||||||
|
import { behindProxy, Fetch } from "@hongminhee/x-forwarded-fetch"
|
||||||
|
import { createRouter } from "../deno/router.ts"
|
||||||
|
import { DotinoVeloce } from "../dv/dotinoVeloce.ts"
|
||||||
|
import { Database } from "../database/index.ts"
|
||||||
|
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
await initLogging()
|
||||||
|
const db = Database.fromEnv()
|
||||||
|
const stratz = StratzAPI.fromEnv()
|
||||||
|
const ap = new DotinoVeloce(db, stratz)
|
||||||
|
const router = createRouter(ap)
|
||||||
|
const routerBehindProxy = behindProxy(router as Fetch)
|
||||||
|
await doServe(routerBehindProxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
23
src/main.ts
23
src/main.ts
|
@ -1,23 +0,0 @@
|
||||||
import { doServe } from "./deno/server.ts"
|
|
||||||
import { initLogging } from "./deno/logging.ts"
|
|
||||||
import { StratzAPI } from "./stratz/api.ts"
|
|
||||||
import { behindProxy, Fetch } from "@hongminhee/x-forwarded-fetch"
|
|
||||||
import { createRouter } from "./deno/router.ts"
|
|
||||||
import { DotinoVeloce } from "./dv/dotinoVeloce.ts"
|
|
||||||
import { createPostgresKvStore } from "./database/kv.ts"
|
|
||||||
import { createPostgresFromEnv } from "./database/postgres.ts"
|
|
||||||
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
await initLogging()
|
|
||||||
const postgres = createPostgresFromEnv()
|
|
||||||
const kv = createPostgresKvStore(postgres)
|
|
||||||
const stratz = StratzAPI.fromEnv()
|
|
||||||
const ap = new DotinoVeloce(kv, stratz)
|
|
||||||
const router = createRouter(ap)
|
|
||||||
const routerBehindProxy = behindProxy(router as Fetch)
|
|
||||||
await doServe(routerBehindProxy)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
main()
|
|
Loading…
Reference in a new issue