From 0571008a352bcb6f88bc75383bff46f015aa0039 Mon Sep 17 00:00:00 2001 From: gnuxie Date: Fri, 25 Nov 2022 13:37:44 +0000 Subject: [PATCH] use matrix-appservice-bridge support for postgres --- mx-tester.yml | 2 - src/appservice/AppService.ts | 3 +- src/appservice/datastore.ts | 50 ------------------- src/appservice/postgres/PgDataStore.ts | 68 ++++++++++++++++++++++++++ src/appservice/postgres/schema/v1.ts | 8 +++ 5 files changed, 78 insertions(+), 53 deletions(-) create mode 100644 src/appservice/postgres/PgDataStore.ts create mode 100644 src/appservice/postgres/schema/v1.ts diff --git a/mx-tester.yml b/mx-tester.yml index 79feba9..ba0af39 100644 --- a/mx-tester.yml +++ b/mx-tester.yml @@ -5,8 +5,6 @@ up: - docker run --rm --network $MX_TEST_NETWORK_NAME --name mjolnir-test-postgres --domainname mjolnir-test-postgres -e POSTGRES_PASSWORD=mjolnir-test -e POSTGRES_USER=mjolnir-tester -e POSTGRES_DB=mjolnir-test-db -d -p 127.0.0.1:8083:5432 postgres # Wait until postgresql is ready - until psql postgres://mjolnir-tester:mjolnir-test@localhost:8083/mjolnir-test-db -c ""; do echo "Waiting for psql..."; sleep 1s; done - # Make table in postgres - - psql postgres://mjolnir-tester:mjolnir-test@localhost:8083/mjolnir-test-db -c "CREATE TABLE mjolnir (local_part VARCHAR(255), owner VARCHAR(255), management_room TEXT)" # Launch the reverse proxy, listening for connections *only* on the local host. - docker run --rm --network host --name mjolnir-test-reverse-proxy -p 127.0.0.1:8081:80 -v $MX_TEST_CWD/test/nginx.conf:/etc/nginx/nginx.conf:ro -d nginx - yarn install diff --git a/src/appservice/AppService.ts b/src/appservice/AppService.ts index 7669ad5..52aa4c5 100644 --- a/src/appservice/AppService.ts +++ b/src/appservice/AppService.ts @@ -16,7 +16,8 @@ limitations under the License. import { AppServiceRegistration, Bridge, Request, WeakEvent, BridgeContext, MatrixUser, Logger } from "matrix-appservice-bridge"; import { MjolnirManager } from ".//MjolnirManager"; -import { DataStore, PgDataStore } from ".//datastore"; +import { DataStore } from ".//datastore"; +import { PgDataStore } from "./postgres/PgDataStore"; import { Api } from "./Api"; import { IConfig } from "./config/config"; import { AccessControl } from "./AccessControl"; diff --git a/src/appservice/datastore.ts b/src/appservice/datastore.ts index 848e210..af823bc 100644 --- a/src/appservice/datastore.ts +++ b/src/appservice/datastore.ts @@ -13,7 +13,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import { Client } from "pg"; export interface MjolnirRecord { local_part: string, @@ -56,53 +55,4 @@ export interface DataStore { lookupByLocalPart(localPart: string): Promise; } -export class PgDataStore implements DataStore { - private pgClient: Client; - constructor(connectionString: string) { - this.pgClient = new Client({ connectionString: connectionString }); - } - - public async init(): Promise { - await this.pgClient.connect(); - } - - public async close(): Promise { - await this.pgClient.end() - } - - public async list(): Promise { - const result = await this.pgClient.query("SELECT local_part, owner, management_room FROM mjolnir"); - - if (!result.rowCount) { - return []; - } - - return result.rows; - } - - public async store(mjolnirRecord: MjolnirRecord): Promise { - await this.pgClient.query( - "INSERT INTO mjolnir (local_part, owner, management_room) VALUES ($1, $2, $3)", - [mjolnirRecord.local_part, mjolnirRecord.owner, mjolnirRecord.management_room], - ); - } - - public async lookupByOwner(owner: string): Promise { - const result = await this.pgClient.query( - "SELECT local_part, owner, management_room FROM mjolnir WHERE owner = $1", - [owner], - ); - - return result.rows; - } - - public async lookupByLocalPart(localPart: string): Promise { - const result = await this.pgClient.query( - "SELECT local_part, owner, management_room FROM mjolnir WHERE local_part = $1", - [localPart], - ); - - return result.rows; - } -} diff --git a/src/appservice/postgres/PgDataStore.ts b/src/appservice/postgres/PgDataStore.ts new file mode 100644 index 0000000..3360be1 --- /dev/null +++ b/src/appservice/postgres/PgDataStore.ts @@ -0,0 +1,68 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { PostgresStore, SchemaUpdateFunction } from "matrix-appservice-bridge"; +import { DataStore, MjolnirRecord } from "../datastore"; + +function getSchema(): SchemaUpdateFunction[] { + const nSchema = 1; + const schema = []; + for (let schemaID = 1; schemaID < nSchema + 1; schemaID++) { + schema.push(require(`./schema/v${schemaID}`).runSchema); + } + return schema; +} + +export class PgDataStore extends PostgresStore implements DataStore { + + constructor(connectionString: string) { + super(getSchema(), { url: connectionString }) + } + + public async init(): Promise { + await this.ensureSchema(); + } + + public async close(): Promise { + await this.destroy(); + } + + public async list(): Promise { + const result = await this.sql`SELECT local_part, owner, management_room FROM mjolnir`; + if (!result.count) { + return []; + } + + return result.flat() as MjolnirRecord[]; + } + + public async store(mjolnirRecord: MjolnirRecord): Promise { + await this.sql`INSERT INTO mjolnir (local_part, owner, management_room) + VALUES (${mjolnirRecord.local_part}, ${mjolnirRecord.owner}, ${mjolnirRecord.management_room})`; + } + + public async lookupByOwner(owner: string): Promise { + const result = await this.sql`SELECT local_part, owner, management_room FROM mjolnir + WHERE owner = ${owner}`; + return result.flat() as MjolnirRecord[]; + } + + public async lookupByLocalPart(localPart: string): Promise { + const result = await this.sql`SELECT local_part, owner, management_room FROM mjolnir + WHERE local_part = ${localPart}`; + return result.flat() as MjolnirRecord[]; + } +} diff --git a/src/appservice/postgres/schema/v1.ts b/src/appservice/postgres/schema/v1.ts new file mode 100644 index 0000000..4972208 --- /dev/null +++ b/src/appservice/postgres/schema/v1.ts @@ -0,0 +1,8 @@ + +import postgres from 'postgres'; + +export async function runSchema(sql: postgres.Sql) { + await sql.begin(s => [ + s`CREATE TABLE mjolnir (local_part VARCHAR(255), owner VARCHAR(255), management_room TEXT);` + ]); +}