mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-11-06 02:25:24 +00:00
v26.10.1 (#1599)
* feat: AI translations at release, 7 new languages and regional fallback * fix: proper plural forms for count strings and full translations * fix: plural forms for selected, hidden and active counts * fix: synced plugin updates failing on desktop and server-only plugins shown as stopped * fix: restore rounded corners on app icons and favicon * feat: desktop app auto updates with automatic, ask first or never modes * feat: community and custom plugin registries * feat: plugin guide for AI tools in the SDK with a lint check * fix: keep the terminal WebSocket open past nginx's 60s default (#1588) * chore: update changelog * feat: show plugin download counts only and stop CI builds inflating them * feat: hide installed plugins in the browse tab by default * chore: pin bundled plugins to latest releases * chore: update translations * fix: focusing a saved password field and saving no longer erases it * fix: tell desktop users when their 2.8 data needs 2.9 first * fix: point windows update info at the x64 installer * fix: keep desktop client tunnel sockets alive behind proxies * chore: pin bundled plugins to latest releases * fix: cover client tunnel keepalive in the c2s runtime tests * fix: typing after opening a host no longer goes to the host search * fix: accept tab and = separators in SSH config import (#1598) * chore: update changelog * chore: drop plugin versions from core changelog * chore: update translations * chore: lint, format, and bump version to 26.10.1 --------- Co-authored-by: Darnel Hunter <68697450+innotelinc@users.noreply.github.com> Co-authored-by: Iain <Iain1970@protonmail.com>
This commit is contained in:
174 files changed
+94334
-39995
No files matched your search
@@ -15,6 +15,8 @@ import { PluginLoader } from "../../plugins/loader.js";
|
||||
const testKey = vi.hoisted(() => ({
|
||||
privateKey: null as crypto.KeyObject | null,
|
||||
key: { id: "test", publicKey: "", addedIn: "2.9.0" },
|
||||
communityPrivateKey: null as crypto.KeyObject | null,
|
||||
community: { id: "community", publicKey: "", addedIn: "26.10.1" },
|
||||
}));
|
||||
|
||||
vi.mock("../../plugins/trust.js", async (importActual) => {
|
||||
@@ -23,6 +25,17 @@ vi.mock("../../plugins/trust.js", async (importActual) => {
|
||||
...actual,
|
||||
verifyPluginArtifact: (buffer: Buffer, sha256: string, signature: string) =>
|
||||
actual.verifyPluginArtifact(buffer, sha256, signature, [testKey.key]),
|
||||
verifyAnyTrusted: (buffer: Buffer, sha256: string, signature: string) => {
|
||||
const official = actual.verifyPluginArtifact(buffer, sha256, signature, [
|
||||
testKey.key,
|
||||
]);
|
||||
if (official.ok === true) return { ...official, tier: "official" };
|
||||
const community = actual.verifyPluginArtifact(buffer, sha256, signature, [
|
||||
testKey.community,
|
||||
]);
|
||||
if (community.ok === true) return { ...community, tier: "community" };
|
||||
return community;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@@ -42,6 +55,12 @@ vi.mock("../../database/repositories/factory.js", () => ({
|
||||
.export({ format: "der", type: "spki" })
|
||||
.subarray(12)
|
||||
.toString("base64");
|
||||
const community = crypto.generateKeyPairSync("ed25519");
|
||||
testKey.communityPrivateKey = community.privateKey;
|
||||
testKey.community.publicKey = community.publicKey
|
||||
.export({ format: "der", type: "spki" })
|
||||
.subarray(12)
|
||||
.toString("base64");
|
||||
}
|
||||
|
||||
const cleanups: Array<() => void> = [];
|
||||
@@ -68,7 +87,7 @@ function setup() {
|
||||
async function writeArtifact(
|
||||
dir: string,
|
||||
id: string,
|
||||
sig: "valid" | "wrong-key" | "none",
|
||||
sig: "valid" | "community" | "wrong-key" | "none",
|
||||
version = "1.0.0",
|
||||
): Promise<string> {
|
||||
const build = tempRoot("termix-build-");
|
||||
@@ -82,7 +101,9 @@ async function writeArtifact(
|
||||
const signer =
|
||||
sig === "valid"
|
||||
? testKey.privateKey
|
||||
: crypto.generateKeyPairSync("ed25519").privateKey;
|
||||
: sig === "community"
|
||||
? testKey.communityPrivateKey
|
||||
: crypto.generateKeyPairSync("ed25519").privateKey;
|
||||
const digest = crypto
|
||||
.createHash("sha256")
|
||||
.update(fs.readFileSync(file))
|
||||
@@ -171,6 +192,27 @@ describe("updating a bundled plugin", () => {
|
||||
expect(plugin?.source).toBe("bundled");
|
||||
expect(plugin?.artifact).toBe(file);
|
||||
expect(plugin?.signedBy).toBe("test");
|
||||
expect(plugin?.signedTier).toBe("official");
|
||||
});
|
||||
|
||||
it("keeps the bundled copy for a community signed newer archive", async () => {
|
||||
const { userDir } = setup();
|
||||
await writeArtifact(userDir, "bundled-one", "community", "2.0.0");
|
||||
const loader = new PluginLoader();
|
||||
await loader.loadAll();
|
||||
expect(loader.get("bundled-one")?.manifest.version).toBe("1.0.0");
|
||||
});
|
||||
|
||||
it("loads a community signed plugin and records its tier", async () => {
|
||||
const { userDir } = setup();
|
||||
process.env.TERMIX_REQUIRE_SIGNED_PLUGINS = "true";
|
||||
await writeArtifact(userDir, "community-one", "community");
|
||||
const loader = new PluginLoader();
|
||||
await loader.loadAll();
|
||||
const plugin = loader.get("community-one");
|
||||
expect(plugin?.source).toBe("user");
|
||||
expect(plugin?.signedBy).toBe("community");
|
||||
expect(plugin?.signedTier).toBe("community");
|
||||
});
|
||||
|
||||
it("keeps the bundled copy for an unsigned newer archive", async () => {
|
||||
|
||||
Reference in new issue
Block a user