{"version":3,"file":"controller-9a122d5B.cjs","sources":["../src/lib/auth/model.ts","../src/lib/auth/state.ts","../src/lib/auth/auto-login.ts","../src/lib/auth/controller.ts"],"sourcesContent":["/**\n * A logged-in user.\n */\nexport interface User {\n\t/**\n\t * The user's username.\n\t */\n\tusername: string;\n\t/**\n\t * The NATS URL that the user is connected to.\n\t */\n\tnatsUrl: string;\n}\n\nexport interface ErrorMessages {\n\tnatsUrlMessage?: string;\n\tusernameMessage?: string;\n\tpasswordMessage?: string;\n}\n\nexport class LoginError extends Error {\n\tpublic messages: ErrorMessages;\n\n\tconstructor(messages: ErrorMessages) {\n\t\tsuper(\n\t\t\t`Login validation errors: ${[\n\t\t\t\tmessages.natsUrlMessage,\n\t\t\t\tmessages.usernameMessage,\n\t\t\t\tmessages.passwordMessage\n\t\t\t]\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.join(', ')}`\n\t\t);\n\t\tthis.name = 'LoginError';\n\t\tthis.messages = messages;\n\t}\n}\n","import { User } from './model.ts';\nimport { NatsConnection } from 'nats.ws';\n\nlet currentUser: User | null = null;\nlet currentNc: NatsConnection | null = null;\n\n/**\n * Sets a new user object or `null` if the user is no longer logged in.\n *\n * @param user - the user object or `null`\n */\nexport function setUser(user: User | null) {\n\tcurrentUser = user;\n}\n\n/**\n * Returns the user object if the user is currently logged in, else returns `null` if no user is currently logged in.\n */\nexport function getUser() {\n\treturn currentUser;\n}\n\nexport function setNatsConnection(nc: NatsConnection | null) {\n\tcurrentNc = nc;\n}\n\nexport function getNatsConnection() {\n\treturn currentNc;\n}\n","import { login } from './controller.ts';\nimport { z } from 'zod';\n\nconst AUTO_LOGIN_KEY = 'auto-login';\n\nconst autoLoginSchema = z.object({\n\t/**\n\t * The URL of the NATS server to connect to.\n\t */\n\tnatsUrl: z.string(),\n\t/**\n\t * The username to use when connecting to the NATS server.\n\t */\n\tusername: z.string(),\n\t/**\n\t * The password to use when connecting to the NATS server.\n\t */\n\tpassword: z.string()\n});\n\n/**\n * Attempt to auto-login using credentials stored in sessionStorage.\n *\n * The credentials will automatically be cleared if they are invalid, the\n * session ends, or {@link logout} is called.\n *\n * Credentials are automatically stored updated by {@link login} and\n * {@link logout}.\n *\n * @returns true if auto-login was successful, false otherwise\n */\nexport async function attemptAutoLogin(): Promise<boolean> {\n\tconsole.log('Attempting auto-login');\n\tconst autoLogin = window.sessionStorage.getItem(AUTO_LOGIN_KEY);\n\n\tif (!autoLogin) {\n\t\t// This is perfectly normal, so don't log a warning, just return false\n\t\treturn false;\n\t}\n\n\tconst parsedAutoLoginData = autoLoginSchema.safeParse(\n\t\tJSON.parse(decrypt(autoLogin))\n\t);\n\n\tif (!parsedAutoLoginData.success) {\n\t\tconsole.warn('Invalid auto-login credentials type');\n\t\treturn false;\n\t}\n\n\tconst { natsUrl, username, password } = parsedAutoLoginData.data;\n\n\ttry {\n\t\tawait login(natsUrl, username, password);\n\t\treturn true;\n\t} catch (err) {\n\t\tconsole.warn('Auto-login failed:', err);\n\t\tclearAutoLogin(); // credentials didn't work, so discard them\n\t\treturn false;\n\t}\n}\n\n/**\n * Sets credentials with which to auto-login.\n *\n * If an auto-login attempt fails, the credentials will be cleared for the remainder of the session and a login form\n * shown to the user. If the user logs in successfully, the credentials will be updated.\n *\n * ### Security Warning\n *\n * Use this function only if user authentication is handled by a separate system. Calling this function in\n * your application means your NATS credentials will be hard-coded into your application, which is a security risk.\n *\n * @param credentials - The credentials to store\n * @deprecated No, this won't be removed anytime soon. You can ignore this warning if you're aware of the security\n * implications.\n */\nexport function setAutoLoginCredentials(\n\tcredentials: z.input<typeof autoLoginSchema>\n) {\n\twindow.sessionStorage.setItem(\n\t\tAUTO_LOGIN_KEY,\n\t\tencrypt(JSON.stringify(autoLoginSchema.parse(credentials)))\n\t);\n}\n\n/**\n * @internal\n * Clear auto-login credentials from sessionStorage.\n */\nexport function clearAutoLogin() {\n\tconsole.log('Clearing auto-login credentials');\n\twindow.sessionStorage.removeItem(AUTO_LOGIN_KEY);\n}\n\n/**\n * @internal\n * Encrypt a string to obfuscate it in sessionStorage.\n * @param str - The string to encrypt\n * @returns The encrypted string\n *\n * @see decrypt\n */\nfunction encrypt(str?: string) {\n\treturn btoa(str ?? 'null');\n}\n\n/**\n * @internal\n * Decrypt a string that was obfuscated in sessionStorage.\n * @param str - The string to decrypt\n * @returns The decrypted string\n *\n * @see encrypt\n */\nfunction decrypt(str?: string) {\n\treturn atob(str ?? 'null');\n}\n","import {\n\tgetNatsConnection,\n\tgetUser,\n\tsetNatsConnection,\n\tsetUser\n} from './state.ts';\nimport { LoginError, ErrorMessages } from './model.ts';\nimport { connect, NatsError } from 'nats.ws';\nimport { z } from 'zod';\nimport { clearAutoLogin, setAutoLoginCredentials } from './auto-login.ts';\n\nconst natsUrlSchema = z.string().url();\nconst credentialsSchema = z.string().min(1).max(800);\n\n/**\n * Logs in a user with the given credentials.\n *\n * @param natsUrl - The url to connect to the NATS server.\n * @param username - The username for authentication.\n * @param password - The password for authentication.\n *\n * @returns A promise that resolves once the user is logged in.\n * The resolved value is the logged-in user object.\n *\n * @throws Error If the provided credentials are incorrect.\n */\nexport async function login(\n\tnatsUrl: string,\n\tusername: string,\n\tpassword: string\n) {\n\tif (isLoggedIn()) {\n\t\tconsole.log('Already logged in');\n\t\treturn getUser();\n\t}\n\n\t// validation\n\tconst errorMessages: ErrorMessages = {};\n\n\ttry {\n\t\tnatsUrl = natsUrlSchema.parse(natsUrl);\n\t} catch (err) {\n\t\terrorMessages.natsUrlMessage = 'Invalid backend URL';\n\t}\n\n\ttry {\n\t\tusername = credentialsSchema.parse(username);\n\t} catch (err) {\n\t\terrorMessages.usernameMessage = 'User does not exist';\n\t}\n\n\ttry {\n\t\tpassword = credentialsSchema.parse(password);\n\t} catch (err) {\n\t\terrorMessages.passwordMessage = 'Invalid password';\n\t}\n\n\tif (Object.keys(errorMessages).length) {\n\t\tconsole.log('The following errors were detected:', errorMessages);\n\t\tthrow new LoginError(errorMessages);\n\t}\n\n\t// user credentials correct\n\n\ttry {\n\t\tconsole.log(\n\t\t\t'Log in with nats url:',\n\t\t\tnatsUrl,\n\t\t\t', username:',\n\t\t\tusername,\n\t\t\t', password:',\n\t\t\tpassword\n\t\t);\n\n\t\tconst nc = await connect({\n\t\t\tservers: natsUrl,\n\t\t\tname: `frontend-${username}`,\n\t\t\tuser: username,\n\t\t\tpass: password\n\t\t});\n\n\t\tsetUser({ natsUrl, username });\n\t\tsetNatsConnection(nc);\n\n\t\tsetAutoLoginCredentials({\n\t\t\tnatsUrl,\n\t\t\tusername,\n\t\t\tpassword: password\n\t\t});\n\n\t\tconsole.log('Successfully logged in');\n\t\treturn getUser();\n\t} catch (err) {\n\t\tif (err instanceof NatsError) {\n\t\t\tthrow new Error(\n\t\t\t\t'Login failed. Please check your connection and credentials, then try again'\n\t\t\t);\n\t\t}\n\n\t\tthrow err;\n\t}\n}\n\n/**\n * Logs out the user if currently logged in.\n *\n * @returns A promise that resolves once the user is logged out.\n */\nexport async function logout() {\n\tclearAutoLogin();\n\n\tif (!isLoggedIn()) {\n\t\tconsole.log('Already logged out');\n\t\treturn;\n\t}\n\n\tconsole.log('Log out');\n\n\tconst nc = getNatsConnection();\n\tif (nc) {\n\t\tawait nc.drain();\n\t\tawait nc.close();\n\t\tsetNatsConnection(null);\n\t}\n\n\tconsole.log('Successfully logged out');\n\tsetUser(null);\n}\n\n/**\n * Checks if a user is logged in.\n *\n * @returns `true` if the user is logged in, `false` otherwise.\n */\nexport function isLoggedIn() {\n\treturn !!getUser();\n}\n"],"names":["LoginError","messages","__publicField","currentUser","currentNc","setUser","user","getUser","setNatsConnection","nc","getNatsConnection","AUTO_LOGIN_KEY","autoLoginSchema","z","attemptAutoLogin","autoLogin","parsedAutoLoginData","decrypt","natsUrl","username","password","login","err","clearAutoLogin","setAutoLoginCredentials","credentials","encrypt","str","natsUrlSchema","credentialsSchema","isLoggedIn","errorMessages","connect","NatsError","logout"],"mappings":"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"}