better-auth
Version:
The most comprehensive authentication framework for TypeScript.
1 lines • 7.46 kB
Source Map (JSON)
{"version":3,"file":"admin.mjs","names":[],"sources":["../../../src/plugins/admin/admin.ts"],"sourcesContent":["import type { BetterAuthPlugin } from \"@better-auth/core\";\nimport { createAuthMiddleware } from \"@better-auth/core/api\";\nimport { BetterAuthError } from \"@better-auth/core/error\";\nimport { APIError } from \"../../api\";\nimport { mergeSchema } from \"../../db/schema\";\nimport { getEndpointResponse } from \"../../utils/plugin-helper\";\nimport { defaultRoles } from \"./access\";\nimport { ADMIN_ERROR_CODES } from \"./error-codes\";\nimport {\n\tadminUpdateUser,\n\tbanUser,\n\tcreateUser,\n\tgetUser,\n\timpersonateUser,\n\tlistUserSessions,\n\tlistUsers,\n\tremoveUser,\n\trevokeUserSession,\n\trevokeUserSessions,\n\tsetRole,\n\tsetUserPassword,\n\tstopImpersonating,\n\tunbanUser,\n\tuserHasPermission,\n} from \"./routes\";\nimport { schema } from \"./schema\";\nimport type {\n\tAdminOptions,\n\tSessionWithImpersonatedBy,\n\tUserWithRole,\n} from \"./types\";\n\nexport const admin = <O extends AdminOptions>(options?: O | undefined) => {\n\tconst opts = {\n\t\tdefaultRole: options?.defaultRole ?? \"user\",\n\t\tadminRoles: options?.adminRoles ?? [\"admin\"],\n\t\tbannedUserMessage:\n\t\t\toptions?.bannedUserMessage ??\n\t\t\t\"You have been banned from this application. Please contact support if you believe this is an error.\",\n\t\t...options,\n\t};\n\n\tif (options?.adminRoles) {\n\t\tconst adminRoles = Array.isArray(options.adminRoles)\n\t\t\t? options.adminRoles\n\t\t\t: [...options.adminRoles.split(\",\")];\n\t\tconst invalidRoles = adminRoles.filter(\n\t\t\t(role) =>\n\t\t\t\t!Object.keys(options?.roles || defaultRoles)\n\t\t\t\t\t.map((r) => r.toLowerCase())\n\t\t\t\t\t.includes(role.toLowerCase()),\n\t\t);\n\t\tif (invalidRoles.length > 0) {\n\t\t\tthrow new BetterAuthError(\n\t\t\t\t`Invalid admin roles: ${invalidRoles.join(\", \")}. Admin roles must be defined in the 'roles' configuration.`,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn {\n\t\tid: \"admin\",\n\t\tinit() {\n\t\t\treturn {\n\t\t\t\toptions: {\n\t\t\t\t\tdatabaseHooks: {\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\tcreate: {\n\t\t\t\t\t\t\t\tasync before(user) {\n\t\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\t\t\trole: options?.defaultRole ?? \"user\",\n\t\t\t\t\t\t\t\t\t\t\t...user,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsession: {\n\t\t\t\t\t\t\tcreate: {\n\t\t\t\t\t\t\t\tasync before(session, ctx) {\n\t\t\t\t\t\t\t\t\tif (!ctx) {\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tconst user = (await ctx.context.internalAdapter.findUserById(\n\t\t\t\t\t\t\t\t\t\tsession.userId,\n\t\t\t\t\t\t\t\t\t)) as UserWithRole;\n\n\t\t\t\t\t\t\t\t\tif (user.banned) {\n\t\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\t\tuser.banExpires &&\n\t\t\t\t\t\t\t\t\t\t\tnew Date(user.banExpires).getTime() < Date.now()\n\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\tawait ctx.context.internalAdapter.updateUser(\n\t\t\t\t\t\t\t\t\t\t\t\tsession.userId,\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tbanned: false,\n\t\t\t\t\t\t\t\t\t\t\t\t\tbanReason: null,\n\t\t\t\t\t\t\t\t\t\t\t\t\tbanExpires: null,\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\t\tctx &&\n\t\t\t\t\t\t\t\t\t\t\t(ctx.path.startsWith(\"/callback\") ||\n\t\t\t\t\t\t\t\t\t\t\t\tctx.path.startsWith(\"/oauth2/callback\"))\n\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\tconst redirectURI =\n\t\t\t\t\t\t\t\t\t\t\t\tctx.context.options.onAPIError?.errorURL ||\n\t\t\t\t\t\t\t\t\t\t\t\t`${ctx.context.baseURL}/error`;\n\t\t\t\t\t\t\t\t\t\t\tthrow ctx.redirect(\n\t\t\t\t\t\t\t\t\t\t\t\t`${redirectURI}?error=banned&error_description=${opts.bannedUserMessage}`,\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\t\t\t\t\t\t\tmessage: opts.bannedUserMessage,\n\t\t\t\t\t\t\t\t\t\t\tcode: \"BANNED_USER\",\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\thooks: {\n\t\t\tafter: [\n\t\t\t\t{\n\t\t\t\t\tmatcher(context) {\n\t\t\t\t\t\treturn context.path === \"/list-sessions\";\n\t\t\t\t\t},\n\t\t\t\t\thandler: createAuthMiddleware(async (ctx) => {\n\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\tawait getEndpointResponse<SessionWithImpersonatedBy[]>(ctx);\n\n\t\t\t\t\t\tif (!response) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst newJson = response.filter((session) => {\n\t\t\t\t\t\t\treturn !session.impersonatedBy;\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\treturn ctx.json(newJson);\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\tendpoints: {\n\t\t\tsetRole: setRole(opts),\n\t\t\tgetUser: getUser(opts),\n\t\t\tcreateUser: createUser(opts),\n\t\t\tadminUpdateUser: adminUpdateUser(opts),\n\t\t\tlistUsers: listUsers(opts),\n\t\t\tlistUserSessions: listUserSessions(opts),\n\t\t\tunbanUser: unbanUser(opts),\n\t\t\tbanUser: banUser(opts),\n\t\t\timpersonateUser: impersonateUser(opts),\n\t\t\tstopImpersonating: stopImpersonating(),\n\t\t\trevokeUserSession: revokeUserSession(opts),\n\t\t\trevokeUserSessions: revokeUserSessions(opts),\n\t\t\tremoveUser: removeUser(opts),\n\t\t\tsetUserPassword: setUserPassword(opts),\n\t\t\tuserHasPermission: userHasPermission(opts as O),\n\t\t},\n\t\t$ERROR_CODES: ADMIN_ERROR_CODES,\n\t\tschema: mergeSchema(schema, opts.schema),\n\t\toptions: options as NoInfer<O>,\n\t} satisfies BetterAuthPlugin;\n};\n"],"mappings":";;;;;;;;;;;;AAgCA,MAAa,SAAiC,YAA4B;CACzE,MAAM,OAAO;EACZ,aAAa,SAAS,eAAe;EACrC,YAAY,SAAS,cAAc,CAAC,QAAQ;EAC5C,mBACC,SAAS,qBACT;EACD,GAAG;EACH;AAED,KAAI,SAAS,YAAY;EAIxB,MAAM,gBAHa,MAAM,QAAQ,QAAQ,WAAW,GACjD,QAAQ,aACR,CAAC,GAAG,QAAQ,WAAW,MAAM,IAAI,CAAC,EACL,QAC9B,SACA,CAAC,OAAO,KAAK,SAAS,SAAS,aAAa,CAC1C,KAAK,MAAM,EAAE,aAAa,CAAC,CAC3B,SAAS,KAAK,aAAa,CAAC,CAC/B;AACD,MAAI,aAAa,SAAS,EACzB,OAAM,IAAI,gBACT,wBAAwB,aAAa,KAAK,KAAK,CAAC,6DAChD;;AAIH,QAAO;EACN,IAAI;EACJ,OAAO;AACN,UAAO,EACN,SAAS,EACR,eAAe;IACd,MAAM,EACL,QAAQ,EACP,MAAM,OAAO,MAAM;AAClB,YAAO,EACN,MAAM;MACL,MAAM,SAAS,eAAe;MAC9B,GAAG;MACH,EACD;OAEF,EACD;IACD,SAAS,EACR,QAAQ,EACP,MAAM,OAAO,SAAS,KAAK;AAC1B,SAAI,CAAC,IACJ;KAED,MAAM,OAAQ,MAAM,IAAI,QAAQ,gBAAgB,aAC/C,QAAQ,OACR;AAED,SAAI,KAAK,QAAQ;AAChB,UACC,KAAK,cACL,IAAI,KAAK,KAAK,WAAW,CAAC,SAAS,GAAG,KAAK,KAAK,EAC/C;AACD,aAAM,IAAI,QAAQ,gBAAgB,WACjC,QAAQ,QACR;QACC,QAAQ;QACR,WAAW;QACX,YAAY;QACZ,CACD;AACD;;AAGD,UACC,QACC,IAAI,KAAK,WAAW,YAAY,IAChC,IAAI,KAAK,WAAW,mBAAmB,GACvC;OACD,MAAM,cACL,IAAI,QAAQ,QAAQ,YAAY,YAChC,GAAG,IAAI,QAAQ,QAAQ;AACxB,aAAM,IAAI,SACT,GAAG,YAAY,kCAAkC,KAAK,oBACtD;;AAGF,YAAM,IAAI,SAAS,aAAa;OAC/B,SAAS,KAAK;OACd,MAAM;OACN,CAAC;;OAGJ,EACD;IACD,EACD,EACD;;EAEF,OAAO,EACN,OAAO,CACN;GACC,QAAQ,SAAS;AAChB,WAAO,QAAQ,SAAS;;GAEzB,SAAS,qBAAqB,OAAO,QAAQ;IAC5C,MAAM,WACL,MAAM,oBAAiD,IAAI;AAE5D,QAAI,CAAC,SACJ;IAED,MAAM,UAAU,SAAS,QAAQ,YAAY;AAC5C,YAAO,CAAC,QAAQ;MACf;AAEF,WAAO,IAAI,KAAK,QAAQ;KACvB;GACF,CACD,EACD;EACD,WAAW;GACV,SAAS,QAAQ,KAAK;GACtB,SAAS,QAAQ,KAAK;GACtB,YAAY,WAAW,KAAK;GAC5B,iBAAiB,gBAAgB,KAAK;GACtC,WAAW,UAAU,KAAK;GAC1B,kBAAkB,iBAAiB,KAAK;GACxC,WAAW,UAAU,KAAK;GAC1B,SAAS,QAAQ,KAAK;GACtB,iBAAiB,gBAAgB,KAAK;GACtC,mBAAmB,mBAAmB;GACtC,mBAAmB,kBAAkB,KAAK;GAC1C,oBAAoB,mBAAmB,KAAK;GAC5C,YAAY,WAAW,KAAK;GAC5B,iBAAiB,gBAAgB,KAAK;GACtC,mBAAmB,kBAAkB,KAAU;GAC/C;EACD,cAAc;EACd,QAAQ,YAAY,QAAQ,KAAK,OAAO;EAC/B;EACT"}