| 1 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 2 | import { assert, it } from "@effect/vitest"; |
| 3 | import * as HostProcess from "@t3tools/shared/HostProcess"; |
| 4 | import * as Effect from "effect/Effect"; |
| 5 | import * as FileSystem from "effect/FileSystem"; |
| 6 | import * as PlatformError from "effect/PlatformError"; |
| 7 | import { safariPermissionCheck } from "./SafariPermission.ts"; |
| 8 | |
| 9 | it.effect("detects Safari access becoming available without reading or importing cookies", () => |
| 10 | Effect.gen(function* () { |
| 11 | const fs = yield* FileSystem.FileSystem; |
| 12 | const home = yield* fs.makeTempDirectoryScoped({ prefix: "t3-safari-access-" }); |
| 13 | const directory = `${home}/Library/Containers/com.apple.Safari/Data/Library/Cookies`; |
| 14 | yield* fs.makeDirectory(directory, { recursive: true }); |
| 15 | const jar = `${directory}/Cookies.binarycookies`; |
| 16 | yield* fs.writeFileString(jar, "not a valid cookie database"); |
| 17 | let allowed = false; |
| 18 | const guardedFs = FileSystem.FileSystem.of({ |
| 19 | ...fs, |
| 20 | open: (path, options) => |
| 21 | allowed |
| 22 | ? fs.open(path, options) |
| 23 | : Effect.fail( |
| 24 | PlatformError.systemError({ |
| 25 | _tag: "Unknown", |
| 26 | module: "FileSystem", |
| 27 | method: "open", |
| 28 | cause: Object.assign(new Error("operation not permitted"), { code: "EPERM" }), |
| 29 | }), |
| 30 | ), |
| 31 | }); |
| 32 | const check = yield* safariPermissionCheck.pipe( |
| 33 | Effect.provideService(HostProcess.Environment, { HOME: home }), |
| 34 | Effect.provideService(HostProcess.Platform, "darwin"), |
| 35 | Effect.provideService(FileSystem.FileSystem, guardedFs), |
| 36 | ); |
| 37 | assert.isFalse(yield* Effect.promise(check)); |
| 38 | allowed = true; |
| 39 | assert.isTrue(yield* Effect.promise(check)); |
| 40 | yield* fs.remove(jar); |
| 41 | assert.isFalse(yield* Effect.promise(check)); |
| 42 | }).pipe(Effect.provide(NodeServices.layer), Effect.scoped), |
| 43 | ); |
| 44 | |
| 45 | it.effect("recognizes access when cookies exist only in a named Safari profile", () => |
| 46 | Effect.gen(function* () { |
| 47 | const fs = yield* FileSystem.FileSystem; |
| 48 | const home = yield* fs.makeTempDirectoryScoped({ prefix: "t3-safari-named-access-" }); |
| 49 | const check = yield* safariPermissionCheck.pipe( |
| 50 | Effect.provideService(HostProcess.Environment, { HOME: home }), |
| 51 | Effect.provideService(HostProcess.Platform, "darwin"), |
| 52 | ); |
| 53 | assert.isFalse(yield* Effect.promise(check)); |
| 54 | const directory = `${home}/Library/Containers/com.apple.Safari/Data/Library/WebKit/WebsiteDataStore/12345678-1234-1234-1234-123456789abc/Cookies`; |
| 55 | yield* fs.makeDirectory(directory, { recursive: true }); |
| 56 | yield* fs.writeFileString(`${directory}/Cookies.binarycookies`, "not parsed"); |
| 57 | assert.isTrue(yield* Effect.promise(check)); |
| 58 | }).pipe(Effect.provide(NodeServices.layer), Effect.scoped), |
| 59 | ); |