mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-29 14:45:24 +00:00
feat: harden plugin api for separate repos, signed updates and generic external login
This commit is contained in:
1 parent
fb9c168b6b
commit
80944301dd
310 files changed
+6577
-4927
No files matched your search
@@ -96,8 +96,8 @@ export interface PluginFiles {
|
||||
* to query through `db`. Both require db:own.
|
||||
*
|
||||
* Scoped by name: every table carries the p_<id>_ prefix, and `refs` exposes
|
||||
* users, ssh_data, roles and user_roles read-only so a plugin can join against
|
||||
* them without being able to write them. In-process code could reach around
|
||||
* users, ssh_data, roles and user_roles (behind db:core-refs) so a plugin can
|
||||
* join against them. In-process code could reach around
|
||||
* all of this. The capability, the prefix, lint and review are the contract,
|
||||
* not a sandbox.
|
||||
*/
|
||||
@@ -106,7 +106,10 @@ export interface PluginDatabase {
|
||||
define: <T = unknown>(definition: PluginTableDefinition) => Promise<T>;
|
||||
/** Drizzle handle, scoped to this plugin's tables. */
|
||||
client: <T = unknown>() => Promise<T>;
|
||||
/** Read-only references to the core tables a plugin may point at. */
|
||||
/**
|
||||
* Core tables a plugin may join against: users, hosts, roles, userRoles.
|
||||
* Needs db:core-refs. Treat them as read-only.
|
||||
*/
|
||||
refs: <T = unknown>() => Promise<T>;
|
||||
/**
|
||||
* Flushes writes to disk. Call it after every write: on SQLite the database
|
||||
@@ -235,6 +238,11 @@ export interface PluginSync {
|
||||
registerEntity: (entity: SyncEntityRegistration) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* A plain key/value hand-off between plugins. `provide` and `revoke` only take
|
||||
* keys under the plugin's own id (`<pluginId>.something`); anyone may
|
||||
* `consume`.
|
||||
*/
|
||||
export interface PluginRegistry {
|
||||
provide: <T>(key: string, value: T) => void;
|
||||
consume: <T>(key: string) => T | undefined;
|
||||
@@ -252,7 +260,11 @@ export interface PluginServices {
|
||||
implementation: T,
|
||||
options?: { name?: string },
|
||||
) => void;
|
||||
/** `provider` picks a named provider; omitted, the unnamed one. */
|
||||
/**
|
||||
* The service must be listed in the manifest's `requires` (or be one this
|
||||
* plugin provides). `provider` picks a named provider; omitted, the unnamed
|
||||
* one. A `userId` other than the acting user needs users:impersonate.
|
||||
*/
|
||||
get: <T extends object>(
|
||||
service: string,
|
||||
options?: { userId?: string; provider?: string },
|
||||
@@ -1340,6 +1352,12 @@ export interface PluginLoginInstance {
|
||||
* route ("oidc", "github", "google", "ldap"). Leave unset otherwise.
|
||||
*/
|
||||
type?: string;
|
||||
/**
|
||||
* Redirect methods: the login page starts this instance without a click,
|
||||
* for a server that signs everyone in through one provider. The first
|
||||
* instance that asks wins.
|
||||
*/
|
||||
autoStart?: boolean;
|
||||
}
|
||||
|
||||
export interface PluginLoginMethod {
|
||||
@@ -1468,7 +1486,13 @@ export interface PluginOpenIsolatedWindowRequest {
|
||||
* Electron only: rejects when the server is not running embedded in the
|
||||
* desktop app. Needs desktop:window.
|
||||
*/
|
||||
export interface PluginNativeRdpRequest {
|
||||
/**
|
||||
* A host to open in the operating system's own client for a protocol. The
|
||||
* desktop app supports "rdp" (mstsc on Windows) today; any other protocol is
|
||||
* refused.
|
||||
*/
|
||||
export interface PluginExternalClientRequest {
|
||||
protocol: string;
|
||||
host: string;
|
||||
port?: number;
|
||||
username?: string;
|
||||
@@ -1480,12 +1504,11 @@ export interface PluginDesktop {
|
||||
request: PluginOpenIsolatedWindowRequest,
|
||||
) => Promise<{ success: true }>;
|
||||
/**
|
||||
* Opens the operating system's own RDP client (mstsc on Windows) for a
|
||||
* host. The password is never passed; the client asks for it. Windows
|
||||
* desktop app only.
|
||||
* Opens the operating system's own client for a protocol. The password is
|
||||
* never passed; the client asks for it. Desktop app only.
|
||||
*/
|
||||
launchNativeRdp: (
|
||||
request: PluginNativeRdpRequest,
|
||||
launchExternalClient: (
|
||||
request: PluginExternalClientRequest,
|
||||
) => Promise<{ success: boolean; error?: string }>;
|
||||
/** Whether the server runs embedded in the desktop app, so the calls above can work. */
|
||||
available: () => boolean;
|
||||
@@ -1942,8 +1965,8 @@ export interface PluginContext {
|
||||
* no request behind it. Always audited, and every core API inside still
|
||||
* applies that user's RBAC.
|
||||
*
|
||||
* This is the only way a plugin can name a user. Nothing else trusts a user
|
||||
* id that came from plugin code.
|
||||
* Needs users:impersonate. That and a `userId` option on services.get or
|
||||
* secrets.getShared are the only ways a plugin can name a user.
|
||||
*/
|
||||
asUser: <T>(userId: string, fn: () => Promise<T> | T) => Promise<T>;
|
||||
|
||||
|
||||
Reference in new issue
Block a user