@slicemachine/manager 0.25.2-beta.4 → 0.25.2-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -142,7 +142,7 @@ class PrismicAuthManager {
142
142
  server.once("listening", () => {
143
143
  resolve2();
144
144
  });
145
- server.listen(args.port);
145
+ server.listen(args.port, "127.0.0.1");
146
146
  });
147
147
  if (args.onListenCallback) {
148
148
  args.onListenCallback();
@@ -1 +1 @@
1
- {"version":3,"file":"PrismicAuthManager.cjs","sources":["../../../src/auth/PrismicAuthManager.ts"],"sourcesContent":["import * as t from \"io-ts\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport * as http from \"node:http\";\n\nimport * as h3 from \"h3\";\nimport fetch from \"../lib/fetch\";\nimport cookie from \"cookie\";\nimport cors from \"cors\";\nimport getPort from \"get-port\";\n\nimport { decode } from \"../lib/decode\";\nimport { serializeCookies } from \"../lib/serializeCookies\";\n\nimport { API_ENDPOINTS } from \"../constants/API_ENDPOINTS\";\nimport { SLICE_MACHINE_USER_AGENT } from \"../constants/SLICE_MACHINE_USER_AGENT\";\nimport { createPrismicAuthManagerMiddleware } from \"./createPrismicAuthManagerMiddleware\";\nimport {\n\tInternalError,\n\tUnauthenticatedError,\n\tUnexpectedDataError,\n} from \"../errors\";\n\nconst COOKIE_SEPARATOR = \"; \";\nconst AUTH_COOKIE_KEY = \"prismic-auth\";\nconst SESSION_COOKIE_KEY = \"SESSION\";\n\nconst PERSISTED_AUTH_STATE_FILE_NAME = \".prismic\";\nconst DEFAULT_PERSISTED_AUTH_STATE: PrismicAuthState = {\n\tbase: \"https://prismic.io\",\n\tcookies: {},\n};\n\nconst PrismicAuthState = t.intersection([\n\tt.type({\n\t\tbase: t.string,\n\t\tcookies: t.intersection([\n\t\t\tt.partial({\n\t\t\t\t[AUTH_COOKIE_KEY]: t.string,\n\t\t\t\tSESSION: t.string,\n\t\t\t}),\n\t\t\tt.record(t.string, t.string),\n\t\t]),\n\t}),\n\tt.partial({\n\t\tshortId: t.string,\n\t\tintercomHash: t.string,\n\t\toauthAccessToken: t.string,\n\t\tauthUrl: t.string,\n\t}),\n]);\nexport type PrismicAuthState = t.TypeOf<typeof PrismicAuthState>;\n\nconst PrismicUserProfile = t.exact(\n\tt.type({\n\t\tuserId: t.string,\n\t\tshortId: t.string,\n\t\tintercomHash: t.string,\n\t\temail: t.string,\n\t\tfirstName: t.string,\n\t\tlastName: t.string,\n\t}),\n);\nexport type PrismicUserProfile = t.TypeOf<typeof PrismicUserProfile>;\n\ntype PrismicAuthManagerConstructorArgs = {\n\tscopedDirectory?: string;\n};\n\ntype PrismicAuthManagerLoginArgs = {\n\temail: string;\n\tcookies: string[];\n};\n\ntype PrismicAuthManagerGetLoginSessionInfoReturnType = {\n\tport: number;\n\turl: string;\n};\n\ntype PrismicAuthManagerNodeLoginSessionArgs = {\n\tport: number;\n\tonListenCallback?: () => void;\n};\n\ntype GetProfileForAuthenticationTokenArgs = {\n\tauthenticationToken: string;\n};\n\nconst checkHasAuthenticationToken = (\n\tauthState: PrismicAuthState,\n): authState is PrismicAuthState & {\n\tcookies: Required<\n\t\tPick<\n\t\t\tPrismicAuthState[\"cookies\"],\n\t\t\ttypeof AUTH_COOKIE_KEY | typeof SESSION_COOKIE_KEY\n\t\t>\n\t>;\n} => {\n\treturn Boolean(\n\t\tauthState.cookies[AUTH_COOKIE_KEY] && authState.cookies[SESSION_COOKIE_KEY],\n\t);\n};\n\nconst parseCookies = (cookies: string): Record<string, string> => {\n\treturn cookie.parse(cookies, {\n\t\t// Don't escape any values.\n\t\tdecode: (value) => value,\n\t});\n};\n\nexport class PrismicAuthManager {\n\t// TODO: Automatically scope the manager to the current Slice Machine\n\t// project? If not, this internal state can be removed.\n\tscopedDirectory: string;\n\n\tconstructor({\n\t\tscopedDirectory = os.homedir(),\n\t}: PrismicAuthManagerConstructorArgs = {}) {\n\t\tthis.scopedDirectory = scopedDirectory;\n\t}\n\n\t// TODO: Make the `cookies` argument more explicit. What are these\n\t// mysterious cookies?\n\tasync login(args: PrismicAuthManagerLoginArgs): Promise<void> {\n\t\tconst authState = await this._readPersistedAuthState();\n\n\t\t// Set the auth's URL base to the current base at runtime.\n\t\tauthState.base = API_ENDPOINTS.PrismicWroom;\n\t\tauthState.cookies = {\n\t\t\t...authState.cookies,\n\t\t\t...parseCookies(args.cookies.join(COOKIE_SEPARATOR)),\n\t\t};\n\n\t\tif (checkHasAuthenticationToken(authState)) {\n\t\t\tconst authenticationToken = authState.cookies[AUTH_COOKIE_KEY];\n\t\t\tconst profile = await this._getProfileForAuthenticationToken({\n\t\t\t\tauthenticationToken,\n\t\t\t});\n\n\t\t\tauthState.shortId = profile.shortId;\n\t\t\tauthState.intercomHash = profile.intercomHash;\n\t\t}\n\n\t\tawait this._writePersistedAuthState(authState);\n\t}\n\n\tasync getLoginSessionInfo(): Promise<PrismicAuthManagerGetLoginSessionInfoReturnType> {\n\t\t// Pick a random port, with a preference for historic `5555`\n\t\tconst port = await getPort({ port: 5555 });\n\n\t\tconst url = new URL(\n\t\t\t`./dashboard/cli/login?source=slice-machine&port=${port}`,\n\t\t\tAPI_ENDPOINTS.PrismicWroom,\n\t\t).toString();\n\n\t\treturn {\n\t\t\tport,\n\t\t\turl,\n\t\t};\n\t}\n\n\tasync nodeLoginSession(\n\t\targs: PrismicAuthManagerNodeLoginSessionArgs,\n\t): Promise<void> {\n\t\treturn new Promise<void>(async (resolve) => {\n\t\t\t// Timeout attempt after 3 minutes\n\t\t\tconst timeout = setTimeout(() => {\n\t\t\t\tserver.close();\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Login timeout, server did not receive a response within a 3-minute delay\",\n\t\t\t\t);\n\t\t\t}, 180_000);\n\n\t\t\tconst app = h3.createApp();\n\t\t\tapp.use(h3.fromNodeMiddleware(cors()));\n\t\t\tapp.use(\n\t\t\t\th3.fromNodeMiddleware(\n\t\t\t\t\tcreatePrismicAuthManagerMiddleware({\n\t\t\t\t\t\tprismicAuthManager: this,\n\t\t\t\t\t\tonLoginCallback() {\n\t\t\t\t\t\t\t// Cleanup process and resolve\n\t\t\t\t\t\t\tclearTimeout(timeout);\n\t\t\t\t\t\t\tserver.close();\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t);\n\n\t\t\t// Start server\n\t\t\tconst server = http.createServer(h3.toNodeListener(app));\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tserver.once(\"listening\", () => {\n\t\t\t\t\tresolve();\n\t\t\t\t});\n\t\t\t\tserver.listen(args.port);\n\t\t\t});\n\n\t\t\tif (args.onListenCallback) {\n\t\t\t\targs.onListenCallback();\n\t\t\t}\n\t\t});\n\t}\n\n\tasync logout(): Promise<void> {\n\t\tconst authState = await this._readPersistedAuthState();\n\n\t\t// Remove all Prismic cookies, short ID, and Intercom hash\n\t\t// associated with the currently logged in user.\n\t\tauthState.cookies = {};\n\t\tauthState.shortId = undefined;\n\t\tauthState.intercomHash = undefined;\n\n\t\tawait this._writePersistedAuthState(authState);\n\t}\n\n\tasync checkIsLoggedIn(): Promise<boolean> {\n\t\tconst authState = await this._readPersistedAuthState();\n\n\t\tif (checkHasAuthenticationToken(authState)) {\n\t\t\tconst url = new URL(\"./validate\", API_ENDPOINTS.PrismicAuthentication);\n\t\t\turl.searchParams.set(\"token\", authState.cookies[AUTH_COOKIE_KEY]);\n\n\t\t\tlet res;\n\t\t\ttry {\n\t\t\t\tres = await fetch(url.toString(), {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"User-Agent\": SLICE_MACHINE_USER_AGENT,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\t// Noop, we return if `res` is not defined.\n\t\t\t}\n\n\t\t\tif (!res || !res.ok) {\n\t\t\t\tawait this.logout();\n\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tasync getAuthenticationCookies(): Promise<\n\t\tPrismicAuthState[\"cookies\"] &\n\t\t\tRequired<\n\t\t\t\tPick<\n\t\t\t\t\tPrismicAuthState[\"cookies\"],\n\t\t\t\t\ttypeof AUTH_COOKIE_KEY | typeof SESSION_COOKIE_KEY\n\t\t\t\t>\n\t\t\t>\n\t> {\n\t\tconst isLoggedIn = await this.checkIsLoggedIn();\n\n\t\tif (isLoggedIn) {\n\t\t\tconst authState = await this._readPersistedAuthState();\n\n\t\t\tif (checkHasAuthenticationToken(authState)) {\n\t\t\t\treturn authState.cookies;\n\t\t\t}\n\t\t}\n\n\t\tthrow new UnauthenticatedError();\n\t}\n\n\tasync getAuthenticationToken(): Promise<string> {\n\t\tconst cookies = await this.getAuthenticationCookies();\n\n\t\treturn cookies[AUTH_COOKIE_KEY];\n\t}\n\n\tasync refreshAuthenticationToken(): Promise<void> {\n\t\tconst authState = await this._readPersistedAuthState();\n\n\t\tif (checkHasAuthenticationToken(authState)) {\n\t\t\tconst url = new URL(\n\t\t\t\t\"./refreshtoken\",\n\t\t\t\tAPI_ENDPOINTS.PrismicAuthentication,\n\t\t\t);\n\t\t\turl.searchParams.set(\"token\", authState.cookies[AUTH_COOKIE_KEY]);\n\n\t\t\tconst res = await fetch(url.toString(), {\n\t\t\t\theaders: {\n\t\t\t\t\t\"User-Agent\": SLICE_MACHINE_USER_AGENT,\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst text = await res.text();\n\n\t\t\tif (res.ok) {\n\t\t\t\tauthState.cookies[AUTH_COOKIE_KEY] = text;\n\n\t\t\t\tawait this._writePersistedAuthState(authState);\n\t\t\t} else {\n\t\t\t\tthrow new InternalError(\"Failed to refresh authentication token.\", {\n\t\t\t\t\tcause: text,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new UnauthenticatedError();\n\t\t}\n\t}\n\n\tasync getProfile(): Promise<PrismicUserProfile> {\n\t\tconst authenticationToken = await this.getAuthenticationToken();\n\n\t\treturn await this._getProfileForAuthenticationToken({\n\t\t\tauthenticationToken,\n\t\t});\n\t}\n\n\tprivate async _getProfileForAuthenticationToken(\n\t\targs: GetProfileForAuthenticationTokenArgs,\n\t): Promise<PrismicUserProfile> {\n\t\tconst url = new URL(\"./profile\", API_ENDPOINTS.PrismicUser);\n\t\tconst res = await fetch(url.toString(), {\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${args.authenticationToken}`,\n\t\t\t\t\"User-Agent\": SLICE_MACHINE_USER_AGENT,\n\t\t\t},\n\t\t});\n\n\t\tif (res.ok) {\n\t\t\tconst json = await res.json();\n\t\t\tconst { value: profile, error } = decode(PrismicUserProfile, json);\n\n\t\t\tif (error) {\n\t\t\t\tthrow new UnexpectedDataError(\n\t\t\t\t\t\"Received invalid data from the Prismic user service.\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn profile;\n\t\t} else {\n\t\t\tconst text = await res.text();\n\t\t\tthrow new InternalError(\n\t\t\t\t\"Failed to retrieve profile from the Prismic user service.\",\n\t\t\t\t{\n\t\t\t\t\tcause: text,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async _readPersistedAuthState(): Promise<PrismicAuthState> {\n\t\tconst authStateFilePath = this._getPersistedAuthStateFilePath();\n\n\t\tlet authStateFileContents: string = JSON.stringify({});\n\t\tlet rawAuthState: Record<string, unknown> = {};\n\n\t\ttry {\n\t\t\tauthStateFileContents = await fs.readFile(authStateFilePath, \"utf8\");\n\t\t\trawAuthState = JSON.parse(authStateFileContents);\n\t\t} catch {\n\t\t\t// Write a default persisted state if it doesn't already exist.\n\n\t\t\trawAuthState = {\n\t\t\t\t...DEFAULT_PERSISTED_AUTH_STATE,\n\t\t\t\tcookies: serializeCookies(DEFAULT_PERSISTED_AUTH_STATE.cookies),\n\t\t\t};\n\t\t\tauthStateFileContents = JSON.stringify(rawAuthState, null, \"\\t\");\n\n\t\t\tawait fs.mkdir(path.dirname(authStateFilePath), { recursive: true });\n\t\t\tawait fs.writeFile(authStateFilePath, authStateFileContents);\n\t\t}\n\n\t\t// Decode cookies into a record for convenience.\n\t\tif (typeof rawAuthState.cookies === \"string\") {\n\t\t\trawAuthState.cookies = parseCookies(rawAuthState.cookies);\n\t\t}\n\n\t\tconst { value: authState, error } = decode(PrismicAuthState, rawAuthState);\n\n\t\tif (error) {\n\t\t\tthrow new UnexpectedDataError(\"Prismic authentication state is invalid.\");\n\t\t}\n\n\t\treturn authState;\n\t}\n\n\tprivate async _writePersistedAuthState(\n\t\tauthState: PrismicAuthState,\n\t): Promise<void> {\n\t\tconst authStateFilePath = this._getPersistedAuthStateFilePath();\n\n\t\tconst preparedAuthState = {\n\t\t\t...authState,\n\t\t\tcookies: serializeCookies(authState.cookies),\n\t\t};\n\n\t\ttry {\n\t\t\tawait fs.writeFile(\n\t\t\t\tauthStateFilePath,\n\t\t\t\tJSON.stringify(preparedAuthState, null, 2),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthrow new InternalError(\n\t\t\t\t\"Failed to write Prismic authentication state to the file system.\",\n\t\t\t\t{\n\t\t\t\t\tcause: error,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate _getPersistedAuthStateFilePath(): string {\n\t\treturn path.resolve(this.scopedDirectory, PERSISTED_AUTH_STATE_FILE_NAME);\n\t}\n}\n"],"names":["t","os","API_ENDPOINTS","getPort","h3","createPrismicAuthManagerMiddleware","http","resolve","fetch","SLICE_MACHINE_USER_AGENT","UnauthenticatedError","InternalError","decode","UnexpectedDataError","fs","serializeCookies","path"],"mappings":"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"}
1
+ {"version":3,"file":"PrismicAuthManager.cjs","sources":["../../../src/auth/PrismicAuthManager.ts"],"sourcesContent":["import * as t from \"io-ts\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport * as http from \"node:http\";\n\nimport * as h3 from \"h3\";\nimport fetch from \"../lib/fetch\";\nimport cookie from \"cookie\";\nimport cors from \"cors\";\nimport getPort from \"get-port\";\n\nimport { decode } from \"../lib/decode\";\nimport { serializeCookies } from \"../lib/serializeCookies\";\n\nimport { API_ENDPOINTS } from \"../constants/API_ENDPOINTS\";\nimport { SLICE_MACHINE_USER_AGENT } from \"../constants/SLICE_MACHINE_USER_AGENT\";\nimport { createPrismicAuthManagerMiddleware } from \"./createPrismicAuthManagerMiddleware\";\nimport {\n\tInternalError,\n\tUnauthenticatedError,\n\tUnexpectedDataError,\n} from \"../errors\";\n\nconst COOKIE_SEPARATOR = \"; \";\nconst AUTH_COOKIE_KEY = \"prismic-auth\";\nconst SESSION_COOKIE_KEY = \"SESSION\";\n\nconst PERSISTED_AUTH_STATE_FILE_NAME = \".prismic\";\nconst DEFAULT_PERSISTED_AUTH_STATE: PrismicAuthState = {\n\tbase: \"https://prismic.io\",\n\tcookies: {},\n};\n\nconst PrismicAuthState = t.intersection([\n\tt.type({\n\t\tbase: t.string,\n\t\tcookies: t.intersection([\n\t\t\tt.partial({\n\t\t\t\t[AUTH_COOKIE_KEY]: t.string,\n\t\t\t\tSESSION: t.string,\n\t\t\t}),\n\t\t\tt.record(t.string, t.string),\n\t\t]),\n\t}),\n\tt.partial({\n\t\tshortId: t.string,\n\t\tintercomHash: t.string,\n\t\toauthAccessToken: t.string,\n\t\tauthUrl: t.string,\n\t}),\n]);\nexport type PrismicAuthState = t.TypeOf<typeof PrismicAuthState>;\n\nconst PrismicUserProfile = t.exact(\n\tt.type({\n\t\tuserId: t.string,\n\t\tshortId: t.string,\n\t\tintercomHash: t.string,\n\t\temail: t.string,\n\t\tfirstName: t.string,\n\t\tlastName: t.string,\n\t}),\n);\nexport type PrismicUserProfile = t.TypeOf<typeof PrismicUserProfile>;\n\ntype PrismicAuthManagerConstructorArgs = {\n\tscopedDirectory?: string;\n};\n\ntype PrismicAuthManagerLoginArgs = {\n\temail: string;\n\tcookies: string[];\n};\n\ntype PrismicAuthManagerGetLoginSessionInfoReturnType = {\n\tport: number;\n\turl: string;\n};\n\ntype PrismicAuthManagerNodeLoginSessionArgs = {\n\tport: number;\n\tonListenCallback?: () => void;\n};\n\ntype GetProfileForAuthenticationTokenArgs = {\n\tauthenticationToken: string;\n};\n\nconst checkHasAuthenticationToken = (\n\tauthState: PrismicAuthState,\n): authState is PrismicAuthState & {\n\tcookies: Required<\n\t\tPick<\n\t\t\tPrismicAuthState[\"cookies\"],\n\t\t\ttypeof AUTH_COOKIE_KEY | typeof SESSION_COOKIE_KEY\n\t\t>\n\t>;\n} => {\n\treturn Boolean(\n\t\tauthState.cookies[AUTH_COOKIE_KEY] && authState.cookies[SESSION_COOKIE_KEY],\n\t);\n};\n\nconst parseCookies = (cookies: string): Record<string, string> => {\n\treturn cookie.parse(cookies, {\n\t\t// Don't escape any values.\n\t\tdecode: (value) => value,\n\t});\n};\n\nexport class PrismicAuthManager {\n\t// TODO: Automatically scope the manager to the current Slice Machine\n\t// project? If not, this internal state can be removed.\n\tscopedDirectory: string;\n\n\tconstructor({\n\t\tscopedDirectory = os.homedir(),\n\t}: PrismicAuthManagerConstructorArgs = {}) {\n\t\tthis.scopedDirectory = scopedDirectory;\n\t}\n\n\t// TODO: Make the `cookies` argument more explicit. What are these\n\t// mysterious cookies?\n\tasync login(args: PrismicAuthManagerLoginArgs): Promise<void> {\n\t\tconst authState = await this._readPersistedAuthState();\n\n\t\t// Set the auth's URL base to the current base at runtime.\n\t\tauthState.base = API_ENDPOINTS.PrismicWroom;\n\t\tauthState.cookies = {\n\t\t\t...authState.cookies,\n\t\t\t...parseCookies(args.cookies.join(COOKIE_SEPARATOR)),\n\t\t};\n\n\t\tif (checkHasAuthenticationToken(authState)) {\n\t\t\tconst authenticationToken = authState.cookies[AUTH_COOKIE_KEY];\n\t\t\tconst profile = await this._getProfileForAuthenticationToken({\n\t\t\t\tauthenticationToken,\n\t\t\t});\n\n\t\t\tauthState.shortId = profile.shortId;\n\t\t\tauthState.intercomHash = profile.intercomHash;\n\t\t}\n\n\t\tawait this._writePersistedAuthState(authState);\n\t}\n\n\tasync getLoginSessionInfo(): Promise<PrismicAuthManagerGetLoginSessionInfoReturnType> {\n\t\t// Pick a random port, with a preference for historic `5555`\n\t\tconst port = await getPort({ port: 5555 });\n\n\t\tconst url = new URL(\n\t\t\t`./dashboard/cli/login?source=slice-machine&port=${port}`,\n\t\t\tAPI_ENDPOINTS.PrismicWroom,\n\t\t).toString();\n\n\t\treturn {\n\t\t\tport,\n\t\t\turl,\n\t\t};\n\t}\n\n\tasync nodeLoginSession(\n\t\targs: PrismicAuthManagerNodeLoginSessionArgs,\n\t): Promise<void> {\n\t\treturn new Promise<void>(async (resolve) => {\n\t\t\t// Timeout attempt after 3 minutes\n\t\t\tconst timeout = setTimeout(() => {\n\t\t\t\tserver.close();\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Login timeout, server did not receive a response within a 3-minute delay\",\n\t\t\t\t);\n\t\t\t}, 180_000);\n\n\t\t\tconst app = h3.createApp();\n\t\t\tapp.use(h3.fromNodeMiddleware(cors()));\n\t\t\tapp.use(\n\t\t\t\th3.fromNodeMiddleware(\n\t\t\t\t\tcreatePrismicAuthManagerMiddleware({\n\t\t\t\t\t\tprismicAuthManager: this,\n\t\t\t\t\t\tonLoginCallback() {\n\t\t\t\t\t\t\t// Cleanup process and resolve\n\t\t\t\t\t\t\tclearTimeout(timeout);\n\t\t\t\t\t\t\tserver.close();\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t);\n\n\t\t\t// Start server\n\t\t\tconst server = http.createServer(h3.toNodeListener(app));\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tserver.once(\"listening\", () => {\n\t\t\t\t\tresolve();\n\t\t\t\t});\n\t\t\t\tserver.listen(args.port, \"127.0.0.1\");\n\t\t\t});\n\n\t\t\tif (args.onListenCallback) {\n\t\t\t\targs.onListenCallback();\n\t\t\t}\n\t\t});\n\t}\n\n\tasync logout(): Promise<void> {\n\t\tconst authState = await this._readPersistedAuthState();\n\n\t\t// Remove all Prismic cookies, short ID, and Intercom hash\n\t\t// associated with the currently logged in user.\n\t\tauthState.cookies = {};\n\t\tauthState.shortId = undefined;\n\t\tauthState.intercomHash = undefined;\n\n\t\tawait this._writePersistedAuthState(authState);\n\t}\n\n\tasync checkIsLoggedIn(): Promise<boolean> {\n\t\tconst authState = await this._readPersistedAuthState();\n\n\t\tif (checkHasAuthenticationToken(authState)) {\n\t\t\tconst url = new URL(\"./validate\", API_ENDPOINTS.PrismicAuthentication);\n\t\t\turl.searchParams.set(\"token\", authState.cookies[AUTH_COOKIE_KEY]);\n\n\t\t\tlet res;\n\t\t\ttry {\n\t\t\t\tres = await fetch(url.toString(), {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"User-Agent\": SLICE_MACHINE_USER_AGENT,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\t// Noop, we return if `res` is not defined.\n\t\t\t}\n\n\t\t\tif (!res || !res.ok) {\n\t\t\t\tawait this.logout();\n\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tasync getAuthenticationCookies(): Promise<\n\t\tPrismicAuthState[\"cookies\"] &\n\t\t\tRequired<\n\t\t\t\tPick<\n\t\t\t\t\tPrismicAuthState[\"cookies\"],\n\t\t\t\t\ttypeof AUTH_COOKIE_KEY | typeof SESSION_COOKIE_KEY\n\t\t\t\t>\n\t\t\t>\n\t> {\n\t\tconst isLoggedIn = await this.checkIsLoggedIn();\n\n\t\tif (isLoggedIn) {\n\t\t\tconst authState = await this._readPersistedAuthState();\n\n\t\t\tif (checkHasAuthenticationToken(authState)) {\n\t\t\t\treturn authState.cookies;\n\t\t\t}\n\t\t}\n\n\t\tthrow new UnauthenticatedError();\n\t}\n\n\tasync getAuthenticationToken(): Promise<string> {\n\t\tconst cookies = await this.getAuthenticationCookies();\n\n\t\treturn cookies[AUTH_COOKIE_KEY];\n\t}\n\n\tasync refreshAuthenticationToken(): Promise<void> {\n\t\tconst authState = await this._readPersistedAuthState();\n\n\t\tif (checkHasAuthenticationToken(authState)) {\n\t\t\tconst url = new URL(\n\t\t\t\t\"./refreshtoken\",\n\t\t\t\tAPI_ENDPOINTS.PrismicAuthentication,\n\t\t\t);\n\t\t\turl.searchParams.set(\"token\", authState.cookies[AUTH_COOKIE_KEY]);\n\n\t\t\tconst res = await fetch(url.toString(), {\n\t\t\t\theaders: {\n\t\t\t\t\t\"User-Agent\": SLICE_MACHINE_USER_AGENT,\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst text = await res.text();\n\n\t\t\tif (res.ok) {\n\t\t\t\tauthState.cookies[AUTH_COOKIE_KEY] = text;\n\n\t\t\t\tawait this._writePersistedAuthState(authState);\n\t\t\t} else {\n\t\t\t\tthrow new InternalError(\"Failed to refresh authentication token.\", {\n\t\t\t\t\tcause: text,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new UnauthenticatedError();\n\t\t}\n\t}\n\n\tasync getProfile(): Promise<PrismicUserProfile> {\n\t\tconst authenticationToken = await this.getAuthenticationToken();\n\n\t\treturn await this._getProfileForAuthenticationToken({\n\t\t\tauthenticationToken,\n\t\t});\n\t}\n\n\tprivate async _getProfileForAuthenticationToken(\n\t\targs: GetProfileForAuthenticationTokenArgs,\n\t): Promise<PrismicUserProfile> {\n\t\tconst url = new URL(\"./profile\", API_ENDPOINTS.PrismicUser);\n\t\tconst res = await fetch(url.toString(), {\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${args.authenticationToken}`,\n\t\t\t\t\"User-Agent\": SLICE_MACHINE_USER_AGENT,\n\t\t\t},\n\t\t});\n\n\t\tif (res.ok) {\n\t\t\tconst json = await res.json();\n\t\t\tconst { value: profile, error } = decode(PrismicUserProfile, json);\n\n\t\t\tif (error) {\n\t\t\t\tthrow new UnexpectedDataError(\n\t\t\t\t\t\"Received invalid data from the Prismic user service.\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn profile;\n\t\t} else {\n\t\t\tconst text = await res.text();\n\t\t\tthrow new InternalError(\n\t\t\t\t\"Failed to retrieve profile from the Prismic user service.\",\n\t\t\t\t{\n\t\t\t\t\tcause: text,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async _readPersistedAuthState(): Promise<PrismicAuthState> {\n\t\tconst authStateFilePath = this._getPersistedAuthStateFilePath();\n\n\t\tlet authStateFileContents: string = JSON.stringify({});\n\t\tlet rawAuthState: Record<string, unknown> = {};\n\n\t\ttry {\n\t\t\tauthStateFileContents = await fs.readFile(authStateFilePath, \"utf8\");\n\t\t\trawAuthState = JSON.parse(authStateFileContents);\n\t\t} catch {\n\t\t\t// Write a default persisted state if it doesn't already exist.\n\n\t\t\trawAuthState = {\n\t\t\t\t...DEFAULT_PERSISTED_AUTH_STATE,\n\t\t\t\tcookies: serializeCookies(DEFAULT_PERSISTED_AUTH_STATE.cookies),\n\t\t\t};\n\t\t\tauthStateFileContents = JSON.stringify(rawAuthState, null, \"\\t\");\n\n\t\t\tawait fs.mkdir(path.dirname(authStateFilePath), { recursive: true });\n\t\t\tawait fs.writeFile(authStateFilePath, authStateFileContents);\n\t\t}\n\n\t\t// Decode cookies into a record for convenience.\n\t\tif (typeof rawAuthState.cookies === \"string\") {\n\t\t\trawAuthState.cookies = parseCookies(rawAuthState.cookies);\n\t\t}\n\n\t\tconst { value: authState, error } = decode(PrismicAuthState, rawAuthState);\n\n\t\tif (error) {\n\t\t\tthrow new UnexpectedDataError(\"Prismic authentication state is invalid.\");\n\t\t}\n\n\t\treturn authState;\n\t}\n\n\tprivate async _writePersistedAuthState(\n\t\tauthState: PrismicAuthState,\n\t): Promise<void> {\n\t\tconst authStateFilePath = this._getPersistedAuthStateFilePath();\n\n\t\tconst preparedAuthState = {\n\t\t\t...authState,\n\t\t\tcookies: serializeCookies(authState.cookies),\n\t\t};\n\n\t\ttry {\n\t\t\tawait fs.writeFile(\n\t\t\t\tauthStateFilePath,\n\t\t\t\tJSON.stringify(preparedAuthState, null, 2),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthrow new InternalError(\n\t\t\t\t\"Failed to write Prismic authentication state to the file system.\",\n\t\t\t\t{\n\t\t\t\t\tcause: error,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate _getPersistedAuthStateFilePath(): string {\n\t\treturn path.resolve(this.scopedDirectory, PERSISTED_AUTH_STATE_FILE_NAME);\n\t}\n}\n"],"names":["t","os","API_ENDPOINTS","getPort","h3","createPrismicAuthManagerMiddleware","http","resolve","fetch","SLICE_MACHINE_USER_AGENT","UnauthenticatedError","InternalError","decode","UnexpectedDataError","fs","serializeCookies","path"],"mappings":"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"}
@@ -118,7 +118,7 @@ class PrismicAuthManager {
118
118
  server.once("listening", () => {
119
119
  resolve2();
120
120
  });
121
- server.listen(args.port);
121
+ server.listen(args.port, "127.0.0.1");
122
122
  });
123
123
  if (args.onListenCallback) {
124
124
  args.onListenCallback();
@@ -1 +1 @@
1
- {"version":3,"file":"PrismicAuthManager.js","sources":["../../../src/auth/PrismicAuthManager.ts"],"sourcesContent":["import * as t from \"io-ts\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport * as http from \"node:http\";\n\nimport * as h3 from \"h3\";\nimport fetch from \"../lib/fetch\";\nimport cookie from \"cookie\";\nimport cors from \"cors\";\nimport getPort from \"get-port\";\n\nimport { decode } from \"../lib/decode\";\nimport { serializeCookies } from \"../lib/serializeCookies\";\n\nimport { API_ENDPOINTS } from \"../constants/API_ENDPOINTS\";\nimport { SLICE_MACHINE_USER_AGENT } from \"../constants/SLICE_MACHINE_USER_AGENT\";\nimport { createPrismicAuthManagerMiddleware } from \"./createPrismicAuthManagerMiddleware\";\nimport {\n\tInternalError,\n\tUnauthenticatedError,\n\tUnexpectedDataError,\n} from \"../errors\";\n\nconst COOKIE_SEPARATOR = \"; \";\nconst AUTH_COOKIE_KEY = \"prismic-auth\";\nconst SESSION_COOKIE_KEY = \"SESSION\";\n\nconst PERSISTED_AUTH_STATE_FILE_NAME = \".prismic\";\nconst DEFAULT_PERSISTED_AUTH_STATE: PrismicAuthState = {\n\tbase: \"https://prismic.io\",\n\tcookies: {},\n};\n\nconst PrismicAuthState = t.intersection([\n\tt.type({\n\t\tbase: t.string,\n\t\tcookies: t.intersection([\n\t\t\tt.partial({\n\t\t\t\t[AUTH_COOKIE_KEY]: t.string,\n\t\t\t\tSESSION: t.string,\n\t\t\t}),\n\t\t\tt.record(t.string, t.string),\n\t\t]),\n\t}),\n\tt.partial({\n\t\tshortId: t.string,\n\t\tintercomHash: t.string,\n\t\toauthAccessToken: t.string,\n\t\tauthUrl: t.string,\n\t}),\n]);\nexport type PrismicAuthState = t.TypeOf<typeof PrismicAuthState>;\n\nconst PrismicUserProfile = t.exact(\n\tt.type({\n\t\tuserId: t.string,\n\t\tshortId: t.string,\n\t\tintercomHash: t.string,\n\t\temail: t.string,\n\t\tfirstName: t.string,\n\t\tlastName: t.string,\n\t}),\n);\nexport type PrismicUserProfile = t.TypeOf<typeof PrismicUserProfile>;\n\ntype PrismicAuthManagerConstructorArgs = {\n\tscopedDirectory?: string;\n};\n\ntype PrismicAuthManagerLoginArgs = {\n\temail: string;\n\tcookies: string[];\n};\n\ntype PrismicAuthManagerGetLoginSessionInfoReturnType = {\n\tport: number;\n\turl: string;\n};\n\ntype PrismicAuthManagerNodeLoginSessionArgs = {\n\tport: number;\n\tonListenCallback?: () => void;\n};\n\ntype GetProfileForAuthenticationTokenArgs = {\n\tauthenticationToken: string;\n};\n\nconst checkHasAuthenticationToken = (\n\tauthState: PrismicAuthState,\n): authState is PrismicAuthState & {\n\tcookies: Required<\n\t\tPick<\n\t\t\tPrismicAuthState[\"cookies\"],\n\t\t\ttypeof AUTH_COOKIE_KEY | typeof SESSION_COOKIE_KEY\n\t\t>\n\t>;\n} => {\n\treturn Boolean(\n\t\tauthState.cookies[AUTH_COOKIE_KEY] && authState.cookies[SESSION_COOKIE_KEY],\n\t);\n};\n\nconst parseCookies = (cookies: string): Record<string, string> => {\n\treturn cookie.parse(cookies, {\n\t\t// Don't escape any values.\n\t\tdecode: (value) => value,\n\t});\n};\n\nexport class PrismicAuthManager {\n\t// TODO: Automatically scope the manager to the current Slice Machine\n\t// project? If not, this internal state can be removed.\n\tscopedDirectory: string;\n\n\tconstructor({\n\t\tscopedDirectory = os.homedir(),\n\t}: PrismicAuthManagerConstructorArgs = {}) {\n\t\tthis.scopedDirectory = scopedDirectory;\n\t}\n\n\t// TODO: Make the `cookies` argument more explicit. What are these\n\t// mysterious cookies?\n\tasync login(args: PrismicAuthManagerLoginArgs): Promise<void> {\n\t\tconst authState = await this._readPersistedAuthState();\n\n\t\t// Set the auth's URL base to the current base at runtime.\n\t\tauthState.base = API_ENDPOINTS.PrismicWroom;\n\t\tauthState.cookies = {\n\t\t\t...authState.cookies,\n\t\t\t...parseCookies(args.cookies.join(COOKIE_SEPARATOR)),\n\t\t};\n\n\t\tif (checkHasAuthenticationToken(authState)) {\n\t\t\tconst authenticationToken = authState.cookies[AUTH_COOKIE_KEY];\n\t\t\tconst profile = await this._getProfileForAuthenticationToken({\n\t\t\t\tauthenticationToken,\n\t\t\t});\n\n\t\t\tauthState.shortId = profile.shortId;\n\t\t\tauthState.intercomHash = profile.intercomHash;\n\t\t}\n\n\t\tawait this._writePersistedAuthState(authState);\n\t}\n\n\tasync getLoginSessionInfo(): Promise<PrismicAuthManagerGetLoginSessionInfoReturnType> {\n\t\t// Pick a random port, with a preference for historic `5555`\n\t\tconst port = await getPort({ port: 5555 });\n\n\t\tconst url = new URL(\n\t\t\t`./dashboard/cli/login?source=slice-machine&port=${port}`,\n\t\t\tAPI_ENDPOINTS.PrismicWroom,\n\t\t).toString();\n\n\t\treturn {\n\t\t\tport,\n\t\t\turl,\n\t\t};\n\t}\n\n\tasync nodeLoginSession(\n\t\targs: PrismicAuthManagerNodeLoginSessionArgs,\n\t): Promise<void> {\n\t\treturn new Promise<void>(async (resolve) => {\n\t\t\t// Timeout attempt after 3 minutes\n\t\t\tconst timeout = setTimeout(() => {\n\t\t\t\tserver.close();\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Login timeout, server did not receive a response within a 3-minute delay\",\n\t\t\t\t);\n\t\t\t}, 180_000);\n\n\t\t\tconst app = h3.createApp();\n\t\t\tapp.use(h3.fromNodeMiddleware(cors()));\n\t\t\tapp.use(\n\t\t\t\th3.fromNodeMiddleware(\n\t\t\t\t\tcreatePrismicAuthManagerMiddleware({\n\t\t\t\t\t\tprismicAuthManager: this,\n\t\t\t\t\t\tonLoginCallback() {\n\t\t\t\t\t\t\t// Cleanup process and resolve\n\t\t\t\t\t\t\tclearTimeout(timeout);\n\t\t\t\t\t\t\tserver.close();\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t);\n\n\t\t\t// Start server\n\t\t\tconst server = http.createServer(h3.toNodeListener(app));\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tserver.once(\"listening\", () => {\n\t\t\t\t\tresolve();\n\t\t\t\t});\n\t\t\t\tserver.listen(args.port);\n\t\t\t});\n\n\t\t\tif (args.onListenCallback) {\n\t\t\t\targs.onListenCallback();\n\t\t\t}\n\t\t});\n\t}\n\n\tasync logout(): Promise<void> {\n\t\tconst authState = await this._readPersistedAuthState();\n\n\t\t// Remove all Prismic cookies, short ID, and Intercom hash\n\t\t// associated with the currently logged in user.\n\t\tauthState.cookies = {};\n\t\tauthState.shortId = undefined;\n\t\tauthState.intercomHash = undefined;\n\n\t\tawait this._writePersistedAuthState(authState);\n\t}\n\n\tasync checkIsLoggedIn(): Promise<boolean> {\n\t\tconst authState = await this._readPersistedAuthState();\n\n\t\tif (checkHasAuthenticationToken(authState)) {\n\t\t\tconst url = new URL(\"./validate\", API_ENDPOINTS.PrismicAuthentication);\n\t\t\turl.searchParams.set(\"token\", authState.cookies[AUTH_COOKIE_KEY]);\n\n\t\t\tlet res;\n\t\t\ttry {\n\t\t\t\tres = await fetch(url.toString(), {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"User-Agent\": SLICE_MACHINE_USER_AGENT,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\t// Noop, we return if `res` is not defined.\n\t\t\t}\n\n\t\t\tif (!res || !res.ok) {\n\t\t\t\tawait this.logout();\n\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tasync getAuthenticationCookies(): Promise<\n\t\tPrismicAuthState[\"cookies\"] &\n\t\t\tRequired<\n\t\t\t\tPick<\n\t\t\t\t\tPrismicAuthState[\"cookies\"],\n\t\t\t\t\ttypeof AUTH_COOKIE_KEY | typeof SESSION_COOKIE_KEY\n\t\t\t\t>\n\t\t\t>\n\t> {\n\t\tconst isLoggedIn = await this.checkIsLoggedIn();\n\n\t\tif (isLoggedIn) {\n\t\t\tconst authState = await this._readPersistedAuthState();\n\n\t\t\tif (checkHasAuthenticationToken(authState)) {\n\t\t\t\treturn authState.cookies;\n\t\t\t}\n\t\t}\n\n\t\tthrow new UnauthenticatedError();\n\t}\n\n\tasync getAuthenticationToken(): Promise<string> {\n\t\tconst cookies = await this.getAuthenticationCookies();\n\n\t\treturn cookies[AUTH_COOKIE_KEY];\n\t}\n\n\tasync refreshAuthenticationToken(): Promise<void> {\n\t\tconst authState = await this._readPersistedAuthState();\n\n\t\tif (checkHasAuthenticationToken(authState)) {\n\t\t\tconst url = new URL(\n\t\t\t\t\"./refreshtoken\",\n\t\t\t\tAPI_ENDPOINTS.PrismicAuthentication,\n\t\t\t);\n\t\t\turl.searchParams.set(\"token\", authState.cookies[AUTH_COOKIE_KEY]);\n\n\t\t\tconst res = await fetch(url.toString(), {\n\t\t\t\theaders: {\n\t\t\t\t\t\"User-Agent\": SLICE_MACHINE_USER_AGENT,\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst text = await res.text();\n\n\t\t\tif (res.ok) {\n\t\t\t\tauthState.cookies[AUTH_COOKIE_KEY] = text;\n\n\t\t\t\tawait this._writePersistedAuthState(authState);\n\t\t\t} else {\n\t\t\t\tthrow new InternalError(\"Failed to refresh authentication token.\", {\n\t\t\t\t\tcause: text,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new UnauthenticatedError();\n\t\t}\n\t}\n\n\tasync getProfile(): Promise<PrismicUserProfile> {\n\t\tconst authenticationToken = await this.getAuthenticationToken();\n\n\t\treturn await this._getProfileForAuthenticationToken({\n\t\t\tauthenticationToken,\n\t\t});\n\t}\n\n\tprivate async _getProfileForAuthenticationToken(\n\t\targs: GetProfileForAuthenticationTokenArgs,\n\t): Promise<PrismicUserProfile> {\n\t\tconst url = new URL(\"./profile\", API_ENDPOINTS.PrismicUser);\n\t\tconst res = await fetch(url.toString(), {\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${args.authenticationToken}`,\n\t\t\t\t\"User-Agent\": SLICE_MACHINE_USER_AGENT,\n\t\t\t},\n\t\t});\n\n\t\tif (res.ok) {\n\t\t\tconst json = await res.json();\n\t\t\tconst { value: profile, error } = decode(PrismicUserProfile, json);\n\n\t\t\tif (error) {\n\t\t\t\tthrow new UnexpectedDataError(\n\t\t\t\t\t\"Received invalid data from the Prismic user service.\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn profile;\n\t\t} else {\n\t\t\tconst text = await res.text();\n\t\t\tthrow new InternalError(\n\t\t\t\t\"Failed to retrieve profile from the Prismic user service.\",\n\t\t\t\t{\n\t\t\t\t\tcause: text,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async _readPersistedAuthState(): Promise<PrismicAuthState> {\n\t\tconst authStateFilePath = this._getPersistedAuthStateFilePath();\n\n\t\tlet authStateFileContents: string = JSON.stringify({});\n\t\tlet rawAuthState: Record<string, unknown> = {};\n\n\t\ttry {\n\t\t\tauthStateFileContents = await fs.readFile(authStateFilePath, \"utf8\");\n\t\t\trawAuthState = JSON.parse(authStateFileContents);\n\t\t} catch {\n\t\t\t// Write a default persisted state if it doesn't already exist.\n\n\t\t\trawAuthState = {\n\t\t\t\t...DEFAULT_PERSISTED_AUTH_STATE,\n\t\t\t\tcookies: serializeCookies(DEFAULT_PERSISTED_AUTH_STATE.cookies),\n\t\t\t};\n\t\t\tauthStateFileContents = JSON.stringify(rawAuthState, null, \"\\t\");\n\n\t\t\tawait fs.mkdir(path.dirname(authStateFilePath), { recursive: true });\n\t\t\tawait fs.writeFile(authStateFilePath, authStateFileContents);\n\t\t}\n\n\t\t// Decode cookies into a record for convenience.\n\t\tif (typeof rawAuthState.cookies === \"string\") {\n\t\t\trawAuthState.cookies = parseCookies(rawAuthState.cookies);\n\t\t}\n\n\t\tconst { value: authState, error } = decode(PrismicAuthState, rawAuthState);\n\n\t\tif (error) {\n\t\t\tthrow new UnexpectedDataError(\"Prismic authentication state is invalid.\");\n\t\t}\n\n\t\treturn authState;\n\t}\n\n\tprivate async _writePersistedAuthState(\n\t\tauthState: PrismicAuthState,\n\t): Promise<void> {\n\t\tconst authStateFilePath = this._getPersistedAuthStateFilePath();\n\n\t\tconst preparedAuthState = {\n\t\t\t...authState,\n\t\t\tcookies: serializeCookies(authState.cookies),\n\t\t};\n\n\t\ttry {\n\t\t\tawait fs.writeFile(\n\t\t\t\tauthStateFilePath,\n\t\t\t\tJSON.stringify(preparedAuthState, null, 2),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthrow new InternalError(\n\t\t\t\t\"Failed to write Prismic authentication state to the file system.\",\n\t\t\t\t{\n\t\t\t\t\tcause: error,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate _getPersistedAuthStateFilePath(): string {\n\t\treturn path.resolve(this.scopedDirectory, PERSISTED_AUTH_STATE_FILE_NAME);\n\t}\n}\n"],"names":["getPort","resolve"],"mappings":"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"}
1
+ {"version":3,"file":"PrismicAuthManager.js","sources":["../../../src/auth/PrismicAuthManager.ts"],"sourcesContent":["import * as t from \"io-ts\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport * as http from \"node:http\";\n\nimport * as h3 from \"h3\";\nimport fetch from \"../lib/fetch\";\nimport cookie from \"cookie\";\nimport cors from \"cors\";\nimport getPort from \"get-port\";\n\nimport { decode } from \"../lib/decode\";\nimport { serializeCookies } from \"../lib/serializeCookies\";\n\nimport { API_ENDPOINTS } from \"../constants/API_ENDPOINTS\";\nimport { SLICE_MACHINE_USER_AGENT } from \"../constants/SLICE_MACHINE_USER_AGENT\";\nimport { createPrismicAuthManagerMiddleware } from \"./createPrismicAuthManagerMiddleware\";\nimport {\n\tInternalError,\n\tUnauthenticatedError,\n\tUnexpectedDataError,\n} from \"../errors\";\n\nconst COOKIE_SEPARATOR = \"; \";\nconst AUTH_COOKIE_KEY = \"prismic-auth\";\nconst SESSION_COOKIE_KEY = \"SESSION\";\n\nconst PERSISTED_AUTH_STATE_FILE_NAME = \".prismic\";\nconst DEFAULT_PERSISTED_AUTH_STATE: PrismicAuthState = {\n\tbase: \"https://prismic.io\",\n\tcookies: {},\n};\n\nconst PrismicAuthState = t.intersection([\n\tt.type({\n\t\tbase: t.string,\n\t\tcookies: t.intersection([\n\t\t\tt.partial({\n\t\t\t\t[AUTH_COOKIE_KEY]: t.string,\n\t\t\t\tSESSION: t.string,\n\t\t\t}),\n\t\t\tt.record(t.string, t.string),\n\t\t]),\n\t}),\n\tt.partial({\n\t\tshortId: t.string,\n\t\tintercomHash: t.string,\n\t\toauthAccessToken: t.string,\n\t\tauthUrl: t.string,\n\t}),\n]);\nexport type PrismicAuthState = t.TypeOf<typeof PrismicAuthState>;\n\nconst PrismicUserProfile = t.exact(\n\tt.type({\n\t\tuserId: t.string,\n\t\tshortId: t.string,\n\t\tintercomHash: t.string,\n\t\temail: t.string,\n\t\tfirstName: t.string,\n\t\tlastName: t.string,\n\t}),\n);\nexport type PrismicUserProfile = t.TypeOf<typeof PrismicUserProfile>;\n\ntype PrismicAuthManagerConstructorArgs = {\n\tscopedDirectory?: string;\n};\n\ntype PrismicAuthManagerLoginArgs = {\n\temail: string;\n\tcookies: string[];\n};\n\ntype PrismicAuthManagerGetLoginSessionInfoReturnType = {\n\tport: number;\n\turl: string;\n};\n\ntype PrismicAuthManagerNodeLoginSessionArgs = {\n\tport: number;\n\tonListenCallback?: () => void;\n};\n\ntype GetProfileForAuthenticationTokenArgs = {\n\tauthenticationToken: string;\n};\n\nconst checkHasAuthenticationToken = (\n\tauthState: PrismicAuthState,\n): authState is PrismicAuthState & {\n\tcookies: Required<\n\t\tPick<\n\t\t\tPrismicAuthState[\"cookies\"],\n\t\t\ttypeof AUTH_COOKIE_KEY | typeof SESSION_COOKIE_KEY\n\t\t>\n\t>;\n} => {\n\treturn Boolean(\n\t\tauthState.cookies[AUTH_COOKIE_KEY] && authState.cookies[SESSION_COOKIE_KEY],\n\t);\n};\n\nconst parseCookies = (cookies: string): Record<string, string> => {\n\treturn cookie.parse(cookies, {\n\t\t// Don't escape any values.\n\t\tdecode: (value) => value,\n\t});\n};\n\nexport class PrismicAuthManager {\n\t// TODO: Automatically scope the manager to the current Slice Machine\n\t// project? If not, this internal state can be removed.\n\tscopedDirectory: string;\n\n\tconstructor({\n\t\tscopedDirectory = os.homedir(),\n\t}: PrismicAuthManagerConstructorArgs = {}) {\n\t\tthis.scopedDirectory = scopedDirectory;\n\t}\n\n\t// TODO: Make the `cookies` argument more explicit. What are these\n\t// mysterious cookies?\n\tasync login(args: PrismicAuthManagerLoginArgs): Promise<void> {\n\t\tconst authState = await this._readPersistedAuthState();\n\n\t\t// Set the auth's URL base to the current base at runtime.\n\t\tauthState.base = API_ENDPOINTS.PrismicWroom;\n\t\tauthState.cookies = {\n\t\t\t...authState.cookies,\n\t\t\t...parseCookies(args.cookies.join(COOKIE_SEPARATOR)),\n\t\t};\n\n\t\tif (checkHasAuthenticationToken(authState)) {\n\t\t\tconst authenticationToken = authState.cookies[AUTH_COOKIE_KEY];\n\t\t\tconst profile = await this._getProfileForAuthenticationToken({\n\t\t\t\tauthenticationToken,\n\t\t\t});\n\n\t\t\tauthState.shortId = profile.shortId;\n\t\t\tauthState.intercomHash = profile.intercomHash;\n\t\t}\n\n\t\tawait this._writePersistedAuthState(authState);\n\t}\n\n\tasync getLoginSessionInfo(): Promise<PrismicAuthManagerGetLoginSessionInfoReturnType> {\n\t\t// Pick a random port, with a preference for historic `5555`\n\t\tconst port = await getPort({ port: 5555 });\n\n\t\tconst url = new URL(\n\t\t\t`./dashboard/cli/login?source=slice-machine&port=${port}`,\n\t\t\tAPI_ENDPOINTS.PrismicWroom,\n\t\t).toString();\n\n\t\treturn {\n\t\t\tport,\n\t\t\turl,\n\t\t};\n\t}\n\n\tasync nodeLoginSession(\n\t\targs: PrismicAuthManagerNodeLoginSessionArgs,\n\t): Promise<void> {\n\t\treturn new Promise<void>(async (resolve) => {\n\t\t\t// Timeout attempt after 3 minutes\n\t\t\tconst timeout = setTimeout(() => {\n\t\t\t\tserver.close();\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Login timeout, server did not receive a response within a 3-minute delay\",\n\t\t\t\t);\n\t\t\t}, 180_000);\n\n\t\t\tconst app = h3.createApp();\n\t\t\tapp.use(h3.fromNodeMiddleware(cors()));\n\t\t\tapp.use(\n\t\t\t\th3.fromNodeMiddleware(\n\t\t\t\t\tcreatePrismicAuthManagerMiddleware({\n\t\t\t\t\t\tprismicAuthManager: this,\n\t\t\t\t\t\tonLoginCallback() {\n\t\t\t\t\t\t\t// Cleanup process and resolve\n\t\t\t\t\t\t\tclearTimeout(timeout);\n\t\t\t\t\t\t\tserver.close();\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t);\n\n\t\t\t// Start server\n\t\t\tconst server = http.createServer(h3.toNodeListener(app));\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tserver.once(\"listening\", () => {\n\t\t\t\t\tresolve();\n\t\t\t\t});\n\t\t\t\tserver.listen(args.port, \"127.0.0.1\");\n\t\t\t});\n\n\t\t\tif (args.onListenCallback) {\n\t\t\t\targs.onListenCallback();\n\t\t\t}\n\t\t});\n\t}\n\n\tasync logout(): Promise<void> {\n\t\tconst authState = await this._readPersistedAuthState();\n\n\t\t// Remove all Prismic cookies, short ID, and Intercom hash\n\t\t// associated with the currently logged in user.\n\t\tauthState.cookies = {};\n\t\tauthState.shortId = undefined;\n\t\tauthState.intercomHash = undefined;\n\n\t\tawait this._writePersistedAuthState(authState);\n\t}\n\n\tasync checkIsLoggedIn(): Promise<boolean> {\n\t\tconst authState = await this._readPersistedAuthState();\n\n\t\tif (checkHasAuthenticationToken(authState)) {\n\t\t\tconst url = new URL(\"./validate\", API_ENDPOINTS.PrismicAuthentication);\n\t\t\turl.searchParams.set(\"token\", authState.cookies[AUTH_COOKIE_KEY]);\n\n\t\t\tlet res;\n\t\t\ttry {\n\t\t\t\tres = await fetch(url.toString(), {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"User-Agent\": SLICE_MACHINE_USER_AGENT,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\t// Noop, we return if `res` is not defined.\n\t\t\t}\n\n\t\t\tif (!res || !res.ok) {\n\t\t\t\tawait this.logout();\n\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tasync getAuthenticationCookies(): Promise<\n\t\tPrismicAuthState[\"cookies\"] &\n\t\t\tRequired<\n\t\t\t\tPick<\n\t\t\t\t\tPrismicAuthState[\"cookies\"],\n\t\t\t\t\ttypeof AUTH_COOKIE_KEY | typeof SESSION_COOKIE_KEY\n\t\t\t\t>\n\t\t\t>\n\t> {\n\t\tconst isLoggedIn = await this.checkIsLoggedIn();\n\n\t\tif (isLoggedIn) {\n\t\t\tconst authState = await this._readPersistedAuthState();\n\n\t\t\tif (checkHasAuthenticationToken(authState)) {\n\t\t\t\treturn authState.cookies;\n\t\t\t}\n\t\t}\n\n\t\tthrow new UnauthenticatedError();\n\t}\n\n\tasync getAuthenticationToken(): Promise<string> {\n\t\tconst cookies = await this.getAuthenticationCookies();\n\n\t\treturn cookies[AUTH_COOKIE_KEY];\n\t}\n\n\tasync refreshAuthenticationToken(): Promise<void> {\n\t\tconst authState = await this._readPersistedAuthState();\n\n\t\tif (checkHasAuthenticationToken(authState)) {\n\t\t\tconst url = new URL(\n\t\t\t\t\"./refreshtoken\",\n\t\t\t\tAPI_ENDPOINTS.PrismicAuthentication,\n\t\t\t);\n\t\t\turl.searchParams.set(\"token\", authState.cookies[AUTH_COOKIE_KEY]);\n\n\t\t\tconst res = await fetch(url.toString(), {\n\t\t\t\theaders: {\n\t\t\t\t\t\"User-Agent\": SLICE_MACHINE_USER_AGENT,\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst text = await res.text();\n\n\t\t\tif (res.ok) {\n\t\t\t\tauthState.cookies[AUTH_COOKIE_KEY] = text;\n\n\t\t\t\tawait this._writePersistedAuthState(authState);\n\t\t\t} else {\n\t\t\t\tthrow new InternalError(\"Failed to refresh authentication token.\", {\n\t\t\t\t\tcause: text,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new UnauthenticatedError();\n\t\t}\n\t}\n\n\tasync getProfile(): Promise<PrismicUserProfile> {\n\t\tconst authenticationToken = await this.getAuthenticationToken();\n\n\t\treturn await this._getProfileForAuthenticationToken({\n\t\t\tauthenticationToken,\n\t\t});\n\t}\n\n\tprivate async _getProfileForAuthenticationToken(\n\t\targs: GetProfileForAuthenticationTokenArgs,\n\t): Promise<PrismicUserProfile> {\n\t\tconst url = new URL(\"./profile\", API_ENDPOINTS.PrismicUser);\n\t\tconst res = await fetch(url.toString(), {\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${args.authenticationToken}`,\n\t\t\t\t\"User-Agent\": SLICE_MACHINE_USER_AGENT,\n\t\t\t},\n\t\t});\n\n\t\tif (res.ok) {\n\t\t\tconst json = await res.json();\n\t\t\tconst { value: profile, error } = decode(PrismicUserProfile, json);\n\n\t\t\tif (error) {\n\t\t\t\tthrow new UnexpectedDataError(\n\t\t\t\t\t\"Received invalid data from the Prismic user service.\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn profile;\n\t\t} else {\n\t\t\tconst text = await res.text();\n\t\t\tthrow new InternalError(\n\t\t\t\t\"Failed to retrieve profile from the Prismic user service.\",\n\t\t\t\t{\n\t\t\t\t\tcause: text,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async _readPersistedAuthState(): Promise<PrismicAuthState> {\n\t\tconst authStateFilePath = this._getPersistedAuthStateFilePath();\n\n\t\tlet authStateFileContents: string = JSON.stringify({});\n\t\tlet rawAuthState: Record<string, unknown> = {};\n\n\t\ttry {\n\t\t\tauthStateFileContents = await fs.readFile(authStateFilePath, \"utf8\");\n\t\t\trawAuthState = JSON.parse(authStateFileContents);\n\t\t} catch {\n\t\t\t// Write a default persisted state if it doesn't already exist.\n\n\t\t\trawAuthState = {\n\t\t\t\t...DEFAULT_PERSISTED_AUTH_STATE,\n\t\t\t\tcookies: serializeCookies(DEFAULT_PERSISTED_AUTH_STATE.cookies),\n\t\t\t};\n\t\t\tauthStateFileContents = JSON.stringify(rawAuthState, null, \"\\t\");\n\n\t\t\tawait fs.mkdir(path.dirname(authStateFilePath), { recursive: true });\n\t\t\tawait fs.writeFile(authStateFilePath, authStateFileContents);\n\t\t}\n\n\t\t// Decode cookies into a record for convenience.\n\t\tif (typeof rawAuthState.cookies === \"string\") {\n\t\t\trawAuthState.cookies = parseCookies(rawAuthState.cookies);\n\t\t}\n\n\t\tconst { value: authState, error } = decode(PrismicAuthState, rawAuthState);\n\n\t\tif (error) {\n\t\t\tthrow new UnexpectedDataError(\"Prismic authentication state is invalid.\");\n\t\t}\n\n\t\treturn authState;\n\t}\n\n\tprivate async _writePersistedAuthState(\n\t\tauthState: PrismicAuthState,\n\t): Promise<void> {\n\t\tconst authStateFilePath = this._getPersistedAuthStateFilePath();\n\n\t\tconst preparedAuthState = {\n\t\t\t...authState,\n\t\t\tcookies: serializeCookies(authState.cookies),\n\t\t};\n\n\t\ttry {\n\t\t\tawait fs.writeFile(\n\t\t\t\tauthStateFilePath,\n\t\t\t\tJSON.stringify(preparedAuthState, null, 2),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthrow new InternalError(\n\t\t\t\t\"Failed to write Prismic authentication state to the file system.\",\n\t\t\t\t{\n\t\t\t\t\tcause: error,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate _getPersistedAuthStateFilePath(): string {\n\t\treturn path.resolve(this.scopedDirectory, PERSISTED_AUTH_STATE_FILE_NAME);\n\t}\n}\n"],"names":["getPort","resolve"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slicemachine/manager",
3
- "version": "0.25.2-beta.4",
3
+ "version": "0.25.2-beta.6",
4
4
  "description": "Manage all aspects of a Slice Machine project.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -70,7 +70,7 @@
70
70
  "@prismicio/mocks": "2.14.0",
71
71
  "@prismicio/types-internal": "3.11.2",
72
72
  "@segment/analytics-node": "^2.1.2",
73
- "@slicemachine/plugin-kit": "0.4.80-beta.4",
73
+ "@slicemachine/plugin-kit": "0.4.80-beta.6",
74
74
  "cookie": "^1.0.1",
75
75
  "cors": "^2.8.5",
76
76
  "execa": "^7.1.1",
@@ -194,7 +194,7 @@ export class PrismicAuthManager {
194
194
  server.once("listening", () => {
195
195
  resolve();
196
196
  });
197
- server.listen(args.port);
197
+ server.listen(args.port, "127.0.0.1");
198
198
  });
199
199
 
200
200
  if (args.onListenCallback) {