mirror of
https://github.com/vector-im/hydrogen-web.git
synced 2024-12-22 19:14:52 +01:00
Write plugin for Dex
This commit is contained in:
parent
193415ac1d
commit
2376ef8b8c
132
cypress/plugins/dex/index.ts
Normal file
132
cypress/plugins/dex/index.ts
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// <reference types="cypress" />
|
||||||
|
|
||||||
|
import * as path from "path";
|
||||||
|
import * as os from "os";
|
||||||
|
import * as fse from "fs-extra";
|
||||||
|
|
||||||
|
import PluginEvents = Cypress.PluginEvents;
|
||||||
|
import PluginConfigOptions = Cypress.PluginConfigOptions;
|
||||||
|
import {dockerRun, dockerStop } from "../docker";
|
||||||
|
|
||||||
|
// A cypress plugins to add command to start & stop dex instances
|
||||||
|
|
||||||
|
interface DexConfig {
|
||||||
|
configDir: string;
|
||||||
|
baseUrl: string;
|
||||||
|
port: number;
|
||||||
|
host: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DexInstance extends DexConfig {
|
||||||
|
dexId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dexConfigs = new Map<string, DexInstance>();
|
||||||
|
let env;
|
||||||
|
|
||||||
|
async function produceConfigWithSynapseURLAdded(): Promise<DexConfig> {
|
||||||
|
const templateDir = path.join(__dirname, "template");
|
||||||
|
|
||||||
|
const stats = await fse.stat(templateDir);
|
||||||
|
if (!stats?.isDirectory) {
|
||||||
|
throw new Error(`Template directory at ${templateDir} not found!`);
|
||||||
|
}
|
||||||
|
const tempDir = await fse.mkdtemp(path.join(os.tmpdir(), 'hydrogen-testing-dex-'));
|
||||||
|
|
||||||
|
// copy the contents of the template dir, omitting config.yaml as we'll template that
|
||||||
|
console.log(`Copy ${templateDir} -> ${tempDir}`);
|
||||||
|
await fse.copy(templateDir, tempDir, { filter: f => path.basename(f) !== 'config.yaml' });
|
||||||
|
|
||||||
|
// now copy config.yaml, applying substitutions
|
||||||
|
console.log(`Gen ${path.join(templateDir, "config.yaml")}`);
|
||||||
|
let hsYaml = await fse.readFile(path.join(templateDir, "config.yaml"), "utf8");
|
||||||
|
const synapseAddress = `${env.SYNAPSE_IP_ADDRESS}:${env.SYNAPSE_PORT}`;
|
||||||
|
hsYaml = hsYaml.replace(/{{SYNAPSE_ADDRESS}}/g, synapseAddress);
|
||||||
|
const host = env.DEX_IP_ADDRESS;
|
||||||
|
const port = env.DEX_PORT;
|
||||||
|
const dexAddress = `${host}:${port}`;
|
||||||
|
hsYaml = hsYaml.replace(/{{DEX_ADDRESS}}/g, dexAddress);
|
||||||
|
await fse.writeFile(path.join(tempDir, "config.yaml"), hsYaml);
|
||||||
|
|
||||||
|
const baseUrl = `http://${host}:${port}`;
|
||||||
|
return {
|
||||||
|
host,
|
||||||
|
port,
|
||||||
|
baseUrl,
|
||||||
|
configDir: tempDir,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function dexStart(): Promise<DexInstance> {
|
||||||
|
const dexCfg = await produceConfigWithSynapseURLAdded();
|
||||||
|
console.log(`Starting dex with config dir ${dexCfg.configDir}...`);
|
||||||
|
const dexId = await dockerRun({
|
||||||
|
image: "bitnami/dex:latest",
|
||||||
|
containerName: "dex",
|
||||||
|
dockerParams: [
|
||||||
|
"--rm",
|
||||||
|
"-v", `${dexCfg.configDir}:/data`,
|
||||||
|
`--ip=${dexCfg.host}`,
|
||||||
|
"-p", `${dexCfg.port}:5556/tcp`,
|
||||||
|
"--network=hydrogen"
|
||||||
|
],
|
||||||
|
applicationParams: [
|
||||||
|
"serve",
|
||||||
|
"data/config.yaml",
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Started dex with id ${dexId} on port ${dexCfg.port}.`);
|
||||||
|
|
||||||
|
const dex: DexInstance = { dexId, ...dexCfg };
|
||||||
|
dexConfigs.set(dexId, dex);
|
||||||
|
return dex;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function dexStop(id: string): Promise<void> {
|
||||||
|
const dexCfg = dexConfigs.get(id);
|
||||||
|
if (!dexCfg) throw new Error("Unknown dex ID");
|
||||||
|
await dockerStop({ containerId: id, });
|
||||||
|
await fse.remove(dexCfg.configDir);
|
||||||
|
dexConfigs.delete(id);
|
||||||
|
console.log(`Stopped dex id ${id}.`);
|
||||||
|
// cypress deliberately fails if you return 'undefined', so
|
||||||
|
// return null to signal all is well, and we've handled the task.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Cypress.PluginConfig}
|
||||||
|
*/
|
||||||
|
export function dexDocker(on: PluginEvents, config: PluginConfigOptions) {
|
||||||
|
env = config.env;
|
||||||
|
|
||||||
|
on("task", {
|
||||||
|
dexStart,
|
||||||
|
dexStop,
|
||||||
|
});
|
||||||
|
|
||||||
|
on("after:spec", async (spec) => {
|
||||||
|
for (const dexId of dexConfigs.keys()) {
|
||||||
|
console.warn(`Cleaning up dex ID ${dexId} after ${spec.name}`);
|
||||||
|
await dexStop(dexId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
56
cypress/plugins/dex/template/config.yaml
Executable file
56
cypress/plugins/dex/template/config.yaml
Executable file
@ -0,0 +1,56 @@
|
|||||||
|
issuer: http://{{DEX_ADDRESS}}/dex
|
||||||
|
|
||||||
|
storage:
|
||||||
|
type: sqlite3
|
||||||
|
config:
|
||||||
|
file: data/dev.db
|
||||||
|
|
||||||
|
|
||||||
|
# Configuration for the HTTP endpoints.
|
||||||
|
web:
|
||||||
|
http: 0.0.0.0:5556
|
||||||
|
# Uncomment for HTTPS options.
|
||||||
|
# https: 127.0.0.1:5554
|
||||||
|
# tlsCert: /etc/dex/tls.crt
|
||||||
|
# tlsKey: /etc/dex/tls.key
|
||||||
|
|
||||||
|
# Configuration for telemetry
|
||||||
|
telemetry:
|
||||||
|
http: 0.0.0.0:5558
|
||||||
|
# enableProfiling: true
|
||||||
|
|
||||||
|
staticClients:
|
||||||
|
- id: synapse
|
||||||
|
secret: secret
|
||||||
|
redirectURIs:
|
||||||
|
- 'http://{{SYNAPSE_ADDRESS}}/_synapse/client/oidc/callback'
|
||||||
|
name: 'Synapse'
|
||||||
|
connectors:
|
||||||
|
- type: mockCallback
|
||||||
|
id: mock
|
||||||
|
name: Example
|
||||||
|
# - type: google
|
||||||
|
# id: google
|
||||||
|
# name: Google
|
||||||
|
# config:
|
||||||
|
# issuer: https://accounts.google.com
|
||||||
|
# # Connector config values starting with a "$" will read from the environment.
|
||||||
|
# clientID: $GOOGLE_CLIENT_ID
|
||||||
|
# clientSecret: $GOOGLE_CLIENT_SECRET
|
||||||
|
# redirectURI: http://127.0.0.1:5556/dex/callback
|
||||||
|
# hostedDomains:
|
||||||
|
# - $GOOGLE_HOSTED_DOMAIN
|
||||||
|
|
||||||
|
# Let dex keep a list of passwords which can be used to login to dex.
|
||||||
|
enablePasswordDB: true
|
||||||
|
|
||||||
|
# A static list of passwords to login the end user. By identifying here, dex
|
||||||
|
# won't look in its underlying storage for passwords.
|
||||||
|
#
|
||||||
|
# If this option isn't chosen users may be added through the gRPC API.
|
||||||
|
staticPasswords:
|
||||||
|
- email: "admin@example.com"
|
||||||
|
# bcrypt hash of the string "password": $(echo password | htpasswd -BinC 10 admin | cut -d: -f2)
|
||||||
|
hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W"
|
||||||
|
username: "admin"
|
||||||
|
userID: "08a8684b-db88-4b73-90a9-3cd1661f5466"
|
BIN
cypress/plugins/dex/template/dev.db
Executable file
BIN
cypress/plugins/dex/template/dev.db
Executable file
Binary file not shown.
@ -20,6 +20,7 @@ import PluginEvents = Cypress.PluginEvents;
|
|||||||
import PluginConfigOptions = Cypress.PluginConfigOptions;
|
import PluginConfigOptions = Cypress.PluginConfigOptions;
|
||||||
import { performance } from "./performance";
|
import { performance } from "./performance";
|
||||||
import { synapseDocker } from "./synapsedocker";
|
import { synapseDocker } from "./synapsedocker";
|
||||||
|
import { dexDocker } from "./dex";
|
||||||
import { webserver } from "./webserver";
|
import { webserver } from "./webserver";
|
||||||
import { docker } from "./docker";
|
import { docker } from "./docker";
|
||||||
import { log } from "./log";
|
import { log } from "./log";
|
||||||
@ -31,6 +32,7 @@ export default function(on: PluginEvents, config: PluginConfigOptions) {
|
|||||||
docker(on, config);
|
docker(on, config);
|
||||||
performance(on, config);
|
performance(on, config);
|
||||||
synapseDocker(on, config);
|
synapseDocker(on, config);
|
||||||
|
dexDocker(on, config);
|
||||||
webserver(on, config);
|
webserver(on, config);
|
||||||
log(on, config);
|
log(on, config);
|
||||||
}
|
}
|
||||||
|
51
cypress/support/dex.ts
Normal file
51
cypress/support/dex.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// <reference types="cypress" />
|
||||||
|
|
||||||
|
import Chainable = Cypress.Chainable;
|
||||||
|
import AUTWindow = Cypress.AUTWindow;
|
||||||
|
import { DexInstance } from "../plugins/dex";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
|
namespace Cypress {
|
||||||
|
interface Chainable {
|
||||||
|
/**
|
||||||
|
* Start the dex server
|
||||||
|
*/
|
||||||
|
startDex(): Chainable<DexInstance>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the dex server
|
||||||
|
* @param dex the dex instance returned by startSynapse
|
||||||
|
*/
|
||||||
|
stopDex(dex: DexInstance): Chainable<AUTWindow>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function startDex(): Chainable<DexInstance> {
|
||||||
|
return cy.task<DexInstance>("dexStart");
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopDex(dex?: DexInstance): Chainable<AUTWindow> {
|
||||||
|
if (!dex) return;
|
||||||
|
cy.task("dexStop", dex.dexId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cypress.Commands.add("startDex", startDex);
|
||||||
|
Cypress.Commands.add("stopDex", stopDex);
|
@ -17,3 +17,4 @@ limitations under the License.
|
|||||||
/// <reference types="cypress" />
|
/// <reference types="cypress" />
|
||||||
|
|
||||||
import "./synapse";
|
import "./synapse";
|
||||||
|
import "./dex";
|
||||||
|
Loading…
Reference in New Issue
Block a user