better-auth 1.7.0-beta.2 → 1.7.0-beta.4
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.
- package/README.md +14 -15
- package/dist/_virtual/_rolldown/runtime.mjs +10 -1
- package/dist/api/index.d.mts +18 -48
- package/dist/api/routes/account.d.mts +4 -23
- package/dist/api/routes/account.mjs +102 -75
- package/dist/api/routes/callback.mjs +42 -20
- package/dist/api/routes/email-verification.d.mts +1 -0
- package/dist/api/routes/email-verification.mjs +6 -5
- package/dist/api/routes/error.mjs +1 -1
- package/dist/api/routes/password.mjs +1 -1
- package/dist/api/routes/session.mjs +15 -10
- package/dist/api/routes/sign-in.d.mts +3 -1
- package/dist/api/routes/sign-in.mjs +13 -15
- package/dist/api/routes/sign-up.d.mts +1 -0
- package/dist/api/routes/sign-up.mjs +10 -8
- package/dist/api/routes/update-user.mjs +8 -8
- package/dist/api/to-auth-endpoints.mjs +7 -1
- package/dist/auth/base.mjs +30 -27
- package/dist/client/config.mjs +8 -1
- package/dist/client/fetch-plugins.mjs +2 -1
- package/dist/client/index.d.mts +2 -2
- package/dist/client/lynx/index.d.mts +13 -0
- package/dist/client/lynx/index.mjs +2 -1
- package/dist/client/parser.mjs +0 -1
- package/dist/client/plugins/index.d.mts +4 -17
- package/dist/client/plugins/index.mjs +1 -4
- package/dist/client/proxy.mjs +2 -1
- package/dist/client/react/index.d.mts +13 -0
- package/dist/client/react/index.mjs +2 -1
- package/dist/client/session-atom.mjs +12 -1
- package/dist/client/solid/index.d.mts +13 -0
- package/dist/client/solid/index.mjs +3 -2
- package/dist/client/svelte/index.d.mts +13 -0
- package/dist/client/svelte/index.mjs +2 -1
- package/dist/client/vanilla.d.mts +13 -0
- package/dist/client/vanilla.mjs +2 -1
- package/dist/client/vue/index.d.mts +13 -0
- package/dist/client/vue/index.mjs +2 -1
- package/dist/context/create-context.mjs +10 -14
- package/dist/context/helpers.mjs +3 -2
- package/dist/cookies/cookie-utils.d.mts +33 -1
- package/dist/cookies/cookie-utils.mjs +95 -14
- package/dist/cookies/index.d.mts +2 -3
- package/dist/cookies/index.mjs +39 -11
- package/dist/cookies/session-store.mjs +4 -23
- package/dist/db/get-migration.mjs +4 -4
- package/dist/db/index.d.mts +2 -2
- package/dist/db/index.mjs +3 -2
- package/dist/db/internal-adapter.mjs +129 -27
- package/dist/db/schema.d.mts +14 -1
- package/dist/db/schema.mjs +26 -1
- package/dist/db/with-hooks.d.mts +1 -0
- package/dist/db/with-hooks.mjs +58 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/integrations/cookie-plugin-guard.mjs +18 -0
- package/dist/integrations/next-js.mjs +6 -0
- package/dist/integrations/svelte-kit.mjs +6 -0
- package/dist/integrations/tanstack-start-solid.mjs +6 -0
- package/dist/integrations/tanstack-start.mjs +6 -0
- package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/index.mjs +32 -0
- package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/lib/linux.mjs +55 -0
- package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/lib/macos.mjs +26 -0
- package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/lib/termux.mjs +39 -0
- package/dist/node_modules/.pnpm/clipboardy@4.0.0/node_modules/clipboardy/lib/windows.mjs +19 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/chunks/prompt.mjs +845 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/core.mjs +386 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/index.mjs +320 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/shared/consola.DRwqZj3T.mjs +62 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/shared/consola.DXBYu-KD.mjs +190 -0
- package/dist/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/utils.mjs +2 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/index.mjs +29 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/enoent.mjs +42 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.mjs +67 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/escape.mjs +23 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.mjs +22 -0
- package/dist/node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.mjs +36 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/adapters/node.d.mts +292 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/adapters/node.mjs +127 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/index.d.mts +145 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.BQXMA5bH.d.mts +298 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.By9qWDAI.mjs +9 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.CipVM6lf.mjs +3549 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.D9ehKjSh.mjs +66 -0
- package/dist/node_modules/.pnpm/crossws@0.3.5/node_modules/crossws/dist/shared/crossws.DfCzGthR.mjs +227 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/index.mjs +224 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/command.mjs +52 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/error.mjs +54 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/kill.mjs +62 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/pipe.mjs +26 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/promise.mjs +32 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/stdio.mjs +19 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/stream.mjs +98 -0
- package/dist/node_modules/.pnpm/execa@8.0.1/node_modules/execa/lib/verbose.mjs +15 -0
- package/dist/node_modules/.pnpm/get-port-please@3.2.0/node_modules/get-port-please/dist/index.d.mts +15 -0
- package/dist/node_modules/.pnpm/get-port-please@3.2.0/node_modules/get-port-please/dist/index.mjs +220 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/array-buffer.mjs +54 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/array.mjs +2 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/buffer.mjs +14 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/contents.mjs +76 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/index.mjs +6 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/string.mjs +35 -0
- package/dist/node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/utils.mjs +10 -0
- package/dist/node_modules/.pnpm/http-shutdown@1.2.2/node_modules/http-shutdown/index.mjs +76 -0
- package/dist/node_modules/.pnpm/human-signals@5.0.0/node_modules/human-signals/build/src/core.mjs +274 -0
- package/dist/node_modules/.pnpm/human-signals@5.0.0/node_modules/human-signals/build/src/main.mjs +44 -0
- package/dist/node_modules/.pnpm/human-signals@5.0.0/node_modules/human-signals/build/src/realtime.mjs +15 -0
- package/dist/node_modules/.pnpm/human-signals@5.0.0/node_modules/human-signals/build/src/signals.mjs +23 -0
- package/dist/node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.mjs +24 -0
- package/dist/node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.mjs +18 -0
- package/dist/node_modules/.pnpm/is-stream@3.0.0/node_modules/is-stream/index.mjs +9 -0
- package/dist/node_modules/.pnpm/is-wsl@3.1.1/node_modules/is-wsl/index.mjs +20 -0
- package/dist/node_modules/.pnpm/is64bit@2.0.0/node_modules/is64bit/index.mjs +13 -0
- package/dist/node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.mjs +47 -0
- package/dist/node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/mode.mjs +33 -0
- package/dist/node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/windows.mjs +33 -0
- package/dist/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/dist/chunks/xdg-open.mjs +1070 -0
- package/dist/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/dist/index.mjs +619 -0
- package/dist/node_modules/.pnpm/listhen@1.9.0/node_modules/listhen/dist/shared/listhen.1c46e31d.d.mts +83 -0
- package/dist/node_modules/.pnpm/merge-stream@2.0.0/node_modules/merge-stream/index.mjs +38 -0
- package/dist/node_modules/.pnpm/mimic-fn@4.0.0/node_modules/mimic-fn/index.mjs +38 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/aes.mjs +597 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/aesCipherSuites.mjs +195 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/asn1-validator.mjs +76 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/asn1.mjs +967 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/baseN.mjs +137 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/cipher.mjs +186 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/cipherModes.mjs +597 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/des.mjs +1187 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/ed25519.mjs +1029 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/forge.mjs +15 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/hmac.mjs +107 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/index.mjs +66 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/jsbn.mjs +1334 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/kem.mjs +146 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/log.mjs +241 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/md.all.mjs +24 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/md.mjs +18 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/md5.mjs +324 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/mgf.mjs +20 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/mgf1.mjs +44 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/oids.mjs +154 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pbe.mjs +815 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pbkdf2.mjs +125 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pem.mjs +175 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pkcs1.mjs +200 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pkcs12.mjs +724 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pkcs7.mjs +642 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pkcs7asn1.mjs +405 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pki.mjs +101 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/prime.mjs +193 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/prng.mjs +290 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/pss.mjs +141 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/random.mjs +141 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/rc2.mjs +538 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/rsa.mjs +1309 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/sha1.mjs +230 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/sha256.mjs +267 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/sha512.mjs +413 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/ssh.mjs +194 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/tls.mjs +3655 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/util.mjs +2117 -0
- package/dist/node_modules/.pnpm/node-forge@1.4.0/node_modules/node-forge/lib/x509.mjs +2168 -0
- package/dist/node_modules/.pnpm/npm-run-path@5.3.0/node_modules/npm-run-path/index.mjs +34 -0
- package/dist/node_modules/.pnpm/onetime@6.0.0/node_modules/onetime/index.mjs +26 -0
- package/dist/node_modules/.pnpm/path-key@3.1.1/node_modules/path-key/index.mjs +14 -0
- package/dist/node_modules/.pnpm/path-key@4.0.0/node_modules/path-key/index.mjs +8 -0
- package/dist/node_modules/.pnpm/pathe@1.1.2/node_modules/pathe/dist/shared/pathe.ff20891b.mjs +176 -0
- package/dist/node_modules/.pnpm/shebang-command@2.0.0/node_modules/shebang-command/index.mjs +17 -0
- package/dist/node_modules/.pnpm/shebang-regex@3.0.0/node_modules/shebang-regex/index.mjs +8 -0
- package/dist/node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/index.mjs +169 -0
- package/dist/node_modules/.pnpm/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/signals.mjs +33 -0
- package/dist/node_modules/.pnpm/std-env@3.10.0/node_modules/std-env/dist/index.mjs +171 -0
- package/dist/node_modules/.pnpm/strip-final-newline@3.0.0/node_modules/strip-final-newline/index.mjs +10 -0
- package/dist/node_modules/.pnpm/system-architecture@0.1.0/node_modules/system-architecture/index.mjs +16 -0
- package/dist/node_modules/.pnpm/uncrypto@0.1.3/node_modules/uncrypto/dist/crypto.node.mjs +7 -0
- package/dist/node_modules/.pnpm/untun@0.1.3/node_modules/untun/dist/chunks/index.mjs +154 -0
- package/dist/node_modules/.pnpm/untun@0.1.3/node_modules/untun/dist/index.mjs +34 -0
- package/dist/node_modules/.pnpm/uqr@0.1.2/node_modules/uqr/dist/index.mjs +896 -0
- package/dist/node_modules/.pnpm/which@2.0.2/node_modules/which/which.mjs +76 -0
- package/dist/oauth2/errors.mjs +27 -0
- package/dist/oauth2/index.d.mts +2 -2
- package/dist/oauth2/index.mjs +3 -3
- package/dist/oauth2/link-account.d.mts +27 -1
- package/dist/oauth2/link-account.mjs +30 -5
- package/dist/oauth2/state.mjs +8 -2
- package/dist/{package.mjs → packages/better-auth/package.mjs} +1 -1
- package/dist/plugins/access/access.d.mts +3 -15
- package/dist/plugins/access/access.mjs +11 -6
- package/dist/plugins/access/index.d.mts +2 -2
- package/dist/plugins/access/types.d.mts +11 -4
- package/dist/plugins/admin/access/statement.d.mts +29 -93
- package/dist/plugins/admin/admin.mjs +0 -4
- package/dist/plugins/admin/client.d.mts +6 -1
- package/dist/plugins/admin/client.mjs +5 -0
- package/dist/plugins/admin/routes.mjs +3 -2
- package/dist/plugins/anonymous/client.d.mts +1 -0
- package/dist/plugins/anonymous/error-codes.d.mts +1 -0
- package/dist/plugins/anonymous/error-codes.mjs +1 -0
- package/dist/plugins/anonymous/index.d.mts +1 -0
- package/dist/plugins/anonymous/index.mjs +16 -2
- package/dist/plugins/bearer/index.mjs +5 -12
- package/dist/plugins/captcha/index.mjs +14 -1
- package/dist/plugins/device-authorization/error-codes.mjs +1 -0
- package/dist/plugins/device-authorization/index.d.mts +1 -0
- package/dist/plugins/device-authorization/routes.mjs +34 -3
- package/dist/plugins/email-otp/routes.mjs +4 -4
- package/dist/plugins/generic-oauth/error-codes.mjs +0 -1
- package/dist/plugins/generic-oauth/index.d.mts +2 -4
- package/dist/plugins/generic-oauth/index.mjs +23 -17
- package/dist/plugins/generic-oauth/providers/auth0.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/gumroad.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/hubspot.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/keycloak.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/line.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/microsoft-entra-id.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/okta.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/patreon.mjs +1 -0
- package/dist/plugins/generic-oauth/providers/slack.mjs +1 -0
- package/dist/plugins/generic-oauth/types.d.mts +30 -8
- package/dist/plugins/index.d.mts +2 -2
- package/dist/plugins/jwt/utils.d.mts +1 -1
- package/dist/plugins/last-login-method/client.mjs +2 -2
- package/dist/plugins/magic-link/index.d.mts +8 -1
- package/dist/plugins/magic-link/index.mjs +4 -17
- package/dist/plugins/mcp/authorize.mjs +8 -2
- package/dist/plugins/mcp/index.mjs +75 -35
- package/dist/plugins/multi-session/index.mjs +2 -2
- package/dist/plugins/oauth-proxy/index.mjs +45 -32
- package/dist/plugins/oauth-proxy/utils.mjs +3 -10
- package/dist/plugins/oidc-provider/authorize.mjs +8 -2
- package/dist/plugins/oidc-provider/index.mjs +65 -38
- package/dist/plugins/one-tap/client.mjs +9 -2
- package/dist/plugins/one-tap/index.mjs +19 -36
- package/dist/plugins/open-api/generator.mjs +25 -5
- package/dist/plugins/organization/access/statement.d.mts +68 -201
- package/dist/plugins/organization/adapter.d.mts +1 -1
- package/dist/plugins/organization/adapter.mjs +65 -58
- package/dist/plugins/organization/client.d.mts +3 -1
- package/dist/plugins/organization/client.mjs +1 -1
- package/dist/plugins/organization/error-codes.d.mts +2 -0
- package/dist/plugins/organization/error-codes.mjs +3 -1
- package/dist/plugins/organization/routes/crud-access-control.d.mts +2 -2
- package/dist/plugins/organization/routes/crud-invites.d.mts +8 -1
- package/dist/plugins/organization/routes/crud-invites.mjs +8 -3
- package/dist/plugins/organization/routes/crud-org.d.mts +4 -4
- package/dist/plugins/organization/routes/crud-org.mjs +2 -2
- package/dist/plugins/organization/routes/crud-team.mjs +7 -2
- package/dist/plugins/organization/schema.d.mts +1 -1
- package/dist/plugins/organization/types.d.mts +15 -5
- package/dist/plugins/phone-number/routes.mjs +1 -1
- package/dist/plugins/siwe/client.d.mts +4 -0
- package/dist/plugins/siwe/client.mjs +5 -1
- package/dist/plugins/siwe/index.d.mts +13 -2
- package/dist/plugins/siwe/index.mjs +179 -165
- package/dist/plugins/two-factor/backup-codes/index.d.mts +4 -3
- package/dist/plugins/two-factor/client.mjs +2 -1
- package/dist/plugins/two-factor/index.mjs +3 -2
- package/dist/plugins/username/client.d.mts +1 -0
- package/dist/plugins/username/error-codes.d.mts +1 -0
- package/dist/plugins/username/error-codes.mjs +2 -1
- package/dist/plugins/username/index.d.mts +43 -2
- package/dist/plugins/username/index.mjs +73 -6
- package/dist/state.d.mts +2 -2
- package/dist/state.mjs +18 -4
- package/dist/test-utils/headers.mjs +2 -7
- package/dist/test-utils/http-test-instance.d.mts +397 -0
- package/dist/test-utils/http-test-instance.mjs +54 -0
- package/dist/test-utils/index.d.mts +2 -1
- package/dist/test-utils/index.mjs +2 -1
- package/dist/test-utils/test-instance.d.mts +4110 -224
- package/dist/test-utils/test-instance.mjs +11 -2
- package/dist/types/auth.d.mts +4 -0
- package/dist/utils/index.d.mts +1 -1
- package/dist/utils/url.d.mts +2 -1
- package/dist/utils/url.mjs +9 -3
- package/dist/version.mjs +1 -1
- package/package.json +14 -14
- package/dist/oauth2/error-codes.d.mts +0 -20
- package/dist/plugins/generic-oauth/client.d.mts +0 -32
- package/dist/plugins/generic-oauth/client.mjs +0 -19
- package/dist/plugins/generic-oauth/error-codes.d.mts +0 -10
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { __commonJSMin, __require } from "../../../../../_virtual/_rolldown/runtime.mjs";
|
|
2
|
+
import { require_isexe } from "../../../isexe@2.0.0/node_modules/isexe/index.mjs";
|
|
3
|
+
//#region ../../node_modules/.pnpm/which@2.0.2/node_modules/which/which.js
|
|
4
|
+
var require_which = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
5
|
+
const isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
|
|
6
|
+
const path = __require("path");
|
|
7
|
+
const COLON = isWindows ? ";" : ":";
|
|
8
|
+
const isexe = require_isexe();
|
|
9
|
+
const getNotFoundError = (cmd) => Object.assign(/* @__PURE__ */ new Error(`not found: ${cmd}`), { code: "ENOENT" });
|
|
10
|
+
const getPathInfo = (cmd, opt) => {
|
|
11
|
+
const colon = opt.colon || COLON;
|
|
12
|
+
const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [""] : [...isWindows ? [process.cwd()] : [], ...(opt.path || process.env.PATH || "").split(colon)];
|
|
13
|
+
const pathExtExe = isWindows ? opt.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : "";
|
|
14
|
+
const pathExt = isWindows ? pathExtExe.split(colon) : [""];
|
|
15
|
+
if (isWindows) {
|
|
16
|
+
if (cmd.indexOf(".") !== -1 && pathExt[0] !== "") pathExt.unshift("");
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
pathEnv,
|
|
20
|
+
pathExt,
|
|
21
|
+
pathExtExe
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
const which = (cmd, opt, cb) => {
|
|
25
|
+
if (typeof opt === "function") {
|
|
26
|
+
cb = opt;
|
|
27
|
+
opt = {};
|
|
28
|
+
}
|
|
29
|
+
if (!opt) opt = {};
|
|
30
|
+
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
|
31
|
+
const found = [];
|
|
32
|
+
const step = (i) => new Promise((resolve, reject) => {
|
|
33
|
+
if (i === pathEnv.length) return opt.all && found.length ? resolve(found) : reject(getNotFoundError(cmd));
|
|
34
|
+
const ppRaw = pathEnv[i];
|
|
35
|
+
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
36
|
+
const pCmd = path.join(pathPart, cmd);
|
|
37
|
+
resolve(subStep(!pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd, i, 0));
|
|
38
|
+
});
|
|
39
|
+
const subStep = (p, i, ii) => new Promise((resolve, reject) => {
|
|
40
|
+
if (ii === pathExt.length) return resolve(step(i + 1));
|
|
41
|
+
const ext = pathExt[ii];
|
|
42
|
+
isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
|
|
43
|
+
if (!er && is) if (opt.all) found.push(p + ext);
|
|
44
|
+
else return resolve(p + ext);
|
|
45
|
+
return resolve(subStep(p, i, ii + 1));
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
|
|
49
|
+
};
|
|
50
|
+
const whichSync = (cmd, opt) => {
|
|
51
|
+
opt = opt || {};
|
|
52
|
+
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
|
53
|
+
const found = [];
|
|
54
|
+
for (let i = 0; i < pathEnv.length; i++) {
|
|
55
|
+
const ppRaw = pathEnv[i];
|
|
56
|
+
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
57
|
+
const pCmd = path.join(pathPart, cmd);
|
|
58
|
+
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
59
|
+
for (let j = 0; j < pathExt.length; j++) {
|
|
60
|
+
const cur = p + pathExt[j];
|
|
61
|
+
try {
|
|
62
|
+
if (isexe.sync(cur, { pathExt: pathExtExe })) if (opt.all) found.push(cur);
|
|
63
|
+
else return cur;
|
|
64
|
+
} catch (ex) {}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (opt.all && found.length) return found;
|
|
68
|
+
if (opt.nothrow) return null;
|
|
69
|
+
throw getNotFoundError(cmd);
|
|
70
|
+
};
|
|
71
|
+
module.exports = which;
|
|
72
|
+
which.sync = whichSync;
|
|
73
|
+
}));
|
|
74
|
+
//#endregion
|
|
75
|
+
export default require_which();
|
|
76
|
+
export { require_which };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/oauth2/errors.ts
|
|
2
|
+
const HANDLING_DOCS_URL = "https://www.better-auth.com/docs/concepts/oauth#handling-providers-without-email";
|
|
3
|
+
/**
|
|
4
|
+
* Redirect the user to the OAuth error page with a machine-readable `error`
|
|
5
|
+
* code (and optional `error_description`).
|
|
6
|
+
*
|
|
7
|
+
* Every OAuth callback path routes its failures through this helper so the
|
|
8
|
+
* query parameter name, the `?`/`&` separator, and URL encoding are decided in
|
|
9
|
+
* one place. The error page reads the `error` query parameter, so callers must
|
|
10
|
+
* never hand-build the redirect with a different parameter name.
|
|
11
|
+
*/
|
|
12
|
+
function redirectOnError(ctx, errorURL, error, description) {
|
|
13
|
+
const params = new URLSearchParams({ error });
|
|
14
|
+
if (description) params.set("error_description", description);
|
|
15
|
+
const sep = errorURL.includes("?") ? "&" : "?";
|
|
16
|
+
throw ctx.redirect(`${errorURL}${sep}${params.toString()}`);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Build the logger message shown when an OAuth provider does not return an
|
|
20
|
+
* email address. Kept in one place so every rejection site points users at
|
|
21
|
+
* the same workaround docs.
|
|
22
|
+
*/
|
|
23
|
+
function missingEmailLogMessage(providerId, options) {
|
|
24
|
+
return `${options?.source === "generic" ? `Generic OAuth provider "${providerId}"` : `Provider "${providerId}"`} did not return an email${options?.source === "id_token" ? " in the id token" : ""}. Either request the provider's email scope, or synthesize one via \`mapProfileToUser\`. See ${HANDLING_DOCS_URL}`;
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { missingEmailLogMessage, redirectOnError };
|
package/dist/oauth2/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { generateState, parseState } from "./state.mjs";
|
|
2
|
-
import { handleOAuthUserInfo } from "./link-account.mjs";
|
|
2
|
+
import { applyUpdateUserInfoOnLink, handleOAuthUserInfo } from "./link-account.mjs";
|
|
3
3
|
import { decryptOAuthToken, setTokenUtil } from "./utils.mjs";
|
|
4
4
|
export * from "@better-auth/core/oauth2";
|
|
5
|
-
export { decryptOAuthToken, generateState, handleOAuthUserInfo, parseState, setTokenUtil };
|
|
5
|
+
export { applyUpdateUserInfoOnLink, decryptOAuthToken, generateState, handleOAuthUserInfo, parseState, setTokenUtil };
|
package/dist/oauth2/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { generateState, parseState } from "./state.mjs";
|
|
2
1
|
import { decryptOAuthToken, setTokenUtil } from "./utils.mjs";
|
|
3
|
-
import { handleOAuthUserInfo } from "./link-account.mjs";
|
|
2
|
+
import { applyUpdateUserInfoOnLink, handleOAuthUserInfo } from "./link-account.mjs";
|
|
3
|
+
import { generateState, parseState } from "./state.mjs";
|
|
4
4
|
export * from "@better-auth/core/oauth2";
|
|
5
|
-
export { decryptOAuthToken, generateState, handleOAuthUserInfo, parseState, setTokenUtil };
|
|
5
|
+
export { applyUpdateUserInfoOnLink, decryptOAuthToken, generateState, handleOAuthUserInfo, parseState, setTokenUtil };
|
|
@@ -42,5 +42,31 @@ declare function handleOAuthUserInfo(c: GenericEndpointContext, opts: {
|
|
|
42
42
|
error: null;
|
|
43
43
|
isRegister: boolean;
|
|
44
44
|
}>;
|
|
45
|
+
/**
|
|
46
|
+
* Provider profile a freshly linked account may copy onto the local user.
|
|
47
|
+
* `id` is the provider's account id (never the local user id), and `email`/
|
|
48
|
+
* `emailVerified` are identity anchors; all three are stripped before the
|
|
49
|
+
* remaining fields are written.
|
|
50
|
+
*/
|
|
51
|
+
type LinkedProviderProfile = {
|
|
52
|
+
id: string | number;
|
|
53
|
+
name?: string | undefined;
|
|
54
|
+
email?: string | null | undefined;
|
|
55
|
+
emailVerified?: boolean | undefined;
|
|
56
|
+
image?: string | null | undefined;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Apply the `account.accountLinking.updateUserInfoOnLink` policy: when enabled,
|
|
60
|
+
* copy the freshly linked provider's profile onto the local user, matching the
|
|
61
|
+
* field set persisted on sign-up. The local `email` and `emailVerified` are
|
|
62
|
+
* never changed, so a link can't rebind the account's identity, and
|
|
63
|
+
* `updateUser` drops `undefined` fields, so a provider that omits one leaves
|
|
64
|
+
* the existing column intact.
|
|
65
|
+
*
|
|
66
|
+
* Returns the updated user so a caller that issues a session can seed the
|
|
67
|
+
* cookie cache with the fresh row. Returns `undefined` when the policy is
|
|
68
|
+
* disabled or the update fails: a failed profile sync must not abort the link.
|
|
69
|
+
*/
|
|
70
|
+
declare function applyUpdateUserInfoOnLink(c: GenericEndpointContext, userId: string, userInfo: LinkedProviderProfile): Promise<User | undefined>;
|
|
45
71
|
//#endregion
|
|
46
|
-
export { handleOAuthUserInfo };
|
|
72
|
+
export { applyUpdateUserInfoOnLink, handleOAuthUserInfo };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isAPIError } from "../utils/is-api-error.mjs";
|
|
2
2
|
import { setAccountCookie } from "../cookies/session-store.mjs";
|
|
3
|
+
import { redirectOnError } from "./errors.mjs";
|
|
3
4
|
import { setTokenUtil } from "./utils.mjs";
|
|
4
5
|
import { createEmailVerificationToken } from "../api/routes/email-verification.mjs";
|
|
5
6
|
import { isDevelopment, logger } from "@better-auth/core/env";
|
|
@@ -8,8 +9,7 @@ async function handleOAuthUserInfo(c, opts) {
|
|
|
8
9
|
const { userInfo, account, callbackURL, disableSignUp, overrideUserInfo } = opts;
|
|
9
10
|
const dbUser = await c.context.internalAdapter.findOAuthUser(userInfo.email.toLowerCase(), account.accountId, account.providerId).catch((e) => {
|
|
10
11
|
logger.error("Better auth was unable to query your database.\nError: ", e);
|
|
11
|
-
|
|
12
|
-
throw c.redirect(`${errorURL}?error=internal_server_error`);
|
|
12
|
+
redirectOnError(c, c.context.options.onAPIError?.errorURL || `${c.context.baseURL}/error`, "internal_server_error");
|
|
13
13
|
});
|
|
14
14
|
let user = dbUser?.user;
|
|
15
15
|
const isRegister = !user;
|
|
@@ -17,7 +17,9 @@ async function handleOAuthUserInfo(c, opts) {
|
|
|
17
17
|
const linkedAccount = dbUser.linkedAccount ?? dbUser.accounts.find((acc) => acc.providerId === account.providerId && acc.accountId === account.accountId);
|
|
18
18
|
if (!linkedAccount) {
|
|
19
19
|
const accountLinking = c.context.options.account?.accountLinking;
|
|
20
|
-
|
|
20
|
+
const isTrustedProvider = opts.isTrustedProvider || c.context.trustedProviders.includes(account.providerId);
|
|
21
|
+
const requireLocalEmailVerified = accountLinking?.requireLocalEmailVerified ?? true;
|
|
22
|
+
if (!isTrustedProvider && !userInfo.emailVerified || requireLocalEmailVerified && !dbUser.user.emailVerified || accountLinking?.enabled === false || accountLinking?.disableImplicitLinking === true) {
|
|
21
23
|
if (isDevelopment()) logger.warn(`User already exist but account isn't linked to ${account.providerId}. To read more about how account linking works in Better Auth see https://www.better-auth.com/docs/concepts/users-accounts#account-linking.`);
|
|
22
24
|
return {
|
|
23
25
|
error: "account not linked",
|
|
@@ -44,6 +46,7 @@ async function handleOAuthUserInfo(c, opts) {
|
|
|
44
46
|
};
|
|
45
47
|
}
|
|
46
48
|
if (userInfo.emailVerified && !dbUser.user.emailVerified && userInfo.email.toLowerCase() === dbUser.user.email) await c.context.internalAdapter.updateUser(dbUser.user.id, { emailVerified: true });
|
|
49
|
+
user = await applyUpdateUserInfoOnLink(c, dbUser.user.id, userInfo) ?? user;
|
|
47
50
|
} else {
|
|
48
51
|
const freshTokens = c.context.options.account?.updateAccountOnSignIn !== false ? Object.fromEntries(Object.entries({
|
|
49
52
|
idToken: account.idToken,
|
|
@@ -94,7 +97,7 @@ async function handleOAuthUserInfo(c, opts) {
|
|
|
94
97
|
if (c.context.options.account?.storeAccountCookie) await setAccountCookie(c, createdAccount);
|
|
95
98
|
if (!userInfo.emailVerified && user && c.context.options.emailVerification?.sendOnSignUp && c.context.options.emailVerification?.sendVerificationEmail) {
|
|
96
99
|
const token = await createEmailVerificationToken(c.context.secret, user.email, void 0, c.context.options.emailVerification?.expiresIn);
|
|
97
|
-
const url = `${c.context.baseURL}/verify-email?token=${token}&callbackURL=${callbackURL}`;
|
|
100
|
+
const url = `${c.context.baseURL}/verify-email?token=${token}&callbackURL=${encodeURIComponent(callbackURL || "/")}`;
|
|
98
101
|
await c.context.runInBackgroundOrAwait(c.context.options.emailVerification.sendVerificationEmail({
|
|
99
102
|
user,
|
|
100
103
|
url,
|
|
@@ -135,5 +138,27 @@ async function handleOAuthUserInfo(c, opts) {
|
|
|
135
138
|
isRegister
|
|
136
139
|
};
|
|
137
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Apply the `account.accountLinking.updateUserInfoOnLink` policy: when enabled,
|
|
143
|
+
* copy the freshly linked provider's profile onto the local user, matching the
|
|
144
|
+
* field set persisted on sign-up. The local `email` and `emailVerified` are
|
|
145
|
+
* never changed, so a link can't rebind the account's identity, and
|
|
146
|
+
* `updateUser` drops `undefined` fields, so a provider that omits one leaves
|
|
147
|
+
* the existing column intact.
|
|
148
|
+
*
|
|
149
|
+
* Returns the updated user so a caller that issues a session can seed the
|
|
150
|
+
* cookie cache with the fresh row. Returns `undefined` when the policy is
|
|
151
|
+
* disabled or the update fails: a failed profile sync must not abort the link.
|
|
152
|
+
*/
|
|
153
|
+
async function applyUpdateUserInfoOnLink(c, userId, userInfo) {
|
|
154
|
+
if (c.context.options.account?.accountLinking?.updateUserInfoOnLink !== true) return;
|
|
155
|
+
const { id: _id, email: _email, emailVerified: _emailVerified, ...profile } = userInfo;
|
|
156
|
+
try {
|
|
157
|
+
return await c.context.internalAdapter.updateUser(userId, profile);
|
|
158
|
+
} catch (e) {
|
|
159
|
+
c.context.logger.warn("Could not update user info on account link", e);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
138
163
|
//#endregion
|
|
139
|
-
export { handleOAuthUserInfo };
|
|
164
|
+
export { applyUpdateUserInfoOnLink, handleOAuthUserInfo };
|
package/dist/oauth2/state.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { generateRandomString } from "../crypto/random.mjs";
|
|
2
|
+
import { redirectOnError } from "./errors.mjs";
|
|
2
3
|
import { setOAuthState } from "../api/state/oauth.mjs";
|
|
3
4
|
import { StateError, generateGenericState, parseGenericState } from "../state.mjs";
|
|
4
5
|
import { APIError, BASE_ERROR_CODES } from "@better-auth/core/error";
|
|
@@ -36,8 +37,13 @@ async function parseState(c) {
|
|
|
36
37
|
parsedData = await parseGenericState(c, state);
|
|
37
38
|
} catch (error) {
|
|
38
39
|
c.context.logger.error("Failed to parse state", error);
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
let code = "internal_server_error";
|
|
41
|
+
let redirectErrorURL = errorURL;
|
|
42
|
+
if (error instanceof StateError) {
|
|
43
|
+
code = error.code === "state_security_mismatch" ? "state_mismatch" : error.code;
|
|
44
|
+
redirectErrorURL = error.errorURL ?? errorURL;
|
|
45
|
+
}
|
|
46
|
+
redirectOnError(c, redirectErrorURL, code);
|
|
41
47
|
}
|
|
42
48
|
if (!parsedData.errorURL) parsedData.errorURL = errorURL;
|
|
43
49
|
if (parsedData) await setOAuthState(parsedData);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExactRoleStatements, Role, RoleInput, Statements } from "./types.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/plugins/access/access.d.ts
|
|
4
4
|
type AuthorizeResponse = {
|
|
@@ -8,21 +8,9 @@ type AuthorizeResponse = {
|
|
|
8
8
|
success: true;
|
|
9
9
|
error?: never | undefined;
|
|
10
10
|
};
|
|
11
|
-
declare function role<
|
|
12
|
-
authorize<K extends keyof TStatements>(request: { [key in K]?: TStatements[key] | {
|
|
13
|
-
actions: TStatements[key];
|
|
14
|
-
connector: "OR" | "AND";
|
|
15
|
-
} }, connector?: "OR" | "AND"): AuthorizeResponse;
|
|
16
|
-
statements: TStatements;
|
|
17
|
-
};
|
|
11
|
+
declare function role<const TRoleStatements extends Statements, TAuthorizeStatements extends Statements = TRoleStatements>(statements: TRoleStatements): Role<ExactRoleStatements<TRoleStatements>, TAuthorizeStatements>;
|
|
18
12
|
declare function createAccessControl<const TStatements extends Statements>(s: TStatements): {
|
|
19
|
-
newRole<
|
|
20
|
-
authorize<K_1 extends K>(request: K_1 extends infer T extends keyof Subset<K, TStatements> ? { [key in T]?: Subset<K, TStatements>[key] | {
|
|
21
|
-
actions: Subset<K, TStatements>[key];
|
|
22
|
-
connector: "OR" | "AND";
|
|
23
|
-
} | undefined } : never, connector?: "OR" | "AND"): AuthorizeResponse;
|
|
24
|
-
statements: Subset<K, TStatements>;
|
|
25
|
-
};
|
|
13
|
+
newRole<const TRoleStatements extends Statements>(statements: RoleInput<TStatements, TRoleStatements>): Role<ExactRoleStatements<TRoleStatements>, TStatements>;
|
|
26
14
|
statements: TStatements;
|
|
27
15
|
};
|
|
28
16
|
//#endregion
|
|
@@ -6,14 +6,19 @@ function role(statements) {
|
|
|
6
6
|
let success = false;
|
|
7
7
|
for (const [requestedResource, requestedActions] of Object.entries(request)) {
|
|
8
8
|
const allowedActions = statements[requestedResource];
|
|
9
|
-
if (!allowedActions)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
if (!allowedActions) {
|
|
10
|
+
if (connector === "AND") return {
|
|
11
|
+
success: false,
|
|
12
|
+
error: `You are not allowed to access resource: ${requestedResource}`
|
|
13
|
+
};
|
|
14
|
+
success = false;
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (Array.isArray(requestedActions)) success = requestedActions.length > 0 && requestedActions.every((requestedAction) => allowedActions.includes(requestedAction));
|
|
14
18
|
else if (typeof requestedActions === "object") {
|
|
15
19
|
const actions = requestedActions;
|
|
16
|
-
if (actions.
|
|
20
|
+
if (!Array.isArray(actions.actions) || actions.actions.length === 0) success = false;
|
|
21
|
+
else if (actions.connector === "OR") success = actions.actions.some((requestedAction) => allowedActions.includes(requestedAction));
|
|
17
22
|
else success = actions.actions.every((requestedAction) => allowedActions.includes(requestedAction));
|
|
18
23
|
} else throw new BetterAuthError("Invalid access control request");
|
|
19
24
|
if (success && connector === "OR") return { success };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { AccessControl, ArrayElement, Role, Statements, SubArray, Subset } from "./types.mjs";
|
|
1
|
+
import { AccessControl, ArrayElement, ExactRoleStatements, Role, RoleAuthorizeRequest, RoleInput, RoleStatements, Statements, SubArray, Subset } from "./types.mjs";
|
|
2
2
|
import { AuthorizeResponse, createAccessControl, role } from "./access.mjs";
|
|
3
|
-
export { AccessControl, ArrayElement, AuthorizeResponse, Role, Statements, SubArray, Subset, createAccessControl, role };
|
|
3
|
+
export { AccessControl, ArrayElement, AuthorizeResponse, ExactRoleStatements, Role, RoleAuthorizeRequest, RoleInput, RoleStatements, Statements, SubArray, Subset, createAccessControl, role };
|
|
@@ -8,10 +8,17 @@ type Subset<K extends keyof R, R extends Record<string | LiteralString, readonly
|
|
|
8
8
|
type Statements = {
|
|
9
9
|
readonly [resource: string]: readonly LiteralString[];
|
|
10
10
|
};
|
|
11
|
+
type RoleStatements<TStatements extends Statements> = { readonly [P in keyof TStatements]?: SubArray<TStatements[P]> };
|
|
12
|
+
type RoleInput<TStatements extends Statements, TRoleStatements extends Statements> = TRoleStatements & (string extends keyof TRoleStatements ? {} : RoleStatements<TStatements> & Record<Exclude<keyof TRoleStatements, keyof TStatements>, never>);
|
|
13
|
+
type ExactRoleStatements<TStatements extends Statements> = { readonly [P in keyof TStatements]: readonly [...TStatements[P]] };
|
|
11
14
|
type AccessControl<TStatements extends Statements = Statements> = ReturnType<typeof createAccessControl<TStatements>>;
|
|
12
|
-
type
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
type RoleAuthorizeRequest<TStatements extends Statements> = { [P in keyof TStatements]?: SubArray<TStatements[P]> | {
|
|
16
|
+
actions: SubArray<TStatements[P]>;
|
|
17
|
+
connector: "OR" | "AND";
|
|
18
|
+
} };
|
|
19
|
+
type Role<TRoleStatements extends Statements = Record<string, any>, TAuthorizeStatements extends Statements = TRoleStatements> = {
|
|
20
|
+
authorize: (request: RoleAuthorizeRequest<TAuthorizeStatements>, connector?: ("OR" | "AND") | undefined) => AuthorizeResponse;
|
|
21
|
+
statements: TRoleStatements;
|
|
15
22
|
};
|
|
16
23
|
//#endregion
|
|
17
|
-
export { AccessControl, ArrayElement, Role, Statements, SubArray, Subset };
|
|
24
|
+
export { AccessControl, ArrayElement, ExactRoleStatements, Role, RoleAuthorizeRequest, RoleInput, RoleStatements, Statements, SubArray, Subset };
|
|
@@ -1,115 +1,51 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { AuthorizeResponse } from "../../access/access.mjs";
|
|
1
|
+
import { ExactRoleStatements, Role, RoleInput, Statements } from "../../access/types.mjs";
|
|
3
2
|
//#region src/plugins/admin/access/statement.d.ts
|
|
4
3
|
declare const defaultStatements: {
|
|
5
4
|
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
6
5
|
readonly session: readonly ["list", "revoke", "delete"];
|
|
7
6
|
};
|
|
8
7
|
declare const defaultAc: {
|
|
9
|
-
newRole<
|
|
8
|
+
newRole<const TRoleStatements extends Statements>(statements: RoleInput<{
|
|
10
9
|
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
11
10
|
readonly session: readonly ["list", "revoke", "delete"];
|
|
12
|
-
}>): {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}> ? { [key in T]?: Subset<K, {
|
|
17
|
-
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
18
|
-
readonly session: readonly ["list", "revoke", "delete"];
|
|
19
|
-
}>[key] | {
|
|
20
|
-
actions: Subset<K, {
|
|
21
|
-
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
22
|
-
readonly session: readonly ["list", "revoke", "delete"];
|
|
23
|
-
}>[key];
|
|
24
|
-
connector: "OR" | "AND";
|
|
25
|
-
} | undefined } : never, connector?: "OR" | "AND"): AuthorizeResponse;
|
|
26
|
-
statements: Subset<K, {
|
|
27
|
-
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
28
|
-
readonly session: readonly ["list", "revoke", "delete"];
|
|
29
|
-
}>;
|
|
30
|
-
};
|
|
11
|
+
}, TRoleStatements>): Role<ExactRoleStatements<TRoleStatements>, {
|
|
12
|
+
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
13
|
+
readonly session: readonly ["list", "revoke", "delete"];
|
|
14
|
+
}>;
|
|
31
15
|
statements: {
|
|
32
16
|
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
33
17
|
readonly session: readonly ["list", "revoke", "delete"];
|
|
34
18
|
};
|
|
35
19
|
};
|
|
36
|
-
declare const adminAc: {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
20
|
+
declare const adminAc: Role<ExactRoleStatements<{
|
|
21
|
+
readonly user: ["create", "list", "set-role", "ban", "impersonate", "delete", "set-password", "get", "update"];
|
|
22
|
+
readonly session: ["list", "revoke", "delete"];
|
|
23
|
+
}>, {
|
|
24
|
+
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
25
|
+
readonly session: readonly ["list", "revoke", "delete"];
|
|
26
|
+
}>;
|
|
27
|
+
declare const userAc: Role<ExactRoleStatements<{
|
|
28
|
+
readonly user: [];
|
|
29
|
+
readonly session: [];
|
|
30
|
+
}>, {
|
|
31
|
+
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
32
|
+
readonly session: readonly ["list", "revoke", "delete"];
|
|
33
|
+
}>;
|
|
34
|
+
declare const defaultRoles: {
|
|
35
|
+
admin: Role<ExactRoleStatements<{
|
|
36
|
+
readonly user: ["create", "list", "set-role", "ban", "impersonate", "delete", "set-password", "get", "update"];
|
|
37
|
+
readonly session: ["list", "revoke", "delete"];
|
|
38
|
+
}>, {
|
|
51
39
|
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
52
40
|
readonly session: readonly ["list", "revoke", "delete"];
|
|
53
41
|
}>;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
readonly session: readonly ["list", "revoke", "delete"];
|
|
59
|
-
}> ? { [key in T]?: Subset<"user" | "session", {
|
|
60
|
-
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
61
|
-
readonly session: readonly ["list", "revoke", "delete"];
|
|
62
|
-
}>[key] | {
|
|
63
|
-
actions: Subset<"user" | "session", {
|
|
64
|
-
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
65
|
-
readonly session: readonly ["list", "revoke", "delete"];
|
|
66
|
-
}>[key];
|
|
67
|
-
connector: "OR" | "AND";
|
|
68
|
-
} | undefined } : never, connector?: "OR" | "AND"): AuthorizeResponse;
|
|
69
|
-
statements: Subset<"user" | "session", {
|
|
42
|
+
user: Role<ExactRoleStatements<{
|
|
43
|
+
readonly user: [];
|
|
44
|
+
readonly session: [];
|
|
45
|
+
}>, {
|
|
70
46
|
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
71
47
|
readonly session: readonly ["list", "revoke", "delete"];
|
|
72
48
|
}>;
|
|
73
49
|
};
|
|
74
|
-
declare const defaultRoles: {
|
|
75
|
-
admin: {
|
|
76
|
-
authorize<K extends "user" | "session">(request: K extends infer T extends keyof Subset<"user" | "session", {
|
|
77
|
-
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
78
|
-
readonly session: readonly ["list", "revoke", "delete"];
|
|
79
|
-
}> ? { [key in T]?: Subset<"user" | "session", {
|
|
80
|
-
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
81
|
-
readonly session: readonly ["list", "revoke", "delete"];
|
|
82
|
-
}>[key] | {
|
|
83
|
-
actions: Subset<"user" | "session", {
|
|
84
|
-
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
85
|
-
readonly session: readonly ["list", "revoke", "delete"];
|
|
86
|
-
}>[key];
|
|
87
|
-
connector: "OR" | "AND";
|
|
88
|
-
} | undefined } : never, connector?: "OR" | "AND"): AuthorizeResponse;
|
|
89
|
-
statements: Subset<"user" | "session", {
|
|
90
|
-
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
91
|
-
readonly session: readonly ["list", "revoke", "delete"];
|
|
92
|
-
}>;
|
|
93
|
-
};
|
|
94
|
-
user: {
|
|
95
|
-
authorize<K extends "user" | "session">(request: K extends infer T extends keyof Subset<"user" | "session", {
|
|
96
|
-
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
97
|
-
readonly session: readonly ["list", "revoke", "delete"];
|
|
98
|
-
}> ? { [key in T]?: Subset<"user" | "session", {
|
|
99
|
-
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
100
|
-
readonly session: readonly ["list", "revoke", "delete"];
|
|
101
|
-
}>[key] | {
|
|
102
|
-
actions: Subset<"user" | "session", {
|
|
103
|
-
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
104
|
-
readonly session: readonly ["list", "revoke", "delete"];
|
|
105
|
-
}>[key];
|
|
106
|
-
connector: "OR" | "AND";
|
|
107
|
-
} | undefined } : never, connector?: "OR" | "AND"): AuthorizeResponse;
|
|
108
|
-
statements: Subset<"user" | "session", {
|
|
109
|
-
readonly user: readonly ["create", "list", "set-role", "ban", "impersonate", "impersonate-admins", "delete", "set-password", "get", "update"];
|
|
110
|
-
readonly session: readonly ["list", "revoke", "delete"];
|
|
111
|
-
}>;
|
|
112
|
-
};
|
|
113
|
-
};
|
|
114
50
|
//#endregion
|
|
115
51
|
export { adminAc, defaultAc, defaultRoles, defaultStatements, userAc };
|
|
@@ -42,10 +42,6 @@ const admin = (options) => {
|
|
|
42
42
|
});
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
|
-
if (ctx.path.startsWith("/callback")) {
|
|
46
|
-
const redirectURI = ctx.context.options.onAPIError?.errorURL || `${ctx.context.baseURL}/error`;
|
|
47
|
-
throw ctx.redirect(`${redirectURI}?error=banned&error_description=${opts.bannedUserMessage}`);
|
|
48
|
-
}
|
|
49
45
|
throw APIError.from("FORBIDDEN", {
|
|
50
46
|
message: opts.bannedUserMessage,
|
|
51
47
|
code: "BANNED_USER"
|
|
@@ -44,8 +44,13 @@ declare const adminClient: <O extends AdminClientOptions>(options?: O | undefine
|
|
|
44
44
|
};
|
|
45
45
|
pathMethods: {
|
|
46
46
|
"/admin/list-users": "GET";
|
|
47
|
+
"/admin/impersonate-user": "POST";
|
|
47
48
|
"/admin/stop-impersonating": "POST";
|
|
48
49
|
};
|
|
50
|
+
atomListeners: {
|
|
51
|
+
matcher: (path: string) => path is "/admin/impersonate-user" | "/admin/stop-impersonating";
|
|
52
|
+
signal: "$sessionSignal";
|
|
53
|
+
}[];
|
|
49
54
|
$ERROR_CODES: {
|
|
50
55
|
USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL: _better_auth_core_utils_error_codes0.RawError<"USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL">;
|
|
51
56
|
FAILED_TO_CREATE_USER: _better_auth_core_utils_error_codes0.RawError<"FAILED_TO_CREATE_USER">;
|
|
@@ -71,4 +76,4 @@ declare const adminClient: <O extends AdminClientOptions>(options?: O | undefine
|
|
|
71
76
|
};
|
|
72
77
|
};
|
|
73
78
|
//#endregion
|
|
74
|
-
export { adminClient };
|
|
79
|
+
export { AdminClientOptions, adminClient };
|
|
@@ -25,8 +25,13 @@ const adminClient = (options) => {
|
|
|
25
25
|
} } }),
|
|
26
26
|
pathMethods: {
|
|
27
27
|
"/admin/list-users": "GET",
|
|
28
|
+
"/admin/impersonate-user": "POST",
|
|
28
29
|
"/admin/stop-impersonating": "POST"
|
|
29
30
|
},
|
|
31
|
+
atomListeners: [{
|
|
32
|
+
matcher: (path) => path === "/admin/impersonate-user" || path === "/admin/stop-impersonating",
|
|
33
|
+
signal: "$sessionSignal"
|
|
34
|
+
}],
|
|
30
35
|
$ERROR_CODES: ADMIN_ERROR_CODES
|
|
31
36
|
};
|
|
32
37
|
};
|
|
@@ -462,7 +462,7 @@ const banUser = (opts) => createAuthEndpoint("/admin/ban-user", {
|
|
|
462
462
|
banExpires: ctx.body.banExpiresIn ? getDate(ctx.body.banExpiresIn, "sec") : opts?.defaultBanExpiresIn ? getDate(opts.defaultBanExpiresIn, "sec") : void 0,
|
|
463
463
|
updatedAt: /* @__PURE__ */ new Date()
|
|
464
464
|
});
|
|
465
|
-
await ctx.context.internalAdapter.
|
|
465
|
+
await ctx.context.internalAdapter.deleteUserSessions(ctx.body.userId);
|
|
466
466
|
return ctx.json({ user: parseUserOutput(ctx.context.options, user) });
|
|
467
467
|
});
|
|
468
468
|
const impersonateUserBodySchema = z.object({ userId: z.coerce.string().meta({ description: "The user id" }) });
|
|
@@ -658,7 +658,7 @@ const revokeUserSessions = (opts) => createAuthEndpoint("/admin/revoke-user-sess
|
|
|
658
658
|
options: opts,
|
|
659
659
|
permissions: { session: ["revoke"] }
|
|
660
660
|
})) throw APIError.from("FORBIDDEN", ADMIN_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_REVOKE_USERS_SESSIONS);
|
|
661
|
-
await ctx.context.internalAdapter.
|
|
661
|
+
await ctx.context.internalAdapter.deleteUserSessions(ctx.body.userId);
|
|
662
662
|
return ctx.json({ success: true });
|
|
663
663
|
});
|
|
664
664
|
const removeUserBodySchema = z.object({ userId: z.coerce.string().meta({ description: "The user id" }) });
|
|
@@ -703,6 +703,7 @@ const removeUser = (opts) => createAuthEndpoint("/admin/remove-user", {
|
|
|
703
703
|
})) throw APIError.from("FORBIDDEN", ADMIN_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_DELETE_USERS);
|
|
704
704
|
if (ctx.body.userId === ctx.context.session.user.id) throw APIError.from("BAD_REQUEST", ADMIN_ERROR_CODES.YOU_CANNOT_REMOVE_YOURSELF);
|
|
705
705
|
if (!await ctx.context.internalAdapter.findUserById(ctx.body.userId)) throw APIError.from("NOT_FOUND", BASE_ERROR_CODES.USER_NOT_FOUND);
|
|
706
|
+
await ctx.context.internalAdapter.deleteUserSessions(ctx.body.userId);
|
|
706
707
|
await ctx.context.internalAdapter.deleteUser(ctx.body.userId);
|
|
707
708
|
return ctx.json({ success: true });
|
|
708
709
|
});
|
|
@@ -23,6 +23,7 @@ declare const anonymousClient: () => {
|
|
|
23
23
|
COULD_NOT_CREATE_SESSION: _better_auth_core_utils_error_codes0.RawError<"COULD_NOT_CREATE_SESSION">;
|
|
24
24
|
ANONYMOUS_USERS_CANNOT_SIGN_IN_AGAIN_ANONYMOUSLY: _better_auth_core_utils_error_codes0.RawError<"ANONYMOUS_USERS_CANNOT_SIGN_IN_AGAIN_ANONYMOUSLY">;
|
|
25
25
|
FAILED_TO_DELETE_ANONYMOUS_USER: _better_auth_core_utils_error_codes0.RawError<"FAILED_TO_DELETE_ANONYMOUS_USER">;
|
|
26
|
+
FAILED_TO_DELETE_ANONYMOUS_USER_SESSIONS: _better_auth_core_utils_error_codes0.RawError<"FAILED_TO_DELETE_ANONYMOUS_USER_SESSIONS">;
|
|
26
27
|
USER_IS_NOT_ANONYMOUS: _better_auth_core_utils_error_codes0.RawError<"USER_IS_NOT_ANONYMOUS">;
|
|
27
28
|
DELETE_ANONYMOUS_USER_DISABLED: _better_auth_core_utils_error_codes0.RawError<"DELETE_ANONYMOUS_USER_DISABLED">;
|
|
28
29
|
};
|
|
@@ -7,6 +7,7 @@ declare const ANONYMOUS_ERROR_CODES: {
|
|
|
7
7
|
COULD_NOT_CREATE_SESSION: _better_auth_core_utils_error_codes0.RawError<"COULD_NOT_CREATE_SESSION">;
|
|
8
8
|
ANONYMOUS_USERS_CANNOT_SIGN_IN_AGAIN_ANONYMOUSLY: _better_auth_core_utils_error_codes0.RawError<"ANONYMOUS_USERS_CANNOT_SIGN_IN_AGAIN_ANONYMOUSLY">;
|
|
9
9
|
FAILED_TO_DELETE_ANONYMOUS_USER: _better_auth_core_utils_error_codes0.RawError<"FAILED_TO_DELETE_ANONYMOUS_USER">;
|
|
10
|
+
FAILED_TO_DELETE_ANONYMOUS_USER_SESSIONS: _better_auth_core_utils_error_codes0.RawError<"FAILED_TO_DELETE_ANONYMOUS_USER_SESSIONS">;
|
|
10
11
|
USER_IS_NOT_ANONYMOUS: _better_auth_core_utils_error_codes0.RawError<"USER_IS_NOT_ANONYMOUS">;
|
|
11
12
|
DELETE_ANONYMOUS_USER_DISABLED: _better_auth_core_utils_error_codes0.RawError<"DELETE_ANONYMOUS_USER_DISABLED">;
|
|
12
13
|
};
|
|
@@ -6,6 +6,7 @@ const ANONYMOUS_ERROR_CODES = defineErrorCodes({
|
|
|
6
6
|
COULD_NOT_CREATE_SESSION: "Could not create session",
|
|
7
7
|
ANONYMOUS_USERS_CANNOT_SIGN_IN_AGAIN_ANONYMOUSLY: "Anonymous users cannot sign in again anonymously",
|
|
8
8
|
FAILED_TO_DELETE_ANONYMOUS_USER: "Failed to delete anonymous user",
|
|
9
|
+
FAILED_TO_DELETE_ANONYMOUS_USER_SESSIONS: "Failed to delete anonymous user sessions",
|
|
9
10
|
USER_IS_NOT_ANONYMOUS: "User is not anonymous",
|
|
10
11
|
DELETE_ANONYMOUS_USER_DISABLED: "Deleting anonymous users is disabled"
|
|
11
12
|
});
|
|
@@ -162,6 +162,7 @@ declare const anonymous: (options?: AnonymousOptions | undefined) => {
|
|
|
162
162
|
COULD_NOT_CREATE_SESSION: _better_auth_core_utils_error_codes0.RawError<"COULD_NOT_CREATE_SESSION">;
|
|
163
163
|
ANONYMOUS_USERS_CANNOT_SIGN_IN_AGAIN_ANONYMOUSLY: _better_auth_core_utils_error_codes0.RawError<"ANONYMOUS_USERS_CANNOT_SIGN_IN_AGAIN_ANONYMOUSLY">;
|
|
164
164
|
FAILED_TO_DELETE_ANONYMOUS_USER: _better_auth_core_utils_error_codes0.RawError<"FAILED_TO_DELETE_ANONYMOUS_USER">;
|
|
165
|
+
FAILED_TO_DELETE_ANONYMOUS_USER_SESSIONS: _better_auth_core_utils_error_codes0.RawError<"FAILED_TO_DELETE_ANONYMOUS_USER_SESSIONS">;
|
|
165
166
|
USER_IS_NOT_ANONYMOUS: _better_auth_core_utils_error_codes0.RawError<"USER_IS_NOT_ANONYMOUS">;
|
|
166
167
|
DELETE_ANONYMOUS_USER_DISABLED: _better_auth_core_utils_error_codes0.RawError<"DELETE_ANONYMOUS_USER_DISABLED">;
|
|
167
168
|
};
|