feat: harden plugin api for separate repos, signed updates and generic external login

This commit is contained in:
LukeGus committed 2026-09-29 18:11:59 -05:00
1 parent fb9c168b6b
commit 80944301dd
310 files changed
+6577 -4927

No files matched your search

+35 -119
View File
@@ -257,7 +257,6 @@
"nav": {
"home": "Home",
"terminal": "Terminal",
"localTerminal": "Local Terminal",
"fileManager": "File Manager",
"serverStats": "Host Metrics",
"admin": "Admin",
@@ -274,11 +273,8 @@
"failedToCopyPassword": "Failed to copy password",
"refreshTab": "Refresh connection",
"renameTab": "Rename tab",
"openFileManager": "Open File Manager",
"dashboard": "Dashboard",
"quickConnect": "Quick Connect",
"sshTools": "SSH Tools",
"history": "History",
"openAsTabHint": "Ctrl+click or middle click to open as a tab",
"openAsTab": "Open as tab",
"openInRightDock": "Open in right dock",
@@ -320,9 +316,6 @@
"addHost": "Add Host",
"editHost": "Edit Host",
"cloneHost": "Clone Host",
"enableTunnel": "Enable Tunnel",
"enableFileManager": "Enable File Manager",
"enableDocker": "Enable Docker",
"defaultPath": "Default Path",
"connection": "Connection",
"upload": "Upload",
@@ -359,19 +352,17 @@
"behavior": "Behavior",
"scrollbackBuffer": "Scrollback Buffer",
"sshAgentForwarding": "SSH Agent Forwarding",
"startupSnippet": "Startup Snippet",
"selectSnippet": "Select snippet",
"forceKeyboardInteractive": "Force Keyboard-Interactive",
"overrideCredentialUsername": "Override Credential Username",
"overrideCredentialUsernameDesc": "Use the username specified above instead of the credential's username",
"oidcUsernameHint": "Use $oidc.preferred_username to substitute your OIDC login name.",
"oidcUsernameHint": "Use $external.username to fill in the name you signed in with through SSO or LDAP.",
"jumpHostChain": "Jump Host Chain",
"portKnocking": "Port Knocking",
"addKnock": "Add Port",
"addProxyNode": "Add Node",
"proxyNode": "Proxy Node",
"proxyType": "Proxy Type",
"quickActions": "Quick Actions",
"sudoPassword": "Sudo Password",
"keepaliveInterval": "Keepalive Interval (ms)",
"environmentVariables": "Environment Variables",
@@ -468,11 +459,6 @@
"keepaliveIntervalLabel": "Keepalive Interval (seconds)",
"maxKeepaliveMisses": "Max Keepalive Misses",
"sameHost": "This host (direct tunnel)",
"proxmoxLastSyncStatus": {
"success": "Success"
},
"proxmoxResultSkippedNoIp": "{{count}} skipped (no IP found)",
"proxmoxStatsUrlCopied": "Proxmox Stats URL copied to clipboard",
"statusChecksLabel": "Status Checks",
"enableStatusChecks": "Enable Status Checks",
"enableStatusChecksDesc": "Periodically ping this host to verify availability",
@@ -634,8 +620,6 @@
"openInNewTab": "Open in new tab",
"deletedHost": "Deleted {{name}}",
"copiedToClipboard": "Copied to clipboard",
"rdpUrlCopied": "RDP URL copied",
"vncUrlCopied": "VNC URL copied",
"remoteDesktopUrlCopied": "Remote Desktop URL copied",
"expandActions": "Expand actions",
"collapseActions": "Collapse actions",
@@ -755,7 +739,6 @@
"filterAuthKey": "SSH Key",
"filterAuthCredential": "Credential",
"filterAuthNone": "None",
"filterAuthStepca": "Step CA",
"filterProtocolGroup": "Protocol",
"filterProtocolSsh": "SSH",
"filterTagsGroup": "Tags",
@@ -843,24 +826,6 @@
"authOverrideLoadError": "Failed to load your SSH authentication. Please try again.",
"authOverrideSaveError": "Failed to save your SSH authentication"
},
"guac": {
"noCredential": "No credential (direct credentials below)",
"authTypeDirect": "Direct",
"authTypeCredential": "Credential",
"authTypeNone": "None",
"recordingPath": "Recording Path",
"recordingName": "Recording Name",
"saveHostFirst": "Save the host first.",
"sharingOptionsAfterSave": "Sharing options are available after the host has been saved.",
"permissionLevel": "Permission Level",
"typeHeader": "Type",
"targetHeader": "Target",
"permissionHeader": "Permission",
"cancelBtn": "Cancel",
"savingBtn": "Saving...",
"updateHostBtn": "Update Host",
"addHostBtn": "Add Host"
},
"arrangeUnlockedSwitchedToManual": "Switched to manual sort so your order sticks",
"dragToRearrange": "Drag to rearrange",
"arrangeUnlocked": "Unlock drag to rearrange",
@@ -872,7 +837,6 @@
"webUiErrorPathInvalid": "Endpoint {{row}} has an invalid path. Use a path like /admin.",
"copyViewUrlAction": "Copy {{name}} link",
"filterAuthAgent": "SSH Agent",
"filterAuthVault": "Vault",
"authTypeNeedsPlugin": "This host uses {{type}}, which needs {{plugin}}. It is turned off on this server.",
"authTypeUnknown": "This host uses {{type}}, which is not available on this server.",
"authFieldsAfterSave": "Save the host first, then fill in these fields.",
@@ -883,7 +847,11 @@
"localOnlyDesc": "This host is not sent to the server and does not appear on your other devices.",
"folderLocalOnly": "Keep on this device only",
"folderLocalOnlyDesc": "This folder and every host in it stay on this device and are not sent to the server.",
"sudoPasswordDesc": "Used when the terminal fills a sudo prompt, and by features that run commands with sudo."
"sudoPasswordDesc": "Used when the terminal fills a sudo prompt, and by features that run commands with sudo.",
"editorCancel": "Cancel",
"editorSaving": "Saving...",
"editorUpdate": "Update Host",
"editorAdd": "Add Host"
},
"commandPalette": {
"searchPlaceholder": "Search hosts, commands, or settings...",
@@ -980,23 +948,9 @@
"expiresIn": "Expires in {{duration}}",
"search": "Search connections...",
"noSearchResults": "No connections match your search",
"rename": "Rename session",
"sectionSharedWithMe": "Shared with me",
"sharedBy": "Shared by {{username}}",
"join": "Join",
"sharedSessionLabel": "{{hostName}} (shared)"
},
"sessionSharing": {
"permissionLevel": {
"readOnly": "Read-only",
"readWrite": "Read-write"
}
"rename": "Rename session"
},
"terminal": {
"connect": "Connect to Host",
"clear": "Clear",
"paste": "Paste",
"tmuxDetach": "Detach from tmux session",
"totpRequired": "Two-Factor Authentication Required",
"totpCodeLabel": "Verification Code",
"totpVerify": "Verify",
@@ -1011,7 +965,6 @@
"browserSignInOpen": "Open in Browser",
"browserSignInContinue": "I've Completed Sign-in",
"browserSignInRequired": "{{provider}} Sign-in Required",
"sudoPasswordPopupTitle": "Insert Password?",
"connectionLogTitle": "Connection Log",
"connectionLogCopy": "Copy logs to clipboard",
"connectionLogEmpty": "No connection logs yet",
@@ -1019,41 +972,6 @@
"connectionLogCopied": "Connection logs copied to clipboard",
"connectionLogCopyFailed": "Failed to copy logs to clipboard"
},
"transfer": {
"collapseRecentDestinations": "Collapse recent destinations",
"expandRecentDestinations": "Expand recent destinations",
"browseDestination": "Browse or enter path",
"transferring": "Transferring…",
"compressing": "Compressing…",
"extracting": "Extracting…",
"transferringItems": "Transferring {{current}} of {{total}} items…",
"transferPartial": "Transfer completed with {{count}} errors",
"selectThisFolder": "Select this folder",
"metricsTitle": "Transfer timings",
"metricsHopSourceRead": "Source → server: {{throughput}}",
"metricsHopDestSftpWrite": "Server → dest (SFTP): {{throughput}}",
"metricsHopDestLocalWrite": "Server → dest (local): {{throughput}}",
"sourceNotDeletedPartial": "Source files kept (partial transfer)"
},
"tunnels": {
"connect": "Connect",
"disconnect": "Disconnect",
"bindIp": "Local IP",
"remoteAddress": "Remote Address",
"endpointSshConfig": "Endpoint SSH Configuration",
"clientTunnel": "Client Tunnel",
"addClientTunnel": "Add Client Tunnel",
"typeServerLocalDesc": "Current host to endpoint.",
"typeServerRemoteDesc": "Endpoint back to current host.",
"typeClientLocalDesc": "Local computer to endpoint.",
"typeClientRemoteDesc": "Endpoint back to local computer.",
"typeClientDynamicDesc": "SOCKS on local computer.",
"typeDynamicDesc": "Forward SOCKS5 CONNECT traffic through SSH",
"maxRetriesDescription": "Maximum amount of retry attempts.",
"retryIntervalDescription": "Time to wait between retry attempts.",
"local": "Local",
"remote": "Remote"
},
"cardGrid": {
"dragToMove": "Drag to move",
"dragToResize": "Drag to resize",
@@ -1092,7 +1010,7 @@
"external": "External",
"loginWithExternal": "Login with External Provider",
"loginWithExternalDesc": "Login using your configured external identity provider",
"externalNotSupportedInElectron": "External authentication is not supported in the Electron app yet. Please use the web version for OIDC login.",
"externalNotSupportedInElectron": "External sign-in is not supported in the desktop app yet. Please use the web version.",
"loginWithProvider": "Login with {{name}}",
"orContinueWith": "or continue with",
"resetPasswordButton": "Reset Password",
@@ -1141,10 +1059,10 @@
"failedVerifyCode": "Failed to verify reset code",
"failedCompleteReset": "Failed to complete password reset",
"invalidTotpCode": "Invalid TOTP code",
"failedOidcLogin": "Failed to start OIDC login",
"silentSigninOidcUnavailable": "Silent sign-in was requested, but OIDC login is not available.",
"failedOidcLogin": "Failed to start external sign-in",
"silentSigninOidcUnavailable": "Silent sign-in was requested, but no external sign-in is set up.",
"failedUserInfo": "Failed to get user info after login",
"oidcAuthFailed": "OIDC authentication failed",
"oidcAuthFailed": "External sign-in failed",
"invalidAuthUrl": "Invalid authorization URL received from backend",
"requiredField": "This field is required",
"minLength": "Minimum length is {{min}}",
@@ -1172,10 +1090,6 @@
"loginSuccess": "Login successful",
"registrationSuccess": "Registration successful"
},
"profile": {
"c2sTunnelConfigDesc": "Local desktop tunnels targeting configured SSH hosts.",
"c2sTunnelPresetsDesc": "Save this desktop client's local tunnel list as a named server preset, or load a preset back into this client."
},
"placeholders": {
"language": "Language",
"keyPassword": "key password",
@@ -1200,7 +1114,6 @@
"healthy": "Healthy",
"error": "Error",
"totalHosts": "Total Hosts",
"totalTunnels": "Total Tunnels",
"totalCredentials": "Total Credentials",
"recentActivity": "Recent Activity",
"reset": "Reset",
@@ -1220,7 +1133,6 @@
"resetLayout": "Reset to Default",
"serverOverviewCard": "Server Overview",
"recentActivityCard": "Recent Activity",
"networkGraphCard": "Network Graph",
"quickActionsCard": "Quick Actions",
"serverStatsCard": "Server Stats",
"panelMain": "Main",
@@ -1319,9 +1231,6 @@
"oidcAutoProvisionDesc": "Create an account the first time someone signs in through an external login such as SSO or LDAP, even when registration is off",
"secondFactorAfterExternalLogin": "Ask for a second factor after external logins (SSO, GitHub, Google, LDAP)",
"secondFactorAfterExternalLoginDesc": "Off, an enrolled second factor is only asked for after password and other local logins, same as before. On, it is asked for after every login method, including SSO and LDAP.",
"oidcSilentLoginDefault": "Silent external login by default",
"oidcSilentLoginDefaultDesc": "Send visitors straight to the external login provider, skipping the login form",
"oidcSilentLoginDefaultLockedDesc": "This setting is set by the OIDC_SILENT_LOGIN_DEFAULT environment variable and cannot be changed here.",
"allowPasswordReset": "Allow Password Reset",
"allowPasswordResetDesc": "Reset code via Docker logs",
"analyticsEnabled": "Share Anonymous Usage Statistics",
@@ -1380,7 +1289,7 @@
"apiKeyNoExpiry": "No expiry",
"revokedBadge": "REVOKED",
"authTypeDual": "Dual Auth",
"authTypeOidc": "OIDC",
"authTypeOidc": "External",
"authTypeLocal": "Local",
"adminStatusAdministrator": "Administrator",
"adminStatusRegularUser": "Regular User",
@@ -1431,34 +1340,33 @@
"editUserAdminStatus": "Admin Status",
"editUserUserId": "User ID",
"linkAccountTitle": "Link Accounts",
"linkAccountDesc": "Merge the OIDC account {{username}} with an existing local account.",
"linkAccountDescLocal": "Link a local account {{username}} with an existing OIDC-only account.",
"linkAccountDesc": "Merge the external account {{username}} with an existing local account.",
"linkAccountDescLocal": "Link a local account {{username}} with an existing external-only account.",
"linkAccountWarningTitle": "This will:",
"linkAccountEffect1": "Delete the OIDC-only account",
"linkAccountEffect2": "Add OIDC login to the target account",
"linkAccountEffect3": "Allow both OIDC and password login",
"linkAccountEffect1": "Delete the external-only account",
"linkAccountEffect2": "Add its external sign-in to the target account",
"linkAccountEffect3": "Allow both external and password sign-in",
"linkAccountTargetUsername": "Local Account Username",
"linkAccountTargetPlaceholder": "Enter the local account username to link to",
"linkAccountOidcUsername": "OIDC Account Username",
"linkAccountOidcPlaceholder": "Enter the OIDC-only account username to merge in",
"linkAccountOidcNotFound": "No OIDC-only account found with that username",
"linkAccountOidcUsername": "External Account Username",
"linkAccountOidcPlaceholder": "Enter the external-only account username to merge in",
"linkAccountOidcNotFound": "No external-only account found with that username",
"linkAccounts": "Link Accounts",
"linkAccountSuccess": "Accounts linked successfully",
"linkAccountFailed": "Failed to link accounts",
"linkAccountInProgress": "Linking...",
"unlinkAccountTitle": "Unlink OIDC",
"unlinkAccountDesc": "Remove OIDC authentication from {{username}}. They will only be able to log in with their password.",
"unlinkAccountWarning": "This will remove OIDC login from this account. The user must have a password set to continue logging in.",
"unlinkAccount": "Unlink OIDC",
"unlinkAccountTitle": "Unlink External Sign-in",
"unlinkAccountDesc": "Remove external sign-in from {{username}}. They will only be able to log in with their password.",
"unlinkAccountWarning": "This will remove external sign-in from this account. The user must have a password set to keep logging in.",
"unlinkAccount": "Unlink External Sign-in",
"unlinkAccountInProgress": "Unlinking...",
"unlinkAccountSuccess": "OIDC unlinked successfully",
"unlinkAccountFailed": "Failed to unlink OIDC",
"unlinkAccountSuccess": "External sign-in unlinked",
"unlinkAccountFailed": "Failed to unlink external sign-in",
"saving": "Saving...",
"updateRegistrationFailed": "Failed to update registration setting",
"updatePasswordLoginFailed": "Failed to update password login setting",
"updateOidcAutoProvisionFailed": "Failed to update the auto-create setting",
"updateSecondFactorAfterExternalLoginFailed": "Failed to update second factor setting",
"updateOidcSilentLoginDefaultFailed": "Failed to update the silent login setting",
"updatePasswordResetFailed": "Failed to update password reset setting",
"sessionTimeoutRange2": "Session timeout must be between 1 and 720 hours",
"sessionTimeoutSaved": "Session timeout saved",
@@ -1795,7 +1703,7 @@
"importFailed": "Import failed: {{error}}",
"roleUser": "User",
"authMethodDual": "Dual Auth",
"authMethodOidc": "OIDC",
"authMethodOidc": "External",
"done": "Done",
"apiKeyNameRequired": "Key name is required",
"apiKeyCreated": "API key \"{{name}}\" created",
@@ -1910,6 +1818,14 @@
"title": "Open desktop windows",
"consequence": "Only in the Termix desktop app."
},
"users:impersonate": {
"title": "Act as other users",
"consequence": "Runs background work with another user's access, such as scheduled jobs. Every use is written to the audit log."
},
"db:core-refs": {
"title": "Read core account tables",
"consequence": "Can query users, roles and hosts directly from the database."
},
"hosts:read": {
"title": "See your host list",
"consequence": "Names and addresses for hosts you can already see."