{"version":3,"file":"me.mjs","names":[],"sources":["../../../../../src/astro/routes/api/auth/me.ts"],"sourcesContent":["/**\n * GET /_emdash/api/auth/me\n *\n * Returns the current authenticated user's info.\n * Used by the admin UI to display user info in the header.\n */\n\nimport type { APIRoute } from \"astro\";\n\nexport const prerender = false;\n\nimport { apiError, apiSuccess, handleError } from \"#api/error.js\";\nimport { isParseError, parseBody } from \"#api/parse.js\";\nimport { authMeActionBody } from \"#api/schemas.js\";\nimport { UserRepository } from \"#db/repositories/user.js\";\n\nexport const GET: APIRoute = async ({ locals }) => {\n\tconst { user, emdash } = locals;\n\n\tif (!user) {\n\t\treturn apiError(\"NOT_AUTHENTICATED\", \"Not authenticated\", 401);\n\t}\n\n\tlet userData = user.data;\n\tif (locals.__playgroundDb) {\n\t\tif (!emdash) return apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\n\t\ttry {\n\t\t\tconst persistedUser = await new UserRepository(emdash.db).findById(user.id);\n\t\t\tif (persistedUser) userData = persistedUser.data;\n\t\t} catch (error) {\n\t\t\treturn handleError(error, \"Failed to fetch current user\", \"CURRENT_USER_ERROR\");\n\t\t}\n\t}\n\n\t// Check if this is the user's first login (for welcome modal).\n\t// The flag is persisted in the user's `data` JSON column so it survives\n\t// session expiry / rotation.\n\tconst isFirstLogin = !userData?.welcomeDismissed;\n\n\t// What this session may do, resolved by the auth middleware. The admin\n\t// uses `adminPages` to decide which sidebar entries to render and\n\t// `permissions` for finer in-page decisions; both are the server's\n\t// answer, so the UI never re-derives authorization from a role level.\n\tconst authz = locals.authz\n\t\t? {\n\t\t\t\trole: locals.authz.role,\n\t\t\t\tpolicies: [...locals.authz.grants.policies],\n\t\t\t\tpermissions: [...locals.authz.grants.permissions],\n\t\t\t\tdeniedPermissions: [...locals.authz.grants.deniedPermissions],\n\t\t\t\tadminPages: [...locals.authz.grants.adminPages],\n\t\t\t\tdeniedAdminPages: [...locals.authz.grants.deniedAdminPages],\n\t\t\t\tallRoutes: locals.authz.grants.allRoutes,\n\t\t\t\tcollections: locals.authz.grants.collections ? [...locals.authz.grants.collections] : null,\n\t\t\t\ttokenAuth: locals.tokenAuth === true,\n\t\t\t}\n\t\t: null;\n\n\t// Return safe user info (no sensitive data)\n\treturn apiSuccess({\n\t\tid: user.id,\n\t\temail: user.email,\n\t\tname: user.name,\n\t\trole: user.role,\n\t\troleId: user.roleId,\n\t\tavatarUrl: user.avatarUrl,\n\t\tisFirstLogin,\n\t\tauthz,\n\t});\n};\n\n/**\n * POST /_emdash/api/auth/me\n *\n * Mark that the user has seen the welcome modal.\n */\nexport const POST: APIRoute = async ({ request, locals }) => {\n\tconst { user, emdash } = locals;\n\n\tif (!user) {\n\t\treturn apiError(\"NOT_AUTHENTICATED\", \"Not authenticated\", 401);\n\t}\n\n\tif (!emdash) return apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\n\tconst body = await parseBody(request, authMeActionBody);\n\tif (isParseError(body)) return body;\n\n\tif (body.action === \"dismissWelcome\") {\n\t\ttry {\n\t\t\t// Persist in the user's data column so it survives session expiry.\n\t\t\tconst userRepo = new UserRepository(emdash.db);\n\t\t\tawait userRepo.update(user.id, {\n\t\t\t\tdata: { ...user.data, welcomeDismissed: true },\n\t\t\t});\n\t\t\treturn apiSuccess({ success: true });\n\t\t} catch (error) {\n\t\t\treturn handleError(error, \"Failed to dismiss welcome\", \"WELCOME_DISMISS_ERROR\");\n\t\t}\n\t}\n\n\treturn apiError(\"UNKNOWN_ACTION\", \"Unknown action\", 400);\n};\n"],"mappings":";;;;;;;;;;;;;AASA,MAAa,YAAY;AAOzB,MAAa,MAAgB,OAAO,EAAE,aAAa;CAClD,MAAM,EAAE,MAAM,WAAW;AAEzB,KAAI,CAAC,KACJ,QAAO,SAAS,qBAAqB,qBAAqB,IAAI;CAG/D,IAAI,WAAW,KAAK;AACpB,KAAI,OAAO,gBAAgB;AAC1B,MAAI,CAAC,OAAQ,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;AAEhF,MAAI;GACH,MAAM,gBAAgB,MAAM,IAAI,eAAe,OAAO,GAAG,CAAC,SAAS,KAAK,GAAG;AAC3E,OAAI,cAAe,YAAW,cAAc;WACpC,OAAO;AACf,UAAO,YAAY,OAAO,gCAAgC,qBAAqB;;;CAOjF,MAAM,eAAe,CAAC,UAAU;CAMhC,MAAM,QAAQ,OAAO,QAClB;EACA,MAAM,OAAO,MAAM;EACnB,UAAU,CAAC,GAAG,OAAO,MAAM,OAAO,SAAS;EAC3C,aAAa,CAAC,GAAG,OAAO,MAAM,OAAO,YAAY;EACjD,mBAAmB,CAAC,GAAG,OAAO,MAAM,OAAO,kBAAkB;EAC7D,YAAY,CAAC,GAAG,OAAO,MAAM,OAAO,WAAW;EAC/C,kBAAkB,CAAC,GAAG,OAAO,MAAM,OAAO,iBAAiB;EAC3D,WAAW,OAAO,MAAM,OAAO;EAC/B,aAAa,OAAO,MAAM,OAAO,cAAc,CAAC,GAAG,OAAO,MAAM,OAAO,YAAY,GAAG;EACtF,WAAW,OAAO,cAAc;EAChC,GACA;AAGH,QAAO,WAAW;EACjB,IAAI,KAAK;EACT,OAAO,KAAK;EACZ,MAAM,KAAK;EACX,MAAM,KAAK;EACX,QAAQ,KAAK;EACb,WAAW,KAAK;EAChB;EACA;EACA,CAAC;;;;;;;AAQH,MAAa,OAAiB,OAAO,EAAE,SAAS,aAAa;CAC5D,MAAM,EAAE,MAAM,WAAW;AAEzB,KAAI,CAAC,KACJ,QAAO,SAAS,qBAAqB,qBAAqB,IAAI;AAG/D,KAAI,CAAC,OAAQ,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;CAEhF,MAAM,OAAO,MAAM,UAAU,SAAS,iBAAiB;AACvD,KAAI,aAAa,KAAK,CAAE,QAAO;AAE/B,KAAI,KAAK,WAAW,iBACnB,KAAI;AAGH,QADiB,IAAI,eAAe,OAAO,GAAG,CAC/B,OAAO,KAAK,IAAI,EAC9B,MAAM;GAAE,GAAG,KAAK;GAAM,kBAAkB;GAAM,EAC9C,CAAC;AACF,SAAO,WAAW,EAAE,SAAS,MAAM,CAAC;UAC5B,OAAO;AACf,SAAO,YAAY,OAAO,6BAA6B,wBAAwB;;AAIjF,QAAO,SAAS,kBAAkB,kBAAkB,IAAI"}