@authup/server-core 1.0.0-beta.63 → 1.0.0-beta.64
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/dist/adapters/database/data-source/options/module.d.ts +1 -0
- package/dist/adapters/database/data-source/options/module.d.ts.map +1 -1
- package/dist/adapters/database/data-source/options/module.mjs +33 -4
- package/dist/adapters/database/data-source/options/module.mjs.map +1 -1
- package/dist/adapters/database/domains/client/entity.d.ts +1 -2
- package/dist/adapters/database/domains/client/entity.d.ts.map +1 -1
- package/dist/adapters/database/domains/client/entity.mjs +7 -14
- package/dist/adapters/database/domains/client/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/identity-provider-attribute/subscriber.d.ts +2 -1
- package/dist/adapters/database/domains/identity-provider-attribute/subscriber.d.ts.map +1 -1
- package/dist/adapters/database/domains/identity-provider-attribute/subscriber.mjs +2 -2
- package/dist/adapters/database/domains/identity-provider-attribute/subscriber.mjs.map +1 -1
- package/dist/adapters/database/domains/session/entity.d.ts +8 -0
- package/dist/adapters/database/domains/session/entity.d.ts.map +1 -1
- package/dist/adapters/database/domains/session/entity.mjs +19 -0
- package/dist/adapters/database/domains/session/entity.mjs.map +1 -1
- package/dist/adapters/database/domains/user/entity.d.ts +1 -0
- package/dist/adapters/database/domains/user/entity.d.ts.map +1 -1
- package/dist/adapters/database/domains/user/entity.mjs +6 -0
- package/dist/adapters/database/domains/user/entity.mjs.map +1 -1
- package/dist/adapters/database/extra-attribute-repository/repository.mjs +1 -1
- package/dist/adapters/database/extra-attribute-repository/repository.mjs.map +1 -1
- package/dist/adapters/database/extra-attribute-repository/tree/adapter.mjs +4 -2
- package/dist/adapters/database/extra-attribute-repository/tree/adapter.mjs.map +1 -1
- package/dist/adapters/database/extra-attribute-repository/tree/repository.mjs +1 -1
- package/dist/adapters/database/extra-attribute-repository/tree/repository.mjs.map +1 -1
- package/dist/adapters/database/index.mjs +3 -3
- package/dist/adapters/database/migrations/mysql/1787571998009-SessionUserAndClientColumns.d.ts +56 -0
- package/dist/adapters/database/migrations/mysql/1787571998009-SessionUserAndClientColumns.d.ts.map +1 -0
- package/dist/adapters/database/migrations/mysql/1787571998009-SessionUserAndClientColumns.mjs +105 -0
- package/dist/adapters/database/migrations/mysql/1787571998009-SessionUserAndClientColumns.mjs.map +1 -0
- package/dist/adapters/database/migrations/postgres/1787571998009-SessionUserAndClientColumns.d.ts +56 -0
- package/dist/adapters/database/migrations/postgres/1787571998009-SessionUserAndClientColumns.d.ts.map +1 -0
- package/dist/adapters/database/migrations/postgres/1787571998009-SessionUserAndClientColumns.mjs +104 -0
- package/dist/adapters/database/migrations/postgres/1787571998009-SessionUserAndClientColumns.mjs.map +1 -0
- package/dist/adapters/database/subscriber/module.d.ts +6 -2
- package/dist/adapters/database/subscriber/module.d.ts.map +1 -1
- package/dist/adapters/database/subscriber/module.mjs +9 -5
- package/dist/adapters/database/subscriber/module.mjs.map +1 -1
- package/dist/adapters/http/adapters/oauth2/authorization/module.mjs +1 -1
- package/dist/adapters/http/adapters/oauth2/authorization/module.mjs.map +1 -1
- package/dist/adapters/http/constants.d.ts +18 -0
- package/dist/adapters/http/constants.d.ts.map +1 -0
- package/dist/adapters/http/constants.mjs +23 -0
- package/dist/adapters/http/constants.mjs.map +1 -0
- package/dist/adapters/http/controllers/entities/identity-provider/module.mjs +3 -3
- package/dist/adapters/http/controllers/entities/identity-provider/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/identity-provider/types.d.ts +6 -0
- package/dist/adapters/http/controllers/entities/identity-provider/types.d.ts.map +1 -1
- package/dist/adapters/http/controllers/entities/realm/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/entities/realm/module.mjs +2 -0
- package/dist/adapters/http/controllers/entities/realm/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/session/module.d.ts +33 -1
- package/dist/adapters/http/controllers/entities/session/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/entities/session/module.mjs +74 -0
- package/dist/adapters/http/controllers/entities/session/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/index.mjs +3 -1
- package/dist/adapters/http/controllers/workflows/account/index.d.ts +1 -0
- package/dist/adapters/http/controllers/workflows/account/index.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/account/module.d.ts +25 -16
- package/dist/adapters/http/controllers/workflows/account/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/account/module.mjs +40 -17
- package/dist/adapters/http/controllers/workflows/account/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/account/types.d.ts +33 -0
- package/dist/adapters/http/controllers/workflows/account/types.d.ts.map +1 -0
- package/dist/adapters/http/controllers/workflows/activate/module.d.ts +8 -4
- package/dist/adapters/http/controllers/workflows/activate/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/activate/module.mjs +7 -9
- package/dist/adapters/http/controllers/workflows/activate/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/admin/index.d.ts.map +1 -0
- package/dist/adapters/http/controllers/workflows/admin/index.mjs +5 -0
- package/dist/adapters/http/controllers/workflows/admin/module.d.ts +30 -0
- package/dist/adapters/http/controllers/workflows/admin/module.d.ts.map +1 -0
- package/dist/adapters/http/controllers/workflows/admin/module.mjs +88 -0
- package/dist/adapters/http/controllers/workflows/admin/module.mjs.map +1 -0
- package/dist/adapters/http/controllers/workflows/admin/types.d.ts +14 -0
- package/dist/adapters/http/controllers/workflows/admin/types.d.ts.map +1 -0
- package/dist/adapters/http/controllers/workflows/auth-console.d.ts +16 -0
- package/dist/adapters/http/controllers/workflows/auth-console.d.ts.map +1 -0
- package/dist/adapters/http/controllers/workflows/auth-console.mjs +32 -0
- package/dist/adapters/http/controllers/workflows/auth-console.mjs.map +1 -0
- package/dist/adapters/http/controllers/workflows/authorize/module.d.ts +16 -1
- package/dist/adapters/http/controllers/workflows/authorize/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/authorize/module.mjs +40 -22
- package/dist/adapters/http/controllers/workflows/authorize/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/authorize/types.d.ts +5 -0
- package/dist/adapters/http/controllers/workflows/authorize/types.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/console-login/index.d.ts +3 -0
- package/dist/adapters/http/controllers/workflows/console-login/index.d.ts.map +1 -0
- package/dist/adapters/http/controllers/workflows/console-login/index.mjs +5 -0
- package/dist/adapters/http/controllers/workflows/console-login/module.d.ts +83 -0
- package/dist/adapters/http/controllers/workflows/console-login/module.d.ts.map +1 -0
- package/dist/adapters/http/controllers/workflows/console-login/module.mjs +230 -0
- package/dist/adapters/http/controllers/workflows/console-login/module.mjs.map +1 -0
- package/dist/adapters/http/controllers/workflows/console-login/types.d.ts +58 -0
- package/dist/adapters/http/controllers/workflows/console-login/types.d.ts.map +1 -0
- package/dist/adapters/http/controllers/workflows/index.d.ts +2 -0
- package/dist/adapters/http/controllers/workflows/index.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/index.mjs +5 -1
- package/dist/adapters/http/controllers/workflows/logout/module.d.ts +32 -3
- package/dist/adapters/http/controllers/workflows/logout/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/logout/module.mjs +48 -24
- package/dist/adapters/http/controllers/workflows/logout/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/logout/types.d.ts +1 -1
- package/dist/adapters/http/controllers/workflows/logout/types.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/password-forgot/module.d.ts +8 -4
- package/dist/adapters/http/controllers/workflows/password-forgot/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/password-forgot/module.mjs +7 -9
- package/dist/adapters/http/controllers/workflows/password-forgot/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/password-reset/module.d.ts +8 -4
- package/dist/adapters/http/controllers/workflows/password-reset/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/password-reset/module.mjs +7 -10
- package/dist/adapters/http/controllers/workflows/password-reset/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/register/module.d.ts +8 -4
- package/dist/adapters/http/controllers/workflows/register/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/register/module.mjs +7 -9
- package/dist/adapters/http/controllers/workflows/register/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/status/module.mjs +1 -1
- package/dist/adapters/http/controllers/workflows/token/module.d.ts +45 -2
- package/dist/adapters/http/controllers/workflows/token/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/token/module.mjs +102 -24
- package/dist/adapters/http/controllers/workflows/token/module.mjs.map +1 -1
- package/dist/adapters/http/cookie/index.d.ts +2 -0
- package/dist/adapters/http/cookie/index.d.ts.map +1 -0
- package/dist/adapters/http/cookie/index.mjs +5 -0
- package/dist/adapters/http/cookie/session.d.ts +35 -0
- package/dist/adapters/http/cookie/session.d.ts.map +1 -0
- package/dist/adapters/http/cookie/session.mjs +62 -0
- package/dist/adapters/http/cookie/session.mjs.map +1 -0
- package/dist/adapters/http/index.d.ts +2 -0
- package/dist/adapters/http/index.d.ts.map +1 -1
- package/dist/adapters/http/index.mjs +20 -16
- package/dist/adapters/http/internal-client/index.d.ts +3 -0
- package/dist/adapters/http/internal-client/index.d.ts.map +1 -0
- package/dist/adapters/http/internal-client/index.mjs +5 -0
- package/dist/adapters/http/internal-client/module.d.ts +21 -0
- package/dist/adapters/http/internal-client/module.d.ts.map +1 -0
- package/dist/adapters/http/{ui/auth-console/http-client.mjs → internal-client/module.mjs} +16 -15
- package/dist/adapters/http/internal-client/module.mjs.map +1 -0
- package/dist/adapters/http/internal-client/types.d.ts +13 -0
- package/dist/adapters/http/internal-client/types.d.ts.map +1 -0
- package/dist/adapters/http/middleware/built-in/authorization/index.d.ts +1 -0
- package/dist/adapters/http/middleware/built-in/authorization/index.d.ts.map +1 -1
- package/dist/adapters/http/middleware/built-in/authorization/index.mjs +2 -1
- package/dist/adapters/http/middleware/built-in/authorization/issuance.d.ts +45 -0
- package/dist/adapters/http/middleware/built-in/authorization/issuance.d.ts.map +1 -0
- package/dist/adapters/http/middleware/built-in/authorization/issuance.mjs +61 -0
- package/dist/adapters/http/middleware/built-in/authorization/issuance.mjs.map +1 -0
- package/dist/adapters/http/middleware/built-in/authorization/module.d.ts +26 -2
- package/dist/adapters/http/middleware/built-in/authorization/module.d.ts.map +1 -1
- package/dist/adapters/http/middleware/built-in/authorization/module.mjs +67 -1
- package/dist/adapters/http/middleware/built-in/authorization/module.mjs.map +1 -1
- package/dist/adapters/http/middleware/built-in/authorization/types.d.ts +21 -1
- package/dist/adapters/http/middleware/built-in/authorization/types.d.ts.map +1 -1
- package/dist/adapters/http/middleware/built-in/basic.d.ts +2 -2
- package/dist/adapters/http/middleware/built-in/basic.d.ts.map +1 -1
- package/dist/adapters/http/middleware/built-in/basic.mjs.map +1 -1
- package/dist/adapters/http/middleware/built-in/cors.d.ts +8 -2
- package/dist/adapters/http/middleware/built-in/cors.d.ts.map +1 -1
- package/dist/adapters/http/middleware/built-in/cors.mjs +20 -3
- package/dist/adapters/http/middleware/built-in/cors.mjs.map +1 -1
- package/dist/adapters/http/middleware/built-in/error.d.ts +2 -2
- package/dist/adapters/http/middleware/built-in/error.d.ts.map +1 -1
- package/dist/adapters/http/middleware/built-in/error.mjs.map +1 -1
- package/dist/adapters/http/middleware/built-in/index.d.ts +1 -4
- package/dist/adapters/http/middleware/built-in/index.d.ts.map +1 -1
- package/dist/adapters/http/middleware/built-in/index.mjs +3 -4
- package/dist/adapters/http/middleware/built-in/internal-http-client.d.ts +17 -0
- package/dist/adapters/http/middleware/built-in/internal-http-client.d.ts.map +1 -0
- package/dist/adapters/http/middleware/built-in/internal-http-client.mjs +27 -0
- package/dist/adapters/http/middleware/built-in/internal-http-client.mjs.map +1 -0
- package/dist/adapters/http/middleware/built-in/logger.mjs +1 -1
- package/dist/adapters/http/middleware/built-in/logger.mjs.map +1 -1
- package/dist/adapters/http/middleware/built-in/prometheus.d.ts +6 -5
- package/dist/adapters/http/middleware/built-in/prometheus.d.ts.map +1 -1
- package/dist/adapters/http/middleware/built-in/prometheus.mjs +3 -2
- package/dist/adapters/http/middleware/built-in/prometheus.mjs.map +1 -1
- package/dist/adapters/http/middleware/built-in/rate-limit.d.ts +2 -2
- package/dist/adapters/http/middleware/built-in/rate-limit.d.ts.map +1 -1
- package/dist/adapters/http/middleware/built-in/rate-limit.mjs +15 -0
- package/dist/adapters/http/middleware/built-in/rate-limit.mjs.map +1 -1
- package/dist/adapters/http/middleware/index.mjs +3 -4
- package/dist/adapters/http/request/constants.d.ts +1 -1
- package/dist/adapters/http/request/constants.d.ts.map +1 -1
- package/dist/adapters/http/request/constants.mjs +1 -5
- package/dist/adapters/http/request/constants.mjs.map +1 -1
- package/dist/adapters/http/request/helpers/index.d.ts +1 -1
- package/dist/adapters/http/request/helpers/index.d.ts.map +1 -1
- package/dist/adapters/http/request/helpers/index.mjs +2 -2
- package/dist/adapters/http/request/helpers/locale.d.ts +2 -1
- package/dist/adapters/http/request/helpers/locale.d.ts.map +1 -1
- package/dist/adapters/http/request/helpers/locale.mjs +1 -1
- package/dist/adapters/http/request/helpers/locale.mjs.map +1 -1
- package/dist/adapters/http/request/helpers/same-origin.d.ts +38 -0
- package/dist/adapters/http/request/helpers/same-origin.d.ts.map +1 -0
- package/dist/adapters/http/request/helpers/same-origin.mjs +68 -0
- package/dist/adapters/http/request/helpers/same-origin.mjs.map +1 -0
- package/dist/adapters/http/request/index.mjs +2 -2
- package/dist/adapters/http/request/permission/module.mjs +1 -1
- package/dist/adapters/http/request/permission/module.mjs.map +1 -1
- package/dist/adapters/http/request/types.d.ts +1 -2
- package/dist/adapters/http/request/types.d.ts.map +1 -1
- package/dist/adapters/shared/ldap/module.d.ts.map +1 -1
- package/dist/adapters/shared/ldap/module.mjs +4 -1
- package/dist/adapters/shared/ldap/module.mjs.map +1 -1
- package/dist/app/builder.d.ts +4 -4
- package/dist/app/builder.d.ts.map +1 -1
- package/dist/app/builder.mjs +7 -4
- package/dist/app/builder.mjs.map +1 -1
- package/dist/app/factory.d.ts +10 -0
- package/dist/app/factory.d.ts.map +1 -1
- package/dist/app/factory.mjs +26 -2
- package/dist/app/factory.mjs.map +1 -1
- package/dist/app/index.mjs +17 -19
- package/dist/app/modules/authentication/module.d.ts.map +1 -1
- package/dist/app/modules/authentication/module.mjs +15 -2
- package/dist/app/modules/authentication/module.mjs.map +1 -1
- package/dist/app/modules/authentication/repositories/session.d.ts +4 -1
- package/dist/app/modules/authentication/repositories/session.d.ts.map +1 -1
- package/dist/app/modules/authentication/repositories/session.mjs +20 -3
- package/dist/app/modules/authentication/repositories/session.mjs.map +1 -1
- package/dist/app/modules/components/index.d.ts +1 -0
- package/dist/app/modules/components/index.d.ts.map +1 -1
- package/dist/app/modules/components/module.d.ts +3 -1
- package/dist/app/modules/components/module.d.ts.map +1 -1
- package/dist/app/modules/components/module.mjs +26 -7
- package/dist/app/modules/components/module.mjs.map +1 -1
- package/dist/app/modules/components/types.d.ts +11 -0
- package/dist/app/modules/components/types.d.ts.map +1 -0
- package/dist/app/modules/config/app-origins.d.ts +10 -0
- package/dist/app/modules/config/app-origins.d.ts.map +1 -0
- package/dist/app/modules/config/app-origins.mjs +21 -0
- package/dist/app/modules/config/app-origins.mjs.map +1 -0
- package/dist/app/modules/config/constants.d.ts +23 -50
- package/dist/app/modules/config/constants.d.ts.map +1 -1
- package/dist/app/modules/config/constants.mjs +34 -51
- package/dist/app/modules/config/constants.mjs.map +1 -1
- package/dist/app/modules/config/index.d.ts +2 -3
- package/dist/app/modules/config/index.d.ts.map +1 -1
- package/dist/app/modules/config/index.mjs +4 -8
- package/dist/app/modules/config/module.d.ts +2 -2
- package/dist/app/modules/config/module.d.ts.map +1 -1
- package/dist/app/modules/config/module.mjs +1 -1
- package/dist/app/modules/config/module.mjs.map +1 -1
- package/dist/app/modules/config/read.d.ts +29 -0
- package/dist/app/modules/config/read.d.ts.map +1 -0
- package/dist/app/modules/config/read.mjs +65 -0
- package/dist/app/modules/config/read.mjs.map +1 -0
- package/dist/app/modules/config/types.d.ts +30 -405
- package/dist/app/modules/config/types.d.ts.map +1 -1
- package/dist/app/modules/config/validator.d.ts.map +1 -1
- package/dist/app/modules/config/validator.mjs +3 -87
- package/dist/app/modules/config/validator.mjs.map +1 -1
- package/dist/app/modules/database/index.d.ts +1 -0
- package/dist/app/modules/database/index.d.ts.map +1 -1
- package/dist/app/modules/database/index.mjs +2 -1
- package/dist/app/modules/database/migration.d.ts +33 -0
- package/dist/app/modules/database/migration.d.ts.map +1 -0
- package/dist/app/modules/database/migration.mjs +52 -0
- package/dist/app/modules/database/migration.mjs.map +1 -0
- package/dist/app/modules/database/module.d.ts.map +1 -1
- package/dist/app/modules/database/module.mjs +12 -6
- package/dist/app/modules/database/module.mjs.map +1 -1
- package/dist/app/modules/database/repositories/client/repository.d.ts +6 -1
- package/dist/app/modules/database/repositories/client/repository.d.ts.map +1 -1
- package/dist/app/modules/database/repositories/client/repository.mjs +21 -4
- package/dist/app/modules/database/repositories/client/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/event/repository.d.ts +29 -2
- package/dist/app/modules/database/repositories/event/repository.d.ts.map +1 -1
- package/dist/app/modules/database/repositories/event/repository.mjs +42 -24
- package/dist/app/modules/database/repositories/event/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/helpers.d.ts +24 -1
- package/dist/app/modules/database/repositories/helpers.d.ts.map +1 -1
- package/dist/app/modules/database/repositories/helpers.mjs +38 -1
- package/dist/app/modules/database/repositories/helpers.mjs.map +1 -1
- package/dist/app/modules/database/repositories/identity-provider/repository.mjs +1 -1
- package/dist/app/modules/database/repositories/identity-provider-account/repository.mjs +4 -2
- package/dist/app/modules/database/repositories/identity-provider-account/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/key/repository.mjs +1 -1
- package/dist/app/modules/database/repositories/permission/repository.mjs +1 -1
- package/dist/app/modules/database/repositories/policy/repository.mjs +1 -1
- package/dist/app/modules/database/repositories/role/repository.mjs +1 -1
- package/dist/app/modules/database/repositories/scope/repository.mjs +1 -1
- package/dist/app/modules/database/repositories/trust-anchor/repository.mjs +1 -1
- package/dist/app/modules/database/repositories/user/repository.d.ts +7 -2
- package/dist/app/modules/database/repositories/user/repository.d.ts.map +1 -1
- package/dist/app/modules/database/repositories/user/repository.mjs +21 -4
- package/dist/app/modules/database/repositories/user/repository.mjs.map +1 -1
- package/dist/app/modules/http/constants.d.ts +3 -1
- package/dist/app/modules/http/constants.d.ts.map +1 -1
- package/dist/app/modules/http/constants.mjs +3 -2
- package/dist/app/modules/http/constants.mjs.map +1 -1
- package/dist/app/modules/http/module.d.ts +30 -9
- package/dist/app/modules/http/module.d.ts.map +1 -1
- package/dist/app/modules/http/module.mjs +31 -33
- package/dist/app/modules/http/module.mjs.map +1 -1
- package/dist/app/modules/http/modules/controller.d.ts +4 -3
- package/dist/app/modules/http/modules/controller.d.ts.map +1 -1
- package/dist/app/modules/http/modules/controller.mjs +65 -36
- package/dist/app/modules/http/modules/controller.mjs.map +1 -1
- package/dist/app/modules/http/modules/middleware.d.ts +13 -22
- package/dist/app/modules/http/modules/middleware.d.ts.map +1 -1
- package/dist/app/modules/http/modules/middleware.mjs +20 -36
- package/dist/app/modules/http/modules/middleware.mjs.map +1 -1
- package/dist/app/modules/identity/module.mjs +4 -4
- package/dist/app/modules/identity/repositories/client.mjs +4 -2
- package/dist/app/modules/identity/repositories/client.mjs.map +1 -1
- package/dist/app/modules/identity/repositories/user.mjs +4 -2
- package/dist/app/modules/identity/repositories/user.mjs.map +1 -1
- package/dist/app/modules/index.mjs +21 -23
- package/dist/app/modules/logger/module.mjs +1 -1
- package/dist/app/modules/logger/module.mjs.map +1 -1
- package/dist/app/modules/mail/module.d.ts.map +1 -1
- package/dist/app/modules/mail/module.mjs.map +1 -1
- package/dist/app/modules/oauth2/constants.d.ts +2 -1
- package/dist/app/modules/oauth2/constants.d.ts.map +1 -1
- package/dist/app/modules/oauth2/constants.mjs +1 -0
- package/dist/app/modules/oauth2/constants.mjs.map +1 -1
- package/dist/app/modules/oauth2/module.d.ts.map +1 -1
- package/dist/app/modules/oauth2/module.mjs +9 -4
- package/dist/app/modules/oauth2/module.mjs.map +1 -1
- package/dist/app/modules/oauth2/repositories/client/repository.mjs +4 -2
- package/dist/app/modules/oauth2/repositories/client/repository.mjs.map +1 -1
- package/dist/app/modules/oauth2/repositories/consent/repository.d.ts.map +1 -1
- package/dist/app/modules/oauth2/repositories/consent/repository.mjs +3 -2
- package/dist/app/modules/oauth2/repositories/consent/repository.mjs.map +1 -1
- package/dist/app/modules/oauth2/repositories/console-login/index.d.ts +2 -0
- package/dist/app/modules/oauth2/repositories/console-login/index.d.ts.map +1 -0
- package/dist/app/modules/oauth2/repositories/console-login/index.mjs +5 -0
- package/dist/app/modules/oauth2/repositories/console-login/store.d.ts +19 -0
- package/dist/app/modules/oauth2/repositories/console-login/store.d.ts.map +1 -0
- package/dist/app/modules/oauth2/repositories/console-login/store.mjs +47 -0
- package/dist/app/modules/oauth2/repositories/console-login/store.mjs.map +1 -0
- package/dist/app/modules/oauth2/repositories/constants.d.ts +1 -0
- package/dist/app/modules/oauth2/repositories/constants.d.ts.map +1 -1
- package/dist/app/modules/oauth2/repositories/constants.mjs +1 -0
- package/dist/app/modules/oauth2/repositories/constants.mjs.map +1 -1
- package/dist/app/modules/oauth2/repositories/index.d.ts +1 -0
- package/dist/app/modules/oauth2/repositories/index.d.ts.map +1 -1
- package/dist/app/modules/oauth2/repositories/index.mjs +3 -1
- package/dist/app/modules/oauth2/repositories/session-token/repository.d.ts +2 -2
- package/dist/app/modules/oauth2/repositories/session-token/repository.d.ts.map +1 -1
- package/dist/app/modules/oauth2/repositories/session-token/repository.mjs +5 -3
- package/dist/app/modules/oauth2/repositories/session-token/repository.mjs.map +1 -1
- package/dist/app/modules/provisioning/module.d.ts.map +1 -1
- package/dist/app/modules/provisioning/module.mjs +5 -6
- package/dist/app/modules/provisioning/module.mjs.map +1 -1
- package/dist/app/modules/provisioning/sources/composite/module.d.ts.map +1 -1
- package/dist/app/modules/provisioning/sources/composite/module.mjs +2 -1
- package/dist/app/modules/provisioning/sources/composite/module.mjs.map +1 -1
- package/dist/app/modules/provisioning/sources/default/module.d.ts.map +1 -1
- package/dist/app/modules/provisioning/sources/default/module.mjs +2 -1
- package/dist/app/modules/provisioning/sources/default/module.mjs.map +1 -1
- package/dist/app/modules/runtime/module.d.ts.map +1 -1
- package/dist/app/modules/runtime/module.mjs +2 -1
- package/dist/app/modules/runtime/module.mjs.map +1 -1
- package/dist/app/types.d.ts +16 -0
- package/dist/app/types.d.ts.map +1 -1
- package/dist/cli/commands/config.d.ts +40 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.mjs +65 -0
- package/dist/cli/commands/config.mjs.map +1 -0
- package/dist/cli/commands/healthcheck.d.ts +3 -2
- package/dist/cli/commands/healthcheck.d.ts.map +1 -1
- package/dist/cli/commands/healthcheck.mjs +6 -3
- package/dist/cli/commands/healthcheck.mjs.map +1 -1
- package/dist/cli/commands/index.d.ts +3 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.mjs +3 -1
- package/dist/cli/commands/migration.d.ts +3 -10
- package/dist/cli/commands/migration.d.ts.map +1 -1
- package/dist/cli/commands/migration.mjs +17 -9
- package/dist/cli/commands/migration.mjs.map +1 -1
- package/dist/cli/commands/shutdown.d.ts +16 -0
- package/dist/cli/commands/shutdown.d.ts.map +1 -0
- package/dist/cli/commands/shutdown.mjs +41 -0
- package/dist/cli/commands/shutdown.mjs.map +1 -0
- package/dist/cli/commands/start.d.ts +3 -2
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.mjs +3 -21
- package/dist/cli/commands/start.mjs.map +1 -1
- package/dist/cli/commands/types.d.ts.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/module.d.ts +0 -2
- package/dist/cli/module.d.ts.map +1 -1
- package/dist/cli/module.mjs +4 -3
- package/dist/cli/module.mjs.map +1 -1
- package/dist/components/oauth2-cleaner/module.d.ts +2 -2
- package/dist/components/oauth2-cleaner/module.d.ts.map +1 -1
- package/dist/components/oauth2-cleaner/module.mjs +10 -7
- package/dist/components/oauth2-cleaner/module.mjs.map +1 -1
- package/dist/core/authentication/index.mjs +2 -1
- package/dist/core/authentication/session/constants.d.ts +10 -0
- package/dist/core/authentication/session/constants.d.ts.map +1 -0
- package/dist/core/authentication/session/constants.mjs +16 -0
- package/dist/core/authentication/session/constants.mjs.map +1 -0
- package/dist/core/authentication/session/index.d.ts +1 -0
- package/dist/core/authentication/session/index.d.ts.map +1 -1
- package/dist/core/authentication/session/index.mjs +2 -1
- package/dist/core/authentication/session/module.d.ts +2 -1
- package/dist/core/authentication/session/module.d.ts.map +1 -1
- package/dist/core/authentication/session/module.mjs +7 -1
- package/dist/core/authentication/session/module.mjs.map +1 -1
- package/dist/core/authentication/session/types.d.ts +70 -1
- package/dist/core/authentication/session/types.d.ts.map +1 -1
- package/dist/core/authentication/session/types.mjs.map +1 -1
- package/dist/core/entities/client/schema.d.ts.map +1 -1
- package/dist/core/entities/client/schema.mjs +1 -2
- package/dist/core/entities/client/schema.mjs.map +1 -1
- package/dist/core/entities/client/service.d.ts.map +1 -1
- package/dist/core/entities/client/service.mjs +15 -1
- package/dist/core/entities/client/service.mjs.map +1 -1
- package/dist/core/entities/client/system-clients.d.ts +0 -5
- package/dist/core/entities/client/system-clients.d.ts.map +1 -1
- package/dist/core/entities/client/system-clients.mjs +0 -6
- package/dist/core/entities/client/system-clients.mjs.map +1 -1
- package/dist/core/entities/client/types.d.ts +12 -0
- package/dist/core/entities/client/types.d.ts.map +1 -1
- package/dist/core/entities/client-permission/service.mjs +1 -1
- package/dist/core/entities/client-permission/service.mjs.map +1 -1
- package/dist/core/entities/event/constants.d.ts +1 -6
- package/dist/core/entities/event/constants.d.ts.map +1 -1
- package/dist/core/entities/event/constants.mjs +1 -5
- package/dist/core/entities/event/constants.mjs.map +1 -1
- package/dist/core/entities/event/entity-event-handler.d.ts.map +1 -1
- package/dist/core/entities/event/entity-event-handler.mjs +3 -2
- package/dist/core/entities/event/entity-event-handler.mjs.map +1 -1
- package/dist/core/entities/event/service.d.ts.map +1 -1
- package/dist/core/entities/event/service.mjs +3 -3
- package/dist/core/entities/event/service.mjs.map +1 -1
- package/dist/core/entities/event/types.d.ts +15 -1
- package/dist/core/entities/event/types.d.ts.map +1 -1
- package/dist/core/entities/permission/service.mjs +1 -2
- package/dist/core/entities/permission/service.mjs.map +1 -1
- package/dist/core/entities/role-permission/service.mjs +1 -1
- package/dist/core/entities/role-permission/service.mjs.map +1 -1
- package/dist/core/entities/session/service.d.ts +13 -1
- package/dist/core/entities/session/service.d.ts.map +1 -1
- package/dist/core/entities/session/service.mjs +19 -16
- package/dist/core/entities/session/service.mjs.map +1 -1
- package/dist/core/entities/user/schema.d.ts.map +1 -1
- package/dist/core/entities/user/schema.mjs +1 -0
- package/dist/core/entities/user/schema.mjs.map +1 -1
- package/dist/core/entities/user/service.d.ts.map +1 -1
- package/dist/core/entities/user/service.mjs +21 -1
- package/dist/core/entities/user/service.mjs.map +1 -1
- package/dist/core/entities/user/types.d.ts +12 -0
- package/dist/core/entities/user/types.d.ts.map +1 -1
- package/dist/core/entities/user-permission/service.mjs +1 -1
- package/dist/core/entities/user-permission/service.mjs.map +1 -1
- package/dist/core/identity/permission/junction-grant.mjs +1 -1
- package/dist/core/identity/permission/junction-grant.mjs.map +1 -1
- package/dist/core/identity/provider/account/module.mjs +1 -1
- package/dist/core/identity/provider/account/module.mjs.map +1 -1
- package/dist/core/identity/provider/authentication/protocols/oauth2/assurance.mjs +1 -1
- package/dist/core/identity/provider/authentication/protocols/oauth2/assurance.mjs.map +1 -1
- package/dist/core/identity/registration/service.d.ts.map +1 -1
- package/dist/core/identity/registration/service.mjs +2 -1
- package/dist/core/identity/registration/service.mjs.map +1 -1
- package/dist/core/index.mjs +11 -3
- package/dist/core/oauth2/authorization/helpers.d.ts +14 -0
- package/dist/core/oauth2/authorization/helpers.d.ts.map +1 -1
- package/dist/core/oauth2/authorization/helpers.mjs +9 -1
- package/dist/core/oauth2/authorization/helpers.mjs.map +1 -1
- package/dist/core/oauth2/authorization/index.mjs +2 -2
- package/dist/core/oauth2/authorization/module.mjs +1 -1
- package/dist/core/oauth2/authorization/module.mjs.map +1 -1
- package/dist/core/oauth2/backchannel-logout/constants.d.ts +16 -0
- package/dist/core/oauth2/backchannel-logout/constants.d.ts.map +1 -0
- package/dist/core/oauth2/backchannel-logout/constants.mjs +20 -0
- package/dist/core/oauth2/backchannel-logout/constants.mjs.map +1 -0
- package/dist/core/oauth2/backchannel-logout/index.d.ts +4 -0
- package/dist/core/oauth2/backchannel-logout/index.d.ts.map +1 -0
- package/dist/core/oauth2/backchannel-logout/index.mjs +6 -0
- package/dist/core/oauth2/backchannel-logout/module.d.ts +26 -0
- package/dist/core/oauth2/backchannel-logout/module.d.ts.map +1 -0
- package/dist/core/oauth2/backchannel-logout/module.mjs +78 -0
- package/dist/core/oauth2/backchannel-logout/module.mjs.map +1 -0
- package/dist/core/oauth2/backchannel-logout/types.d.ts +29 -0
- package/dist/core/oauth2/backchannel-logout/types.d.ts.map +1 -0
- package/dist/core/oauth2/console-login/constants.d.ts +19 -0
- package/dist/core/oauth2/console-login/constants.d.ts.map +1 -0
- package/dist/core/oauth2/console-login/constants.mjs +24 -0
- package/dist/core/oauth2/console-login/constants.mjs.map +1 -0
- package/dist/core/oauth2/console-login/index.d.ts +3 -0
- package/dist/core/oauth2/console-login/index.d.ts.map +1 -0
- package/dist/core/oauth2/console-login/index.mjs +5 -0
- package/dist/core/oauth2/console-login/types.d.ts +53 -0
- package/dist/core/oauth2/console-login/types.d.ts.map +1 -0
- package/dist/core/oauth2/end-session/service.mjs +1 -1
- package/dist/core/oauth2/end-session/service.mjs.map +1 -1
- package/dist/core/oauth2/federated-login/module.mjs +3 -3
- package/dist/core/oauth2/federated-login/module.mjs.map +1 -1
- package/dist/core/oauth2/index.d.ts +4 -0
- package/dist/core/oauth2/index.d.ts.map +1 -1
- package/dist/core/oauth2/index.mjs +13 -3
- package/dist/core/oauth2/introspection/index.d.ts +3 -0
- package/dist/core/oauth2/introspection/index.d.ts.map +1 -0
- package/dist/core/oauth2/introspection/index.mjs +5 -0
- package/dist/core/oauth2/introspection/module.d.ts +14 -0
- package/dist/core/oauth2/introspection/module.d.ts.map +1 -0
- package/dist/core/oauth2/introspection/module.mjs +49 -0
- package/dist/core/oauth2/introspection/module.mjs.map +1 -0
- package/dist/core/oauth2/introspection/types.d.ts +45 -0
- package/dist/core/oauth2/introspection/types.d.ts.map +1 -0
- package/dist/core/oauth2/introspection/types.mjs +4 -0
- package/dist/core/oauth2/openid/claims.d.ts +20 -2
- package/dist/core/oauth2/openid/claims.d.ts.map +1 -1
- package/dist/core/oauth2/openid/claims.mjs +18 -4
- package/dist/core/oauth2/openid/claims.mjs.map +1 -1
- package/dist/core/oauth2/session-credential/constants.d.ts +30 -0
- package/dist/core/oauth2/session-credential/constants.d.ts.map +1 -0
- package/dist/core/oauth2/session-credential/constants.mjs +34 -0
- package/dist/core/oauth2/session-credential/constants.mjs.map +1 -0
- package/dist/core/oauth2/session-credential/index.d.ts +3 -0
- package/dist/core/oauth2/session-credential/index.d.ts.map +1 -0
- package/dist/core/oauth2/session-credential/index.mjs +6 -0
- package/dist/core/oauth2/session-credential/module.d.ts +31 -0
- package/dist/core/oauth2/session-credential/module.d.ts.map +1 -0
- package/dist/core/oauth2/session-credential/module.mjs +43 -0
- package/dist/core/oauth2/session-credential/module.mjs.map +1 -0
- package/dist/core/oauth2/session-token/constants.d.ts +10 -0
- package/dist/core/oauth2/session-token/constants.d.ts.map +1 -0
- package/dist/core/oauth2/session-token/constants.mjs +16 -0
- package/dist/core/oauth2/session-token/constants.mjs.map +1 -0
- package/dist/core/oauth2/session-token/index.d.ts +1 -0
- package/dist/core/oauth2/session-token/index.d.ts.map +1 -1
- package/dist/core/oauth2/session-token/index.mjs +2 -1
- package/dist/core/oauth2/session-token/types.d.ts +13 -2
- package/dist/core/oauth2/session-token/types.d.ts.map +1 -1
- package/dist/core/provisioning/merge/module.mjs +5 -3
- package/dist/core/provisioning/merge/module.mjs.map +1 -1
- package/dist/core/query/module.mjs +1 -1
- package/dist/core/query/module.mjs.map +1 -1
- package/dist/core/security/policy/evaluator.mjs +1 -1
- package/dist/core/security/policy/evaluator.mjs.map +1 -1
- package/dist/index.mjs +62 -59
- package/dist/path.mjs +1 -1
- package/dist/swagger.json +466 -104
- package/dist/utils/error.d.ts +6 -0
- package/dist/utils/error.d.ts.map +1 -1
- package/dist/utils/error.mjs +6 -2
- package/dist/utils/error.mjs.map +1 -1
- package/dist/utils/index.mjs +2 -2
- package/package.json +31 -25
- package/dist/adapters/http/middleware/built-in/assets.d.ts +0 -11
- package/dist/adapters/http/middleware/built-in/assets.d.ts.map +0 -1
- package/dist/adapters/http/middleware/built-in/assets.mjs +0 -91
- package/dist/adapters/http/middleware/built-in/assets.mjs.map +0 -1
- package/dist/adapters/http/middleware/built-in/theme.d.ts +0 -15
- package/dist/adapters/http/middleware/built-in/theme.d.ts.map +0 -1
- package/dist/adapters/http/middleware/built-in/theme.mjs +0 -27
- package/dist/adapters/http/middleware/built-in/theme.mjs.map +0 -1
- package/dist/adapters/http/middleware/built-in/types.d.ts +0 -14
- package/dist/adapters/http/middleware/built-in/types.d.ts.map +0 -1
- package/dist/adapters/http/middleware/built-in/ui-http-client.d.ts +0 -15
- package/dist/adapters/http/middleware/built-in/ui-http-client.d.ts.map +0 -1
- package/dist/adapters/http/middleware/built-in/ui-http-client.mjs +0 -25
- package/dist/adapters/http/middleware/built-in/ui-http-client.mjs.map +0 -1
- package/dist/adapters/http/request/helpers/redirect.d.ts +0 -14
- package/dist/adapters/http/request/helpers/redirect.d.ts.map +0 -1
- package/dist/adapters/http/request/helpers/redirect.mjs +0 -36
- package/dist/adapters/http/request/helpers/redirect.mjs.map +0 -1
- package/dist/adapters/http/ui/account-console/index.d.ts +0 -4
- package/dist/adapters/http/ui/account-console/index.d.ts.map +0 -1
- package/dist/adapters/http/ui/account-console/index.mjs +0 -6
- package/dist/adapters/http/ui/account-console/module.d.ts +0 -28
- package/dist/adapters/http/ui/account-console/module.d.ts.map +0 -1
- package/dist/adapters/http/ui/account-console/module.mjs +0 -80
- package/dist/adapters/http/ui/account-console/module.mjs.map +0 -1
- package/dist/adapters/http/ui/account-console/ref.d.ts +0 -30
- package/dist/adapters/http/ui/account-console/ref.d.ts.map +0 -1
- package/dist/adapters/http/ui/account-console/ref.mjs +0 -50
- package/dist/adapters/http/ui/account-console/ref.mjs.map +0 -1
- package/dist/adapters/http/ui/account-console/types.d.ts +0 -11
- package/dist/adapters/http/ui/account-console/types.d.ts.map +0 -1
- package/dist/adapters/http/ui/auth-console/http-client.d.ts +0 -22
- package/dist/adapters/http/ui/auth-console/http-client.d.ts.map +0 -1
- package/dist/adapters/http/ui/auth-console/http-client.mjs.map +0 -1
- package/dist/adapters/http/ui/auth-console/index.d.ts +0 -6
- package/dist/adapters/http/ui/auth-console/index.d.ts.map +0 -1
- package/dist/adapters/http/ui/auth-console/index.mjs +0 -8
- package/dist/adapters/http/ui/auth-console/module.d.ts +0 -4
- package/dist/adapters/http/ui/auth-console/module.d.ts.map +0 -1
- package/dist/adapters/http/ui/auth-console/module.mjs +0 -73
- package/dist/adapters/http/ui/auth-console/module.mjs.map +0 -1
- package/dist/adapters/http/ui/auth-console/resolve.d.ts +0 -21
- package/dist/adapters/http/ui/auth-console/resolve.d.ts.map +0 -1
- package/dist/adapters/http/ui/auth-console/resolve.mjs +0 -53
- package/dist/adapters/http/ui/auth-console/resolve.mjs.map +0 -1
- package/dist/adapters/http/ui/auth-console/serve.d.ts +0 -9
- package/dist/adapters/http/ui/auth-console/serve.d.ts.map +0 -1
- package/dist/adapters/http/ui/auth-console/serve.mjs +0 -35
- package/dist/adapters/http/ui/auth-console/serve.mjs.map +0 -1
- package/dist/adapters/http/ui/auth-console/types.d.ts +0 -26
- package/dist/adapters/http/ui/auth-console/types.d.ts.map +0 -1
- package/dist/adapters/http/ui/console-packages/index.d.ts.map +0 -1
- package/dist/adapters/http/ui/console-packages/index.mjs +0 -5
- package/dist/adapters/http/ui/console-packages/module.d.ts +0 -33
- package/dist/adapters/http/ui/console-packages/module.d.ts.map +0 -1
- package/dist/adapters/http/ui/console-packages/module.mjs +0 -70
- package/dist/adapters/http/ui/console-packages/module.mjs.map +0 -1
- package/dist/adapters/http/ui/console-packages/types.d.ts +0 -12
- package/dist/adapters/http/ui/console-packages/types.d.ts.map +0 -1
- package/dist/adapters/http/ui/index.d.ts +0 -6
- package/dist/adapters/http/ui/index.d.ts.map +0 -1
- package/dist/adapters/http/ui/index.mjs +0 -25
- package/dist/adapters/http/ui/shared/html.d.ts +0 -76
- package/dist/adapters/http/ui/shared/html.d.ts.map +0 -1
- package/dist/adapters/http/ui/shared/html.mjs +0 -104
- package/dist/adapters/http/ui/shared/html.mjs.map +0 -1
- package/dist/adapters/http/ui/shared/index.d.ts +0 -2
- package/dist/adapters/http/ui/shared/index.d.ts.map +0 -1
- package/dist/adapters/http/ui/shared/index.mjs +0 -5
- package/dist/adapters/http/ui/theme/apply.d.ts +0 -12
- package/dist/adapters/http/ui/theme/apply.d.ts.map +0 -1
- package/dist/adapters/http/ui/theme/apply.mjs +0 -29
- package/dist/adapters/http/ui/theme/apply.mjs.map +0 -1
- package/dist/adapters/http/ui/theme/assets.d.ts +0 -20
- package/dist/adapters/http/ui/theme/assets.d.ts.map +0 -1
- package/dist/adapters/http/ui/theme/assets.mjs +0 -86
- package/dist/adapters/http/ui/theme/assets.mjs.map +0 -1
- package/dist/adapters/http/ui/theme/constants.d.ts +0 -16
- package/dist/adapters/http/ui/theme/constants.d.ts.map +0 -1
- package/dist/adapters/http/ui/theme/constants.mjs +0 -20
- package/dist/adapters/http/ui/theme/constants.mjs.map +0 -1
- package/dist/adapters/http/ui/theme/contract/constants.d.ts +0 -120
- package/dist/adapters/http/ui/theme/contract/constants.d.ts.map +0 -1
- package/dist/adapters/http/ui/theme/contract/constants.mjs +0 -136
- package/dist/adapters/http/ui/theme/contract/constants.mjs.map +0 -1
- package/dist/adapters/http/ui/theme/contract/head.d.ts +0 -12
- package/dist/adapters/http/ui/theme/contract/head.d.ts.map +0 -1
- package/dist/adapters/http/ui/theme/contract/head.mjs +0 -61
- package/dist/adapters/http/ui/theme/contract/head.mjs.map +0 -1
- package/dist/adapters/http/ui/theme/contract/index.d.ts +0 -6
- package/dist/adapters/http/ui/theme/contract/index.d.ts.map +0 -1
- package/dist/adapters/http/ui/theme/contract/index.mjs +0 -8
- package/dist/adapters/http/ui/theme/contract/manifest.d.ts +0 -25
- package/dist/adapters/http/ui/theme/contract/manifest.d.ts.map +0 -1
- package/dist/adapters/http/ui/theme/contract/manifest.mjs +0 -77
- package/dist/adapters/http/ui/theme/contract/manifest.mjs.map +0 -1
- package/dist/adapters/http/ui/theme/contract/types.d.ts +0 -26
- package/dist/adapters/http/ui/theme/contract/types.d.ts.map +0 -1
- package/dist/adapters/http/ui/theme/contract/utils.d.ts +0 -11
- package/dist/adapters/http/ui/theme/contract/utils.d.ts.map +0 -1
- package/dist/adapters/http/ui/theme/contract/utils.mjs +0 -22
- package/dist/adapters/http/ui/theme/contract/utils.mjs.map +0 -1
- package/dist/adapters/http/ui/theme/index.d.ts +0 -7
- package/dist/adapters/http/ui/theme/index.d.ts.map +0 -1
- package/dist/adapters/http/ui/theme/index.mjs +0 -13
- package/dist/adapters/http/ui/theme/module.d.ts +0 -79
- package/dist/adapters/http/ui/theme/module.d.ts.map +0 -1
- package/dist/adapters/http/ui/theme/module.mjs +0 -206
- package/dist/adapters/http/ui/theme/module.mjs.map +0 -1
- package/dist/adapters/http/ui/theme/types.d.ts +0 -42
- package/dist/adapters/http/ui/theme/types.d.ts.map +0 -1
- package/dist/app/modules/config/helpers.d.ts +0 -9
- package/dist/app/modules/config/helpers.d.ts.map +0 -1
- package/dist/app/modules/config/helpers.mjs +0 -22
- package/dist/app/modules/config/helpers.mjs.map +0 -1
- package/dist/app/modules/config/normalize.d.ts +0 -3
- package/dist/app/modules/config/normalize.d.ts.map +0 -1
- package/dist/app/modules/config/normalize.mjs +0 -117
- package/dist/app/modules/config/normalize.mjs.map +0 -1
- package/dist/app/modules/config/origins.d.ts +0 -25
- package/dist/app/modules/config/origins.d.ts.map +0 -1
- package/dist/app/modules/config/origins.mjs +0 -46
- package/dist/app/modules/config/origins.mjs.map +0 -1
- package/dist/app/modules/config/read/env.d.ts +0 -3
- package/dist/app/modules/config/read/env.d.ts.map +0 -1
- package/dist/app/modules/config/read/env.mjs +0 -139
- package/dist/app/modules/config/read/env.mjs.map +0 -1
- package/dist/app/modules/config/read/fs.d.ts +0 -3
- package/dist/app/modules/config/read/fs.d.ts.map +0 -1
- package/dist/app/modules/config/read/fs.mjs +0 -60
- package/dist/app/modules/config/read/fs.mjs.map +0 -1
- package/dist/app/modules/config/read/index.d.ts +0 -5
- package/dist/app/modules/config/read/index.d.ts.map +0 -1
- package/dist/app/modules/config/read/index.mjs +0 -7
- package/dist/app/modules/config/read/module.d.ts +0 -4
- package/dist/app/modules/config/read/module.d.ts.map +0 -1
- package/dist/app/modules/config/read/module.mjs +0 -29
- package/dist/app/modules/config/read/module.mjs.map +0 -1
- package/dist/app/modules/config/read/types.d.ts +0 -9
- package/dist/app/modules/config/read/types.d.ts.map +0 -1
- package/dist/app/modules/config/trust-proxy.d.ts +0 -28
- package/dist/app/modules/config/trust-proxy.d.ts.map +0 -1
- package/dist/app/modules/config/trust-proxy.mjs +0 -64
- package/dist/app/modules/config/trust-proxy.mjs.map +0 -1
- package/dist/cli/config.d.ts +0 -18
- package/dist/cli/config.d.ts.map +0 -1
- package/dist/cli/config.mjs +0 -34
- package/dist/cli/config.mjs.map +0 -1
- package/dist/cli/types.d.ts.map +0 -1
- package/dist/utils/host.d.ts +0 -2
- package/dist/utils/host.d.ts.map +0 -1
- package/dist/utils/host.mjs +0 -12
- package/dist/utils/host.mjs.map +0 -1
- /package/dist/adapters/http/{middleware/built-in → controllers/workflows/account}/types.mjs +0 -0
- /package/dist/adapters/http/{ui/console-packages → controllers/workflows/admin}/index.d.ts +0 -0
- /package/dist/adapters/http/{ui/account-console → controllers/workflows/admin}/types.mjs +0 -0
- /package/dist/adapters/http/{ui/auth-console → controllers/workflows/console-login}/types.mjs +0 -0
- /package/dist/adapters/http/{ui/console-packages → internal-client}/types.mjs +0 -0
- /package/dist/{adapters/http/ui/theme/contract → app/modules/components}/types.mjs +0 -0
- /package/dist/cli/{types.d.ts → commands/types.d.ts} +0 -0
- /package/dist/{adapters/http/ui/theme → cli/commands}/types.mjs +0 -0
- /package/dist/{app/modules/config/read → core/oauth2/backchannel-logout}/types.mjs +0 -0
- /package/dist/{cli → core/oauth2/console-login}/types.mjs +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.mjs","names":["randomUUID","BuiltInPolicyType","definePolicyData","and","eq","inArray","or","PermissionName","EntityNotFoundError","AbstractEntityService","EVENT_ACTOR_NAME_MAX_LENGTH","EVENT_LOG_RETENTION_DAYS_DEFAULT","sanitizeEventData","appendQueryConditions","decodeQuery","eventSchema","DAY_IN_MS","EventService","repository","options","logger","ctx","isOwnedBy","entity","actor","identity","actorId","data","id","actorType","type","canReadRealm","realmId","permissionEvaluator","evaluate","name","EVENT_READ","REALM_MATCH","policiesIncluded","COMPOSITE","PERMISSION_BINDING","resolveReadVisibility","actorRealmId","getActorRealmId","foreignRealmId","undefined","realmIds","push","owner","record","input","info","scope","refType","refId","clientId","sessionId","enabled","retentionDays","create","truncate","actorName","requestPath","requestMethod","requestIpAddress","requestUserAgent","expiring","expiresAt","Date","now","toISOString","save","warn","getMany","query","parsed","schema","canReadAll","preEvaluate","e","findMany","compiled","compile","verdict","ownership","scoped","condition","visibility","entities","meta","ATTRIBUTES","resourceRealmMatch","total","length","getOne","findOneById","value","maxLength","substring"],"sources":["../../../../src/core/entities/event/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { BuiltInPolicyType, definePolicyData } from '@authup/access';\nimport {\n and, \n eq, \n inArray, \n or,\n} from '@rapiq/core';\nimport { PermissionName } from '@authup/core-kit';\nimport type { Event } from '@authup/core-kit';\nimport { EntityNotFoundError } from '@authup/errors';\nimport { AbstractEntityService } from '@authup/server-kit';\nimport type { ActorContext, EntityRepositoryFindManyResult, Logger } from '@authup/server-kit';\nimport { EVENT_ACTOR_NAME_MAX_LENGTH, EVENT_LOG_RETENTION_DAYS_DEFAULT } from './constants.ts';\nimport { sanitizeEventData } from './sanitize.ts';\nimport type {\n EventReadVisibility,\n EventRecordInput,\n EventServiceOptions,\n EventServiceReadOptions,\n IEventRepository,\n IEventService,\n} from './types.ts';\nimport { appendQueryConditions, decodeQuery } from '../../query/index.ts';\nimport { eventSchema } from './schema.ts';\n\nexport type EventServiceContext = {\n repository: IEventRepository,\n options?: EventServiceOptions,\n logger?: Logger,\n};\n\nconst DAY_IN_MS = 86_400_000;\n\nexport class EventService extends AbstractEntityService implements IEventService {\n protected repository: IEventRepository;\n\n protected options: EventServiceOptions;\n\n protected logger?: Logger;\n\n constructor(ctx: EventServiceContext) {\n super();\n\n this.repository = ctx.repository;\n this.options = ctx.options ?? {};\n this.logger = ctx.logger;\n }\n\n protected isOwnedBy(entity: Event, actor: ActorContext): boolean {\n return !!actor.identity &&\n !!entity.actorId &&\n entity.actorId === actor.identity.data.id &&\n entity.actorType === actor.identity.type;\n }\n\n protected async canReadRealm(actor: ActorContext, realmId: string | null): Promise<boolean> {\n try {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.EVENT_READ,\n data: definePolicyData({ [BuiltInPolicyType.REALM_MATCH]: realmId }),\n options: {\n policiesIncluded: [\n BuiltInPolicyType.COMPOSITE,\n BuiltInPolicyType.PERMISSION_BINDING,\n BuiltInPolicyType.REALM_MATCH,\n ],\n },\n });\n return true;\n } catch {\n return false;\n }\n }\n\n protected async resolveReadVisibility(actor: ActorContext): Promise<EventReadVisibility | undefined> {\n const actorRealmId = this.getActorRealmId(actor);\n let foreignRealmId = randomUUID();\n while (foreignRealmId === actorRealmId) {\n foreignRealmId = randomUUID();\n }\n\n if (await this.canReadRealm(actor, foreignRealmId)) {\n return undefined;\n }\n\n const realmIds: Array<string | null> = [];\n if (actorRealmId && await this.canReadRealm(actor, actorRealmId)) {\n realmIds.push(actorRealmId);\n }\n if (await this.canReadRealm(actor, null)) {\n realmIds.push(null);\n }\n\n return {\n realmIds,\n ...(actor.identity ? {\n owner: {\n actorId: actor.identity.data.id,\n actorType: actor.identity.type,\n },\n } : {}),\n };\n }\n\n async record(input: EventRecordInput): Promise<void> {\n const data = sanitizeEventData(input.data);\n\n // complementary structured log line — fires even when persistence is\n // disabled, so a SIEM/Loki pipeline can pick the events up for free.\n this.logger?.info(`audit: ${input.scope}.${input.name}`, {\n scope: input.scope,\n name: input.name,\n refType: input.refType ?? null,\n refId: input.refId ?? null,\n clientId: input.clientId ?? null,\n sessionId: input.sessionId ?? null,\n actorType: input.actorType ?? null,\n actorId: input.actorId ?? null,\n realmId: input.realmId ?? null,\n ...(data ? { data } : {}),\n });\n\n if (this.options.enabled === false) {\n return;\n }\n\n try {\n const retentionDays = input.retentionDays ?? this.options.retentionDays ?? EVENT_LOG_RETENTION_DAYS_DEFAULT;\n\n const entity = this.repository.create({\n id: randomUUID(),\n scope: input.scope,\n name: input.name,\n refType: truncate(input.refType, 64),\n refId: truncate(input.refId, 64),\n clientId: input.clientId ?? null,\n sessionId: input.sessionId ?? null,\n actorType: input.actorType ?? null,\n actorId: input.actorId ?? null,\n actorName: truncate(input.actorName, EVENT_ACTOR_NAME_MAX_LENGTH),\n requestPath: truncate(input.requestPath, 256),\n requestMethod: truncate(input.requestMethod, 10),\n requestIpAddress: truncate(input.requestIpAddress, 45),\n requestUserAgent: truncate(input.requestUserAgent, 512),\n realmId: input.realmId ?? null,\n data,\n expiring: retentionDays > 0,\n expiresAt: retentionDays > 0 ?\n new Date(Date.now() + (retentionDays * DAY_IN_MS)).toISOString() :\n null,\n });\n\n await this.repository.save(entity);\n } catch {\n // an audit write failure must never fail the originating operation\n this.logger?.warn(`Recording the audit event ${input.scope}.${input.name} failed.`);\n }\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n options: EventServiceReadOptions = {},\n ): Promise<EntityRepositoryFindManyResult<Event>> {\n const parsed = await decodeQuery(query, { schema: eventSchema, actor });\n\n let canReadAll = true;\n try {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.EVENT_READ });\n } catch (e) {\n if (!actor.identity) {\n throw e;\n }\n canReadAll = false;\n }\n\n if (!canReadAll) {\n // self-service: only the actor's own rows (\"my sign-in history\")\n return this.repository.findMany(parsed, {\n owner: {\n actorId: actor.identity!.data.id,\n actorType: actor.identity!.type,\n },\n ...(options.realmId ? { realmId: options.realmId } : {}),\n });\n }\n\n // Compile EVENT_READ into a row condition (#3286 phase 3). Own rows are\n // always readable, so ownership composes as an OR-alternative — the whole\n // gate runs as WHERE (replacing the probe-based visibility derivation, and\n // additionally covering junction ATTRIBUTES policies the probe excluded)\n // and pagination/totals stay exact. A non-expressible policy falls back to\n // the probe + per-row loop below.\n const compiled = await actor.permissionEvaluator.compile({ name: PermissionName.EVENT_READ });\n if (compiled.verdict !== 'post') {\n const ownership = actor.identity ?\n and(eq('actorId', actor.identity.data.id), eq('actorType', actor.identity.type)) :\n null;\n\n let scoped = parsed;\n if (compiled.verdict === 'deny') {\n scoped = appendQueryConditions(parsed, ownership ?? inArray('id', []));\n } else if (compiled.verdict === 'conditional') {\n scoped = appendQueryConditions(\n parsed,\n ownership ? or(ownership, compiled.condition) : compiled.condition,\n );\n }\n\n return this.repository.findMany(scoped, { ...(options.realmId ? { realmId: options.realmId } : {}) });\n }\n\n const visibility = await this.resolveReadVisibility(actor);\n const { data: entities, meta } = await this.repository.findMany(parsed, {\n ...(options.realmId ? { realmId: options.realmId } : {}),\n ...(visibility ? { visibility } : {}),\n });\n\n const data: Event[] = [];\n\n for (const entity of entities) {\n if (this.isOwnedBy(entity, actor)) {\n data.push(entity);\n continue;\n }\n\n try {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.EVENT_READ,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: entity,\n ...this.resourceRealmMatch(entity),\n }),\n });\n data.push(entity);\n } catch {\n continue;\n }\n }\n\n return {\n data,\n meta: {\n ...meta,\n total: meta.total - (entities.length - data.length),\n },\n };\n }\n\n async getOne(id: string, actor: ActorContext, options: EventServiceReadOptions = {}): Promise<Event> {\n const entity = await this.repository.findOneById(id);\n if (!entity || (options.realmId && entity.realmId !== options.realmId)) {\n throw new EntityNotFoundError();\n }\n\n if (!this.isOwnedBy(entity, actor)) {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.EVENT_READ });\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.EVENT_READ,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: entity,\n ...this.resourceRealmMatch(entity),\n }),\n });\n }\n\n return entity;\n }\n}\n\nfunction truncate(value: string | null | undefined, maxLength: number): string | null {\n if (typeof value !== 'string') {\n return null;\n }\n\n if (value.length <= maxLength) {\n return value;\n }\n\n return value.substring(0, maxLength);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service.mjs","names":["randomUUID","BuiltInPolicyType","definePolicyData","and","eq","inArray","or","PermissionName","EntityNotFoundError","AbstractEntityService","EVENT_ACTOR_NAME_MAX_LENGTH","EVENT_LOG_RETENTION_DAYS_DEFAULT","sanitizeEventData","appendQueryConditions","decodeQuery","eventSchema","DAY_IN_MS","EventService","repository","options","logger","ctx","isOwnedBy","entity","actor","identity","actorId","data","id","actorType","type","canReadRealm","realmId","permissionEvaluator","evaluate","name","EVENT_READ","REALM_MATCH","policiesIncluded","COMPOSITE","PERMISSION_BINDING","resolveReadVisibility","actorRealmId","getActorRealmId","foreignRealmId","undefined","realmIds","push","owner","record","input","info","scope","refType","refId","clientId","sessionId","enabled","retentionDays","create","truncate","actorName","requestPath","requestMethod","requestIpAddress","requestUserAgent","expiring","expiresAt","Date","now","toISOString","save","transaction","warn","getMany","query","parsed","schema","canReadAll","preEvaluate","e","findMany","compiled","compile","verdict","ownership","scoped","condition","visibility","entities","meta","ATTRIBUTES","resourceRealmMatch","total","length","getOne","findOneById","value","maxLength","substring"],"sources":["../../../../src/core/entities/event/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { BuiltInPolicyType, definePolicyData } from '@authup/access';\nimport {\n and, \n eq, \n inArray, \n or,\n} from '@rapiq/core';\nimport { PermissionName } from '@authup/core-kit';\nimport type { Event } from '@authup/core-kit';\nimport { EntityNotFoundError } from '@authup/errors';\nimport { AbstractEntityService } from '@authup/server-kit';\nimport type { ActorContext, EntityRepositoryFindManyResult, Logger } from '@authup/server-kit';\nimport { EVENT_ACTOR_NAME_MAX_LENGTH, EVENT_LOG_RETENTION_DAYS_DEFAULT } from './constants.ts';\nimport { sanitizeEventData } from './sanitize.ts';\nimport type {\n EventReadVisibility,\n EventRecordInput,\n EventServiceOptions,\n EventServiceReadOptions,\n IEventRepository,\n IEventService,\n} from './types.ts';\nimport { appendQueryConditions, decodeQuery } from '../../query/index.ts';\nimport { eventSchema } from './schema.ts';\n\nexport type EventServiceContext = {\n repository: IEventRepository,\n options?: EventServiceOptions,\n logger?: Logger,\n};\n\nconst DAY_IN_MS = 86_400_000;\n\nexport class EventService extends AbstractEntityService implements IEventService {\n protected repository: IEventRepository;\n\n protected options: EventServiceOptions;\n\n protected logger?: Logger;\n\n constructor(ctx: EventServiceContext) {\n super();\n\n this.repository = ctx.repository;\n this.options = ctx.options ?? {};\n this.logger = ctx.logger;\n }\n\n protected isOwnedBy(entity: Event, actor: ActorContext): boolean {\n return !!actor.identity &&\n !!entity.actorId &&\n entity.actorId === actor.identity.data.id &&\n entity.actorType === actor.identity.type;\n }\n\n protected async canReadRealm(actor: ActorContext, realmId: string | null): Promise<boolean> {\n try {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.EVENT_READ,\n data: definePolicyData({ [BuiltInPolicyType.REALM_MATCH]: realmId }),\n options: {\n policiesIncluded: [\n BuiltInPolicyType.COMPOSITE,\n BuiltInPolicyType.PERMISSION_BINDING,\n BuiltInPolicyType.REALM_MATCH,\n ],\n },\n });\n return true;\n } catch {\n return false;\n }\n }\n\n protected async resolveReadVisibility(actor: ActorContext): Promise<EventReadVisibility | undefined> {\n const actorRealmId = this.getActorRealmId(actor);\n let foreignRealmId = randomUUID();\n while (foreignRealmId === actorRealmId) {\n foreignRealmId = randomUUID();\n }\n\n if (await this.canReadRealm(actor, foreignRealmId)) {\n return undefined;\n }\n\n const realmIds: Array<string | null> = [];\n if (actorRealmId && await this.canReadRealm(actor, actorRealmId)) {\n realmIds.push(actorRealmId);\n }\n if (await this.canReadRealm(actor, null)) {\n realmIds.push(null);\n }\n\n return {\n realmIds,\n ...(actor.identity ? {\n owner: {\n actorId: actor.identity.data.id,\n actorType: actor.identity.type,\n },\n } : {}),\n };\n }\n\n async record(input: EventRecordInput): Promise<void> {\n const data = sanitizeEventData(input.data);\n\n // complementary structured log line — fires even when persistence is\n // disabled, so a SIEM/Loki pipeline can pick the events up for free.\n this.logger?.info(`audit: ${input.scope}.${input.name}`, {\n scope: input.scope,\n name: input.name,\n refType: input.refType ?? null,\n refId: input.refId ?? null,\n clientId: input.clientId ?? null,\n sessionId: input.sessionId ?? null,\n actorType: input.actorType ?? null,\n actorId: input.actorId ?? null,\n realmId: input.realmId ?? null,\n ...(data ? { data } : {}),\n });\n\n if (this.options.enabled === false) {\n return;\n }\n\n try {\n const retentionDays = input.retentionDays ?? this.options.retentionDays ?? EVENT_LOG_RETENTION_DAYS_DEFAULT;\n\n const entity = this.repository.create({\n id: randomUUID(),\n scope: input.scope,\n name: input.name,\n refType: truncate(input.refType, 64),\n refId: truncate(input.refId, 64),\n clientId: input.clientId ?? null,\n sessionId: input.sessionId ?? null,\n actorType: input.actorType ?? null,\n actorId: input.actorId ?? null,\n actorName: truncate(input.actorName, EVENT_ACTOR_NAME_MAX_LENGTH),\n requestPath: truncate(input.requestPath, 256),\n requestMethod: truncate(input.requestMethod, 10),\n requestIpAddress: truncate(input.requestIpAddress, 45),\n requestUserAgent: truncate(input.requestUserAgent, 512),\n realmId: input.realmId ?? null,\n data,\n expiring: retentionDays > 0,\n expiresAt: retentionDays > 0 ?\n new Date(Date.now() + (retentionDays * DAY_IN_MS)).toISOString() :\n null,\n });\n\n await this.repository.save(entity, { transaction: input.transaction });\n } catch {\n // an audit write failure must never fail the originating operation\n // from here; a save that joined the write's transaction can still\n // have doomed it on postgres, see EventRepositoryAdapter.save\n this.logger?.warn(`Recording the audit event ${input.scope}.${input.name} failed.`);\n }\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n options: EventServiceReadOptions = {},\n ): Promise<EntityRepositoryFindManyResult<Event>> {\n const parsed = await decodeQuery(query, { schema: eventSchema, actor });\n\n let canReadAll = true;\n try {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.EVENT_READ });\n } catch (e) {\n if (!actor.identity) {\n throw e;\n }\n canReadAll = false;\n }\n\n if (!canReadAll) {\n // self-service: only the actor's own rows (\"my sign-in history\")\n return this.repository.findMany(parsed, {\n owner: {\n actorId: actor.identity!.data.id,\n actorType: actor.identity!.type,\n },\n ...(options.realmId ? { realmId: options.realmId } : {}),\n });\n }\n\n // Compile EVENT_READ into a row condition (#3286 phase 3). Own rows are\n // always readable, so ownership composes as an OR-alternative — the whole\n // gate runs as WHERE (replacing the probe-based visibility derivation, and\n // additionally covering junction ATTRIBUTES policies the probe excluded)\n // and pagination/totals stay exact. A non-expressible policy falls back to\n // the probe + per-row loop below.\n const compiled = await actor.permissionEvaluator.compile({ name: PermissionName.EVENT_READ });\n if (compiled.verdict !== 'post') {\n const ownership = actor.identity ?\n and(eq('actorId', actor.identity.data.id), eq('actorType', actor.identity.type)) :\n null;\n\n let scoped = parsed;\n if (compiled.verdict === 'deny') {\n scoped = appendQueryConditions(parsed, ownership ?? inArray('id', []));\n } else if (compiled.verdict === 'conditional') {\n scoped = appendQueryConditions(\n parsed,\n ownership ? or(ownership, compiled.condition) : compiled.condition,\n );\n }\n\n return this.repository.findMany(scoped, { ...(options.realmId ? { realmId: options.realmId } : {}) });\n }\n\n const visibility = await this.resolveReadVisibility(actor);\n const { data: entities, meta } = await this.repository.findMany(parsed, {\n ...(options.realmId ? { realmId: options.realmId } : {}),\n ...(visibility ? { visibility } : {}),\n });\n\n const data: Event[] = [];\n\n for (const entity of entities) {\n if (this.isOwnedBy(entity, actor)) {\n data.push(entity);\n continue;\n }\n\n try {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.EVENT_READ,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: entity,\n ...this.resourceRealmMatch(entity),\n }),\n });\n data.push(entity);\n } catch {\n continue;\n }\n }\n\n return {\n data,\n meta: {\n ...meta,\n total: meta.total - (entities.length - data.length),\n },\n };\n }\n\n async getOne(id: string, actor: ActorContext, options: EventServiceReadOptions = {}): Promise<Event> {\n const entity = await this.repository.findOneById(id);\n if (!entity || (options.realmId && entity.realmId !== options.realmId)) {\n throw new EntityNotFoundError();\n }\n\n if (!this.isOwnedBy(entity, actor)) {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.EVENT_READ });\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.EVENT_READ,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: entity,\n ...this.resourceRealmMatch(entity),\n }),\n });\n }\n\n return entity;\n }\n}\n\nfunction truncate(value: string | null | undefined, maxLength: number): string | null {\n if (typeof value !== 'string') {\n return null;\n }\n\n if (value.length <= maxLength) {\n return value;\n }\n\n return value.substring(0, maxLength);\n}\n"],"mappings":"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"}
|
|
@@ -33,9 +33,17 @@ export type EventCountRecentFilter = {
|
|
|
33
33
|
*/
|
|
34
34
|
since: string;
|
|
35
35
|
};
|
|
36
|
+
export type EventSaveOptions = {
|
|
37
|
+
/**
|
|
38
|
+
* The transaction the row rides, as the opaque handle the domain event
|
|
39
|
+
* carried. The adapter decides whether it recognizes the handle; without
|
|
40
|
+
* one the row saves on a connection of its own.
|
|
41
|
+
*/
|
|
42
|
+
transaction?: unknown;
|
|
43
|
+
};
|
|
36
44
|
export interface IEventRepository {
|
|
37
45
|
create(data: Partial<Event>): Event;
|
|
38
|
-
save(entity: Event): Promise<Event>;
|
|
46
|
+
save(entity: Event, options?: EventSaveOptions): Promise<Event>;
|
|
39
47
|
findMany(query: IQuery, options?: EventFindManyOptions): Promise<EntityRepositoryFindManyResult<Event>>;
|
|
40
48
|
findOneById(id: string): Promise<Event | null>;
|
|
41
49
|
countRecent(filter: EventCountRecentFilter): Promise<number>;
|
|
@@ -77,6 +85,12 @@ export type EventRecordInput = {
|
|
|
77
85
|
* effective value.
|
|
78
86
|
*/
|
|
79
87
|
retentionDays?: number;
|
|
88
|
+
/**
|
|
89
|
+
* The transaction the originating write rides, when the caller is inside
|
|
90
|
+
* one (the entity-CRUD bridge). The row joins it instead of taking a
|
|
91
|
+
* second pooled connection (#3539).
|
|
92
|
+
*/
|
|
93
|
+
transaction?: unknown;
|
|
80
94
|
};
|
|
81
95
|
export type EventServiceOptions = {
|
|
82
96
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/core/entities/event/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACR,KAAK,EACL,SAAS,EACT,UAAU,EACV,YAAY,EACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AACvF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,MAAM,UAAU,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAC9B,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAC/B;;;OAGG;IACH,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,mBAAmB,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACjC,IAAI,EAAE,GAAG,SAAS,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC7B,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;IAEpC,IAAI,CAAC,MAAM,EAAE,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/core/entities/event/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACR,KAAK,EACL,SAAS,EACT,UAAU,EACV,YAAY,EACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AACvF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,MAAM,UAAU,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAC9B,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAC/B;;;OAGG;IACH,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,mBAAmB,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACjC,IAAI,EAAE,GAAG,SAAS,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC3B;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC7B,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;IAEpC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAEhE,QAAQ,CACJ,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,oBAAoB,GAC/B,OAAO,CAAC,8BAA8B,CAAC,KAAK,CAAC,CAAC,CAAC;IAElD,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IAE/C,WAAW,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE7D;;;;;OAKG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACpF;AAED,MAAM,MAAM,yBAAyB,GAAG;IACpC;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,KAAK,EAAE,GAAG,UAAU,EAAE,CAAC;IACvB,IAAI,EAAE,GAAG,SAAS,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,GAAG,YAAY,EAAE,GAAG,IAAI,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IAClC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAC9B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAC9B,SAAS,EAAE,GAAG,YAAY,EAAE,GAAG,IAAI,CAAC;IACpC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACpC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,WAAW,aAAa;IAC1B;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/C;;;;OAIG;IACH,OAAO,CACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1B,KAAK,EAAE,YAAY,EACnB,OAAO,CAAC,EAAE,uBAAuB,GAClC,OAAO,CAAC,8BAA8B,CAAC,KAAK,CAAC,CAAC,CAAC;IAElD;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;CAC9F"}
|
|
@@ -232,8 +232,7 @@ var PermissionService = class extends AbstractEntityService {
|
|
|
232
232
|
* - Custom global permissions (non-built-in with realmId: null)
|
|
233
233
|
*/ async assignToRealmAdminRoles(permission) {
|
|
234
234
|
if (REALM_ADMIN_EXCLUDED_PERMISSIONS.includes(permission.name)) return;
|
|
235
|
-
|
|
236
|
-
if (!permission.realmId && !isBuiltIn) return;
|
|
235
|
+
if (!Object.values(PermissionName).includes(permission.name) && !permission.realmId) return;
|
|
237
236
|
const realmScope = REALM_ADMIN_BOUND_PERMISSIONS.includes(permission.name) ? RealmScope.OWN : RealmScope.OWN_OR_NULL;
|
|
238
237
|
const realmAdminRoles = await this.roleRepository.findManyBy({ name: ROLE_REALM_ADMIN_NAME });
|
|
239
238
|
for (const role of realmAdminRoles) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.mjs","names":["BuiltInPolicyType","RealmScope","SystemPolicyName","definePolicyData","ValidatorGroup","isPropertySet","isUUID","AuthupError","EntityNotFoundError","ValidationError","PermissionName","PermissionValidator","ROLE_ADMIN_NAME","ROLE_REALM_ADMIN_NAME","AbstractEntityService","decodeQuery","permissionSchema","REALM_ADMIN_EXCLUDED_PERMISSIONS","REALM_CREATE","REALM_UPDATE","REALM_DELETE","REALM_ADMIN_BOUND_PERMISSIONS","CLIENT_CREATE","CLIENT_UPDATE","CLIENT_DELETE","IDENTITY_PROVIDER_CREATE","IDENTITY_PROVIDER_UPDATE","IDENTITY_PROVIDER_DELETE","PERMISSION_CREATE","PERMISSION_UPDATE","PERMISSION_DELETE","ROLE_CREATE","ROLE_UPDATE","ROLE_DELETE","SCOPE_CREATE","SCOPE_UPDATE","SCOPE_DELETE","USER_CREATE","USER_UPDATE","USER_DELETE","PermissionService","repository","realmRepository","roleRepository","rolePermissionRepository","policyRepository","permissionPolicyRepository","validator","ctx","getMany","query","actor","permissionEvaluator","preEvaluateOneOf","name","PERMISSION_READ","findMany","schema","getOne","idOrName","realm","entity","findOneByIdOrName","create","data","save","undefined","update","updateOnly","options","group","realmId","resolve","where","id","findOneBy","preEvaluate","UPDATE","CREATE","validated","run","validateJoinColumns","builtIn","evaluate","ATTRIBUTES","REALM_MATCH","checkUniqueness","merge","created","identity","getActorRealmId","resourceRealmMatch","assignToAdminRole","assignToRealmAdminRoles","assignDefaultPolicy","e","remove","catch","delete","entityId","permission","defaultPolicy","findOneByName","DEFAULT","existing","permissionId","policyId","entry","permissionRealmId","policyRealmId","adminRole","roleId","roleRealmId","realmScope","ANY","includes","isBuiltIn","Object","values","OWN","OWN_OR_NULL","realmAdminRoles","findManyBy","role"],"sources":["../../../../src/core/entities/permission/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { \n BuiltInPolicyType, \n RealmScope, \n SystemPolicyName, \n definePolicyData, \n} from '@authup/access';\nimport { ValidatorGroup, isPropertySet, isUUID } from '@authup/kit';\nimport { AuthupError, EntityNotFoundError, ValidationError } from '@authup/errors';\nimport {\n PermissionName,\n PermissionValidator,\n ROLE_ADMIN_NAME,\n ROLE_REALM_ADMIN_NAME,\n} from '@authup/core-kit';\nimport type { Permission } from '@authup/core-kit';\nimport type { ActorContext, EntityRepositoryFindManyResult } from '@authup/server-kit';\nimport type { IPermissionPolicyRepository } from '../permission-policy/types.ts';\nimport type { IPolicyRepository } from '../policy/types.ts';\nimport type { IRealmRepository } from '../realm/types.ts';\nimport type { IRoleRepository } from '../role/types.ts';\nimport type { IRolePermissionRepository } from '../role-permission/types.ts';\nimport { AbstractEntityService } from '@authup/server-kit';\nimport type { IPermissionRepository, IPermissionService } from './types.ts';\nimport { decodeQuery } from '../../query/index.ts';\nimport { permissionSchema } from './schema.ts';\n\nconst REALM_ADMIN_EXCLUDED_PERMISSIONS = [\n PermissionName.REALM_CREATE,\n PermissionName.REALM_UPDATE,\n PermissionName.REALM_DELETE,\n];\n\n/**\n * Direct-entity CUD permissions that realm_admin grants at `realmScope: own`\n * (strictly the actor's own realm — see line 372). Every other realm_admin\n * permission defaults to `ownOrNull` (own realm OR global/null resources) so it\n * can act on global building blocks.\n *\n * Junction CUD (e.g. user_role, role_permission) is intentionally NOT listed here:\n * it stays `ownOrNull` because a junction can legitimately reference a global\n * side (realmId: null) — a strict `own` would reject those.\n */\nconst REALM_ADMIN_BOUND_PERMISSIONS = [\n PermissionName.CLIENT_CREATE,\n PermissionName.CLIENT_UPDATE,\n PermissionName.CLIENT_DELETE,\n PermissionName.IDENTITY_PROVIDER_CREATE,\n PermissionName.IDENTITY_PROVIDER_UPDATE,\n PermissionName.IDENTITY_PROVIDER_DELETE,\n PermissionName.PERMISSION_CREATE,\n PermissionName.PERMISSION_UPDATE,\n PermissionName.PERMISSION_DELETE,\n PermissionName.ROLE_CREATE,\n PermissionName.ROLE_UPDATE,\n PermissionName.ROLE_DELETE,\n PermissionName.SCOPE_CREATE,\n PermissionName.SCOPE_UPDATE,\n PermissionName.SCOPE_DELETE,\n PermissionName.USER_CREATE,\n PermissionName.USER_UPDATE,\n PermissionName.USER_DELETE,\n];\n\nexport type PermissionServiceContext = {\n repository: IPermissionRepository;\n realmRepository: IRealmRepository;\n roleRepository: IRoleRepository;\n rolePermissionRepository: IRolePermissionRepository;\n policyRepository: IPolicyRepository;\n permissionPolicyRepository: IPermissionPolicyRepository;\n};\n\nexport class PermissionService extends AbstractEntityService implements IPermissionService {\n protected repository: IPermissionRepository;\n\n protected realmRepository: IRealmRepository;\n\n protected roleRepository: IRoleRepository;\n\n protected rolePermissionRepository: IRolePermissionRepository;\n\n protected policyRepository: IPolicyRepository;\n\n protected permissionPolicyRepository: IPermissionPolicyRepository;\n\n protected validator: PermissionValidator;\n\n constructor(ctx: PermissionServiceContext) {\n super();\n this.repository = ctx.repository;\n this.realmRepository = ctx.realmRepository;\n this.roleRepository = ctx.roleRepository;\n this.rolePermissionRepository = ctx.rolePermissionRepository;\n this.policyRepository = ctx.policyRepository;\n this.permissionPolicyRepository = ctx.permissionPolicyRepository;\n this.validator = new PermissionValidator();\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n ): Promise<EntityRepositoryFindManyResult<Permission>> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.PERMISSION_READ,\n PermissionName.PERMISSION_UPDATE,\n PermissionName.PERMISSION_DELETE,\n ],\n });\n\n return this.repository.findMany(await decodeQuery(query, { schema: permissionSchema, actor }));\n }\n\n async getOne(\n idOrName: string,\n actor: ActorContext,\n realm?: string,\n ): Promise<Permission> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.PERMISSION_READ,\n PermissionName.PERMISSION_UPDATE,\n PermissionName.PERMISSION_DELETE,\n ],\n });\n\n const entity = await this.repository.findOneByIdOrName(idOrName, realm);\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n return entity;\n }\n\n async create(\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<Permission> {\n const { entity } = await this.save(undefined, data, actor);\n return entity;\n }\n\n async update(\n idOrName: string,\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<Permission> {\n const { entity } = await this.save(idOrName, data, actor, { updateOnly: true });\n return entity;\n }\n\n async save(\n idOrName: string | undefined,\n data: Record<string, any>,\n actor: ActorContext,\n options: { updateOnly?: boolean } = {},\n ): Promise<{\n entity: Permission,\n created: boolean\n }> {\n let group: string;\n\n const realm = typeof data.realmId === 'string' ?\n await this.realmRepository.resolve(data.realmId) :\n undefined;\n\n let entity: Permission | null | undefined;\n if (idOrName) {\n const where: Record<string, any> = {};\n if (isUUID(idOrName)) {\n where.id = idOrName;\n } else {\n where.name = idOrName;\n }\n\n if (realm) {\n where.realmId = realm.id;\n }\n\n entity = await this.repository.findOneBy(where);\n // Only a NAME key may upsert-create. A UUID addresses one specific\n // row, so a miss is a 404 (creating would write a different id).\n if (!entity && (options.updateOnly || where.id)) {\n throw new EntityNotFoundError();\n }\n } else if (options.updateOnly) {\n throw new EntityNotFoundError();\n }\n\n if (entity) {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.PERMISSION_UPDATE });\n group = ValidatorGroup.UPDATE;\n } else {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.PERMISSION_CREATE });\n group = ValidatorGroup.CREATE;\n }\n\n const validated = await this.validator.run(data, { group });\n\n await this.repository.validateJoinColumns(validated);\n\n if (entity) {\n if (\n entity.builtIn &&\n isPropertySet(validated, 'name') &&\n entity.name !== validated.name\n ) {\n throw new ValidationError('The name of a built-in permission can not be changed.');\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.PERMISSION_UPDATE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: {\n ...entity,\n ...validated,\n },\n [BuiltInPolicyType.REALM_MATCH]: validated.realmId ?? entity.realmId ?? null,\n }),\n });\n\n await this.repository.checkUniqueness(validated, entity);\n\n entity = this.repository.merge(entity, validated);\n\n await this.repository.save(entity);\n\n return {\n entity,\n created: false,\n };\n }\n\n if (!isPropertySet(validated, 'realmId') && actor.identity) {\n validated.realmId = this.getActorRealmId(actor) || null;\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.PERMISSION_CREATE,\n data: definePolicyData({ [BuiltInPolicyType.ATTRIBUTES]: validated, ...this.resourceRealmMatch(validated) }),\n });\n\n await this.repository.checkUniqueness(validated);\n\n entity = this.repository.create(validated);\n entity = await this.repository.save(entity);\n\n // The permission row is now committed, but its security wiring — the\n // admin/realm_admin grants and the system.default binding — is written\n // through separate repositories with no shared transaction. A failure\n // partway through would strand the permission bound by system.default\n // yet held by nobody, which the uniform member gate on\n // POST /role-permissions then makes permanently un-grantable (#3303).\n // Two safeguards:\n // 1. Establish the grants BEFORE binding system.default, so even an\n // un-compensated interruption (a hard process crash) cannot produce\n // the bound-but-ungranted strand — at worst a benign, still-grantable\n // permission that lacks its baseline policy.\n // 2. On any thrown failure, remove the just-created permission — its\n // CASCADE foreign keys drop any partial junction/binding rows — and\n // rethrow so the caller sees the failure instead of a stale record.\n try {\n await this.assignToAdminRole(entity);\n await this.assignToRealmAdminRoles(entity);\n await this.assignDefaultPolicy(entity);\n } catch (e) {\n await this.repository.remove(entity).catch(() => { /* best-effort rollback */ });\n throw e;\n }\n\n return {\n entity,\n created: true,\n };\n }\n\n async delete(\n id: string,\n actor: ActorContext,\n ): Promise<Permission> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.PERMISSION_DELETE });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n if (entity.builtIn) {\n throw new ValidationError('A built-in permission can not be deleted.');\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.PERMISSION_DELETE,\n data: definePolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity, ...this.resourceRealmMatch(entity) }),\n });\n\n const { id: entityId } = entity;\n await this.repository.remove(entity);\n entity.id = entityId;\n\n return entity;\n }\n\n /**\n * Assign the system.default policy to a newly created permission.\n * This ensures all permissions are evaluated with the baseline security\n * policy (identity, permission-binding, realm-match) by default.\n */\n private async assignDefaultPolicy(permission: Permission): Promise<void> {\n const defaultPolicy = await this.policyRepository.findOneByName(SystemPolicyName.DEFAULT);\n if (!defaultPolicy) {\n throw new AuthupError(`The ${SystemPolicyName.DEFAULT} policy is not provisioned. Cannot create permissions without the default security policy.`);\n }\n\n const existing = await this.permissionPolicyRepository.findOneBy({\n permissionId: permission.id,\n policyId: defaultPolicy.id,\n });\n if (existing) {\n return;\n }\n\n const entry = this.permissionPolicyRepository.create({\n permissionId: permission.id,\n permissionRealmId: permission.realmId,\n policyId: defaultPolicy.id,\n policyRealmId: defaultPolicy.realmId,\n });\n await this.permissionPolicyRepository.save(entry);\n }\n\n /**\n * Assign a newly created permission to the global admin role.\n * The admin role receives every permission without policy restrictions.\n *\n * Throws when the admin role is not provisioned: without an admin grant the\n * permission is bound by `system.default` yet held by nobody, and the uniform\n * member gate on junction creation makes it permanently un-grantable (even by\n * admin). Fail loud so the stranded state is surfaced instead of swallowed.\n */\n private async assignToAdminRole(permission: Permission): Promise<void> {\n const adminRole = await this.roleRepository.findOneByName(ROLE_ADMIN_NAME);\n if (!adminRole) {\n throw new AuthupError(`The ${ROLE_ADMIN_NAME} role is not provisioned. Cannot grant the created permission to the administrator role.`);\n }\n\n const existing = await this.rolePermissionRepository.findOneBy({\n roleId: adminRole.id,\n permissionId: permission.id,\n });\n if (existing) {\n return;\n }\n\n const entry = this.rolePermissionRepository.create({\n roleId: adminRole.id,\n roleRealmId: adminRole.realmId,\n permissionId: permission.id,\n permissionRealmId: permission.realmId,\n // Global admin: unrestricted realm reach.\n realmScope: RealmScope.ANY,\n });\n await this.rolePermissionRepository.save(entry);\n }\n\n /**\n * Assign a newly created permission to all matching realm_admin roles.\n *\n * Uses differentiated realmScope on the junction:\n * - CUD on global-capable entity types → own (strictly own realm)\n * - Everything else → ownOrNull (own realm + null/global resources)\n *\n * Eligible permissions:\n * - Built-in authup permissions (global) — assigned to all realm_admin roles\n * - Realm-scoped permissions — assigned to the realm_admin in the matching realm\n *\n * Excluded:\n * - Realm CRUD permissions (realm_create, realm_update, realm_delete)\n * - Custom global permissions (non-built-in with realmId: null)\n */\n private async assignToRealmAdminRoles(permission: Permission): Promise<void> {\n if (REALM_ADMIN_EXCLUDED_PERMISSIONS.includes(permission.name as PermissionName)) {\n return;\n }\n\n const isBuiltIn = (Object.values(PermissionName) as string[]).includes(permission.name);\n if (!permission.realmId && !isBuiltIn) {\n return;\n }\n\n const realmScope = REALM_ADMIN_BOUND_PERMISSIONS.includes(permission.name as PermissionName) ?\n RealmScope.OWN :\n RealmScope.OWN_OR_NULL;\n\n const realmAdminRoles = await this.roleRepository.findManyBy({ name: ROLE_REALM_ADMIN_NAME });\n\n for (const role of realmAdminRoles) {\n if (permission.realmId && permission.realmId !== role.realmId) {\n continue;\n }\n\n const existing = await this.rolePermissionRepository.findOneBy({\n roleId: role.id,\n permissionId: permission.id,\n });\n if (existing) {\n continue;\n }\n\n const entry = this.rolePermissionRepository.create({\n roleId: role.id,\n roleRealmId: role.realmId,\n permissionId: permission.id,\n permissionRealmId: permission.realmId,\n realmScope,\n });\n await this.rolePermissionRepository.save(entry);\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service.mjs","names":["BuiltInPolicyType","RealmScope","SystemPolicyName","definePolicyData","ValidatorGroup","isPropertySet","isUUID","AuthupError","EntityNotFoundError","ValidationError","PermissionName","PermissionValidator","ROLE_ADMIN_NAME","ROLE_REALM_ADMIN_NAME","AbstractEntityService","decodeQuery","permissionSchema","REALM_ADMIN_EXCLUDED_PERMISSIONS","REALM_CREATE","REALM_UPDATE","REALM_DELETE","REALM_ADMIN_BOUND_PERMISSIONS","CLIENT_CREATE","CLIENT_UPDATE","CLIENT_DELETE","IDENTITY_PROVIDER_CREATE","IDENTITY_PROVIDER_UPDATE","IDENTITY_PROVIDER_DELETE","PERMISSION_CREATE","PERMISSION_UPDATE","PERMISSION_DELETE","ROLE_CREATE","ROLE_UPDATE","ROLE_DELETE","SCOPE_CREATE","SCOPE_UPDATE","SCOPE_DELETE","USER_CREATE","USER_UPDATE","USER_DELETE","PermissionService","repository","realmRepository","roleRepository","rolePermissionRepository","policyRepository","permissionPolicyRepository","validator","ctx","getMany","query","actor","permissionEvaluator","preEvaluateOneOf","name","PERMISSION_READ","findMany","schema","getOne","idOrName","realm","entity","findOneByIdOrName","create","data","save","undefined","update","updateOnly","options","group","realmId","resolve","where","id","findOneBy","preEvaluate","UPDATE","CREATE","validated","run","validateJoinColumns","builtIn","evaluate","ATTRIBUTES","REALM_MATCH","checkUniqueness","merge","created","identity","getActorRealmId","resourceRealmMatch","assignToAdminRole","assignToRealmAdminRoles","assignDefaultPolicy","e","remove","catch","delete","entityId","permission","defaultPolicy","findOneByName","DEFAULT","existing","permissionId","policyId","entry","permissionRealmId","policyRealmId","adminRole","roleId","roleRealmId","realmScope","ANY","includes","isBuiltIn","Object","values","OWN","OWN_OR_NULL","realmAdminRoles","findManyBy","role"],"sources":["../../../../src/core/entities/permission/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { \n BuiltInPolicyType, \n RealmScope, \n SystemPolicyName, \n definePolicyData, \n} from '@authup/access';\nimport { ValidatorGroup, isPropertySet, isUUID } from '@authup/kit';\nimport { AuthupError, EntityNotFoundError, ValidationError } from '@authup/errors';\nimport {\n PermissionName,\n PermissionValidator,\n ROLE_ADMIN_NAME,\n ROLE_REALM_ADMIN_NAME,\n} from '@authup/core-kit';\nimport type { Permission } from '@authup/core-kit';\nimport type { ActorContext, EntityRepositoryFindManyResult } from '@authup/server-kit';\nimport type { IPermissionPolicyRepository } from '../permission-policy/types.ts';\nimport type { IPolicyRepository } from '../policy/types.ts';\nimport type { IRealmRepository } from '../realm/types.ts';\nimport type { IRoleRepository } from '../role/types.ts';\nimport type { IRolePermissionRepository } from '../role-permission/types.ts';\nimport { AbstractEntityService } from '@authup/server-kit';\nimport type { IPermissionRepository, IPermissionService } from './types.ts';\nimport { decodeQuery } from '../../query/index.ts';\nimport { permissionSchema } from './schema.ts';\n\nconst REALM_ADMIN_EXCLUDED_PERMISSIONS = [\n PermissionName.REALM_CREATE,\n PermissionName.REALM_UPDATE,\n PermissionName.REALM_DELETE,\n];\n\n/**\n * Direct-entity CUD permissions that realm_admin grants at `realmScope: own`\n * (strictly the actor's own realm — see line 372). Every other realm_admin\n * permission defaults to `ownOrNull` (own realm OR global/null resources) so it\n * can act on global building blocks.\n *\n * Junction CUD (e.g. user_role, role_permission) is intentionally NOT listed here:\n * it stays `ownOrNull` because a junction can legitimately reference a global\n * side (realmId: null) — a strict `own` would reject those.\n */\nconst REALM_ADMIN_BOUND_PERMISSIONS = [\n PermissionName.CLIENT_CREATE,\n PermissionName.CLIENT_UPDATE,\n PermissionName.CLIENT_DELETE,\n PermissionName.IDENTITY_PROVIDER_CREATE,\n PermissionName.IDENTITY_PROVIDER_UPDATE,\n PermissionName.IDENTITY_PROVIDER_DELETE,\n PermissionName.PERMISSION_CREATE,\n PermissionName.PERMISSION_UPDATE,\n PermissionName.PERMISSION_DELETE,\n PermissionName.ROLE_CREATE,\n PermissionName.ROLE_UPDATE,\n PermissionName.ROLE_DELETE,\n PermissionName.SCOPE_CREATE,\n PermissionName.SCOPE_UPDATE,\n PermissionName.SCOPE_DELETE,\n PermissionName.USER_CREATE,\n PermissionName.USER_UPDATE,\n PermissionName.USER_DELETE,\n];\n\nexport type PermissionServiceContext = {\n repository: IPermissionRepository;\n realmRepository: IRealmRepository;\n roleRepository: IRoleRepository;\n rolePermissionRepository: IRolePermissionRepository;\n policyRepository: IPolicyRepository;\n permissionPolicyRepository: IPermissionPolicyRepository;\n};\n\nexport class PermissionService extends AbstractEntityService implements IPermissionService {\n protected repository: IPermissionRepository;\n\n protected realmRepository: IRealmRepository;\n\n protected roleRepository: IRoleRepository;\n\n protected rolePermissionRepository: IRolePermissionRepository;\n\n protected policyRepository: IPolicyRepository;\n\n protected permissionPolicyRepository: IPermissionPolicyRepository;\n\n protected validator: PermissionValidator;\n\n constructor(ctx: PermissionServiceContext) {\n super();\n this.repository = ctx.repository;\n this.realmRepository = ctx.realmRepository;\n this.roleRepository = ctx.roleRepository;\n this.rolePermissionRepository = ctx.rolePermissionRepository;\n this.policyRepository = ctx.policyRepository;\n this.permissionPolicyRepository = ctx.permissionPolicyRepository;\n this.validator = new PermissionValidator();\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n ): Promise<EntityRepositoryFindManyResult<Permission>> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.PERMISSION_READ,\n PermissionName.PERMISSION_UPDATE,\n PermissionName.PERMISSION_DELETE,\n ],\n });\n\n return this.repository.findMany(await decodeQuery(query, { schema: permissionSchema, actor }));\n }\n\n async getOne(\n idOrName: string,\n actor: ActorContext,\n realm?: string,\n ): Promise<Permission> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.PERMISSION_READ,\n PermissionName.PERMISSION_UPDATE,\n PermissionName.PERMISSION_DELETE,\n ],\n });\n\n const entity = await this.repository.findOneByIdOrName(idOrName, realm);\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n return entity;\n }\n\n async create(\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<Permission> {\n const { entity } = await this.save(undefined, data, actor);\n return entity;\n }\n\n async update(\n idOrName: string,\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<Permission> {\n const { entity } = await this.save(idOrName, data, actor, { updateOnly: true });\n return entity;\n }\n\n async save(\n idOrName: string | undefined,\n data: Record<string, any>,\n actor: ActorContext,\n options: { updateOnly?: boolean } = {},\n ): Promise<{\n entity: Permission,\n created: boolean\n }> {\n let group: string;\n\n const realm = typeof data.realmId === 'string' ?\n await this.realmRepository.resolve(data.realmId) :\n undefined;\n\n let entity: Permission | null | undefined;\n if (idOrName) {\n const where: Record<string, any> = {};\n if (isUUID(idOrName)) {\n where.id = idOrName;\n } else {\n where.name = idOrName;\n }\n\n if (realm) {\n where.realmId = realm.id;\n }\n\n entity = await this.repository.findOneBy(where);\n // Only a NAME key may upsert-create. A UUID addresses one specific\n // row, so a miss is a 404 (creating would write a different id).\n if (!entity && (options.updateOnly || where.id)) {\n throw new EntityNotFoundError();\n }\n } else if (options.updateOnly) {\n throw new EntityNotFoundError();\n }\n\n if (entity) {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.PERMISSION_UPDATE });\n group = ValidatorGroup.UPDATE;\n } else {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.PERMISSION_CREATE });\n group = ValidatorGroup.CREATE;\n }\n\n const validated = await this.validator.run(data, { group });\n\n await this.repository.validateJoinColumns(validated);\n\n if (entity) {\n if (\n entity.builtIn &&\n isPropertySet(validated, 'name') &&\n entity.name !== validated.name\n ) {\n throw new ValidationError('The name of a built-in permission can not be changed.');\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.PERMISSION_UPDATE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: {\n ...entity,\n ...validated,\n },\n [BuiltInPolicyType.REALM_MATCH]: validated.realmId ?? entity.realmId ?? null,\n }),\n });\n\n await this.repository.checkUniqueness(validated, entity);\n\n entity = this.repository.merge(entity, validated);\n\n await this.repository.save(entity);\n\n return {\n entity,\n created: false,\n };\n }\n\n if (!isPropertySet(validated, 'realmId') && actor.identity) {\n validated.realmId = this.getActorRealmId(actor) || null;\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.PERMISSION_CREATE,\n data: definePolicyData({ [BuiltInPolicyType.ATTRIBUTES]: validated, ...this.resourceRealmMatch(validated) }),\n });\n\n await this.repository.checkUniqueness(validated);\n\n entity = this.repository.create(validated);\n entity = await this.repository.save(entity);\n\n // The permission row is now committed, but its security wiring — the\n // admin/realm_admin grants and the system.default binding — is written\n // through separate repositories with no shared transaction. A failure\n // partway through would strand the permission bound by system.default\n // yet held by nobody, which the uniform member gate on\n // POST /role-permissions then makes permanently un-grantable (#3303).\n // Two safeguards:\n // 1. Establish the grants BEFORE binding system.default, so even an\n // un-compensated interruption (a hard process crash) cannot produce\n // the bound-but-ungranted strand — at worst a benign, still-grantable\n // permission that lacks its baseline policy.\n // 2. On any thrown failure, remove the just-created permission — its\n // CASCADE foreign keys drop any partial junction/binding rows — and\n // rethrow so the caller sees the failure instead of a stale record.\n try {\n await this.assignToAdminRole(entity);\n await this.assignToRealmAdminRoles(entity);\n await this.assignDefaultPolicy(entity);\n } catch (e) {\n await this.repository.remove(entity).catch(() => { /* best-effort rollback */ });\n throw e;\n }\n\n return {\n entity,\n created: true,\n };\n }\n\n async delete(\n id: string,\n actor: ActorContext,\n ): Promise<Permission> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.PERMISSION_DELETE });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n if (entity.builtIn) {\n throw new ValidationError('A built-in permission can not be deleted.');\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.PERMISSION_DELETE,\n data: definePolicyData({ [BuiltInPolicyType.ATTRIBUTES]: entity, ...this.resourceRealmMatch(entity) }),\n });\n\n const { id: entityId } = entity;\n await this.repository.remove(entity);\n entity.id = entityId;\n\n return entity;\n }\n\n /**\n * Assign the system.default policy to a newly created permission.\n * This ensures all permissions are evaluated with the baseline security\n * policy (identity, permission-binding, realm-match) by default.\n */\n private async assignDefaultPolicy(permission: Permission): Promise<void> {\n const defaultPolicy = await this.policyRepository.findOneByName(SystemPolicyName.DEFAULT);\n if (!defaultPolicy) {\n throw new AuthupError(`The ${SystemPolicyName.DEFAULT} policy is not provisioned. Cannot create permissions without the default security policy.`);\n }\n\n const existing = await this.permissionPolicyRepository.findOneBy({\n permissionId: permission.id,\n policyId: defaultPolicy.id,\n });\n if (existing) {\n return;\n }\n\n const entry = this.permissionPolicyRepository.create({\n permissionId: permission.id,\n permissionRealmId: permission.realmId,\n policyId: defaultPolicy.id,\n policyRealmId: defaultPolicy.realmId,\n });\n await this.permissionPolicyRepository.save(entry);\n }\n\n /**\n * Assign a newly created permission to the global admin role.\n * The admin role receives every permission without policy restrictions.\n *\n * Throws when the admin role is not provisioned: without an admin grant the\n * permission is bound by `system.default` yet held by nobody, and the uniform\n * member gate on junction creation makes it permanently un-grantable (even by\n * admin). Fail loud so the stranded state is surfaced instead of swallowed.\n */\n private async assignToAdminRole(permission: Permission): Promise<void> {\n const adminRole = await this.roleRepository.findOneByName(ROLE_ADMIN_NAME);\n if (!adminRole) {\n throw new AuthupError(`The ${ROLE_ADMIN_NAME} role is not provisioned. Cannot grant the created permission to the administrator role.`);\n }\n\n const existing = await this.rolePermissionRepository.findOneBy({\n roleId: adminRole.id,\n permissionId: permission.id,\n });\n if (existing) {\n return;\n }\n\n const entry = this.rolePermissionRepository.create({\n roleId: adminRole.id,\n roleRealmId: adminRole.realmId,\n permissionId: permission.id,\n permissionRealmId: permission.realmId,\n // Global admin: unrestricted realm reach.\n realmScope: RealmScope.ANY,\n });\n await this.rolePermissionRepository.save(entry);\n }\n\n /**\n * Assign a newly created permission to all matching realm_admin roles.\n *\n * Uses differentiated realmScope on the junction:\n * - CUD on global-capable entity types → own (strictly own realm)\n * - Everything else → ownOrNull (own realm + null/global resources)\n *\n * Eligible permissions:\n * - Built-in authup permissions (global) — assigned to all realm_admin roles\n * - Realm-scoped permissions — assigned to the realm_admin in the matching realm\n *\n * Excluded:\n * - Realm CRUD permissions (realm_create, realm_update, realm_delete)\n * - Custom global permissions (non-built-in with realmId: null)\n */\n private async assignToRealmAdminRoles(permission: Permission): Promise<void> {\n if (REALM_ADMIN_EXCLUDED_PERMISSIONS.includes(permission.name as PermissionName)) {\n return;\n }\n\n const isBuiltIn = (Object.values(PermissionName) as string[]).includes(permission.name);\n if (!isBuiltIn && !permission.realmId) {\n return;\n }\n\n const realmScope = REALM_ADMIN_BOUND_PERMISSIONS.includes(permission.name as PermissionName) ?\n RealmScope.OWN :\n RealmScope.OWN_OR_NULL;\n\n const realmAdminRoles = await this.roleRepository.findManyBy({ name: ROLE_REALM_ADMIN_NAME });\n\n for (const role of realmAdminRoles) {\n if (permission.realmId && permission.realmId !== role.realmId) {\n continue;\n }\n\n const existing = await this.rolePermissionRepository.findOneBy({\n roleId: role.id,\n permissionId: permission.id,\n });\n if (existing) {\n continue;\n }\n\n const entry = this.rolePermissionRepository.create({\n roleId: role.id,\n roleRealmId: role.realmId,\n permissionId: permission.id,\n permissionRealmId: permission.realmId,\n realmScope,\n });\n await this.rolePermissionRepository.save(entry);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -91,7 +91,7 @@ var RolePermissionService = class extends JunctionEntityService {
|
|
|
91
91
|
let actorScope = RealmScope.ANY;
|
|
92
92
|
let actorPolicyFree = true;
|
|
93
93
|
let actorPolicyId = null;
|
|
94
|
-
if (actor.identity
|
|
94
|
+
if (permission && actor.identity) {
|
|
95
95
|
const grant = await this.identityPermissionProvider.resolveJunctionGrant({
|
|
96
96
|
type: actor.identity.type,
|
|
97
97
|
id: actor.identity.data.id
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.mjs","names":["BuiltInPolicyType","RealmScope","definePolicyData","EntityConflictError","EntityNotFoundError","ValidatorGroup","PermissionName","RolePermissionValidator","applyJunctionCreateGrant","buildJunctionUpdateData","JunctionEntityService","decodeQuery","rolePermissionSchema","RolePermissionService","ownerRealmKey","repository","permissionRepository","identityPermissionProvider","validator","ctx","getMany","query","actor","permissionEvaluator","preEvaluateOneOf","name","ROLE_PERMISSION_DELETE","ROLE_PERMISSION_READ","findMany","schema","getOne","id","entity","findOneBy","create","data","preEvaluate","ROLE_PERMISSION_CREATE","validated","run","group","CREATE","validateJoinColumns","existing","roleId","permissionId","permission","permissionRealmId","realmId","clientId","role","roleRealmId","identity","grant","resolveJunctionGrant","type","realmScope","OWN","evaluate","ATTRIBUTES","junctionAttributes","REALM_MATCH","junctionResourceRealm","save","update","ROLE_PERMISSION_UPDATE","UPDATE","findOneById","actorScope","ANY","actorPolicyFree","actorPolicyId","policy","updateData","existingScope","merged","merge","delete","entityId","remove"],"sources":["../../../../src/core/entities/role-permission/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport {\n BuiltInPolicyType,\n RealmScope,\n definePolicyData,\n} from '@authup/access';\nimport { EntityConflictError, EntityNotFoundError } from '@authup/errors';\nimport { ValidatorGroup } from '@authup/kit';\nimport {\n PermissionName,\n RolePermissionValidator,\n} from '@authup/core-kit';\nimport type { Permission, RolePermission } from '@authup/core-kit';\nimport type { IIdentityPermissionProvider } from '../../identity/permission/types.ts';\nimport { applyJunctionCreateGrant, buildJunctionUpdateData } from '../../identity/permission/junction-grant.ts';\nimport type { ActorContext, EntityRepositoryFindManyResult, IEntityRepository } from '@authup/server-kit';\nimport { JunctionEntityService } from '@authup/server-kit';\nimport type { IRolePermissionRepository, IRolePermissionService } from './types.ts';\nimport { decodeQuery } from '../../query/index.ts';\nimport { rolePermissionSchema } from './schema.ts';\n\nexport type RolePermissionServiceContext = {\n repository: IRolePermissionRepository;\n permissionRepository: IEntityRepository<Permission>;\n identityPermissionProvider: IIdentityPermissionProvider;\n};\n\nexport class RolePermissionService extends JunctionEntityService implements IRolePermissionService {\n protected readonly ownerRealmKey = 'roleRealmId';\n\n protected repository: IRolePermissionRepository;\n\n protected permissionRepository: IEntityRepository<Permission>;\n\n protected identityPermissionProvider: IIdentityPermissionProvider;\n\n protected validator: RolePermissionValidator;\n\n constructor(ctx: RolePermissionServiceContext) {\n super();\n this.repository = ctx.repository;\n this.permissionRepository = ctx.permissionRepository;\n this.identityPermissionProvider = ctx.identityPermissionProvider;\n this.validator = new RolePermissionValidator();\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n ): Promise<EntityRepositoryFindManyResult<RolePermission>> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.ROLE_PERMISSION_DELETE,\n PermissionName.ROLE_PERMISSION_READ,\n ],\n });\n\n return this.repository.findMany(await decodeQuery(query, { schema: rolePermissionSchema, actor }));\n }\n\n async getOne(\n id: string,\n actor: ActorContext,\n ): Promise<RolePermission> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.ROLE_PERMISSION_DELETE,\n PermissionName.ROLE_PERMISSION_READ,\n ],\n });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n return entity;\n }\n\n async create(\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<RolePermission> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.ROLE_PERMISSION_CREATE });\n\n const validated = await this.validator.run(data, { group: ValidatorGroup.CREATE });\n\n await this.repository.validateJoinColumns(validated);\n\n const existing = await this.repository.findOneBy({\n roleId: validated.roleId,\n permissionId: validated.permissionId,\n });\n if (existing) {\n throw new EntityConflictError({ entity: 'role-permission' });\n }\n\n if (validated.permission) {\n validated.permissionRealmId = validated.permission.realmId;\n\n // Q4: the superset gate runs uniformly — no ROLE_ADMIN_NAME bypass.\n await actor.permissionEvaluator.preEvaluate({\n name: validated.permission.name,\n realmId: validated.permission.realmId,\n clientId: validated.permission.clientId,\n });\n }\n\n if (validated.role) {\n validated.roleRealmId = validated.role.realmId;\n }\n\n if (validated.permission && actor.identity) {\n const grant = await this.identityPermissionProvider.resolveJunctionGrant(\n {\n type: actor.identity.type,\n id: actor.identity.data.id,\n },\n {\n name: validated.permission.name,\n realmId: validated.permission.realmId,\n clientId: validated.permission.clientId,\n realmScope: validated.realmScope ?? RealmScope.OWN,\n },\n );\n\n applyJunctionCreateGrant(validated, grant);\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.ROLE_PERMISSION_CREATE,\n // Stamp the owner (role) realm as the canonical `realmId` so the realmScope\n // factor gates this junction write against the actor's reach (no cross-realm).\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: this.junctionAttributes(validated),\n [BuiltInPolicyType.REALM_MATCH]: this.junctionResourceRealm(validated),\n }),\n });\n\n let entity = this.repository.create(validated);\n entity = await this.repository.save(entity);\n\n return entity;\n }\n\n async update(\n id: string,\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<RolePermission> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.ROLE_PERMISSION_UPDATE });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n const validated = await this.validator.run(data, { group: ValidatorGroup.UPDATE });\n\n // Resolve the actor's grant for this junction's permission (the existing entity only\n // carries scalar FKs — load the permission relation to derive it).\n const permission = await this.permissionRepository.findOneById(entity.permissionId);\n if (permission) {\n // Member-permission gate: an actor may only modify a binding for a permission it\n // holds (mirrors create()).\n await actor.permissionEvaluator.preEvaluate({\n name: permission.name,\n realmId: permission.realmId,\n clientId: permission.clientId,\n });\n }\n\n // No actor identity (system context) is not realm-gated here; the operation is still\n // authorized by the evaluate() below.\n let actorScope: `${RealmScope}` = RealmScope.ANY;\n let actorPolicyFree = true;\n let actorPolicyId: string | null = null;\n if (actor.identity && permission) {\n const grant = await this.identityPermissionProvider.resolveJunctionGrant(\n { type: actor.identity.type, id: actor.identity.data.id },\n {\n name: permission.name,\n realmId: permission.realmId,\n clientId: permission.clientId,\n realmScope: validated.realmScope ?? entity.realmScope,\n },\n );\n actorScope = grant.realmScope;\n actorPolicyFree = !grant.policy;\n actorPolicyId = grant.policy ? grant.policy.id : null;\n } else if (actor.identity) {\n actorScope = RealmScope.OWN;\n }\n\n const updateData = buildJunctionUpdateData({\n data: validated,\n existingScope: entity.realmScope,\n actorScope,\n actorPolicyFree,\n actorPolicyId,\n });\n\n await this.repository.validateJoinColumns(updateData);\n\n const merged = this.repository.merge(entity, updateData);\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.ROLE_PERMISSION_UPDATE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: this.junctionAttributes(merged),\n [BuiltInPolicyType.REALM_MATCH]: this.junctionResourceRealm(merged),\n }),\n });\n\n return this.repository.save(merged);\n }\n\n async delete(\n id: string,\n actor: ActorContext,\n ): Promise<RolePermission> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.ROLE_PERMISSION_DELETE });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.ROLE_PERMISSION_DELETE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: this.junctionAttributes(entity),\n [BuiltInPolicyType.REALM_MATCH]: this.junctionResourceRealm(entity),\n }),\n });\n\n const { id: entityId } = entity;\n await this.repository.remove(entity);\n entity.id = entityId;\n\n return entity;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service.mjs","names":["BuiltInPolicyType","RealmScope","definePolicyData","EntityConflictError","EntityNotFoundError","ValidatorGroup","PermissionName","RolePermissionValidator","applyJunctionCreateGrant","buildJunctionUpdateData","JunctionEntityService","decodeQuery","rolePermissionSchema","RolePermissionService","ownerRealmKey","repository","permissionRepository","identityPermissionProvider","validator","ctx","getMany","query","actor","permissionEvaluator","preEvaluateOneOf","name","ROLE_PERMISSION_DELETE","ROLE_PERMISSION_READ","findMany","schema","getOne","id","entity","findOneBy","create","data","preEvaluate","ROLE_PERMISSION_CREATE","validated","run","group","CREATE","validateJoinColumns","existing","roleId","permissionId","permission","permissionRealmId","realmId","clientId","role","roleRealmId","identity","grant","resolveJunctionGrant","type","realmScope","OWN","evaluate","ATTRIBUTES","junctionAttributes","REALM_MATCH","junctionResourceRealm","save","update","ROLE_PERMISSION_UPDATE","UPDATE","findOneById","actorScope","ANY","actorPolicyFree","actorPolicyId","policy","updateData","existingScope","merged","merge","delete","entityId","remove"],"sources":["../../../../src/core/entities/role-permission/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport {\n BuiltInPolicyType,\n RealmScope,\n definePolicyData,\n} from '@authup/access';\nimport { EntityConflictError, EntityNotFoundError } from '@authup/errors';\nimport { ValidatorGroup } from '@authup/kit';\nimport {\n PermissionName,\n RolePermissionValidator,\n} from '@authup/core-kit';\nimport type { Permission, RolePermission } from '@authup/core-kit';\nimport type { IIdentityPermissionProvider } from '../../identity/permission/types.ts';\nimport { applyJunctionCreateGrant, buildJunctionUpdateData } from '../../identity/permission/junction-grant.ts';\nimport type { ActorContext, EntityRepositoryFindManyResult, IEntityRepository } from '@authup/server-kit';\nimport { JunctionEntityService } from '@authup/server-kit';\nimport type { IRolePermissionRepository, IRolePermissionService } from './types.ts';\nimport { decodeQuery } from '../../query/index.ts';\nimport { rolePermissionSchema } from './schema.ts';\n\nexport type RolePermissionServiceContext = {\n repository: IRolePermissionRepository;\n permissionRepository: IEntityRepository<Permission>;\n identityPermissionProvider: IIdentityPermissionProvider;\n};\n\nexport class RolePermissionService extends JunctionEntityService implements IRolePermissionService {\n protected readonly ownerRealmKey = 'roleRealmId';\n\n protected repository: IRolePermissionRepository;\n\n protected permissionRepository: IEntityRepository<Permission>;\n\n protected identityPermissionProvider: IIdentityPermissionProvider;\n\n protected validator: RolePermissionValidator;\n\n constructor(ctx: RolePermissionServiceContext) {\n super();\n this.repository = ctx.repository;\n this.permissionRepository = ctx.permissionRepository;\n this.identityPermissionProvider = ctx.identityPermissionProvider;\n this.validator = new RolePermissionValidator();\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n ): Promise<EntityRepositoryFindManyResult<RolePermission>> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.ROLE_PERMISSION_DELETE,\n PermissionName.ROLE_PERMISSION_READ,\n ],\n });\n\n return this.repository.findMany(await decodeQuery(query, { schema: rolePermissionSchema, actor }));\n }\n\n async getOne(\n id: string,\n actor: ActorContext,\n ): Promise<RolePermission> {\n await actor.permissionEvaluator.preEvaluateOneOf({\n name: [\n PermissionName.ROLE_PERMISSION_DELETE,\n PermissionName.ROLE_PERMISSION_READ,\n ],\n });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n return entity;\n }\n\n async create(\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<RolePermission> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.ROLE_PERMISSION_CREATE });\n\n const validated = await this.validator.run(data, { group: ValidatorGroup.CREATE });\n\n await this.repository.validateJoinColumns(validated);\n\n const existing = await this.repository.findOneBy({\n roleId: validated.roleId,\n permissionId: validated.permissionId,\n });\n if (existing) {\n throw new EntityConflictError({ entity: 'role-permission' });\n }\n\n if (validated.permission) {\n validated.permissionRealmId = validated.permission.realmId;\n\n // Q4: the superset gate runs uniformly — no ROLE_ADMIN_NAME bypass.\n await actor.permissionEvaluator.preEvaluate({\n name: validated.permission.name,\n realmId: validated.permission.realmId,\n clientId: validated.permission.clientId,\n });\n }\n\n if (validated.role) {\n validated.roleRealmId = validated.role.realmId;\n }\n\n if (validated.permission && actor.identity) {\n const grant = await this.identityPermissionProvider.resolveJunctionGrant(\n {\n type: actor.identity.type,\n id: actor.identity.data.id,\n },\n {\n name: validated.permission.name,\n realmId: validated.permission.realmId,\n clientId: validated.permission.clientId,\n realmScope: validated.realmScope ?? RealmScope.OWN,\n },\n );\n\n applyJunctionCreateGrant(validated, grant);\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.ROLE_PERMISSION_CREATE,\n // Stamp the owner (role) realm as the canonical `realmId` so the realmScope\n // factor gates this junction write against the actor's reach (no cross-realm).\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: this.junctionAttributes(validated),\n [BuiltInPolicyType.REALM_MATCH]: this.junctionResourceRealm(validated),\n }),\n });\n\n let entity = this.repository.create(validated);\n entity = await this.repository.save(entity);\n\n return entity;\n }\n\n async update(\n id: string,\n data: Record<string, any>,\n actor: ActorContext,\n ): Promise<RolePermission> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.ROLE_PERMISSION_UPDATE });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n const validated = await this.validator.run(data, { group: ValidatorGroup.UPDATE });\n\n // Resolve the actor's grant for this junction's permission (the existing entity only\n // carries scalar FKs — load the permission relation to derive it).\n const permission = await this.permissionRepository.findOneById(entity.permissionId);\n if (permission) {\n // Member-permission gate: an actor may only modify a binding for a permission it\n // holds (mirrors create()).\n await actor.permissionEvaluator.preEvaluate({\n name: permission.name,\n realmId: permission.realmId,\n clientId: permission.clientId,\n });\n }\n\n // No actor identity (system context) is not realm-gated here; the operation is still\n // authorized by the evaluate() below.\n let actorScope: `${RealmScope}` = RealmScope.ANY;\n let actorPolicyFree = true;\n let actorPolicyId: string | null = null;\n if (permission && actor.identity) {\n const grant = await this.identityPermissionProvider.resolveJunctionGrant(\n { type: actor.identity.type, id: actor.identity.data.id },\n {\n name: permission.name,\n realmId: permission.realmId,\n clientId: permission.clientId,\n realmScope: validated.realmScope ?? entity.realmScope,\n },\n );\n actorScope = grant.realmScope;\n actorPolicyFree = !grant.policy;\n actorPolicyId = grant.policy ? grant.policy.id : null;\n } else if (actor.identity) {\n actorScope = RealmScope.OWN;\n }\n\n const updateData = buildJunctionUpdateData({\n data: validated,\n existingScope: entity.realmScope,\n actorScope,\n actorPolicyFree,\n actorPolicyId,\n });\n\n await this.repository.validateJoinColumns(updateData);\n\n const merged = this.repository.merge(entity, updateData);\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.ROLE_PERMISSION_UPDATE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: this.junctionAttributes(merged),\n [BuiltInPolicyType.REALM_MATCH]: this.junctionResourceRealm(merged),\n }),\n });\n\n return this.repository.save(merged);\n }\n\n async delete(\n id: string,\n actor: ActorContext,\n ): Promise<RolePermission> {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.ROLE_PERMISSION_DELETE });\n\n const entity = await this.repository.findOneBy({ id });\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.ROLE_PERMISSION_DELETE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: this.junctionAttributes(entity),\n [BuiltInPolicyType.REALM_MATCH]: this.junctionResourceRealm(entity),\n }),\n });\n\n const { id: entityId } = entity;\n await this.repository.remove(entity);\n entity.id = entityId;\n\n return entity;\n }\n}\n"],"mappings":"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"}
|
|
@@ -2,13 +2,19 @@ import type { ICondition } from '@rapiq/core';
|
|
|
2
2
|
import type { Session } from '@authup/core-kit';
|
|
3
3
|
import { AbstractEntityService } from '@authup/server-kit';
|
|
4
4
|
import type { ActorContext, EntityRepositoryFindManyResult } from '@authup/server-kit';
|
|
5
|
-
import type { ISessionRepository } from '../../authentication/index.ts';
|
|
5
|
+
import type { ISessionManager, ISessionRepository } from '../../authentication/index.ts';
|
|
6
6
|
import type { ISessionService, SessionDeleteManyOptions, SessionDeleteManyResult } from './types.ts';
|
|
7
7
|
export type SessionServiceContext = {
|
|
8
8
|
repository: ISessionRepository;
|
|
9
|
+
/**
|
|
10
|
+
* Every revoke goes through the manager rather than the repository: its
|
|
11
|
+
* `revoke` is the one chokepoint that pushes the back-channel logout.
|
|
12
|
+
*/
|
|
13
|
+
sessionManager: ISessionManager;
|
|
9
14
|
};
|
|
10
15
|
export declare class SessionService extends AbstractEntityService implements ISessionService {
|
|
11
16
|
protected repository: ISessionRepository;
|
|
17
|
+
protected sessionManager: ISessionManager;
|
|
12
18
|
constructor(ctx: SessionServiceContext);
|
|
13
19
|
protected isOwnedBy(session: Session, actor: ActorContext): boolean;
|
|
14
20
|
getMany(query: Record<string, any>, actor: ActorContext): Promise<EntityRepositoryFindManyResult<Session>>;
|
|
@@ -34,5 +40,11 @@ export declare class SessionService extends AbstractEntityService implements ISe
|
|
|
34
40
|
protected static queryCodec: import("@rapiq/codec-url").URLCodec;
|
|
35
41
|
protected deleteManyForSelf(actor: ActorContext, currentSessionId?: string): Promise<SessionDeleteManyResult>;
|
|
36
42
|
protected deleteManyByQuery(actor: ActorContext, query: Record<string, any>): Promise<SessionDeleteManyResult>;
|
|
43
|
+
/**
|
|
44
|
+
* Revokes in batches. Every revoke waits for its back-channel deliveries,
|
|
45
|
+
* so one at a time costs a hanging RP one timeout per session, while all
|
|
46
|
+
* at once is an unbounded burst of row deletes and outbound requests.
|
|
47
|
+
*/
|
|
48
|
+
protected revokeAll(sessions: Session[]): Promise<void>;
|
|
37
49
|
}
|
|
38
50
|
//# sourceMappingURL=service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../src/core/entities/session/service.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAU9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AACvF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../src/core/entities/session/service.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAU9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AACvF,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEzF,OAAO,KAAK,EAAE,eAAe,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAIrG,MAAM,MAAM,qBAAqB,GAAG;IAChC,UAAU,EAAE,kBAAkB,CAAC;IAC/B;;;OAGG;IACH,cAAc,EAAE,eAAe,CAAC;CACnC,CAAC;AAIF,qBAAa,cAAe,SAAQ,qBAAsB,YAAW,eAAe;IAChF,SAAS,CAAC,UAAU,EAAE,kBAAkB,CAAC;IAEzC,SAAS,CAAC,cAAc,EAAE,eAAe,CAAC;gBAE9B,GAAG,EAAE,qBAAqB;IAMtC,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO;IAM7D,OAAO,CACT,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1B,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,8BAA8B,CAAC,OAAO,CAAC,CAAC;IAgF7C,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;IAoBzD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;IAsBzD,UAAU,CACZ,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE,wBAA6B,GACvC,OAAO,CAAC,uBAAuB,CAAC;IAYnC;;;;;;;;;OASG;IACH,SAAS,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO;IAoB/D,SAAS,CAAC,kBAAkB,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO;IAa5D;;;OAGG;IACH,SAAS,CAAC,MAAM,CAAC,UAAU,sCAAoB;cAE/B,iBAAiB,CAC7B,KAAK,EAAE,YAAY,EACnB,gBAAgB,CAAC,EAAE,MAAM,GAC1B,OAAO,CAAC,uBAAuB,CAAC;cAanB,iBAAiB,CAC7B,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC3B,OAAO,CAAC,uBAAuB,CAAC;IAwCnC;;;;OAIG;cACa,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAOhE"}
|
|
@@ -14,11 +14,14 @@ import { AuthupError, EntityNotFoundError, ErrorCode } from "@authup/errors";
|
|
|
14
14
|
import { and, eq, inArray, isFilter, isFilters, or } from "@rapiq/core";
|
|
15
15
|
import { createURLCodec } from "@rapiq/codec-url";
|
|
16
16
|
//#region src/core/entities/session/service.ts
|
|
17
|
+
const SESSION_REVOKE_CONCURRENCY = 10;
|
|
17
18
|
var SessionService = class SessionService extends AbstractEntityService {
|
|
18
19
|
repository;
|
|
20
|
+
sessionManager;
|
|
19
21
|
constructor(ctx) {
|
|
20
22
|
super();
|
|
21
23
|
this.repository = ctx.repository;
|
|
24
|
+
this.sessionManager = ctx.sessionManager;
|
|
22
25
|
}
|
|
23
26
|
isOwnedBy(session, actor) {
|
|
24
27
|
return !!actor.identity && session.sub === actor.identity.data.id && session.subKind === actor.identity.type;
|
|
@@ -104,9 +107,7 @@ var SessionService = class SessionService extends AbstractEntityService {
|
|
|
104
107
|
})
|
|
105
108
|
});
|
|
106
109
|
}
|
|
107
|
-
|
|
108
|
-
await this.repository.remove(entity);
|
|
109
|
-
entity.id = entityId;
|
|
110
|
+
await this.sessionManager.revoke(entity.id);
|
|
110
111
|
return entity;
|
|
111
112
|
}
|
|
112
113
|
async deleteMany(actor, options = {}) {
|
|
@@ -147,17 +148,12 @@ var SessionService = class SessionService extends AbstractEntityService {
|
|
|
147
148
|
* enforced downstream by the repository's schema-bound decode.
|
|
148
149
|
*/ static queryCodec = createURLCodec();
|
|
149
150
|
async deleteManyForSelf(actor, currentSessionId) {
|
|
150
|
-
const
|
|
151
|
+
const toRevoke = (await this.repository.findAllByOwner({
|
|
151
152
|
sub: actor.identity.data.id,
|
|
152
153
|
subKind: actor.identity.type
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if (currentSessionId && session.id === currentSessionId) continue;
|
|
157
|
-
await this.repository.remove(session);
|
|
158
|
-
count += 1;
|
|
159
|
-
}
|
|
160
|
-
return { count };
|
|
154
|
+
})).filter((session) => !currentSessionId || session.id !== currentSessionId);
|
|
155
|
+
await this.revokeAll(toRevoke);
|
|
156
|
+
return { count: toRevoke.length };
|
|
161
157
|
}
|
|
162
158
|
async deleteManyByQuery(actor, query) {
|
|
163
159
|
await actor.permissionEvaluator.preEvaluate({ name: PermissionName.SESSION_DELETE });
|
|
@@ -166,7 +162,7 @@ var SessionService = class SessionService extends AbstractEntityService {
|
|
|
166
162
|
parameters: ["filters"],
|
|
167
163
|
actor
|
|
168
164
|
}));
|
|
169
|
-
|
|
165
|
+
const toRevoke = [];
|
|
170
166
|
for (const session of sessions) {
|
|
171
167
|
if (!this.isOwnedBy(session, actor)) try {
|
|
172
168
|
await actor.permissionEvaluator.evaluate({
|
|
@@ -179,10 +175,17 @@ var SessionService = class SessionService extends AbstractEntityService {
|
|
|
179
175
|
} catch {
|
|
180
176
|
continue;
|
|
181
177
|
}
|
|
182
|
-
|
|
183
|
-
count += 1;
|
|
178
|
+
toRevoke.push(session);
|
|
184
179
|
}
|
|
185
|
-
|
|
180
|
+
await this.revokeAll(toRevoke);
|
|
181
|
+
return { count: toRevoke.length };
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Revokes in batches. Every revoke waits for its back-channel deliveries,
|
|
185
|
+
* so one at a time costs a hanging RP one timeout per session, while all
|
|
186
|
+
* at once is an unbounded burst of row deletes and outbound requests.
|
|
187
|
+
*/ async revokeAll(sessions) {
|
|
188
|
+
for (let i = 0; i < sessions.length; i += SESSION_REVOKE_CONCURRENCY) await Promise.all(sessions.slice(i, i + SESSION_REVOKE_CONCURRENCY).map((session) => this.sessionManager.revoke(session.id)));
|
|
186
189
|
}
|
|
187
190
|
};
|
|
188
191
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.mjs","names":["BuiltInPolicyType","definePolicyData","AuthupError","EntityNotFoundError","ErrorCode","isObject","createURLCodec","and","eq","inArray","isFilter","isFilters","or","PermissionName","AbstractEntityService","SESSION_FILTER_KEYS","appendQueryConditions","decodeQuery","sessionSchema","SessionService","repository","ctx","isOwnedBy","session","actor","identity","sub","data","id","subKind","type","getMany","query","parsed","schema","canReadAll","permissionEvaluator","preEvaluate","name","SESSION_READ","e","findMany","owner","compiled","compile","verdict","ownership","scoped","condition","entities","meta","total","entity","push","evaluate","ATTRIBUTES","resourceRealmMatch","getOne","findOneById","delete","SESSION_DELETE","entityId","remove","deleteMany","options","code","IDENTITY_UNAUTHORIZED","message","hasTargetFilter","deleteManyByQuery","deleteManyForSelf","currentSessionId","queryCodec","decode","hasTargetCondition","filters","value","some","child","includes","field","sessions","findAllByOwner","count","findAllByQuery","parameters"],"sources":["../../../../src/core/entities/session/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { BuiltInPolicyType, definePolicyData } from '@authup/access';\nimport { AuthupError, EntityNotFoundError, ErrorCode } from '@authup/errors';\nimport { isObject } from '@authup/kit';\nimport { createURLCodec } from '@rapiq/codec-url';\nimport type { ICondition } from '@rapiq/core';\nimport {\n and, \n eq, \n inArray, \n isFilter, \n isFilters, \n or,\n} from '@rapiq/core';\nimport { PermissionName } from '@authup/core-kit';\nimport type { Session } from '@authup/core-kit';\nimport { AbstractEntityService } from '@authup/server-kit';\nimport type { ActorContext, EntityRepositoryFindManyResult } from '@authup/server-kit';\nimport type { ISessionRepository } from '../../authentication/index.ts';\nimport { SESSION_FILTER_KEYS } from '../../authentication/index.ts';\nimport type { ISessionService, SessionDeleteManyOptions, SessionDeleteManyResult } from './types.ts';\nimport { appendQueryConditions, decodeQuery } from '../../query/index.ts';\nimport { sessionSchema } from './schema.ts';\n\nexport type SessionServiceContext = {\n repository: ISessionRepository,\n};\n\nexport class SessionService extends AbstractEntityService implements ISessionService {\n protected repository: ISessionRepository;\n\n constructor(ctx: SessionServiceContext) {\n super();\n this.repository = ctx.repository;\n }\n\n protected isOwnedBy(session: Session, actor: ActorContext): boolean {\n return !!actor.identity &&\n session.sub === actor.identity.data.id &&\n session.subKind === actor.identity.type;\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n ): Promise<EntityRepositoryFindManyResult<Session>> {\n const parsed = await decodeQuery(query, { schema: sessionSchema, actor });\n\n let canReadAll = true;\n try {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.SESSION_READ });\n } catch (e) {\n if (!actor.identity) {\n throw e;\n }\n canReadAll = false;\n }\n\n if (!canReadAll) {\n // self-service: only the actor's own sessions\n return this.repository.findMany(parsed, {\n owner: {\n sub: actor.identity!.data.id,\n subKind: actor.identity!.type,\n },\n });\n }\n\n // Compile SESSION_READ into a row condition (#3286 phase 3). Own sessions\n // are always readable, so ownership composes as an OR-alternative — the\n // whole gate runs as WHERE and pagination/totals stay exact. Only a\n // non-expressible policy falls back to the per-row loop below.\n const compiled = await actor.permissionEvaluator.compile({ name: PermissionName.SESSION_READ });\n if (compiled.verdict !== 'post') {\n const ownership = actor.identity ?\n and(eq('sub', actor.identity.data.id), eq('subKind', actor.identity.type)) :\n null;\n\n let scoped = parsed;\n if (compiled.verdict === 'deny') {\n scoped = appendQueryConditions(parsed, ownership ?? inArray('id', []));\n } else if (compiled.verdict === 'conditional') {\n scoped = appendQueryConditions(\n parsed,\n ownership ? or(ownership, compiled.condition) : compiled.condition,\n );\n }\n\n return this.repository.findMany(scoped);\n }\n\n const { data: entities, meta } = await this.repository.findMany(parsed);\n\n const data: Session[] = [];\n let { total } = meta;\n\n for (const entity of entities) {\n if (this.isOwnedBy(entity, actor)) {\n data.push(entity);\n continue;\n }\n\n try {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.SESSION_READ,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: entity,\n ...this.resourceRealmMatch(entity),\n }),\n });\n data.push(entity);\n } catch {\n total -= 1;\n }\n }\n\n return {\n data,\n meta: {\n ...meta,\n total,\n },\n };\n }\n\n async getOne(id: string, actor: ActorContext): Promise<Session> {\n const entity = await this.repository.findOneById(id);\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n if (!this.isOwnedBy(entity, actor)) {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.SESSION_READ });\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.SESSION_READ,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: entity,\n ...this.resourceRealmMatch(entity),\n }),\n });\n }\n\n return entity;\n }\n\n async delete(id: string, actor: ActorContext): Promise<Session> {\n const entity = await this.repository.findOneById(id);\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n if (!this.isOwnedBy(entity, actor)) {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.SESSION_DELETE });\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.SESSION_DELETE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: entity,\n ...this.resourceRealmMatch(entity),\n }),\n });\n }\n\n const { id: entityId } = entity;\n await this.repository.remove(entity);\n entity.id = entityId;\n\n return entity;\n }\n\n async deleteMany(\n actor: ActorContext,\n options: SessionDeleteManyOptions = {},\n ): Promise<SessionDeleteManyResult> {\n if (!actor.identity) {\n throw new AuthupError({ code: ErrorCode.IDENTITY_UNAUTHORIZED, message: 'Authentication required.' });\n }\n\n if (this.hasTargetFilter(options.query)) {\n return this.deleteManyByQuery(actor, options.query!);\n }\n\n return this.deleteManyForSelf(actor, options.currentSessionId);\n }\n\n /**\n * True when the query carries at least one recognized target filter — the\n * discriminator between the admin bulk-revoke path and self-service. An\n * unrecognized / empty filter falls through to self-service (fail-safe: a\n * typo can never trigger an unconstrained mass delete).\n *\n * The wire may carry either dialect (v2 expression or legacy bracket\n * filters), so the decision decodes to the rapiq IR and inspects the\n * condition tree instead of poking at the raw payload.\n */\n protected hasTargetFilter(query?: Record<string, any>): boolean {\n if (!isObject(query)) {\n return false;\n }\n\n let parsed;\n try {\n parsed = SessionService.queryCodec.decode(query);\n } catch {\n // unreadable filter — fail-safe to self-service\n return false;\n }\n\n if (!parsed) {\n return false;\n }\n\n return this.hasTargetCondition(parsed.filters);\n }\n\n protected hasTargetCondition(condition: ICondition): boolean {\n if (isFilters(condition)) {\n return condition.value.some((child) => this.hasTargetCondition(child));\n }\n\n if (isFilter(condition)) {\n return (SESSION_FILTER_KEYS as readonly string[]).includes(condition.field) &&\n condition.value !== '';\n }\n\n return false;\n }\n\n /**\n * Schemaless decode — dialect detection only. The allow-list is\n * enforced downstream by the repository's schema-bound decode.\n */\n protected static queryCodec = createURLCodec();\n\n protected async deleteManyForSelf(\n actor: ActorContext,\n currentSessionId?: string,\n ): Promise<SessionDeleteManyResult> {\n const sessions = await this.repository.findAllByOwner({\n sub: actor.identity!.data.id,\n subKind: actor.identity!.type,\n });\n\n let count = 0;\n for (const session of sessions) {\n if (currentSessionId && session.id === currentSessionId) {\n continue;\n }\n await this.repository.remove(session);\n count += 1;\n }\n\n return { count };\n }\n\n protected async deleteManyByQuery(\n actor: ActorContext,\n query: Record<string, any>,\n ): Promise<SessionDeleteManyResult> {\n // Gate: an actor without SESSION_DELETE cannot force-logout anyone → 403.\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.SESSION_DELETE });\n\n const sessions = await this.repository.findAllByQuery(\n await decodeQuery(query, {\n schema: sessionSchema, \n parameters: ['filters'], \n actor, \n }),\n );\n\n let count = 0;\n for (const session of sessions) {\n // Own sessions are always deletable by the actor (mirrors getMany).\n // Otherwise per-session realm-match: a realm_admin only reaches\n // sessions in its realm — cross-realm rows are skipped, not failed,\n // so filter breadth cannot escalate beyond the actor's reach.\n if (!this.isOwnedBy(session, actor)) {\n try {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.SESSION_DELETE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: session,\n ...this.resourceRealmMatch(session),\n }),\n });\n } catch {\n continue;\n }\n }\n\n await this.repository.remove(session);\n count += 1;\n }\n\n return { count };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAkCA,IAAamB,iBAAb,MAAaA,uBAAuBL,sBAAAA;CACtBM;CAEV,YAAYC,KAA4B;EACpC,MAAK;EACL,KAAKD,aAAaC,IAAID;CAC1B;CAEUE,UAAUC,SAAkBC,OAA8B;EAChE,OAAO,CAAC,CAACA,MAAMC,YACXF,QAAQG,QAAQF,MAAMC,SAASE,KAAKC,MACpCL,QAAQM,YAAYL,MAAMC,SAASK;CAC3C;CAEA,MAAMC,QACFC,OACAR,OACgD;EAChD,MAAMS,SAAS,MAAMhB,YAAYe,OAAO;GAAEE,QAAQhB;GAAeM;EAAM,CAAA;EAEvE,IAAIW,aAAa;EACjB,IAAI;GACA,MAAMX,MAAMY,oBAAoBC,YAAY,EAAEC,MAAMzB,eAAe0B,aAAa,CAAA;EACpF,SAASC,GAAG;GACR,IAAI,CAAChB,MAAMC,UACP,MAAMe;GAEVL,aAAa;EACjB;EAEA,IAAI,CAACA,YAED,OAAO,KAAKf,WAAWqB,SAASR,QAAQ,EACpCS,OAAO;GACHhB,KAAKF,MAAMC,SAAUE,KAAKC;GAC1BC,SAASL,MAAMC,SAAUK;EAC7B,EACJ,CAAA;EAOJ,MAAMa,WAAW,MAAMnB,MAAMY,oBAAoBQ,QAAQ,EAAEN,MAAMzB,eAAe0B,aAAa,CAAA;EAC7F,IAAII,SAASE,YAAY,QAAQ;GAC7B,MAAMC,YAAYtB,MAAMC,WACpBlB,IAAIC,GAAG,OAAOgB,MAAMC,SAASE,KAAKC,EAAE,GAAGpB,GAAG,WAAWgB,MAAMC,SAASK,IAAI,CAAA,IACxE;GAEJ,IAAIiB,SAASd;GACb,IAAIU,SAASE,YAAY,QACrBE,SAAS/B,sBAAsBiB,QAAQa,aAAarC,QAAQ,MAAM,CAAA,CAAE,CAAA;QACjE,IAAIkC,SAASE,YAAY,eAC5BE,SAAS/B,sBACLiB,QACAa,YAAYlC,GAAGkC,WAAWH,SAASK,SAAS,IAAIL,SAASK,SAAS;GAI1E,OAAO,KAAK5B,WAAWqB,SAASM,MAAAA;EACpC;EAEA,MAAM,EAAEpB,MAAMsB,UAAUC,SAAS,MAAM,KAAK9B,WAAWqB,SAASR,MAAAA;EAEhE,MAAMN,OAAkB,CAAA;EACxB,IAAI,EAAEwB,UAAUD;EAEhB,KAAK,MAAME,UAAUH,UAAU;GAC3B,IAAI,KAAK3B,UAAU8B,QAAQ5B,KAAAA,GAAQ;IAC/BG,KAAK0B,KAAKD,MAAAA;IACV;GACJ;GAEA,IAAI;IACA,MAAM5B,MAAMY,oBAAoBkB,SAAS;KACrChB,MAAMzB,eAAe0B;KACrBZ,MAAM1B,iBAAiB;OAClBD,kBAAkBuD,aAAaH;MAChC,GAAG,KAAKI,mBAAmBJ,MAAAA;KAC/B,CAAA;IACJ,CAAA;IACAzB,KAAK0B,KAAKD,MAAAA;GACd,QAAQ;IACJD,SAAS;GACb;EACJ;EAEA,OAAO;GACHxB;GACAuB,MAAM;IACF,GAAGA;IACHC;GACJ;EACJ;CACJ;CAEA,MAAMM,OAAO7B,IAAYJ,OAAuC;EAC5D,MAAM4B,SAAS,MAAM,KAAKhC,WAAWsC,YAAY9B,EAAAA;EACjD,IAAI,CAACwB,QACD,MAAM,IAAIjD,oBAAAA;EAGd,IAAI,CAAC,KAAKmB,UAAU8B,QAAQ5B,KAAAA,GAAQ;GAChC,MAAMA,MAAMY,oBAAoBC,YAAY,EAAEC,MAAMzB,eAAe0B,aAAa,CAAA;GAChF,MAAMf,MAAMY,oBAAoBkB,SAAS;IACrChB,MAAMzB,eAAe0B;IACrBZ,MAAM1B,iBAAiB;MAClBD,kBAAkBuD,aAAaH;KAChC,GAAG,KAAKI,mBAAmBJ,MAAAA;IAC/B,CAAA;GACJ,CAAA;EACJ;EAEA,OAAOA;CACX;CAEA,MAAMO,OAAO/B,IAAYJ,OAAuC;EAC5D,MAAM4B,SAAS,MAAM,KAAKhC,WAAWsC,YAAY9B,EAAAA;EACjD,IAAI,CAACwB,QACD,MAAM,IAAIjD,oBAAAA;EAGd,IAAI,CAAC,KAAKmB,UAAU8B,QAAQ5B,KAAAA,GAAQ;GAChC,MAAMA,MAAMY,oBAAoBC,YAAY,EAAEC,MAAMzB,eAAe+C,eAAe,CAAA;GAClF,MAAMpC,MAAMY,oBAAoBkB,SAAS;IACrChB,MAAMzB,eAAe+C;IACrBjC,MAAM1B,iBAAiB;MAClBD,kBAAkBuD,aAAaH;KAChC,GAAG,KAAKI,mBAAmBJ,MAAAA;IAC/B,CAAA;GACJ,CAAA;EACJ;EAEA,MAAM,EAAExB,IAAIiC,aAAaT;EACzB,MAAM,KAAKhC,WAAW0C,OAAOV,MAAAA;EAC7BA,OAAOxB,KAAKiC;EAEZ,OAAOT;CACX;CAEA,MAAMW,WACFvC,OACAwC,UAAoC,CAAC,GACL;EAChC,IAAI,CAACxC,MAAMC,UACP,MAAM,IAAIvB,YAAY;GAAE+D,MAAM7D,UAAU8D;GAAuBC,SAAS;EAA2B,CAAA;EAGvG,IAAI,KAAKC,gBAAgBJ,QAAQhC,KAAK,GAClC,OAAO,KAAKqC,kBAAkB7C,OAAOwC,QAAQhC,KAAK;EAGtD,OAAO,KAAKsC,kBAAkB9C,OAAOwC,QAAQO,gBAAgB;CACjE;;;;;;;;;;IAYA,gBAA0BvC,OAAsC;EAC5D,IAAI,CAAC3B,SAAS2B,KAAAA,GACV,OAAO;EAGX,IAAIC;EACJ,IAAI;GACAA,SAASd,eAAeqD,WAAWC,OAAOzC,KAAAA;EAC9C,QAAQ;GAEJ,OAAO;EACX;EAEA,IAAI,CAACC,QACD,OAAO;EAGX,OAAO,KAAKyC,mBAAmBzC,OAAO0C,OAAO;CACjD;CAEUD,mBAAmB1B,WAAgC;EACzD,IAAIrC,UAAUqC,SAAAA,GACV,OAAOA,UAAU4B,MAAMC,MAAMC,UAAU,KAAKJ,mBAAmBI,KAAAA,CAAAA;EAGnE,IAAIpE,SAASsC,SAAAA,GACT,OAAO,oBAA2C+B,SAAS/B,UAAUgC,KAAK,KACtEhC,UAAU4B,UAAU;EAG5B,OAAO;CACX;;;;IAMA,OAAiBJ,aAAalE,eAAAA;CAE9B,MAAgBgE,kBACZ9C,OACA+C,kBACgC;EAChC,MAAMU,WAAW,MAAM,KAAK7D,WAAW8D,eAAe;GAClDxD,KAAKF,MAAMC,SAAUE,KAAKC;GAC1BC,SAASL,MAAMC,SAAUK;EAC7B,CAAA;EAEA,IAAIqD,QAAQ;EACZ,KAAK,MAAM5D,WAAW0D,UAAU;GAC5B,IAAIV,oBAAoBhD,QAAQK,OAAO2C,kBACnC;GAEJ,MAAM,KAAKnD,WAAW0C,OAAOvC,OAAAA;GAC7B4D,SAAS;EACb;EAEA,OAAO,EAAEA,MAAM;CACnB;CAEA,MAAgBd,kBACZ7C,OACAQ,OACgC;EAEhC,MAAMR,MAAMY,oBAAoBC,YAAY,EAAEC,MAAMzB,eAAe+C,eAAe,CAAA;EAElF,MAAMqB,WAAW,MAAM,KAAK7D,WAAWgE,eACnC,MAAMnE,YAAYe,OAAO;GACrBE,QAAQhB;GACRmE,YAAY,CAAC,SAAU;GACvB7D;EACJ,CAAA,CAAA;EAGJ,IAAI2D,QAAQ;EACZ,KAAK,MAAM5D,WAAW0D,UAAU;GAK5B,IAAI,CAAC,KAAK3D,UAAUC,SAASC,KAAAA,GACzB,IAAI;IACA,MAAMA,MAAMY,oBAAoBkB,SAAS;KACrChB,MAAMzB,eAAe+C;KACrBjC,MAAM1B,iBAAiB;OAClBD,kBAAkBuD,aAAahC;MAChC,GAAG,KAAKiC,mBAAmBjC,OAAAA;KAC/B,CAAA;IACJ,CAAA;GACJ,QAAQ;IACJ;GACJ;GAGJ,MAAM,KAAKH,WAAW0C,OAAOvC,OAAAA;GAC7B4D,SAAS;EACb;EAEA,OAAO,EAAEA,MAAM;CACnB;AACJ"}
|
|
1
|
+
{"version":3,"file":"service.mjs","names":["BuiltInPolicyType","definePolicyData","AuthupError","EntityNotFoundError","ErrorCode","isObject","createURLCodec","and","eq","inArray","isFilter","isFilters","or","PermissionName","AbstractEntityService","SESSION_FILTER_KEYS","appendQueryConditions","decodeQuery","sessionSchema","SESSION_REVOKE_CONCURRENCY","SessionService","repository","sessionManager","ctx","isOwnedBy","session","actor","identity","sub","data","id","subKind","type","getMany","query","parsed","schema","canReadAll","permissionEvaluator","preEvaluate","name","SESSION_READ","e","findMany","owner","compiled","compile","verdict","ownership","scoped","condition","entities","meta","total","entity","push","evaluate","ATTRIBUTES","resourceRealmMatch","getOne","findOneById","delete","SESSION_DELETE","revoke","deleteMany","options","code","IDENTITY_UNAUTHORIZED","message","hasTargetFilter","deleteManyByQuery","deleteManyForSelf","currentSessionId","queryCodec","decode","hasTargetCondition","filters","value","some","child","includes","field","sessions","findAllByOwner","toRevoke","filter","revokeAll","count","length","findAllByQuery","parameters","i","Promise","all","slice","map"],"sources":["../../../../src/core/entities/session/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { BuiltInPolicyType, definePolicyData } from '@authup/access';\nimport { AuthupError, EntityNotFoundError, ErrorCode } from '@authup/errors';\nimport { isObject } from '@authup/kit';\nimport { createURLCodec } from '@rapiq/codec-url';\nimport type { ICondition } from '@rapiq/core';\nimport {\n and, \n eq, \n inArray, \n isFilter, \n isFilters, \n or,\n} from '@rapiq/core';\nimport { PermissionName } from '@authup/core-kit';\nimport type { Session } from '@authup/core-kit';\nimport { AbstractEntityService } from '@authup/server-kit';\nimport type { ActorContext, EntityRepositoryFindManyResult } from '@authup/server-kit';\nimport type { ISessionManager, ISessionRepository } from '../../authentication/index.ts';\nimport { SESSION_FILTER_KEYS } from '../../authentication/index.ts';\nimport type { ISessionService, SessionDeleteManyOptions, SessionDeleteManyResult } from './types.ts';\nimport { appendQueryConditions, decodeQuery } from '../../query/index.ts';\nimport { sessionSchema } from './schema.ts';\n\nexport type SessionServiceContext = {\n repository: ISessionRepository,\n /**\n * Every revoke goes through the manager rather than the repository: its\n * `revoke` is the one chokepoint that pushes the back-channel logout.\n */\n sessionManager: ISessionManager,\n};\n\nconst SESSION_REVOKE_CONCURRENCY = 10;\n\nexport class SessionService extends AbstractEntityService implements ISessionService {\n protected repository: ISessionRepository;\n\n protected sessionManager: ISessionManager;\n\n constructor(ctx: SessionServiceContext) {\n super();\n this.repository = ctx.repository;\n this.sessionManager = ctx.sessionManager;\n }\n\n protected isOwnedBy(session: Session, actor: ActorContext): boolean {\n return !!actor.identity &&\n session.sub === actor.identity.data.id &&\n session.subKind === actor.identity.type;\n }\n\n async getMany(\n query: Record<string, any>,\n actor: ActorContext,\n ): Promise<EntityRepositoryFindManyResult<Session>> {\n const parsed = await decodeQuery(query, { schema: sessionSchema, actor });\n\n let canReadAll = true;\n try {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.SESSION_READ });\n } catch (e) {\n if (!actor.identity) {\n throw e;\n }\n canReadAll = false;\n }\n\n if (!canReadAll) {\n // self-service: only the actor's own sessions\n return this.repository.findMany(parsed, {\n owner: {\n sub: actor.identity!.data.id,\n subKind: actor.identity!.type,\n },\n });\n }\n\n // Compile SESSION_READ into a row condition (#3286 phase 3). Own sessions\n // are always readable, so ownership composes as an OR-alternative — the\n // whole gate runs as WHERE and pagination/totals stay exact. Only a\n // non-expressible policy falls back to the per-row loop below.\n const compiled = await actor.permissionEvaluator.compile({ name: PermissionName.SESSION_READ });\n if (compiled.verdict !== 'post') {\n const ownership = actor.identity ?\n and(eq('sub', actor.identity.data.id), eq('subKind', actor.identity.type)) :\n null;\n\n let scoped = parsed;\n if (compiled.verdict === 'deny') {\n scoped = appendQueryConditions(parsed, ownership ?? inArray('id', []));\n } else if (compiled.verdict === 'conditional') {\n scoped = appendQueryConditions(\n parsed,\n ownership ? or(ownership, compiled.condition) : compiled.condition,\n );\n }\n\n return this.repository.findMany(scoped);\n }\n\n const { data: entities, meta } = await this.repository.findMany(parsed);\n\n const data: Session[] = [];\n let { total } = meta;\n\n for (const entity of entities) {\n if (this.isOwnedBy(entity, actor)) {\n data.push(entity);\n continue;\n }\n\n try {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.SESSION_READ,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: entity,\n ...this.resourceRealmMatch(entity),\n }),\n });\n data.push(entity);\n } catch {\n total -= 1;\n }\n }\n\n return {\n data,\n meta: {\n ...meta,\n total,\n },\n };\n }\n\n async getOne(id: string, actor: ActorContext): Promise<Session> {\n const entity = await this.repository.findOneById(id);\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n if (!this.isOwnedBy(entity, actor)) {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.SESSION_READ });\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.SESSION_READ,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: entity,\n ...this.resourceRealmMatch(entity),\n }),\n });\n }\n\n return entity;\n }\n\n async delete(id: string, actor: ActorContext): Promise<Session> {\n const entity = await this.repository.findOneById(id);\n if (!entity) {\n throw new EntityNotFoundError();\n }\n\n if (!this.isOwnedBy(entity, actor)) {\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.SESSION_DELETE });\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.SESSION_DELETE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: entity,\n ...this.resourceRealmMatch(entity),\n }),\n });\n }\n\n await this.sessionManager.revoke(entity.id);\n\n return entity;\n }\n\n async deleteMany(\n actor: ActorContext,\n options: SessionDeleteManyOptions = {},\n ): Promise<SessionDeleteManyResult> {\n if (!actor.identity) {\n throw new AuthupError({ code: ErrorCode.IDENTITY_UNAUTHORIZED, message: 'Authentication required.' });\n }\n\n if (this.hasTargetFilter(options.query)) {\n return this.deleteManyByQuery(actor, options.query!);\n }\n\n return this.deleteManyForSelf(actor, options.currentSessionId);\n }\n\n /**\n * True when the query carries at least one recognized target filter — the\n * discriminator between the admin bulk-revoke path and self-service. An\n * unrecognized / empty filter falls through to self-service (fail-safe: a\n * typo can never trigger an unconstrained mass delete).\n *\n * The wire may carry either dialect (v2 expression or legacy bracket\n * filters), so the decision decodes to the rapiq IR and inspects the\n * condition tree instead of poking at the raw payload.\n */\n protected hasTargetFilter(query?: Record<string, any>): boolean {\n if (!isObject(query)) {\n return false;\n }\n\n let parsed;\n try {\n parsed = SessionService.queryCodec.decode(query);\n } catch {\n // unreadable filter — fail-safe to self-service\n return false;\n }\n\n if (!parsed) {\n return false;\n }\n\n return this.hasTargetCondition(parsed.filters);\n }\n\n protected hasTargetCondition(condition: ICondition): boolean {\n if (isFilters(condition)) {\n return condition.value.some((child) => this.hasTargetCondition(child));\n }\n\n if (isFilter(condition)) {\n return (SESSION_FILTER_KEYS as readonly string[]).includes(condition.field) &&\n condition.value !== '';\n }\n\n return false;\n }\n\n /**\n * Schemaless decode — dialect detection only. The allow-list is\n * enforced downstream by the repository's schema-bound decode.\n */\n protected static queryCodec = createURLCodec();\n\n protected async deleteManyForSelf(\n actor: ActorContext,\n currentSessionId?: string,\n ): Promise<SessionDeleteManyResult> {\n const sessions = await this.repository.findAllByOwner({\n sub: actor.identity!.data.id,\n subKind: actor.identity!.type,\n });\n\n const toRevoke = sessions.filter((session) => !currentSessionId || session.id !== currentSessionId);\n\n await this.revokeAll(toRevoke);\n\n return { count: toRevoke.length };\n }\n\n protected async deleteManyByQuery(\n actor: ActorContext,\n query: Record<string, any>,\n ): Promise<SessionDeleteManyResult> {\n // Gate: an actor without SESSION_DELETE cannot force-logout anyone → 403.\n await actor.permissionEvaluator.preEvaluate({ name: PermissionName.SESSION_DELETE });\n\n const sessions = await this.repository.findAllByQuery(\n await decodeQuery(query, {\n schema: sessionSchema, \n parameters: ['filters'], \n actor, \n }),\n );\n\n const toRevoke: Session[] = [];\n for (const session of sessions) {\n // Own sessions are always deletable by the actor (mirrors getMany).\n // Otherwise per-session realm-match: a realm_admin only reaches\n // sessions in its realm — cross-realm rows are skipped, not failed,\n // so filter breadth cannot escalate beyond the actor's reach.\n if (!this.isOwnedBy(session, actor)) {\n try {\n await actor.permissionEvaluator.evaluate({\n name: PermissionName.SESSION_DELETE,\n data: definePolicyData({\n [BuiltInPolicyType.ATTRIBUTES]: session,\n ...this.resourceRealmMatch(session),\n }),\n });\n } catch {\n continue;\n }\n }\n\n toRevoke.push(session);\n }\n\n await this.revokeAll(toRevoke);\n\n return { count: toRevoke.length };\n }\n\n /**\n * Revokes in batches. Every revoke waits for its back-channel deliveries,\n * so one at a time costs a hanging RP one timeout per session, while all\n * at once is an unbounded burst of row deletes and outbound requests.\n */\n protected async revokeAll(sessions: Session[]): Promise<void> {\n for (let i = 0; i < sessions.length; i += SESSION_REVOKE_CONCURRENCY) {\n await Promise.all(sessions\n .slice(i, i + SESSION_REVOKE_CONCURRENCY)\n .map((session) => this.sessionManager.revoke(session.id)));\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../src/core/entities/user/schema.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAM7C,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../src/core/entities/user/schema.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAM7C,eAAO,MAAM,UAAU,yCAoCrB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.mjs","names":["defineSchema","EntityType","createRelationsReadGate","schemaMapping","realm","REALM","userSchema","name","USER","indexes","fields","default","allowed","filters","indexed","relations","validate","sorts","pagination","maxLimit"],"sources":["../../../../src/core/entities/user/schema.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { defineSchema } from '@rapiq/core';\nimport type { User } from '@authup/core-kit';\nimport { EntityType } from '@authup/core-kit';\nimport { createRelationsReadGate } from '../../query/relations.ts';\n\nconst schemaMapping = { realm: EntityType.REALM };\n\nexport const userSchema = defineSchema<User>({\n name: EntityType.USER,\n indexes: [\n ['id'],\n ['name', 'realmId'],\n ['displayName'],\n ['realmId'],\n ['active'],\n ['createdAt'],\n ['updatedAt'],\n ],\n fields: {\n default: [\n 'id',\n 'name',\n 'nameLocked',\n 'firstName',\n 'lastName',\n 'displayName',\n 'avatar',\n 'cover',\n 'active',\n 'status',\n 'statusMessage',\n 'createdAt',\n 'updatedAt',\n 'realmId',\n ],\n allowed: ['email'],\n },\n filters: { allowed: ['id', 'name', 'displayName', 'realmId', 'active'], indexed: true },\n relations: { allowed: ['realm'], validate: createRelationsReadGate(schemaMapping) },\n sorts: { allowed: ['id', 'name', 'displayName', 'createdAt', 'updatedAt'], indexed: true },\n pagination: { maxLimit: 50 },\n schemaMapping,\n});\n"],"mappings":";;;;;;;AAYA,MAAMG,gBAAgB,EAAEC,OAAOH,WAAWI,MAAM;AAEhD,MAAaC,aAAaN,aAAmB;CACzCO,MAAMN,WAAWO;CACjBC,SAAS;EACL,CAAC,IAAK;EACN,CAAC,QAAQ,SAAU;EACnB,CAAC,aAAc;EACf,CAAC,SAAU;EACX,CAAC,QAAS;EACV,CAAC,WAAY;EACb,CAAC,WAAY;CAChB;CACDC,QAAQ;EACJC,SAAS;GACL;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACH;EACDC,SAAS,CAAC,OAAQ;CACtB;CACAC,SAAS;EAAED,SAAS;GAAC;GAAM;GAAQ;GAAe;GAAW;EAAS;EAAEE,SAAS;CAAK;CACtFC,WAAW;EAAEH,SAAS,CAAC,OAAQ;EAAEI,UAAUd,wBAAwBC,aAAAA;CAAe;CAClFc,OAAO;EAAEL,SAAS;GAAC;GAAM;GAAQ;GAAe;GAAa;EAAY;EAAEE,SAAS;CAAK;CACzFI,YAAY,EAAEC,UAAU,GAAG;CAC3BhB;AACJ,CAAA"}
|
|
1
|
+
{"version":3,"file":"schema.mjs","names":["defineSchema","EntityType","createRelationsReadGate","schemaMapping","realm","REALM","userSchema","name","USER","indexes","fields","default","allowed","filters","indexed","relations","validate","sorts","pagination","maxLimit"],"sources":["../../../../src/core/entities/user/schema.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { defineSchema } from '@rapiq/core';\nimport type { User } from '@authup/core-kit';\nimport { EntityType } from '@authup/core-kit';\nimport { createRelationsReadGate } from '../../query/relations.ts';\n\nconst schemaMapping = { realm: EntityType.REALM };\n\nexport const userSchema = defineSchema<User>({\n name: EntityType.USER,\n indexes: [\n ['id'],\n ['name', 'realmId'],\n ['displayName'],\n ['realmId'],\n ['active'],\n ['createdAt'],\n ['updatedAt'],\n ],\n fields: {\n default: [\n 'id',\n 'name',\n 'nameLocked',\n 'firstName',\n 'lastName',\n 'displayName',\n 'emailVerified',\n 'avatar',\n 'cover',\n 'active',\n 'status',\n 'statusMessage',\n 'createdAt',\n 'updatedAt',\n 'realmId',\n ],\n allowed: ['email'],\n },\n filters: { allowed: ['id', 'name', 'displayName', 'realmId', 'active'], indexed: true },\n relations: { allowed: ['realm'], validate: createRelationsReadGate(schemaMapping) },\n sorts: { allowed: ['id', 'name', 'displayName', 'createdAt', 'updatedAt'], indexed: true },\n pagination: { maxLimit: 50 },\n schemaMapping,\n});\n"],"mappings":";;;;;;;AAYA,MAAMG,gBAAgB,EAAEC,OAAOH,WAAWI,MAAM;AAEhD,MAAaC,aAAaN,aAAmB;CACzCO,MAAMN,WAAWO;CACjBC,SAAS;EACL,CAAC,IAAK;EACN,CAAC,QAAQ,SAAU;EACnB,CAAC,aAAc;EACf,CAAC,SAAU;EACX,CAAC,QAAS;EACV,CAAC,WAAY;EACb,CAAC,WAAY;CAChB;CACDC,QAAQ;EACJC,SAAS;GACL;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACH;EACDC,SAAS,CAAC,OAAQ;CACtB;CACAC,SAAS;EAAED,SAAS;GAAC;GAAM;GAAQ;GAAe;GAAW;EAAS;EAAEE,SAAS;CAAK;CACtFC,WAAW;EAAEH,SAAS,CAAC,OAAQ;EAAEI,UAAUd,wBAAwBC,aAAAA;CAAe;CAClFc,OAAO;EAAEL,SAAS;GAAC;GAAM;GAAQ;GAAe;GAAa;EAAY;EAAEE,SAAS;CAAK;CACzFI,YAAY,EAAEC,UAAU,GAAG;CAC3BhB;AACJ,CAAA"}
|