mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-29 22:55:24 +00:00
feat: move opkssh and warpgate into plugins (C3)
This commit is contained in:
1 parent
925da4a661
commit
98d367d7e2
336 files changed
+22380
-4746
No files matched your search
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate Gateway",
|
||||
"description": "This host connects through a Warpgate SSH proxy. Termix will handle the browser-based approval flow automatically after authenticating."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate-poort",
|
||||
"description": "Hierdie gasheer koppel deur 'n Warpgate SSH-instaanbediener. Termix sal die blaaiergebaseerde goedkeuringsvloei outomaties hanteer na verifikasie."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "بوابة Warpgate",
|
||||
"description": "يتصل هذا المضيف عبر وكيل SSH من Warpgate. سيتولى Termix عملية الموافقة عبر المتصفح تلقائيًا بعد المصادقة."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Порталът на Уорпгейт",
|
||||
"description": "Този хост се свързва чрез Warpgate SSH прокси. Termix ще обработи процеса на одобрение, базиран на браузър, автоматично след удостоверяване."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "ওয়ার্পগেট গেটওয়ে",
|
||||
"description": "এই হোস্টটি একটি ওয়ার্পগেট এসএসএইচ প্রক্সির মাধ্যমে সংযুক্ত হয়। প্রমাণীকরণের পর টার্মিক্স স্বয়ংক্রিয়ভাবে ব্রাউজার-ভিত্তিক অনুমোদন প্রক্রিয়াটি পরিচালনা করবে।"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Porta de Warpgate",
|
||||
"description": "Aquest amfitrió es connecta a través d'un proxy SSH Warpgate. Termix gestionarà automàticament el flux d'aprovació basat en navegador després de l'autenticació."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Brána Warpgate",
|
||||
"description": "Tento hostitel se připojuje přes proxy Warpgate SSH. Termix po ověření automaticky zpracuje proces schvalování v prohlížeči."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate Gateway",
|
||||
"description": "Denne vært opretter forbindelse via en Warpgate SSH-proxy. Termix håndterer den browserbaserede godkendelsesproces automatisk efter godkendelse."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate Gateway",
|
||||
"description": "Dieser Host verbindet sich über einen Warpgate SSH-Proxy. Termix übernimmt nach der Authentifizierung automatisch den browserbasierten Genehmigungsablauf."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Πύλη Warpgate",
|
||||
"description": "Αυτός ο κεντρικός υπολογιστής συνδέεται μέσω ενός διακομιστή μεσολάβησης Warpgate SSH. Το Termix θα χειριστεί αυτόματα τη ροή έγκρισης που βασίζεται σε πρόγραμμα περιήγησης μετά τον έλεγχο ταυτότητας."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate Gateway",
|
||||
"description": "Este host se conecta a través de un proxy SSH de Warpgate. Termix gestionará el flujo de aprobación basado en navegador automáticamente después de autenticarse."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate-yhdyskäytävä",
|
||||
"description": "Tämä isäntä muodostaa yhteyden Warpgate SSH -välityspalvelimen kautta. Termix käsittelee selainpohjaisen hyväksyntäprosessin automaattisesti todennuksen jälkeen."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate Gateway",
|
||||
"description": "Cet hôte se connecte via un proxy SSH Warpgate. Termix gérera automatiquement le flux d'approbation basé sur le navigateur après l'authentification."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "שער וורפגייט",
|
||||
"description": "מארח זה מתחבר דרך פרוקסי Warpgate SSH. Termix יטפל בזרימת האישור מבוססת הדפדפן באופן אוטומטי לאחר האימות."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate गेटवे",
|
||||
"description": "यह होस्ट Warpgate SSH प्रॉक्सी के माध्यम से कनेक्ट होता है। Termix प्रमाणीकरण के बाद ब्राउज़र-आधारित अनुमोदन प्रवाह को स्वचालित रूप से संभालेगा।"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate átjáró",
|
||||
"description": "Ez a gazdagép egy Warpgate SSH proxyn keresztül csatlakozik. A Termix a hitelesítés után automatikusan kezeli a böngészőalapú jóváhagyási folyamatot."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Gerbang Warpgate",
|
||||
"description": "Host ini terhubung melalui proxy SSH Warpgate. Termix akan menangani alur persetujuan berbasis browser secara otomatis setelah otentikasi."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate Gateway",
|
||||
"description": "Questo host si connette tramite un proxy SSH Warpgate. Termix gestirà automaticamente il flusso di approvazione basato su browser dopo l'autenticazione."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgateゲートウェイ",
|
||||
"description": "このホストはWarpgate SSHプロキシ経由で接続します。認証後、Termixがブラウザベースの承認フローを自動的に処理します。"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate 게이트웨이",
|
||||
"description": "이 호스트는 Warpgate SSH 프록시를 통해 연결됩니다. Termix는 인증 후 브라우저 기반 승인 과정을 자동으로 처리합니다."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate-poort",
|
||||
"description": "Deze host maakt verbinding via een Warpgate SSH-proxy. Termix handelt de browsergebaseerde goedkeuringsprocedure automatisch af na authenticatie."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate-porten",
|
||||
"description": "Denne verten kobler seg til via en Warpgate SSH-proxy. Termix håndterer den nettleserbaserte godkjenningsflyten automatisk etter autentisering."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Brama Warpgate",
|
||||
"description": "Ten host łączy się przez proxy SSH Warpgate. Termix automatycznie obsłuży proces zatwierdzania w przeglądarce po uwierzytelnieniu."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Portal de Dobra",
|
||||
"description": "Este host se conecta através de um proxy SSH Warpgate. O Termix cuidará automaticamente do fluxo de aprovação baseado em navegador após a autenticação."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate Gateway",
|
||||
"description": "Este anfitrião liga-se através de um proxy SSH Warpgate. O Termix irá gerir automaticamente o fluxo de aprovação baseado no navegador após a autenticação."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Poarta Warpgate",
|
||||
"description": "Această gazdă se conectează printr-un proxy SSH Warpgate. Termix va gestiona automat fluxul de aprobare bazat pe browser după autentificare."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Шлюз Warpgate",
|
||||
"description": "Этот хост подключается через SSH-прокси Warpgate. Termix автоматически обработает процесс подтверждения в браузере после аутентификации."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Капија Варпгејта",
|
||||
"description": "Овај хост се повезује преко Warpgate SSH проксија. Termix ће аутоматски обрадити ток одобрења заснован на прегледачу након аутентификације."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate Gateway",
|
||||
"description": "Denna värd ansluter via en Warpgate SSH-proxy. Termix hanterar det webbläsarbaserade godkännandeflödet automatiskt efter autentisering."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "ประตูวาร์ปเกต",
|
||||
"description": "โฮสต์นี้เชื่อมต่อผ่านพร็อกซี SSH ของ Warpgate Termix จะจัดการขั้นตอนการอนุมัติผ่านเบราว์เซอร์โดยอัตโนมัติหลังจากยืนยันตัวตนแล้ว"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate Ağ Geçidi",
|
||||
"description": "Bu sunucu bir Warpgate SSH proxy'si üzerinden bağlanır. Termix, kimlik doğrulamasından sonra tarayıcı tabanlı onay akışını otomatik olarak yönetir."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Брама Варпгейту",
|
||||
"description": "Цей хост підключається через проксі-сервер Warpgate SSH. Termix автоматично обробить процес затвердження на основі браузера після автентифікації."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Cổng Warpgate",
|
||||
"description": "Máy chủ này kết nối thông qua proxy SSH Warpgate. Termix sẽ tự động xử lý luồng phê duyệt trên trình duyệt sau khi xác thực."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate 网关",
|
||||
"description": "此主机通过 Warpgate SSH 代理连接。Termix 将在认证后自动处理基于浏览器的审批流程。"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"host": {
|
||||
"useWarpgate": {
|
||||
"label": "Warpgate 閘道",
|
||||
"description": "此主機透過 Warpgate SSH 代理連線。Termix 會在驗證後自動處理瀏覽器核准流程。"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"id": "warpgate",
|
||||
"name": "Warpgate",
|
||||
"version": "1.0.0",
|
||||
"description": "Connect through a Warpgate SSH bastion: its browser approval shows as a sign-in dialog, and the stored password answers its password prompt.",
|
||||
"author": {
|
||||
"name": "Termix"
|
||||
},
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/Termix-SSH/Termix",
|
||||
"category": "Access & Security",
|
||||
"icon": "DoorOpen",
|
||||
"engine": {
|
||||
"termix": ">=2.9.0",
|
||||
"api": "1"
|
||||
},
|
||||
"capabilities": ["auth:provide"],
|
||||
"contributes": {
|
||||
"auth": {
|
||||
"keyboardInteractive": ["warpgate"]
|
||||
},
|
||||
"settings": {
|
||||
"host": {
|
||||
"fields": [
|
||||
{
|
||||
"key": "useWarpgate",
|
||||
"type": "boolean",
|
||||
"labelKey": "settings.host.useWarpgate.label",
|
||||
"descriptionKey": "settings.host.useWarpgate.description",
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"locales": "locales",
|
||||
"platforms": ["linux", "win32", "darwin"]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "@termix-plugin/warpgate",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "termix-plugin build",
|
||||
"test": "termix-plugin test",
|
||||
"typecheck": "tsc -p tsconfig.json",
|
||||
"validate": "termix-plugin validate"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@termix/plugin-sdk": "*"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import type {
|
||||
PluginKeyboardInteractiveDetection,
|
||||
PluginKeyboardInteractivePrompt,
|
||||
} from "@termix/plugin-sdk/backend";
|
||||
|
||||
const WARPGATE_PATTERN = /warpgate\s+authentication/i;
|
||||
const URL_PATTERN = /https?:\/\/[^\s\n]+/i;
|
||||
const SECURITY_KEY_PATTERN =
|
||||
/security key[:\s]+([a-z0-9](?:\s+[a-z0-9]){3}|[a-z0-9]{4})/i;
|
||||
|
||||
/**
|
||||
* Warpgate asks for its browser approval as a keyboard-interactive round
|
||||
* that names itself and carries the sign-in URL and a security key.
|
||||
*/
|
||||
export function detectWarpgateRound(round: {
|
||||
name: string;
|
||||
instructions: string;
|
||||
prompts: PluginKeyboardInteractivePrompt[];
|
||||
}): PluginKeyboardInteractiveDetection | null {
|
||||
const texts = round.prompts.map((prompt) => prompt.prompt);
|
||||
const isWarpgate =
|
||||
WARPGATE_PATTERN.test(round.name) ||
|
||||
WARPGATE_PATTERN.test(round.instructions) ||
|
||||
texts.some((text) => WARPGATE_PATTERN.test(text));
|
||||
if (!isWarpgate) return null;
|
||||
|
||||
const fullText = `${round.name}\n${round.instructions}\n${texts.join("\n")}`;
|
||||
const url = fullText.match(URL_PATTERN);
|
||||
if (!url) return null;
|
||||
const key = fullText.match(SECURITY_KEY_PATTERN);
|
||||
return {
|
||||
kind: "browser",
|
||||
url: url[0],
|
||||
code: key ? key[1] : "N/A",
|
||||
instructions: round.instructions,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Registered as "warpgate.hostImportNormalizer" so core's host import keeps
|
||||
* the flag. Reads a Termix export's pluginSettings.warpgate first, then the
|
||||
* useWarpgate host field exports had before 2.9.0.
|
||||
*/
|
||||
export function hostImportNormalizer(
|
||||
raw: Record<string, unknown>,
|
||||
): Record<string, unknown> | null {
|
||||
const pluginSettings = raw.pluginSettings as
|
||||
Record<string, Record<string, unknown> | undefined> | undefined;
|
||||
const value = pluginSettings?.warpgate?.useWarpgate ?? raw.useWarpgate;
|
||||
if (value === undefined || value === null) return null;
|
||||
return { useWarpgate: value === true || value === 1 || value === "true" };
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import type { PluginContext } from "@termix/plugin-sdk/backend";
|
||||
import { detectWarpgateRound } from "./detect.js";
|
||||
import { hostImportNormalizer } from "./host-import.js";
|
||||
|
||||
export const HANDLER_ID = "warpgate";
|
||||
|
||||
export async function activate(ctx: PluginContext) {
|
||||
ctx.auth.registerKeyboardInteractiveHandler({
|
||||
id: HANDLER_ID,
|
||||
label: "Warpgate",
|
||||
detect: (round) => detectWarpgateRound(round),
|
||||
// Warpgate asks for the password before its browser round; answer it
|
||||
// silently so the only thing the user sees is the sign-in dialog.
|
||||
autoAnswerPasswords: (_host, settings) => settings.useWarpgate === true,
|
||||
});
|
||||
|
||||
ctx.registry.provide("warpgate.hostImportNormalizer", hostImportNormalizer);
|
||||
}
|
||||
|
||||
export async function deactivate() {
|
||||
// Registered through ctx, so core removes it.
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { TermixApp } from "@termix/plugin-sdk/frontend";
|
||||
|
||||
// The host setting is drawn by core's schema form and the sign-in dialog is
|
||||
// the transports' own, so there is nothing to register.
|
||||
export function activate(_app: TermixApp): void {}
|
||||
@@ -0,0 +1,113 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { PluginCapabilityError } from "@termix/plugin-sdk/backend";
|
||||
import { createMockCtx } from "@termix/plugin-sdk/testing";
|
||||
import type { PluginManifest } from "@termix/plugin-sdk/manifest";
|
||||
import manifestJson from "../../manifest.json";
|
||||
import { activate } from "../../src/backend/index.js";
|
||||
import { detectWarpgateRound } from "../../src/backend/detect.js";
|
||||
import { hostImportNormalizer } from "../../src/backend/host-import.js";
|
||||
|
||||
const manifest = manifestJson as unknown as PluginManifest;
|
||||
const HOST = { id: 1, ip: "10.0.0.1", port: 22, username: "root" };
|
||||
|
||||
async function register() {
|
||||
const mock = createMockCtx({
|
||||
pluginId: manifest.id,
|
||||
manifest,
|
||||
capabilities: manifest.capabilities,
|
||||
});
|
||||
await activate(mock.ctx);
|
||||
return mock.auth.keyboardInteractiveHandlers[0];
|
||||
}
|
||||
|
||||
describe("detectWarpgateRound", () => {
|
||||
it("claims a Warpgate round with its URL and security key", () => {
|
||||
expect(
|
||||
detectWarpgateRound({
|
||||
name: "Warpgate authentication",
|
||||
instructions:
|
||||
"Open https://gate.example/@warpgate#/login/abc to continue. Security key: a b c d",
|
||||
prompts: [{ prompt: "Press Enter when done: " }],
|
||||
}),
|
||||
).toEqual({
|
||||
kind: "browser",
|
||||
url: "https://gate.example/@warpgate#/login/abc",
|
||||
code: "a b c d",
|
||||
instructions:
|
||||
"Open https://gate.example/@warpgate#/login/abc to continue. Security key: a b c d",
|
||||
});
|
||||
});
|
||||
|
||||
it("finds the marker in a prompt too, and says N/A without a key", () => {
|
||||
expect(
|
||||
detectWarpgateRound({
|
||||
name: "",
|
||||
instructions: "",
|
||||
prompts: [
|
||||
{ prompt: "Warpgate authentication: visit https://gate.example/x" },
|
||||
],
|
||||
}),
|
||||
).toMatchObject({ url: "https://gate.example/x", code: "N/A" });
|
||||
});
|
||||
|
||||
it("leaves other rounds, and a Warpgate round without a URL, alone", () => {
|
||||
expect(
|
||||
detectWarpgateRound({
|
||||
name: "",
|
||||
instructions: "",
|
||||
prompts: [{ prompt: "Verification code:" }],
|
||||
}),
|
||||
).toBeNull();
|
||||
expect(
|
||||
detectWarpgateRound({
|
||||
name: "Warpgate authentication",
|
||||
instructions: "",
|
||||
prompts: [],
|
||||
}),
|
||||
).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("the warpgate handler", () => {
|
||||
it("registers under its id and label", async () => {
|
||||
const handler = await register();
|
||||
expect(handler).toMatchObject({ id: "warpgate", label: "Warpgate" });
|
||||
});
|
||||
|
||||
it("answers password prompts itself only on hosts with the setting on", async () => {
|
||||
const handler = await register();
|
||||
expect(handler.autoAnswerPasswords!(HOST, { useWarpgate: true })).toBe(
|
||||
true,
|
||||
);
|
||||
expect(handler.autoAnswerPasswords!(HOST, { useWarpgate: false })).toBe(
|
||||
false,
|
||||
);
|
||||
expect(handler.autoAnswerPasswords!(HOST, {})).toBe(false);
|
||||
});
|
||||
|
||||
it("fails closed without auth:provide", async () => {
|
||||
const mock = createMockCtx({
|
||||
pluginId: manifest.id,
|
||||
manifest,
|
||||
capabilities: [],
|
||||
});
|
||||
await expect(activate(mock.ctx)).rejects.toThrow(PluginCapabilityError);
|
||||
});
|
||||
});
|
||||
|
||||
describe("hostImportNormalizer", () => {
|
||||
it("reads the plugin's own settings first, then the 2.8 host field", () => {
|
||||
expect(
|
||||
hostImportNormalizer({
|
||||
pluginSettings: { warpgate: { useWarpgate: true } },
|
||||
}),
|
||||
).toEqual({ useWarpgate: true });
|
||||
expect(hostImportNormalizer({ useWarpgate: 1 })).toEqual({
|
||||
useWarpgate: true,
|
||||
});
|
||||
expect(hostImportNormalizer({ useWarpgate: false })).toEqual({
|
||||
useWarpgate: false,
|
||||
});
|
||||
expect(hostImportNormalizer({ name: "x" })).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "@termix/plugin-sdk/tsconfig.plugin.json",
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx", "tests/**/*.ts", "tests/**/*.tsx"]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import { pluginVitestConfig } from "@termix/plugin-sdk/vitest-preset";
|
||||
|
||||
export default pluginVitestConfig(import.meta.url);
|
||||
Reference in new issue
Block a user