mirror of
https://github.com/VibedByKaKi/t3-code-android-nightly.git
synced 2026-10-09 11:51:15 +02:00
109 lines
4 KiB
TypeScript
109 lines
4 KiB
TypeScript
import { NodeHttpServer, NodeServices } from "@effect/platform-node";
|
|
import { assert, it } from "@effect/vitest";
|
|
import * as Effect from "effect/Effect";
|
|
import * as FileSystem from "effect/FileSystem";
|
|
import * as Layer from "effect/Layer";
|
|
import * as Path from "effect/Path";
|
|
import { HttpClient, HttpRouter } from "effect/http";
|
|
|
|
import { makeMockUpdateRouteLayer } from "./mock-update-server.ts";
|
|
import { symlinksSupported } from "@t3tools/shared/testing/symlinks";
|
|
|
|
const withMockUpdateServer = <A, E, R>(rootRealPath: string, effect: Effect.Effect<A, E, R>) =>
|
|
effect.pipe(
|
|
Effect.provide(
|
|
HttpRouter.serve(makeMockUpdateRouteLayer(rootRealPath), {
|
|
disableListenLog: true,
|
|
disableLogger: true,
|
|
}).pipe(Layer.provideMerge(NodeHttpServer.layerTest)),
|
|
),
|
|
);
|
|
|
|
it.layer(NodeServices.layer)("mock-update-server", (it) => {
|
|
it.effect("serves files from the configured root", () =>
|
|
Effect.gen(function* () {
|
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
const path = yield* Path.Path;
|
|
const root = yield* fileSystem.makeTempDirectoryScoped({
|
|
prefix: "mock-update-server-root-",
|
|
});
|
|
const rootRealPath = yield* fileSystem.realPath(root);
|
|
const filePath = path.join(root, "latest.yml");
|
|
|
|
yield* fileSystem.writeFileString(filePath, "version: 0.0.1\n");
|
|
|
|
yield* withMockUpdateServer(
|
|
rootRealPath,
|
|
Effect.gen(function* () {
|
|
const client = yield* HttpClient.HttpClient;
|
|
const response = yield* client.get("/latest.yml");
|
|
|
|
assert.equal(response.status, 200);
|
|
assert.equal(response.headers["content-type"], "text/yaml");
|
|
assert.equal(yield* response.text, "version: 0.0.1\n");
|
|
}),
|
|
);
|
|
}),
|
|
);
|
|
|
|
it.effect("rejects encoded path traversal outside the configured root", () =>
|
|
Effect.gen(function* () {
|
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
const path = yield* Path.Path;
|
|
const root = yield* fileSystem.makeTempDirectoryScoped({
|
|
prefix: "mock-update-server-root-",
|
|
});
|
|
const outside = yield* fileSystem.makeTempDirectoryScoped({
|
|
prefix: "mock-update-server-outside-",
|
|
});
|
|
const rootRealPath = yield* fileSystem.realPath(root);
|
|
|
|
yield* fileSystem.writeFileString(path.join(outside, "secret.txt"), "nope\n");
|
|
|
|
yield* withMockUpdateServer(
|
|
rootRealPath,
|
|
Effect.gen(function* () {
|
|
const client = yield* HttpClient.HttpClient;
|
|
const response = yield* client.get("/%2e%2e/secret.txt");
|
|
|
|
assert.equal(response.status, 404);
|
|
assert.equal(yield* response.text, "Not Found");
|
|
}),
|
|
);
|
|
}),
|
|
);
|
|
|
|
it.effect.skipIf(!symlinksSupported)(
|
|
"rejects symlinked files that escape the configured root",
|
|
() =>
|
|
Effect.gen(function* () {
|
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
const path = yield* Path.Path;
|
|
const root = yield* fileSystem.makeTempDirectoryScoped({
|
|
prefix: "mock-update-server-root-",
|
|
});
|
|
const outside = yield* fileSystem.makeTempDirectoryScoped({
|
|
prefix: "mock-update-server-outside-",
|
|
});
|
|
const rootRealPath = yield* fileSystem.realPath(root);
|
|
const outsideFile = path.join(outside, "outside.yml");
|
|
const linksDir = path.join(root, "links");
|
|
const symlinkPath = path.join(linksDir, "outside.yml");
|
|
|
|
yield* fileSystem.writeFileString(outsideFile, "version: outside\n");
|
|
yield* fileSystem.makeDirectory(linksDir, { recursive: true });
|
|
yield* fileSystem.symlink(outsideFile, symlinkPath);
|
|
|
|
yield* withMockUpdateServer(
|
|
rootRealPath,
|
|
Effect.gen(function* () {
|
|
const client = yield* HttpClient.HttpClient;
|
|
const response = yield* client.get("/links/outside.yml");
|
|
|
|
assert.equal(response.status, 404);
|
|
assert.equal(yield* response.text, "Not Found");
|
|
}),
|
|
);
|
|
}),
|
|
);
|
|
});
|