@tinyrack/issuary-server 0.22.0 → 0.23.0
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/entities/oauth-client.entity.d.ts +0 -18
- package/dist/entities/oauth-client.entity.d.ts.map +1 -1
- package/dist/entities/oauth-code.entity.d.ts +0 -18
- package/dist/entities/oauth-code.entity.d.ts.map +1 -1
- package/dist/entities/oauth-device-code.entity.d.ts +0 -18
- package/dist/entities/oauth-device-code.entity.d.ts.map +1 -1
- package/dist/entities/revoked-token.entity.d.ts +0 -18
- package/dist/entities/revoked-token.entity.d.ts.map +1 -1
- package/dist/entities/terms-content.entity.d.ts +0 -9
- package/dist/entities/terms-content.entity.d.ts.map +1 -1
- package/dist/entities/terms.entity.d.ts +0 -9
- package/dist/entities/terms.entity.d.ts.map +1 -1
- package/dist/entities/user-consent.entity.d.ts +0 -18
- package/dist/entities/user-consent.entity.d.ts.map +1 -1
- package/dist/entities/user-terms-consent.entity.d.ts +0 -9
- package/dist/entities/user-terms-consent.entity.d.ts.map +1 -1
- package/dist/entities/user-totp-recovery-code.entity.d.ts +0 -9
- package/dist/entities/user-totp-recovery-code.entity.d.ts.map +1 -1
- package/dist/entities/user-totp.entity.d.ts +0 -9
- package/dist/entities/user-totp.entity.d.ts.map +1 -1
- package/dist/entities/user.entity.d.ts +0 -9
- package/dist/entities/user.entity.d.ts.map +1 -1
- package/dist/entities/user.entity.js +0 -4
- package/dist/entities/user.entity.js.map +1 -1
- package/dist/entrypoints/app.d.ts +0 -53
- package/dist/entrypoints/app.d.ts.map +1 -1
- package/dist/entrypoints/database/postgres/compiled-functions.d.ts +20 -23
- package/dist/entrypoints/database/postgres/compiled-functions.d.ts.map +1 -1
- package/dist/entrypoints/database/postgres/compiled-functions.js +104 -134
- package/dist/entrypoints/database/postgres/compiled-functions.js.map +1 -1
- package/dist/entrypoints/database/sqlite/compiled-functions.d.ts +20 -23
- package/dist/entrypoints/database/sqlite/compiled-functions.d.ts.map +1 -1
- package/dist/entrypoints/database/sqlite/compiled-functions.js +104 -134
- package/dist/entrypoints/database/sqlite/compiled-functions.js.map +1 -1
- package/dist/lib/config/resolved.d.ts +0 -1
- package/dist/lib/config/resolved.d.ts.map +1 -1
- package/dist/lib/config/security.d.ts +0 -2
- package/dist/lib/config/security.d.ts.map +1 -1
- package/dist/lib/config/security.js +0 -5
- package/dist/lib/config/security.js.map +1 -1
- package/dist/middleware/auth.d.ts +0 -8
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +0 -64
- package/dist/middleware/auth.js.map +1 -1
- package/dist/middleware/session.d.ts +0 -9
- package/dist/middleware/session.d.ts.map +1 -1
- package/dist/middleware/session.js +0 -18
- package/dist/middleware/session.js.map +1 -1
- package/dist/migrations/postgres/Migration20260825140000_drop_password_reset_required.d.ts +6 -0
- package/dist/migrations/postgres/Migration20260825140000_drop_password_reset_required.d.ts.map +1 -0
- package/dist/migrations/postgres/Migration20260825140000_drop_password_reset_required.js +19 -0
- package/dist/migrations/postgres/Migration20260825140000_drop_password_reset_required.js.map +1 -0
- package/dist/migrations/postgres/index.d.ts.map +1 -1
- package/dist/migrations/postgres/index.js +2 -0
- package/dist/migrations/postgres/index.js.map +1 -1
- package/dist/migrations/sqlite/Migration20260825140000_drop_password_reset_required.d.ts +6 -0
- package/dist/migrations/sqlite/Migration20260825140000_drop_password_reset_required.d.ts.map +1 -0
- package/dist/migrations/sqlite/Migration20260825140000_drop_password_reset_required.js +19 -0
- package/dist/migrations/sqlite/Migration20260825140000_drop_password_reset_required.js.map +1 -0
- package/dist/migrations/sqlite/index.d.ts.map +1 -1
- package/dist/migrations/sqlite/index.js +2 -0
- package/dist/migrations/sqlite/index.js.map +1 -1
- package/dist/repositories/oauth-code.repository.d.ts +2 -2
- package/dist/repositories/oauth-code.repository.d.ts.map +1 -1
- package/dist/repositories/oauth-code.repository.js +3 -7
- package/dist/repositories/oauth-code.repository.js.map +1 -1
- package/dist/repositories/oauth-device-code.repository.d.ts +4 -4
- package/dist/repositories/oauth-device-code.repository.d.ts.map +1 -1
- package/dist/repositories/oauth-device-code.repository.js +6 -18
- package/dist/repositories/oauth-device-code.repository.js.map +1 -1
- package/dist/repositories/user-totp-recovery-code.repository.d.ts +1 -7
- package/dist/repositories/user-totp-recovery-code.repository.d.ts.map +1 -1
- package/dist/repositories/user-totp-recovery-code.repository.js +1 -2
- package/dist/repositories/user-totp-recovery-code.repository.js.map +1 -1
- package/dist/repositories/user-totp.repository.d.ts +0 -9
- package/dist/repositories/user-totp.repository.d.ts.map +1 -1
- package/dist/routes/api/auth/index.d.ts +0 -52
- package/dist/routes/api/auth/index.d.ts.map +1 -1
- package/dist/routes/api/auth/index.js +0 -2
- package/dist/routes/api/auth/index.js.map +1 -1
- package/dist/routes/api/auth/passkey/verify/post.d.ts +0 -37
- package/dist/routes/api/auth/passkey/verify/post.d.ts.map +1 -1
- package/dist/routes/api/auth/passkey/verify/post.js +2 -8
- package/dist/routes/api/auth/passkey/verify/post.js.map +1 -1
- package/dist/routes/api/index.d.ts +0 -52
- package/dist/routes/api/index.d.ts.map +1 -1
- package/dist/routes/index.d.ts +0 -52
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/oauth/device/get-post.js +5 -5
- package/dist/routes/oauth/device/get-post.js.map +1 -1
- package/dist/schemas/error.d.ts +0 -25
- package/dist/schemas/error.d.ts.map +1 -1
- package/dist/schemas/error.js +0 -1
- package/dist/schemas/error.js.map +1 -1
- package/dist/schemas/response.d.ts +0 -22
- package/dist/schemas/response.d.ts.map +1 -1
- package/dist/schemas/response.js +0 -8
- package/dist/schemas/response.js.map +1 -1
- package/dist/seeders/config.seeder.js +0 -1
- package/dist/seeders/config.seeder.js.map +1 -1
- package/dist/services/container.d.ts +0 -1
- package/dist/services/container.d.ts.map +1 -1
- package/dist/services/container.js +0 -15
- package/dist/services/container.js.map +1 -1
- package/dist/services/oauth-client.service.d.ts +0 -1
- package/dist/services/oauth-client.service.d.ts.map +1 -1
- package/dist/services/oauth-client.service.js +2 -17
- package/dist/services/oauth-client.service.js.map +1 -1
- package/dist/services/oauth-connect.service.d.ts.map +1 -1
- package/dist/services/oauth-connect.service.js +0 -4
- package/dist/services/oauth-connect.service.js.map +1 -1
- package/dist/services/oauth-token.service.d.ts.map +1 -1
- package/dist/services/oauth-token.service.js +4 -4
- package/dist/services/oauth-token.service.js.map +1 -1
- package/dist/services/password-auth.service.d.ts.map +1 -1
- package/dist/services/password-auth.service.js +3 -12
- package/dist/services/password-auth.service.js.map +1 -1
- package/dist/services/security.service.d.ts +0 -8
- package/dist/services/security.service.d.ts.map +1 -1
- package/dist/services/security.service.js +21 -82
- package/dist/services/security.service.js.map +1 -1
- package/dist/services/totp.service.js +2 -2
- package/dist/services/totp.service.js.map +1 -1
- package/package.json +1 -1
- package/public/assets/2fa-B5vLgDXQ.js +2 -0
- package/public/assets/{2fa-BgveHSB_.js.map → 2fa-B5vLgDXQ.js.map} +1 -1
- package/public/assets/2fa-BqsM_D-X.js +2 -0
- package/public/assets/{2fa-kiqzGSz2.js.map → 2fa-BqsM_D-X.js.map} +1 -1
- package/public/assets/2fa-C5vUVgr_.js +2 -0
- package/public/assets/{2fa-UL_cNRnQ.js.map → 2fa-C5vUVgr_.js.map} +1 -1
- package/public/assets/2fa-CCOTIHDZ.js +2 -0
- package/public/assets/{2fa-C37MUkye.js.map → 2fa-CCOTIHDZ.js.map} +1 -1
- package/public/assets/{DialogHandle-Zvz8SgS0.js → DialogHandle-BmtK2pRn.js} +2 -2
- package/public/assets/{DialogHandle-Zvz8SgS0.js.map → DialogHandle-BmtK2pRn.js.map} +1 -1
- package/public/assets/admin-BPijkLw-.js +2 -0
- package/public/assets/{admin-DbDuu6AI.js.map → admin-BPijkLw-.js.map} +1 -1
- package/public/assets/admin-users-DvPbw1Vq.js +2 -0
- package/public/assets/{admin-users-CwTJdiih.js.map → admin-users-DvPbw1Vq.js.map} +1 -1
- package/public/assets/{auth-choice-row-BlSsUI7d.js → auth-choice-row-BCGjuedo.js} +2 -2
- package/public/assets/{auth-choice-row-BlSsUI7d.js.map → auth-choice-row-BCGjuedo.js.map} +1 -1
- package/public/assets/{auth-field-HwxENJnB.js → auth-field-DD8kvl--.js} +2 -2
- package/public/assets/{auth-field-HwxENJnB.js.map → auth-field-DD8kvl--.js.map} +1 -1
- package/public/assets/{auth-layout-CoeqNhTT.js → auth-layout-VtpryDof.js} +2 -2
- package/public/assets/{auth-layout-CoeqNhTT.js.map → auth-layout-VtpryDof.js.map} +1 -1
- package/public/assets/{auth-page-header-CIs08f5Y.js → auth-page-header-CIn2E4zI.js} +2 -2
- package/public/assets/{auth-page-header-CIs08f5Y.js.map → auth-page-header-CIn2E4zI.js.map} +1 -1
- package/public/assets/{authorization-context-banner-BbtQmMYH.js → authorization-context-banner-SOuBHWIb.js} +2 -2
- package/public/assets/{authorization-context-banner-BbtQmMYH.js.map → authorization-context-banner-SOuBHWIb.js.map} +1 -1
- package/public/assets/{avatar-CttWiIv3.js → avatar-BEQjf2x6.js} +2 -2
- package/public/assets/{avatar-CttWiIv3.js.map → avatar-BEQjf2x6.js.map} +1 -1
- package/public/assets/{checkbox-CJrRV8S1.js → checkbox-gdHnSFQ-.js} +2 -2
- package/public/assets/{checkbox-CJrRV8S1.js.map → checkbox-gdHnSFQ-.js.map} +1 -1
- package/public/assets/config-DTQCUlfZ.js +2 -0
- package/public/assets/config-DTQCUlfZ.js.map +1 -0
- package/public/assets/{consent-BIhxtXHx.js → consent-BqqFDdsr.js} +2 -2
- package/public/assets/{consent-BIhxtXHx.js.map → consent-BqqFDdsr.js.map} +1 -1
- package/public/assets/{consent-DRmENn26.js → consent-CfRbz2R7.js} +2 -2
- package/public/assets/{consent-DRmENn26.js.map → consent-CfRbz2R7.js.map} +1 -1
- package/public/assets/email-C5vUVgr_.js +2 -0
- package/public/assets/{email-UL_cNRnQ.js.map → email-C5vUVgr_.js.map} +1 -1
- package/public/assets/{email-CVRDeJ78.js → email-CKKakxPJ.js} +2 -2
- package/public/assets/{email-CVRDeJ78.js.map → email-CKKakxPJ.js.map} +1 -1
- package/public/assets/error-BMXxpgfR.js +2 -0
- package/public/assets/{error-2VPY5w8V.js.map → error-BMXxpgfR.js.map} +1 -1
- package/public/assets/{field-DDt6F9TZ.js → field-Cn4H1CUj.js} +2 -2
- package/public/assets/{field-DDt6F9TZ.js.map → field-Cn4H1CUj.js.map} +1 -1
- package/public/assets/forgot-C5vUVgr_.js +2 -0
- package/public/assets/{forgot-UL_cNRnQ.js.map → forgot-C5vUVgr_.js.map} +1 -1
- package/public/assets/forgot-rO9sByfV.js +2 -0
- package/public/assets/{forgot-DzDcduho.js.map → forgot-rO9sByfV.js.map} +1 -1
- package/public/assets/index-CS23Ozt6.js +11 -0
- package/public/assets/index-CS23Ozt6.js.map +1 -0
- package/public/assets/{initial-avatar-CZzHAPm3.js → initial-avatar-CtuDUz_W.js} +2 -2
- package/public/assets/{initial-avatar-CZzHAPm3.js.map → initial-avatar-CtuDUz_W.js.map} +1 -1
- package/public/assets/{input-CNRpSR08.js → input-CzQki7k6.js} +2 -2
- package/public/assets/{input-CNRpSR08.js.map → input-CzQki7k6.js.map} +1 -1
- package/public/assets/{labeled-separator-fnKySKv2.js → labeled-separator-CV7nb0XW.js} +2 -2
- package/public/assets/{labeled-separator-fnKySKv2.js.map → labeled-separator-CV7nb0XW.js.map} +1 -1
- package/public/assets/login-C5vUVgr_.js +2 -0
- package/public/assets/login-C5vUVgr_.js.map +1 -0
- package/public/assets/login-nukebli4.js +2 -0
- package/public/assets/login-nukebli4.js.map +1 -0
- package/public/assets/{logout-CHdmF_16.js → logout-B5T52P8u.js} +2 -2
- package/public/assets/{logout-CHdmF_16.js.map → logout-B5T52P8u.js.map} +1 -1
- package/public/assets/{modal-sCM_zT82.js → modal-BDQFucjz.js} +2 -2
- package/public/assets/{modal-sCM_zT82.js.map → modal-BDQFucjz.js.map} +1 -1
- package/public/assets/{mutationOptions-CrswitPs.js → mutationOptions-DyYFUbyn.js} +2 -2
- package/public/assets/{mutationOptions-CrswitPs.js.map → mutationOptions-DyYFUbyn.js.map} +1 -1
- package/public/assets/passkey-BE9JvJOP.js +2 -0
- package/public/assets/{passkey-CU8x9J2w.js.map → passkey-BE9JvJOP.js.map} +1 -1
- package/public/assets/passkey-C5vUVgr_.js +2 -0
- package/public/assets/{passkey-UL_cNRnQ.js.map → passkey-C5vUVgr_.js.map} +1 -1
- package/public/assets/passkey-CynCz1Dt.js +2 -0
- package/public/assets/{passkey-CEx1VZ5R.js.map → passkey-CynCz1Dt.js.map} +1 -1
- package/public/assets/passkey-J1qnYp9A.js +2 -0
- package/public/assets/{passkey-B2Blw47e.js.map → passkey-J1qnYp9A.js.map} +1 -1
- package/public/assets/password-C5vUVgr_.js +2 -0
- package/public/assets/password-C5vUVgr_.js.map +1 -0
- package/public/assets/password-RkUttbhD.js +2 -0
- package/public/assets/password-RkUttbhD.js.map +1 -0
- package/public/assets/password-reset-sU5KkBKi.js +2 -0
- package/public/assets/{password-reset-CIacHnvA.js.map → password-reset-sU5KkBKi.js.map} +1 -1
- package/public/assets/{password-strength-C0Zkrrct.js → password-strength-BeSOu_Ga.js} +2 -2
- package/public/assets/{password-strength-C0Zkrrct.js.map → password-strength-BeSOu_Ga.js.map} +1 -1
- package/public/assets/{pin-input-BlD4tPZJ.js → pin-input-Cc-VkrQ3.js} +2 -2
- package/public/assets/{pin-input-BlD4tPZJ.js.map → pin-input-Cc-VkrQ3.js.map} +1 -1
- package/public/assets/{profile-D43Yq-6S.js → profile-B5NaJfeS.js} +2 -2
- package/public/assets/{profile-D43Yq-6S.js.map → profile-B5NaJfeS.js.map} +1 -1
- package/public/assets/{profile-D1cEjfs8.js → profile-BcjsVYOx.js} +2 -2
- package/public/assets/{profile-D1cEjfs8.js.map → profile-BcjsVYOx.js.map} +1 -1
- package/public/assets/recovery-PnUATiUi.js +2 -0
- package/public/assets/{recovery-CLExnfYX.js.map → recovery-PnUATiUi.js.map} +1 -1
- package/public/assets/register-C5vUVgr_.js +2 -0
- package/public/assets/{register-UL_cNRnQ.js.map → register-C5vUVgr_.js.map} +1 -1
- package/public/assets/register-DQXhru0_.js +2 -0
- package/public/assets/{register-CZUyWXRO.js.map → register-DQXhru0_.js.map} +1 -1
- package/public/assets/reset-C5vUVgr_.js +2 -0
- package/public/assets/{reset-UL_cNRnQ.js.map → reset-C5vUVgr_.js.map} +1 -1
- package/public/assets/reset-CQgIa3yf.js +2 -0
- package/public/assets/reset-CQgIa3yf.js.map +1 -0
- package/public/assets/select-C5vUVgr_.js +2 -0
- package/public/assets/{select-UL_cNRnQ.js.map → select-C5vUVgr_.js.map} +1 -1
- package/public/assets/{select-CWdSzsVo.js → select-DqZynXSt.js} +2 -2
- package/public/assets/{select-CWdSzsVo.js.map → select-DqZynXSt.js.map} +1 -1
- package/public/assets/{separator-BWGym8uM.js → separator-B0Bvh1he.js} +2 -2
- package/public/assets/{separator-BWGym8uM.js.map → separator-B0Bvh1he.js.map} +1 -1
- package/public/assets/shell-header-bar-CjG5qvPg.js +2 -0
- package/public/assets/{shell-header-bar-C9AB5lT-.js.map → shell-header-bar-CjG5qvPg.js.map} +1 -1
- package/public/assets/{terms-D43Yq-6S.js → terms-B5NaJfeS.js} +2 -2
- package/public/assets/{terms-D43Yq-6S.js.map → terms-B5NaJfeS.js.map} +1 -1
- package/public/assets/{terms-COVFmzyl.js → terms-BHDAgn-H.js} +2 -2
- package/public/assets/{terms-COVFmzyl.js.map → terms-BHDAgn-H.js.map} +1 -1
- package/public/assets/{terms-checkbox-list-Cw0zB-lO.js → terms-checkbox-list-6jteUTIZ.js} +2 -2
- package/public/assets/{terms-checkbox-list-Cw0zB-lO.js.map → terms-checkbox-list-6jteUTIZ.js.map} +1 -1
- package/public/assets/{totp-BfCm6IWl.js → totp-BNZ904Zm.js} +2 -2
- package/public/assets/{totp-BfCm6IWl.js.map → totp-BNZ904Zm.js.map} +1 -1
- package/public/assets/totp-CJtfVNEq.js +2 -0
- package/public/assets/{totp-BFJEXxk0.js.map → totp-CJtfVNEq.js.map} +1 -1
- package/public/assets/totp-ECvOUcFx.js +2 -0
- package/public/assets/{totp-MINhsVxT.js.map → totp-ECvOUcFx.js.map} +1 -1
- package/public/assets/use-totp-setup-BbS3XcZA.js +3 -0
- package/public/assets/{use-totp-setup-C7Zk_2IY.js.map → use-totp-setup-BbS3XcZA.js.map} +1 -1
- package/public/assets/{useAriaLabelledBy-CiOCg6X5.js → useAriaLabelledBy-ByuMi3Ry.js} +2 -2
- package/public/assets/{useAriaLabelledBy-CiOCg6X5.js.map → useAriaLabelledBy-ByuMi3Ry.js.map} +1 -1
- package/public/assets/{useMutation-ZLFeJg75.js → useMutation-BWZ0G4Td.js} +2 -2
- package/public/assets/{useMutation-ZLFeJg75.js.map → useMutation-BWZ0G4Td.js.map} +1 -1
- package/public/assets/useQuery-Ckxjmvtl.js +2 -0
- package/public/assets/{useQuery-BvMz34BW.js.map → useQuery-Ckxjmvtl.js.map} +1 -1
- package/public/assets/{users-COM7u3A-.js → users-CmFxrCQT.js} +2 -2
- package/public/assets/{users-COM7u3A-.js.map → users-CmFxrCQT.js.map} +1 -1
- package/public/index.html +3 -4
- package/dist/routes/api/auth/password/reset-required/post.d.ts +0 -18
- package/dist/routes/api/auth/password/reset-required/post.d.ts.map +0 -1
- package/dist/routes/api/auth/password/reset-required/post.js +0 -39
- package/dist/routes/api/auth/password/reset-required/post.js.map +0 -1
- package/dist/services/legacy-credential-retirement.service.d.ts +0 -20
- package/dist/services/legacy-credential-retirement.service.d.ts.map +0 -1
- package/dist/services/legacy-credential-retirement.service.js +0 -90
- package/dist/services/legacy-credential-retirement.service.js.map +0 -1
- package/public/assets/2fa-BgveHSB_.js +0 -2
- package/public/assets/2fa-C37MUkye.js +0 -2
- package/public/assets/2fa-UL_cNRnQ.js +0 -2
- package/public/assets/2fa-kiqzGSz2.js +0 -2
- package/public/assets/admin-DbDuu6AI.js +0 -2
- package/public/assets/admin-users-CwTJdiih.js +0 -2
- package/public/assets/config-v3-oy_ef.js +0 -2
- package/public/assets/config-v3-oy_ef.js.map +0 -1
- package/public/assets/email-UL_cNRnQ.js +0 -2
- package/public/assets/error-2VPY5w8V.js +0 -2
- package/public/assets/forgot-DzDcduho.js +0 -2
- package/public/assets/forgot-UL_cNRnQ.js +0 -2
- package/public/assets/index-gliHKncz.js +0 -11
- package/public/assets/index-gliHKncz.js.map +0 -1
- package/public/assets/link-BN90emXr.js +0 -2
- package/public/assets/link-BN90emXr.js.map +0 -1
- package/public/assets/lock-keyhole-Cz72xkCn.js +0 -2
- package/public/assets/lock-keyhole-Cz72xkCn.js.map +0 -1
- package/public/assets/login-C6m2qSUt.js +0 -2
- package/public/assets/login-C6m2qSUt.js.map +0 -1
- package/public/assets/login-UL_cNRnQ.js +0 -2
- package/public/assets/login-UL_cNRnQ.js.map +0 -1
- package/public/assets/passkey-B2Blw47e.js +0 -2
- package/public/assets/passkey-CEx1VZ5R.js +0 -2
- package/public/assets/passkey-CU8x9J2w.js +0 -2
- package/public/assets/passkey-UL_cNRnQ.js +0 -2
- package/public/assets/password-BhU_a0cR.js +0 -2
- package/public/assets/password-BhU_a0cR.js.map +0 -1
- package/public/assets/password-UL_cNRnQ.js +0 -2
- package/public/assets/password-UL_cNRnQ.js.map +0 -1
- package/public/assets/password-reset-CIacHnvA.js +0 -2
- package/public/assets/recovery-CLExnfYX.js +0 -2
- package/public/assets/register-CZUyWXRO.js +0 -2
- package/public/assets/register-UL_cNRnQ.js +0 -2
- package/public/assets/reset-N3RQTYEB.js +0 -2
- package/public/assets/reset-N3RQTYEB.js.map +0 -1
- package/public/assets/reset-UL_cNRnQ.js +0 -2
- package/public/assets/reset-required-Cv5edDS6.js +0 -2
- package/public/assets/reset-required-Cv5edDS6.js.map +0 -1
- package/public/assets/reset-required-UL_cNRnQ.js +0 -2
- package/public/assets/reset-required-UL_cNRnQ.js.map +0 -1
- package/public/assets/select-UL_cNRnQ.js +0 -2
- package/public/assets/shell-header-bar-C9AB5lT-.js +0 -2
- package/public/assets/totp-BFJEXxk0.js +0 -2
- package/public/assets/totp-MINhsVxT.js +0 -2
- package/public/assets/use-totp-setup-C7Zk_2IY.js +0 -3
- package/public/assets/useQuery-BvMz34BW.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"users-COM7u3A-.js","names":["useMutation","useQueryClient","useSuspenseQuery","TRBadge","TRButton","TRCard","useState","useTranslation","AdminGateScreen","AdminShell","AdminUserFormModal","AdminUsersFilterBar","getActiveQuickFilter","AdminUsersNotice","AdminUsersSummary","AdminUsersTable","AdminUsersToolbar","adminUsersQueryOptions","createAdminUser","deleteAdminUser","normalizeAdminUsersQuery","updateAdminUser","appConfigQueryOptions","Route","AdminUsersPage","user","useRouteContext","select","context","role","AdminUsersGate","SessionUser","data","config","admin","enabled","AdminUsersContent","t","queryClient","draftQuery","setDraftQuery","draftIncludeDeleted","setDraftIncludeDeleted","filters","setFilters","notice","setNotice","NoticeState","modal","setModal","UserModalState","activeUsers","users","filter","managedUser","deleted_at","length","configUsers","managed_by","databaseUsers","activeQuickFilter","hasActiveFilters","query","includeDeleted","managedBy","undefined","pageStart","pagination","total","page","page_size","pageEnd","Math","min","noticeOn","message","tone","noticeFail","createMutation","mutationFn","onSuccess","nextUser","invalidateQueries","queryKey","email","onError","updateMutation","deleteMutation","isMutating","isPending","applySearch","current","trim","clearFilters","applyQuickFilter","nextFilter","QuickFilter","type","pageSize","values","mutate","sub","component"],"sources":["../../../../node_modules/.pnpm/lucide-react@1.25.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/search.mjs","../../../frontend/src/features/admin/users/admin-users-filters.ts","../../../frontend/src/features/admin/users/admin-user-form-modal.tsx","../../../frontend/src/features/admin/users/admin-users-filter-bar.tsx","../../../frontend/src/features/admin/users/admin-users-notice.tsx","../../../frontend/src/features/admin/users/admin-users-summary.tsx","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-body.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-caption.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-cell.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-footer.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-head.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-header.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-root.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-row.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/index.js","../../../frontend/src/features/admin/users/admin-users-table.tsx","../../../frontend/src/features/admin/users/admin-users-toolbar.tsx","../../../frontend/src/routes/admin/users/index.tsx?tsr-split=component"],"sourcesContent":["/**\n * @license lucide-react v1.25.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"m21 21-4.34-4.34\", key: \"14j7rj\" }],\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"8\", key: \"4ej97u\" }]\n];\nconst Search = createLucideIcon(\"search\", __iconNode);\n\nexport { __iconNode, Search as default };\n//# sourceMappingURL=search.mjs.map\n","import type {\n AdminUser,\n normalizeAdminUsersQuery,\n} from '#frontend/queries/admin-users.ts';\n\nexport type QuickFilter = 'all' | 'database' | 'config' | 'admins';\n\nexport type NoticeState = {\n tone: 'success' | 'error';\n message: string;\n} | null;\n\nexport type UserModalState =\n | { type: 'create' }\n | { type: 'edit'; user: AdminUser }\n | { type: 'delete'; user: AdminUser }\n | null;\n\nexport function parseUserRole(\n value: FormDataEntryValue | null,\n): 'user' | 'admin' {\n return value === 'admin' ? 'admin' : 'user';\n}\n\nexport function getActiveQuickFilter(\n filters: ReturnType<typeof normalizeAdminUsersQuery>,\n): QuickFilter {\n if (filters.role === 'admin') return 'admins';\n if (filters.managedBy === 'database') return 'database';\n if (filters.managedBy === 'config') return 'config';\n return 'all';\n}\n","import { TRButton } from '@tinyrack/ui/components/button';\nimport { TRCheckbox } from '@tinyrack/ui/components/checkbox';\nimport { TRField } from '@tinyrack/ui/components/field';\nimport { TRInput } from '@tinyrack/ui/components/input';\nimport { TRSelect } from '@tinyrack/ui/components/select';\nimport { TRText } from '@tinyrack/ui/components/text';\nimport { CheckIcon, TriangleAlertIcon } from 'lucide-react';\nimport type { FormEvent } from 'react';\nimport { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Modal, ModalActions } from '#frontend/components/ui/modal.tsx';\nimport {\n parseUserRole,\n type UserModalState,\n} from '#frontend/features/admin/users/admin-users-filters.ts';\n\ntype AdminUserFormModalProps = {\n modal: UserModalState;\n isMutating: boolean;\n onClose: () => void;\n onCreate: (values: {\n email: string;\n password: string;\n role: 'user' | 'admin';\n email_verified: boolean;\n }) => void;\n onUpdate: (values: {\n sub: string;\n email: string;\n role: 'user' | 'admin';\n email_verified: boolean;\n }) => void;\n onDelete: (sub: string) => void;\n};\n\nexport function AdminUserFormModal({\n modal,\n isMutating,\n onClose,\n onCreate,\n onUpdate,\n onDelete,\n}: AdminUserFormModalProps) {\n const { t } = useTranslation();\n const defaultValues = useMemo(\n () => (modal?.type === 'edit' ? modal.user : null),\n [modal],\n );\n\n if (!modal) return null;\n\n if (modal.type === 'delete') {\n return (\n <Modal\n isOpen\n onClose={onClose}\n title={t('admin.users.deleteTitle', { email: modal.user.email })}\n variant=\"destructive\"\n >\n <div className=\"flex flex-col gap-tinyrack-xs rounded-tinyrack-md border border-tinyrack-danger-border bg-tinyrack-danger-surface p-tinyrack-lg text-tinyrack-danger\">\n <div className=\"flex items-center gap-tinyrack-sm\">\n <TriangleAlertIcon aria-hidden className=\"size-tinyrack-lg\" />\n <TRText as=\"p\" weight=\"medium\">\n {t('admin.users.deleteWarning')}\n </TRText>\n </div>\n <TRText as=\"p\" variant=\"bodySm\">\n {t('admin.users.deleteDescription')}\n </TRText>\n </div>\n <ModalActions>\n <TRButton\n disabled={isMutating}\n onClick={onClose}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('admin.users.cancel')}\n </TRButton>\n <TRButton\n disabled={isMutating}\n intent=\"danger\"\n onClick={() => onDelete(modal.user.sub)}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('admin.users.deleteConfirm')}\n </TRButton>\n </ModalActions>\n </Modal>\n );\n }\n\n const title =\n modal.type === 'create'\n ? t('admin.users.create')\n : t('admin.users.editTitle');\n const submit =\n modal.type === 'create'\n ? t('admin.users.createSubmit')\n : t('admin.users.save');\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const formData = new FormData(event.currentTarget);\n const values = {\n email: String(formData.get('email') ?? ''),\n role: parseUserRole(formData.get('role')),\n email_verified: formData.get('email_verified') === 'on',\n };\n if (modal.type === 'create') {\n onCreate({\n ...values,\n password: String(formData.get('password') ?? ''),\n });\n } else {\n onUpdate({ sub: modal.user.sub, ...values });\n }\n };\n\n return (\n <Modal\n description={\n modal.type === 'create'\n ? t('admin.users.createHint')\n : t('admin.users.editHint')\n }\n isOpen\n onClose={onClose}\n title={title}\n >\n <form\n className=\"mt-tinyrack-lg flex flex-col gap-tinyrack-lg\"\n onSubmit={handleSubmit}\n >\n <TRField.Root>\n <TRField.Label htmlFor=\"admin-user-email\">\n {t('profile.email.label')}\n </TRField.Label>\n <TRInput\n defaultValue={defaultValues?.email ?? ''}\n id=\"admin-user-email\"\n name=\"email\"\n required\n type=\"email\"\n uiSize=\"sm\"\n />\n </TRField.Root>\n\n {modal.type === 'create' ? (\n <TRField.Root>\n <TRField.Label htmlFor=\"admin-user-password\">\n {t('admin.users.password')}\n </TRField.Label>\n <TRInput\n id=\"admin-user-password\"\n name=\"password\"\n required\n type=\"password\"\n uiSize=\"sm\"\n />\n </TRField.Root>\n ) : null}\n\n <TRField.Root>\n <TRField.Label htmlFor=\"admin-user-role\">\n {t('admin.users.role')}\n </TRField.Label>\n <TRSelect.Root\n defaultValue={defaultValues?.role ?? 'user'}\n name=\"role\"\n >\n <TRSelect.Trigger id=\"admin-user-role\" uiSize=\"sm\">\n <TRSelect.Value />\n </TRSelect.Trigger>\n <TRSelect.Positioner>\n <TRSelect.Popup>\n <TRSelect.List>\n {['user', 'admin'].map((role) => (\n <TRSelect.Item key={role} value={role}>\n <TRSelect.ItemText>\n {t(\n `admin.users.role${role === 'user' ? 'User' : 'Admin'}`,\n )}\n </TRSelect.ItemText>\n <TRSelect.ItemIndicator>\n <CheckIcon aria-hidden />\n </TRSelect.ItemIndicator>\n </TRSelect.Item>\n ))}\n </TRSelect.List>\n </TRSelect.Popup>\n </TRSelect.Positioner>\n </TRSelect.Root>\n </TRField.Root>\n\n <TRField.Root>\n <div className=\"flex items-center gap-tinyrack-md rounded-tinyrack-md border border-tinyrack-border bg-tinyrack-surface px-tinyrack-md py-tinyrack-sm\">\n <TRCheckbox.Root\n aria-label={t('admin.users.emailVerified')}\n defaultChecked={defaultValues?.email_verified ?? false}\n name=\"email_verified\"\n uiSize=\"md\"\n value=\"on\"\n >\n <TRCheckbox.Indicator />\n </TRCheckbox.Root>\n <TRField.Label className=\"cursor-pointer\">\n {t('admin.users.emailVerified')}\n </TRField.Label>\n </div>\n </TRField.Root>\n\n <ModalActions>\n <TRButton\n disabled={isMutating}\n onClick={onClose}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('admin.users.cancel')}\n </TRButton>\n <TRButton\n disabled={isMutating}\n intent=\"primary\"\n type=\"submit\"\n uiSize=\"sm\"\n >\n {submit}\n </TRButton>\n </ModalActions>\n </form>\n </Modal>\n );\n}\n","import { TRBadge } from '@tinyrack/ui/components/badge';\nimport { TRButton } from '@tinyrack/ui/components/button';\nimport { TRSelect } from '@tinyrack/ui/components/select';\nimport { TRText } from '@tinyrack/ui/components/text';\nimport { CheckIcon } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport type { QuickFilter } from '#frontend/features/admin/users/admin-users-filters.ts';\n\ntype AdminUsersFilterBarProps = {\n pageStart: number;\n pageEnd: number;\n total: number;\n query: string;\n includeDeleted: boolean;\n activeQuickFilter: QuickFilter;\n hasActiveFilters: boolean;\n onClearFilters: () => void;\n pageSize: number;\n onPageSizeChange: (pageSize: number) => void;\n};\n\nconst PAGE_SIZES = [10, 20, 50];\n\n/** What the current result set is filtered by, and how much of it is shown. */\nexport function AdminUsersFilterBar({\n pageStart,\n pageEnd,\n total,\n query,\n includeDeleted,\n activeQuickFilter,\n hasActiveFilters,\n onClearFilters,\n pageSize,\n onPageSizeChange,\n}: AdminUsersFilterBarProps) {\n const { t } = useTranslation();\n\n return (\n <div className=\"flex flex-wrap items-center justify-between gap-tinyrack-md px-tinyrack-xl\">\n <div className=\"flex flex-wrap items-center gap-tinyrack-sm\">\n <TRText color=\"muted\" variant=\"bodySm\">\n {t('admin.users.showingRange', {\n from: pageStart,\n to: pageEnd,\n total,\n })}\n </TRText>\n {query ? (\n <TRBadge uiSize=\"md\" variant=\"neutral\">\n {t('admin.users.queryChip', { query })}\n </TRBadge>\n ) : null}\n {includeDeleted ? (\n <TRBadge uiSize=\"md\" variant=\"warning\">\n {t('admin.users.includeDeleted')}\n </TRBadge>\n ) : null}\n {activeQuickFilter !== 'all' ? (\n <TRBadge uiSize=\"md\">\n {t(`admin.users.filter.${activeQuickFilter}`)}\n </TRBadge>\n ) : null}\n {hasActiveFilters ? (\n <TRButton\n appearance=\"ghost\"\n onClick={onClearFilters}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('admin.users.clearFilters')}\n </TRButton>\n ) : null}\n </div>\n\n <div className=\"flex items-center gap-tinyrack-sm\">\n <TRText color=\"muted\" variant=\"bodySm\">\n {t('admin.users.pageSize')}\n </TRText>\n <TRSelect.Root\n onValueChange={(value) => {\n if (typeof value === 'number') onPageSizeChange(value);\n }}\n value={pageSize}\n >\n <TRSelect.Trigger aria-label={t('admin.users.pageSize')} uiSize=\"sm\">\n <TRSelect.Value />\n </TRSelect.Trigger>\n <TRSelect.Portal>\n <TRSelect.Positioner>\n <TRSelect.Popup>\n <TRSelect.List>\n {PAGE_SIZES.map((size) => (\n <TRSelect.Item key={size} value={size}>\n <TRSelect.ItemText>{size}</TRSelect.ItemText>\n <TRSelect.ItemIndicator>\n <CheckIcon />\n </TRSelect.ItemIndicator>\n </TRSelect.Item>\n ))}\n </TRSelect.List>\n </TRSelect.Popup>\n </TRSelect.Positioner>\n </TRSelect.Portal>\n </TRSelect.Root>\n </div>\n </div>\n );\n}\n","import { TRAlert } from '@tinyrack/ui/components/alert';\nimport { TRButton } from '@tinyrack/ui/components/button';\nimport { CheckIcon, TriangleAlertIcon, XIcon } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport type { NoticeState } from '#frontend/features/admin/users/admin-users-filters.ts';\n\ntype AdminUsersNoticeProps = {\n notice: NonNullable<NoticeState>;\n onDismiss: () => void;\n};\n\n/**\n * Result of the last create/update/delete.\n *\n * Stays an inline banner rather than becoming a toast now that the shell\n * mounts a viewport: Base UI renders toasts as `dialog`/`alertdialog` inside a\n * `region`, never as a live `status`, so a toast would silently drop the\n * polite announcement this makes.\n */\nexport function AdminUsersNotice({ notice, onDismiss }: AdminUsersNoticeProps) {\n const { t } = useTranslation();\n const isSuccess = notice.tone === 'success';\n\n return (\n <TRAlert.Root\n aria-live={isSuccess ? 'polite' : 'assertive'}\n role={isSuccess ? 'status' : 'alert'}\n variant={isSuccess ? 'success' : 'danger'}\n >\n {isSuccess ? (\n <CheckIcon aria-hidden className=\"size-tinyrack-xl\" />\n ) : (\n <TriangleAlertIcon aria-hidden className=\"size-tinyrack-xl\" />\n )}\n <TRAlert.Title>{notice.message}</TRAlert.Title>\n <TRButton\n appearance=\"ghost\"\n aria-label={t('common.close')}\n className=\"ms-auto\"\n onClick={onDismiss}\n type=\"button\"\n uiSize=\"sm\"\n >\n <XIcon aria-hidden className=\"size-tinyrack-lg\" />\n </TRButton>\n </TRAlert.Root>\n );\n}\n","import { useTranslation } from 'react-i18next';\nimport { AdminStat } from '#frontend/features/admin/admin-stat.tsx';\n\ntype AdminUsersSummaryProps = {\n active: number;\n config: number;\n database: number;\n};\n\n/** Counts for the page currently in view, not the whole directory. */\nexport function AdminUsersSummary({\n active,\n config,\n database,\n}: AdminUsersSummaryProps) {\n const { t } = useTranslation();\n const hint = t('admin.users.currentPage');\n\n return (\n <div className=\"flex flex-col overflow-hidden rounded-tinyrack-lg border border-tinyrack-border bg-tinyrack-surface shadow-tinyrack-raised lg:flex-row lg:divide-x lg:divide-tinyrack-border\">\n <AdminStat\n hint={hint}\n label={t('admin.users.activeOnPage')}\n value={active}\n />\n <AdminStat\n hint={hint}\n label={t('admin.users.configOnPage')}\n value={config}\n />\n <AdminStat\n hint={hint}\n label={t('admin.users.databaseOnPage')}\n value={database}\n />\n </div>\n );\n}\n","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-body.tsx\nfunction TRTableBody({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"tbody\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-body\", className)\n\t});\n}\n//#endregion\nexport { TRTableBody };\n\n//# sourceMappingURL=table-body.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-caption.tsx\nfunction TRTableCaption({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"caption\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-caption\", className)\n\t});\n}\n//#endregion\nexport { TRTableCaption };\n\n//# sourceMappingURL=table-caption.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-cell.tsx\nfunction TRTableCell({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"td\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-cell\", className)\n\t});\n}\n//#endregion\nexport { TRTableCell };\n\n//# sourceMappingURL=table-cell.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-footer.tsx\nfunction TRTableFooter({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"tfoot\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-footer\", className)\n\t});\n}\n//#endregion\nexport { TRTableFooter };\n\n//# sourceMappingURL=table-footer.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-head.tsx\nfunction TRTableHead({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"th\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-head\", className)\n\t});\n}\n//#endregion\nexport { TRTableHead };\n\n//# sourceMappingURL=table-head.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-header.tsx\nfunction TRTableHeader({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"thead\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-header\", className)\n\t});\n}\n//#endregion\nexport { TRTableHeader };\n\n//# sourceMappingURL=table-header.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-root.tsx\nfunction TRTableRoot({ className, containerClassName, containerProps, containerRef, density = \"comfortable\", striped = false, ...props }) {\n\tconst { className: containerPropsClassName, ref: containerPropsRef, ...restContainerProps } = containerProps ?? {};\n\treturn /* @__PURE__ */ jsx(\"div\", {\n\t\t...restContainerProps,\n\t\tclassName: mergeClassNames(\"tr-table-container\", containerClassName, containerPropsClassName),\n\t\tref: containerRef ?? containerPropsRef,\n\t\tchildren: /* @__PURE__ */ jsx(\"table\", {\n\t\t\t...props,\n\t\t\tclassName: mergeClassNames(\"tr-table\", className),\n\t\t\t\"data-density\": density,\n\t\t\t\"data-striped\": striped ? \"true\" : void 0\n\t\t})\n\t});\n}\n//#endregion\nexport { TRTableRoot };\n\n//# sourceMappingURL=table-root.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-row.tsx\nfunction TRTableRow({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"tr\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-row\", className)\n\t});\n}\n//#endregion\nexport { TRTableRow };\n\n//# sourceMappingURL=table-row.js.map","import { TRTableBody } from \"./table-body.js\";\nimport { TRTableCaption } from \"./table-caption.js\";\nimport { TRTableCell } from \"./table-cell.js\";\nimport { TRTableFooter } from \"./table-footer.js\";\nimport { TRTableHead } from \"./table-head.js\";\nimport { TRTableHeader } from \"./table-header.js\";\nimport { TRTableRoot } from \"./table-root.js\";\nimport { TRTableRow } from \"./table-row.js\";\n//#region src/components/table/index.tsx\nconst TRTable = {\n\tRoot: TRTableRoot,\n\tCaption: TRTableCaption,\n\tHeader: TRTableHeader,\n\tBody: TRTableBody,\n\tFooter: TRTableFooter,\n\tRow: TRTableRow,\n\tHead: TRTableHead,\n\tCell: TRTableCell\n};\n//#endregion\nexport { TRTable, TRTableBody, TRTableCaption, TRTableCell, TRTableFooter, TRTableHead, TRTableHeader, TRTableRoot, TRTableRow };\n\n//# sourceMappingURL=index.js.map","import { TRBadge } from '@tinyrack/ui/components/badge';\nimport { TRButton } from '@tinyrack/ui/components/button';\nimport { TRTable } from '@tinyrack/ui/components/table';\nimport { TRText } from '@tinyrack/ui/components/text';\nimport { useTranslation } from 'react-i18next';\nimport {\n formatAdminRole,\n formatManagedBy,\n} from '#frontend/features/admin/format-admin-user.ts';\nimport type { AdminUser } from '#frontend/queries/admin-users.ts';\n\ntype AdminUsersTableProps = {\n users: AdminUser[];\n onEdit: (user: AdminUser) => void;\n onDelete: (user: AdminUser) => void;\n};\n\nexport function AdminUsersTable({\n users,\n onEdit,\n onDelete,\n}: AdminUsersTableProps) {\n const { t } = useTranslation();\n\n return (\n <div className=\"overflow-x-auto pb-tinyrack-sm\">\n <TRTable.Root density=\"compact\" striped>\n <TRTable.Header>\n <TRTable.Row>\n <TRTable.Head>{t('profile.email.label')}</TRTable.Head>\n <TRTable.Head>{t('admin.users.role')}</TRTable.Head>\n <TRTable.Head>{t('admin.users.source')}</TRTable.Head>\n <TRTable.Head>{t('admin.users.emailVerified')}</TRTable.Head>\n <TRTable.Head>{t('admin.users.secondFactor')}</TRTable.Head>\n <TRTable.Head>{t('admin.users.status')}</TRTable.Head>\n <TRTable.Head>{t('admin.users.actions')}</TRTable.Head>\n </TRTable.Row>\n </TRTable.Header>\n <TRTable.Body>\n {users.map((managedUser) => (\n <TRTable.Row key={managedUser.sub}>\n <TRTable.Cell>\n <div className=\"flex flex-col gap-tinyrack-3xs\">\n <TRText as=\"div\" variant=\"bodySm\" weight=\"medium\">\n {managedUser.email}\n </TRText>\n {/*\n Mono on a bare span: a font utility on `TRText` loses to\n the component's own per-variant `font-family` rule.\n */}\n <TRText\n as=\"div\"\n className=\"max-w-tinyrack-measure-lg\"\n color=\"muted\"\n truncate\n variant=\"caption\"\n >\n <span className=\"font-tinyrack-mono\">\n {managedUser.sub}\n </span>\n </TRText>\n </div>\n </TRTable.Cell>\n {/*\n `whitespace-nowrap` on every badge: without it a narrow\n viewport squeezes these columns until the labels break one\n letter per line. Keeping them intact makes the table wider\n than the phone, which is what the horizontal scroller below\n is for.\n */}\n <TRTable.Cell>\n <TRBadge\n className=\"whitespace-nowrap\"\n uiSize=\"md\"\n variant={managedUser.role === 'admin' ? 'neutral' : undefined}\n >\n {formatAdminRole(t, managedUser.role)}\n </TRBadge>\n </TRTable.Cell>\n <TRTable.Cell>\n <TRBadge\n className=\"whitespace-nowrap\"\n uiSize=\"md\"\n variant={\n managedUser.managed_by === 'config' ? 'warning' : 'info'\n }\n >\n {formatManagedBy(t, managedUser.managed_by)}\n </TRBadge>\n </TRTable.Cell>\n <TRTable.Cell>\n {managedUser.email_verified ? t('common.yes') : t('common.no')}\n </TRTable.Cell>\n <TRTable.Cell>\n {managedUser.totp_registered\n ? t('admin.users.secondFactorTotp')\n : managedUser.passkey_count > 0\n ? t(\n managedUser.passkey_count === 1\n ? 'admin.users.secondFactorPasskey'\n : 'admin.users.secondFactorPasskeys',\n { count: managedUser.passkey_count },\n )\n : t('common.none')}\n </TRTable.Cell>\n <TRTable.Cell>\n {/*\n `variant` here is a test contract: the directory test reads\n `[data-variant=\"success\"]` out of the row to assert the\n status. Changing these tones breaks it.\n */}\n <TRBadge\n className=\"whitespace-nowrap\"\n uiSize=\"md\"\n variant={managedUser.deleted_at ? 'danger' : 'success'}\n >\n {managedUser.deleted_at\n ? t('admin.users.deleted')\n : t('admin.users.active')}\n </TRBadge>\n </TRTable.Cell>\n <TRTable.Cell>\n {managedUser.managed_by === 'database' &&\n !managedUser.deleted_at ? (\n <div className=\"inline-flex items-center whitespace-nowrap rounded-tinyrack-md border border-tinyrack-border bg-tinyrack-surface-muted\">\n <TRButton\n appearance=\"ghost\"\n aria-label={t('admin.users.editUser', {\n email: managedUser.email,\n })}\n onClick={() => onEdit(managedUser)}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('admin.users.edit')}\n </TRButton>\n <TRButton\n appearance=\"outline\"\n aria-label={t('admin.users.deleteUser', {\n email: managedUser.email,\n })}\n intent=\"danger\"\n onClick={() => onDelete(managedUser)}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('admin.users.delete')}\n </TRButton>\n </div>\n ) : (\n <TRBadge className=\"whitespace-nowrap\" uiSize=\"md\">\n {t('admin.users.readonly')}\n </TRBadge>\n )}\n </TRTable.Cell>\n </TRTable.Row>\n ))}\n {users.length === 0 ? (\n <TRTable.Row>\n <TRTable.Cell\n className=\"py-tinyrack-3xl text-center text-tinyrack-text-muted\"\n colSpan={7}\n >\n {t('admin.users.emptyFiltered')}\n </TRTable.Cell>\n </TRTable.Row>\n ) : null}\n </TRTable.Body>\n </TRTable.Root>\n </div>\n );\n}\n","import { TRButton } from '@tinyrack/ui/components/button';\nimport { TRCard } from '@tinyrack/ui/components/card';\nimport { TRCheckbox } from '@tinyrack/ui/components/checkbox';\nimport { TRField } from '@tinyrack/ui/components/field';\nimport { TRInput } from '@tinyrack/ui/components/input';\nimport { TRText } from '@tinyrack/ui/components/text';\nimport { PlusIcon, SearchIcon, UsersIcon } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport type { QuickFilter } from '#frontend/features/admin/users/admin-users-filters.ts';\n\ntype AdminUsersToolbarProps = {\n total: number;\n draftQuery: string;\n onDraftQueryChange: (value: string) => void;\n draftIncludeDeleted: boolean;\n onDraftIncludeDeletedChange: (value: boolean) => void;\n onSearch: () => void;\n onCreate: () => void;\n activeQuickFilter: QuickFilter;\n onQuickFilter: (filter: QuickFilter) => void;\n};\n\nconst QUICK_FILTERS: QuickFilter[] = ['all', 'database', 'config', 'admins'];\n\nexport function AdminUsersToolbar({\n total,\n draftQuery,\n onDraftQueryChange,\n draftIncludeDeleted,\n onDraftIncludeDeletedChange,\n onSearch,\n onCreate,\n activeQuickFilter,\n onQuickFilter,\n}: AdminUsersToolbarProps) {\n const { t } = useTranslation();\n\n return (\n <div className=\"flex flex-col gap-tinyrack-lg border-tinyrack-border border-b-tinyrack-default bg-tinyrack-surface-muted p-tinyrack-xl xl:flex-row xl:items-end xl:justify-between\">\n <div className=\"flex flex-col gap-tinyrack-sm\">\n <div className=\"flex items-center gap-tinyrack-sm\">\n <UsersIcon\n aria-hidden\n className=\"size-tinyrack-lg text-tinyrack-success\"\n />\n <TRText color=\"muted\" variant=\"label\">\n {t('admin.users.directoryEyebrow')}\n </TRText>\n </div>\n <TRCard.Title>{t('admin.users.directory')}</TRCard.Title>\n <TRCard.Description className=\"text-tinyrack-sm\">\n {t('admin.users.total', { count: total })}\n </TRCard.Description>\n </div>\n\n <div className=\"flex flex-col gap-tinyrack-md xl:items-end\">\n <div className=\"flex flex-col gap-tinyrack-sm lg:flex-row lg:items-center\">\n <TRInput\n aria-label={t('admin.users.searchPlaceholder')}\n className=\"w-full lg:w-tinyrack-overlay-width-sm\"\n onChange={(event) => onDraftQueryChange(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') onSearch();\n }}\n placeholder={t('admin.users.searchPlaceholder')}\n type=\"search\"\n uiSize=\"sm\"\n value={draftQuery}\n />\n\n {/*\n `aria-label` rather than relying on the label association: the\n design system's checkbox is a `button[role=checkbox]`, and the\n accessible-name path through `Field.Label` for a non-input control\n is not something to gamble a test contract on.\n */}\n <TRField.Root>\n <div className=\"flex items-center gap-tinyrack-sm rounded-tinyrack-md border border-tinyrack-border bg-tinyrack-surface px-tinyrack-md py-tinyrack-sm\">\n <TRCheckbox.Root\n aria-label={t('admin.users.includeDeleted')}\n checked={draftIncludeDeleted}\n onCheckedChange={(checked) =>\n onDraftIncludeDeletedChange(checked === true)\n }\n uiSize=\"md\"\n >\n <TRCheckbox.Indicator />\n </TRCheckbox.Root>\n <TRField.Label className=\"cursor-pointer\">\n {t('admin.users.includeDeleted')}\n </TRField.Label>\n </div>\n </TRField.Root>\n\n <TRButton\n appearance=\"outline\"\n onClick={onSearch}\n type=\"button\"\n uiSize=\"sm\"\n >\n <SearchIcon aria-hidden className=\"size-tinyrack-lg\" />\n {t('admin.users.search')}\n </TRButton>\n <TRButton\n intent=\"primary\"\n onClick={onCreate}\n type=\"button\"\n uiSize=\"sm\"\n >\n <PlusIcon aria-hidden className=\"size-tinyrack-lg\" />\n {t('admin.users.create')}\n </TRButton>\n </div>\n\n <div className=\"inline-flex items-center gap-tinyrack-3xs rounded-tinyrack-md border border-tinyrack-border bg-tinyrack-surface-muted p-tinyrack-xs\">\n {QUICK_FILTERS.map((filter) => (\n <TRButton\n appearance={activeQuickFilter === filter ? 'solid' : 'ghost'}\n intent={activeQuickFilter === filter ? 'primary' : undefined}\n key={filter}\n onClick={() => onQuickFilter(filter)}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t(`admin.users.filter.${filter}`)}\n </TRButton>\n ))}\n </div>\n </div>\n </div>\n );\n}\n","import {\n useMutation,\n useQueryClient,\n useSuspenseQuery,\n} from '@tanstack/react-query';\nimport { createFileRoute, redirect } from '@tanstack/react-router';\nimport { TRBadge } from '@tinyrack/ui/components/badge';\nimport { TRButton } from '@tinyrack/ui/components/button';\nimport { TRCard } from '@tinyrack/ui/components/card';\nimport { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { AdminGateScreen } from '#frontend/features/admin/admin-gate-screen.tsx';\nimport { AdminShell } from '#frontend/features/admin/admin-shell.tsx';\nimport { AdminUserFormModal } from '#frontend/features/admin/users/admin-user-form-modal.tsx';\nimport { AdminUsersFilterBar } from '#frontend/features/admin/users/admin-users-filter-bar.tsx';\nimport {\n getActiveQuickFilter,\n type NoticeState,\n type QuickFilter,\n type UserModalState,\n} from '#frontend/features/admin/users/admin-users-filters.ts';\nimport { AdminUsersNotice } from '#frontend/features/admin/users/admin-users-notice.tsx';\nimport { AdminUsersSummary } from '#frontend/features/admin/users/admin-users-summary.tsx';\nimport { AdminUsersTable } from '#frontend/features/admin/users/admin-users-table.tsx';\nimport { AdminUsersToolbar } from '#frontend/features/admin/users/admin-users-toolbar.tsx';\nimport {\n adminUsersQueryOptions,\n createAdminUser,\n deleteAdminUser,\n normalizeAdminUsersQuery,\n updateAdminUser,\n} from '#frontend/queries/admin-users.ts';\nimport { appConfigQueryOptions } from '#frontend/queries/config.ts';\nimport type { SessionUser } from '#frontend/queries/session.ts';\n\nexport const Route = createFileRoute('/admin/users/')({\n component: AdminUsersPage,\n beforeLoad: async ({ context }) => {\n if (!context.user) {\n throw redirect({ to: '/login' });\n }\n },\n});\n\nfunction AdminUsersPage() {\n const user = Route.useRouteContext({ select: (context) => context.user });\n\n if (user?.role !== 'admin') {\n return <AdminGateScreen reason=\"access-required\" />;\n }\n\n return <AdminUsersGate user={user} />;\n}\n\nfunction AdminUsersGate({ user }: { user: SessionUser }) {\n const { data: config } = useSuspenseQuery(appConfigQueryOptions);\n if (!config.admin.enabled) {\n return <AdminGateScreen reason=\"console-disabled\" />;\n }\n return <AdminUsersContent user={user} />;\n}\n\nfunction AdminUsersContent({ user }: { user: SessionUser }) {\n const { t } = useTranslation();\n const queryClient = useQueryClient();\n const [draftQuery, setDraftQuery] = useState('');\n const [draftIncludeDeleted, setDraftIncludeDeleted] = useState(false);\n const [filters, setFilters] = useState(() => normalizeAdminUsersQuery());\n const [notice, setNotice] = useState<NoticeState>(null);\n const [modal, setModal] = useState<UserModalState>(null);\n const { data } = useSuspenseQuery(adminUsersQueryOptions(filters));\n\n const activeUsers = data.users.filter(\n (managedUser) => !managedUser.deleted_at,\n ).length;\n const configUsers = data.users.filter(\n (managedUser) => managedUser.managed_by === 'config',\n ).length;\n const databaseUsers = data.users.filter(\n (managedUser) => managedUser.managed_by === 'database',\n ).length;\n const activeQuickFilter = getActiveQuickFilter(filters);\n const hasActiveFilters =\n filters.query !== '' ||\n filters.includeDeleted ||\n filters.managedBy !== undefined ||\n filters.role !== undefined;\n const pageStart =\n data.pagination.total === 0\n ? 0\n : (data.pagination.page - 1) * data.pagination.page_size + 1;\n const pageEnd = Math.min(\n data.pagination.page * data.pagination.page_size,\n data.pagination.total,\n );\n\n const noticeOn = (message: string) => setNotice({ tone: 'success', message });\n const noticeFail = () =>\n setNotice({ tone: 'error', message: t('admin.users.operationFailed') });\n\n const createMutation = useMutation({\n mutationFn: createAdminUser,\n onSuccess: ({ user: nextUser }) => {\n void queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });\n noticeOn(t('admin.users.createdNotice', { email: nextUser.email }));\n setModal(null);\n },\n onError: noticeFail,\n });\n\n const updateMutation = useMutation({\n mutationFn: updateAdminUser,\n onSuccess: ({ user: nextUser }) => {\n void queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });\n noticeOn(t('admin.users.updatedNotice', { email: nextUser.email }));\n setModal(null);\n },\n onError: noticeFail,\n });\n\n const deleteMutation = useMutation({\n mutationFn: deleteAdminUser,\n onSuccess: ({ user: nextUser }) => {\n void queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });\n noticeOn(t('admin.users.deletedNotice', { email: nextUser.email }));\n setModal(null);\n },\n onError: noticeFail,\n });\n\n const isMutating =\n createMutation.isPending ||\n updateMutation.isPending ||\n deleteMutation.isPending;\n\n const applySearch = () => {\n setFilters((current) => ({\n ...current,\n query: draftQuery.trim(),\n includeDeleted: draftIncludeDeleted,\n page: 1,\n }));\n };\n\n const clearFilters = () => {\n setDraftQuery('');\n setDraftIncludeDeleted(false);\n setFilters(normalizeAdminUsersQuery());\n };\n\n const applyQuickFilter = (nextFilter: QuickFilter) => {\n setFilters((current) => ({\n ...current,\n page: 1,\n managedBy:\n nextFilter === 'database'\n ? 'database'\n : nextFilter === 'config'\n ? 'config'\n : undefined,\n role: nextFilter === 'admins' ? 'admin' : undefined,\n }));\n };\n\n return (\n <AdminShell\n current=\"users\"\n description={t('admin.users.description')}\n title={t('admin.users.title')}\n user={user}\n >\n <AdminUsersSummary\n active={activeUsers}\n config={configUsers}\n database={databaseUsers}\n />\n\n {notice ? (\n <AdminUsersNotice notice={notice} onDismiss={() => setNotice(null)} />\n ) : null}\n\n <TRCard.Root\n className=\"overflow-hidden shadow-tinyrack-raised\"\n data-testid=\"admin-users-directory\"\n variant=\"outlined\"\n >\n <TRCard.Content className=\"gap-tinyrack-lg p-0\">\n <AdminUsersToolbar\n activeQuickFilter={activeQuickFilter}\n draftIncludeDeleted={draftIncludeDeleted}\n draftQuery={draftQuery}\n onCreate={() => setModal({ type: 'create' })}\n onDraftIncludeDeletedChange={setDraftIncludeDeleted}\n onDraftQueryChange={setDraftQuery}\n onQuickFilter={applyQuickFilter}\n onSearch={applySearch}\n total={data.pagination.total}\n />\n\n <AdminUsersFilterBar\n activeQuickFilter={activeQuickFilter}\n hasActiveFilters={hasActiveFilters}\n includeDeleted={filters.includeDeleted}\n onClearFilters={clearFilters}\n onPageSizeChange={(pageSize) =>\n setFilters((current) => ({ ...current, page: 1, pageSize }))\n }\n pageEnd={pageEnd}\n pageSize={filters.pageSize}\n pageStart={pageStart}\n query={filters.query}\n total={data.pagination.total}\n />\n\n <AdminUsersTable\n onDelete={(managedUser) =>\n setModal({ type: 'delete', user: managedUser })\n }\n onEdit={(managedUser) =>\n setModal({ type: 'edit', user: managedUser })\n }\n users={data.users}\n />\n\n <div className=\"flex items-center justify-between border-tinyrack-border border-t-tinyrack-default bg-tinyrack-surface-muted p-tinyrack-lg\">\n <TRButton\n appearance=\"outline\"\n disabled={filters.page <= 1}\n onClick={() =>\n setFilters((current) => ({\n ...current,\n page: current.page - 1,\n }))\n }\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('admin.users.previous')}\n </TRButton>\n <TRBadge uiSize=\"md\">\n {t('admin.users.page', { page: data.pagination.page })}\n </TRBadge>\n <TRButton\n appearance=\"outline\"\n disabled={\n data.pagination.page * data.pagination.page_size >=\n data.pagination.total\n }\n onClick={() =>\n setFilters((current) => ({\n ...current,\n page: current.page + 1,\n }))\n }\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('admin.users.next')}\n </TRButton>\n </div>\n </TRCard.Content>\n </TRCard.Root>\n\n <AdminUserFormModal\n isMutating={isMutating}\n modal={modal}\n onClose={() => setModal(null)}\n onCreate={(values) => createMutation.mutate(values)}\n onDelete={(sub) => deleteMutation.mutate(sub)}\n onUpdate={(values) => updateMutation.mutate(values)}\n />\n </AdminShell>\n );\n}\n"],"x_google_ignoreList":[0,6,7,8,9,10,11,12,13,14],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"users-CmFxrCQT.js","names":["useMutation","useQueryClient","useSuspenseQuery","TRBadge","TRButton","TRCard","useState","useTranslation","AdminGateScreen","AdminShell","AdminUserFormModal","AdminUsersFilterBar","getActiveQuickFilter","AdminUsersNotice","AdminUsersSummary","AdminUsersTable","AdminUsersToolbar","adminUsersQueryOptions","createAdminUser","deleteAdminUser","normalizeAdminUsersQuery","updateAdminUser","appConfigQueryOptions","Route","AdminUsersPage","user","useRouteContext","select","context","role","AdminUsersGate","SessionUser","data","config","admin","enabled","AdminUsersContent","t","queryClient","draftQuery","setDraftQuery","draftIncludeDeleted","setDraftIncludeDeleted","filters","setFilters","notice","setNotice","NoticeState","modal","setModal","UserModalState","activeUsers","users","filter","managedUser","deleted_at","length","configUsers","managed_by","databaseUsers","activeQuickFilter","hasActiveFilters","query","includeDeleted","managedBy","undefined","pageStart","pagination","total","page","page_size","pageEnd","Math","min","noticeOn","message","tone","noticeFail","createMutation","mutationFn","onSuccess","nextUser","invalidateQueries","queryKey","email","onError","updateMutation","deleteMutation","isMutating","isPending","applySearch","current","trim","clearFilters","applyQuickFilter","nextFilter","QuickFilter","type","pageSize","values","mutate","sub","component"],"sources":["../../../../node_modules/.pnpm/lucide-react@1.25.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/search.mjs","../../../frontend/src/features/admin/users/admin-users-filters.ts","../../../frontend/src/features/admin/users/admin-user-form-modal.tsx","../../../frontend/src/features/admin/users/admin-users-filter-bar.tsx","../../../frontend/src/features/admin/users/admin-users-notice.tsx","../../../frontend/src/features/admin/users/admin-users-summary.tsx","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-body.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-caption.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-cell.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-footer.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-head.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-header.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-root.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/table-row.js","../../../../node_modules/.pnpm/@tinyrack+ui@0.25.0_@types+react@19.2.17_react-dom@19.2.7_react@19.2.7__react@19.2.7_shiki@4.3.1_tailwindcss@4.3.2/node_modules/@tinyrack/ui/dist/components/table/index.js","../../../frontend/src/features/admin/users/admin-users-table.tsx","../../../frontend/src/features/admin/users/admin-users-toolbar.tsx","../../../frontend/src/routes/admin/users/index.tsx?tsr-split=component"],"sourcesContent":["/**\n * @license lucide-react v1.25.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"m21 21-4.34-4.34\", key: \"14j7rj\" }],\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"8\", key: \"4ej97u\" }]\n];\nconst Search = createLucideIcon(\"search\", __iconNode);\n\nexport { __iconNode, Search as default };\n//# sourceMappingURL=search.mjs.map\n","import type {\n AdminUser,\n normalizeAdminUsersQuery,\n} from '#frontend/queries/admin-users.ts';\n\nexport type QuickFilter = 'all' | 'database' | 'config' | 'admins';\n\nexport type NoticeState = {\n tone: 'success' | 'error';\n message: string;\n} | null;\n\nexport type UserModalState =\n | { type: 'create' }\n | { type: 'edit'; user: AdminUser }\n | { type: 'delete'; user: AdminUser }\n | null;\n\nexport function parseUserRole(\n value: FormDataEntryValue | null,\n): 'user' | 'admin' {\n return value === 'admin' ? 'admin' : 'user';\n}\n\nexport function getActiveQuickFilter(\n filters: ReturnType<typeof normalizeAdminUsersQuery>,\n): QuickFilter {\n if (filters.role === 'admin') return 'admins';\n if (filters.managedBy === 'database') return 'database';\n if (filters.managedBy === 'config') return 'config';\n return 'all';\n}\n","import { TRButton } from '@tinyrack/ui/components/button';\nimport { TRCheckbox } from '@tinyrack/ui/components/checkbox';\nimport { TRField } from '@tinyrack/ui/components/field';\nimport { TRInput } from '@tinyrack/ui/components/input';\nimport { TRSelect } from '@tinyrack/ui/components/select';\nimport { TRText } from '@tinyrack/ui/components/text';\nimport { CheckIcon, TriangleAlertIcon } from 'lucide-react';\nimport type { FormEvent } from 'react';\nimport { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Modal, ModalActions } from '#frontend/components/ui/modal.tsx';\nimport {\n parseUserRole,\n type UserModalState,\n} from '#frontend/features/admin/users/admin-users-filters.ts';\n\ntype AdminUserFormModalProps = {\n modal: UserModalState;\n isMutating: boolean;\n onClose: () => void;\n onCreate: (values: {\n email: string;\n password: string;\n role: 'user' | 'admin';\n email_verified: boolean;\n }) => void;\n onUpdate: (values: {\n sub: string;\n email: string;\n role: 'user' | 'admin';\n email_verified: boolean;\n }) => void;\n onDelete: (sub: string) => void;\n};\n\nexport function AdminUserFormModal({\n modal,\n isMutating,\n onClose,\n onCreate,\n onUpdate,\n onDelete,\n}: AdminUserFormModalProps) {\n const { t } = useTranslation();\n const defaultValues = useMemo(\n () => (modal?.type === 'edit' ? modal.user : null),\n [modal],\n );\n\n if (!modal) return null;\n\n if (modal.type === 'delete') {\n return (\n <Modal\n isOpen\n onClose={onClose}\n title={t('admin.users.deleteTitle', { email: modal.user.email })}\n variant=\"destructive\"\n >\n <div className=\"flex flex-col gap-tinyrack-xs rounded-tinyrack-md border border-tinyrack-danger-border bg-tinyrack-danger-surface p-tinyrack-lg text-tinyrack-danger\">\n <div className=\"flex items-center gap-tinyrack-sm\">\n <TriangleAlertIcon aria-hidden className=\"size-tinyrack-lg\" />\n <TRText as=\"p\" weight=\"medium\">\n {t('admin.users.deleteWarning')}\n </TRText>\n </div>\n <TRText as=\"p\" variant=\"bodySm\">\n {t('admin.users.deleteDescription')}\n </TRText>\n </div>\n <ModalActions>\n <TRButton\n disabled={isMutating}\n onClick={onClose}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('admin.users.cancel')}\n </TRButton>\n <TRButton\n disabled={isMutating}\n intent=\"danger\"\n onClick={() => onDelete(modal.user.sub)}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('admin.users.deleteConfirm')}\n </TRButton>\n </ModalActions>\n </Modal>\n );\n }\n\n const title =\n modal.type === 'create'\n ? t('admin.users.create')\n : t('admin.users.editTitle');\n const submit =\n modal.type === 'create'\n ? t('admin.users.createSubmit')\n : t('admin.users.save');\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const formData = new FormData(event.currentTarget);\n const values = {\n email: String(formData.get('email') ?? ''),\n role: parseUserRole(formData.get('role')),\n email_verified: formData.get('email_verified') === 'on',\n };\n if (modal.type === 'create') {\n onCreate({\n ...values,\n password: String(formData.get('password') ?? ''),\n });\n } else {\n onUpdate({ sub: modal.user.sub, ...values });\n }\n };\n\n return (\n <Modal\n description={\n modal.type === 'create'\n ? t('admin.users.createHint')\n : t('admin.users.editHint')\n }\n isOpen\n onClose={onClose}\n title={title}\n >\n <form\n className=\"mt-tinyrack-lg flex flex-col gap-tinyrack-lg\"\n onSubmit={handleSubmit}\n >\n <TRField.Root>\n <TRField.Label htmlFor=\"admin-user-email\">\n {t('profile.email.label')}\n </TRField.Label>\n <TRInput\n defaultValue={defaultValues?.email ?? ''}\n id=\"admin-user-email\"\n name=\"email\"\n required\n type=\"email\"\n uiSize=\"sm\"\n />\n </TRField.Root>\n\n {modal.type === 'create' ? (\n <TRField.Root>\n <TRField.Label htmlFor=\"admin-user-password\">\n {t('admin.users.password')}\n </TRField.Label>\n <TRInput\n id=\"admin-user-password\"\n name=\"password\"\n required\n type=\"password\"\n uiSize=\"sm\"\n />\n </TRField.Root>\n ) : null}\n\n <TRField.Root>\n <TRField.Label htmlFor=\"admin-user-role\">\n {t('admin.users.role')}\n </TRField.Label>\n <TRSelect.Root\n defaultValue={defaultValues?.role ?? 'user'}\n name=\"role\"\n >\n <TRSelect.Trigger id=\"admin-user-role\" uiSize=\"sm\">\n <TRSelect.Value />\n </TRSelect.Trigger>\n <TRSelect.Positioner>\n <TRSelect.Popup>\n <TRSelect.List>\n {['user', 'admin'].map((role) => (\n <TRSelect.Item key={role} value={role}>\n <TRSelect.ItemText>\n {t(\n `admin.users.role${role === 'user' ? 'User' : 'Admin'}`,\n )}\n </TRSelect.ItemText>\n <TRSelect.ItemIndicator>\n <CheckIcon aria-hidden />\n </TRSelect.ItemIndicator>\n </TRSelect.Item>\n ))}\n </TRSelect.List>\n </TRSelect.Popup>\n </TRSelect.Positioner>\n </TRSelect.Root>\n </TRField.Root>\n\n <TRField.Root>\n <div className=\"flex items-center gap-tinyrack-md rounded-tinyrack-md border border-tinyrack-border bg-tinyrack-surface px-tinyrack-md py-tinyrack-sm\">\n <TRCheckbox.Root\n aria-label={t('admin.users.emailVerified')}\n defaultChecked={defaultValues?.email_verified ?? false}\n name=\"email_verified\"\n uiSize=\"md\"\n value=\"on\"\n >\n <TRCheckbox.Indicator />\n </TRCheckbox.Root>\n <TRField.Label className=\"cursor-pointer\">\n {t('admin.users.emailVerified')}\n </TRField.Label>\n </div>\n </TRField.Root>\n\n <ModalActions>\n <TRButton\n disabled={isMutating}\n onClick={onClose}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('admin.users.cancel')}\n </TRButton>\n <TRButton\n disabled={isMutating}\n intent=\"primary\"\n type=\"submit\"\n uiSize=\"sm\"\n >\n {submit}\n </TRButton>\n </ModalActions>\n </form>\n </Modal>\n );\n}\n","import { TRBadge } from '@tinyrack/ui/components/badge';\nimport { TRButton } from '@tinyrack/ui/components/button';\nimport { TRSelect } from '@tinyrack/ui/components/select';\nimport { TRText } from '@tinyrack/ui/components/text';\nimport { CheckIcon } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport type { QuickFilter } from '#frontend/features/admin/users/admin-users-filters.ts';\n\ntype AdminUsersFilterBarProps = {\n pageStart: number;\n pageEnd: number;\n total: number;\n query: string;\n includeDeleted: boolean;\n activeQuickFilter: QuickFilter;\n hasActiveFilters: boolean;\n onClearFilters: () => void;\n pageSize: number;\n onPageSizeChange: (pageSize: number) => void;\n};\n\nconst PAGE_SIZES = [10, 20, 50];\n\n/** What the current result set is filtered by, and how much of it is shown. */\nexport function AdminUsersFilterBar({\n pageStart,\n pageEnd,\n total,\n query,\n includeDeleted,\n activeQuickFilter,\n hasActiveFilters,\n onClearFilters,\n pageSize,\n onPageSizeChange,\n}: AdminUsersFilterBarProps) {\n const { t } = useTranslation();\n\n return (\n <div className=\"flex flex-wrap items-center justify-between gap-tinyrack-md px-tinyrack-xl\">\n <div className=\"flex flex-wrap items-center gap-tinyrack-sm\">\n <TRText color=\"muted\" variant=\"bodySm\">\n {t('admin.users.showingRange', {\n from: pageStart,\n to: pageEnd,\n total,\n })}\n </TRText>\n {query ? (\n <TRBadge uiSize=\"md\" variant=\"neutral\">\n {t('admin.users.queryChip', { query })}\n </TRBadge>\n ) : null}\n {includeDeleted ? (\n <TRBadge uiSize=\"md\" variant=\"warning\">\n {t('admin.users.includeDeleted')}\n </TRBadge>\n ) : null}\n {activeQuickFilter !== 'all' ? (\n <TRBadge uiSize=\"md\">\n {t(`admin.users.filter.${activeQuickFilter}`)}\n </TRBadge>\n ) : null}\n {hasActiveFilters ? (\n <TRButton\n appearance=\"ghost\"\n onClick={onClearFilters}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('admin.users.clearFilters')}\n </TRButton>\n ) : null}\n </div>\n\n <div className=\"flex items-center gap-tinyrack-sm\">\n <TRText color=\"muted\" variant=\"bodySm\">\n {t('admin.users.pageSize')}\n </TRText>\n <TRSelect.Root\n onValueChange={(value) => {\n if (typeof value === 'number') onPageSizeChange(value);\n }}\n value={pageSize}\n >\n <TRSelect.Trigger aria-label={t('admin.users.pageSize')} uiSize=\"sm\">\n <TRSelect.Value />\n </TRSelect.Trigger>\n <TRSelect.Portal>\n <TRSelect.Positioner>\n <TRSelect.Popup>\n <TRSelect.List>\n {PAGE_SIZES.map((size) => (\n <TRSelect.Item key={size} value={size}>\n <TRSelect.ItemText>{size}</TRSelect.ItemText>\n <TRSelect.ItemIndicator>\n <CheckIcon />\n </TRSelect.ItemIndicator>\n </TRSelect.Item>\n ))}\n </TRSelect.List>\n </TRSelect.Popup>\n </TRSelect.Positioner>\n </TRSelect.Portal>\n </TRSelect.Root>\n </div>\n </div>\n );\n}\n","import { TRAlert } from '@tinyrack/ui/components/alert';\nimport { TRButton } from '@tinyrack/ui/components/button';\nimport { CheckIcon, TriangleAlertIcon, XIcon } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport type { NoticeState } from '#frontend/features/admin/users/admin-users-filters.ts';\n\ntype AdminUsersNoticeProps = {\n notice: NonNullable<NoticeState>;\n onDismiss: () => void;\n};\n\n/**\n * Result of the last create/update/delete.\n *\n * Stays an inline banner rather than becoming a toast now that the shell\n * mounts a viewport: Base UI renders toasts as `dialog`/`alertdialog` inside a\n * `region`, never as a live `status`, so a toast would silently drop the\n * polite announcement this makes.\n */\nexport function AdminUsersNotice({ notice, onDismiss }: AdminUsersNoticeProps) {\n const { t } = useTranslation();\n const isSuccess = notice.tone === 'success';\n\n return (\n <TRAlert.Root\n aria-live={isSuccess ? 'polite' : 'assertive'}\n role={isSuccess ? 'status' : 'alert'}\n variant={isSuccess ? 'success' : 'danger'}\n >\n {isSuccess ? (\n <CheckIcon aria-hidden className=\"size-tinyrack-xl\" />\n ) : (\n <TriangleAlertIcon aria-hidden className=\"size-tinyrack-xl\" />\n )}\n <TRAlert.Title>{notice.message}</TRAlert.Title>\n <TRButton\n appearance=\"ghost\"\n aria-label={t('common.close')}\n className=\"ms-auto\"\n onClick={onDismiss}\n type=\"button\"\n uiSize=\"sm\"\n >\n <XIcon aria-hidden className=\"size-tinyrack-lg\" />\n </TRButton>\n </TRAlert.Root>\n );\n}\n","import { useTranslation } from 'react-i18next';\nimport { AdminStat } from '#frontend/features/admin/admin-stat.tsx';\n\ntype AdminUsersSummaryProps = {\n active: number;\n config: number;\n database: number;\n};\n\n/** Counts for the page currently in view, not the whole directory. */\nexport function AdminUsersSummary({\n active,\n config,\n database,\n}: AdminUsersSummaryProps) {\n const { t } = useTranslation();\n const hint = t('admin.users.currentPage');\n\n return (\n <div className=\"flex flex-col overflow-hidden rounded-tinyrack-lg border border-tinyrack-border bg-tinyrack-surface shadow-tinyrack-raised lg:flex-row lg:divide-x lg:divide-tinyrack-border\">\n <AdminStat\n hint={hint}\n label={t('admin.users.activeOnPage')}\n value={active}\n />\n <AdminStat\n hint={hint}\n label={t('admin.users.configOnPage')}\n value={config}\n />\n <AdminStat\n hint={hint}\n label={t('admin.users.databaseOnPage')}\n value={database}\n />\n </div>\n );\n}\n","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-body.tsx\nfunction TRTableBody({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"tbody\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-body\", className)\n\t});\n}\n//#endregion\nexport { TRTableBody };\n\n//# sourceMappingURL=table-body.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-caption.tsx\nfunction TRTableCaption({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"caption\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-caption\", className)\n\t});\n}\n//#endregion\nexport { TRTableCaption };\n\n//# sourceMappingURL=table-caption.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-cell.tsx\nfunction TRTableCell({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"td\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-cell\", className)\n\t});\n}\n//#endregion\nexport { TRTableCell };\n\n//# sourceMappingURL=table-cell.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-footer.tsx\nfunction TRTableFooter({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"tfoot\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-footer\", className)\n\t});\n}\n//#endregion\nexport { TRTableFooter };\n\n//# sourceMappingURL=table-footer.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-head.tsx\nfunction TRTableHead({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"th\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-head\", className)\n\t});\n}\n//#endregion\nexport { TRTableHead };\n\n//# sourceMappingURL=table-head.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-header.tsx\nfunction TRTableHeader({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"thead\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-header\", className)\n\t});\n}\n//#endregion\nexport { TRTableHeader };\n\n//# sourceMappingURL=table-header.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-root.tsx\nfunction TRTableRoot({ className, containerClassName, containerProps, containerRef, density = \"comfortable\", striped = false, ...props }) {\n\tconst { className: containerPropsClassName, ref: containerPropsRef, ...restContainerProps } = containerProps ?? {};\n\treturn /* @__PURE__ */ jsx(\"div\", {\n\t\t...restContainerProps,\n\t\tclassName: mergeClassNames(\"tr-table-container\", containerClassName, containerPropsClassName),\n\t\tref: containerRef ?? containerPropsRef,\n\t\tchildren: /* @__PURE__ */ jsx(\"table\", {\n\t\t\t...props,\n\t\t\tclassName: mergeClassNames(\"tr-table\", className),\n\t\t\t\"data-density\": density,\n\t\t\t\"data-striped\": striped ? \"true\" : void 0\n\t\t})\n\t});\n}\n//#endregion\nexport { TRTableRoot };\n\n//# sourceMappingURL=table-root.js.map","import { mergeClassNames } from \"../../internal/component-class-name.js\";\nimport { jsx } from \"react/jsx-runtime\";\n//#region src/components/table/table-row.tsx\nfunction TRTableRow({ className, ...props }) {\n\treturn /* @__PURE__ */ jsx(\"tr\", {\n\t\t...props,\n\t\tclassName: mergeClassNames(\"tr-table-row\", className)\n\t});\n}\n//#endregion\nexport { TRTableRow };\n\n//# sourceMappingURL=table-row.js.map","import { TRTableBody } from \"./table-body.js\";\nimport { TRTableCaption } from \"./table-caption.js\";\nimport { TRTableCell } from \"./table-cell.js\";\nimport { TRTableFooter } from \"./table-footer.js\";\nimport { TRTableHead } from \"./table-head.js\";\nimport { TRTableHeader } from \"./table-header.js\";\nimport { TRTableRoot } from \"./table-root.js\";\nimport { TRTableRow } from \"./table-row.js\";\n//#region src/components/table/index.tsx\nconst TRTable = {\n\tRoot: TRTableRoot,\n\tCaption: TRTableCaption,\n\tHeader: TRTableHeader,\n\tBody: TRTableBody,\n\tFooter: TRTableFooter,\n\tRow: TRTableRow,\n\tHead: TRTableHead,\n\tCell: TRTableCell\n};\n//#endregion\nexport { TRTable, TRTableBody, TRTableCaption, TRTableCell, TRTableFooter, TRTableHead, TRTableHeader, TRTableRoot, TRTableRow };\n\n//# sourceMappingURL=index.js.map","import { TRBadge } from '@tinyrack/ui/components/badge';\nimport { TRButton } from '@tinyrack/ui/components/button';\nimport { TRTable } from '@tinyrack/ui/components/table';\nimport { TRText } from '@tinyrack/ui/components/text';\nimport { useTranslation } from 'react-i18next';\nimport {\n formatAdminRole,\n formatManagedBy,\n} from '#frontend/features/admin/format-admin-user.ts';\nimport type { AdminUser } from '#frontend/queries/admin-users.ts';\n\ntype AdminUsersTableProps = {\n users: AdminUser[];\n onEdit: (user: AdminUser) => void;\n onDelete: (user: AdminUser) => void;\n};\n\nexport function AdminUsersTable({\n users,\n onEdit,\n onDelete,\n}: AdminUsersTableProps) {\n const { t } = useTranslation();\n\n return (\n <div className=\"overflow-x-auto pb-tinyrack-sm\">\n <TRTable.Root density=\"compact\" striped>\n <TRTable.Header>\n <TRTable.Row>\n <TRTable.Head>{t('profile.email.label')}</TRTable.Head>\n <TRTable.Head>{t('admin.users.role')}</TRTable.Head>\n <TRTable.Head>{t('admin.users.source')}</TRTable.Head>\n <TRTable.Head>{t('admin.users.emailVerified')}</TRTable.Head>\n <TRTable.Head>{t('admin.users.secondFactor')}</TRTable.Head>\n <TRTable.Head>{t('admin.users.status')}</TRTable.Head>\n <TRTable.Head>{t('admin.users.actions')}</TRTable.Head>\n </TRTable.Row>\n </TRTable.Header>\n <TRTable.Body>\n {users.map((managedUser) => (\n <TRTable.Row key={managedUser.sub}>\n <TRTable.Cell>\n <div className=\"flex flex-col gap-tinyrack-3xs\">\n <TRText as=\"div\" variant=\"bodySm\" weight=\"medium\">\n {managedUser.email}\n </TRText>\n {/*\n Mono on a bare span: a font utility on `TRText` loses to\n the component's own per-variant `font-family` rule.\n */}\n <TRText\n as=\"div\"\n className=\"max-w-tinyrack-measure-lg\"\n color=\"muted\"\n truncate\n variant=\"caption\"\n >\n <span className=\"font-tinyrack-mono\">\n {managedUser.sub}\n </span>\n </TRText>\n </div>\n </TRTable.Cell>\n {/*\n `whitespace-nowrap` on every badge: without it a narrow\n viewport squeezes these columns until the labels break one\n letter per line. Keeping them intact makes the table wider\n than the phone, which is what the horizontal scroller below\n is for.\n */}\n <TRTable.Cell>\n <TRBadge\n className=\"whitespace-nowrap\"\n uiSize=\"md\"\n variant={managedUser.role === 'admin' ? 'neutral' : undefined}\n >\n {formatAdminRole(t, managedUser.role)}\n </TRBadge>\n </TRTable.Cell>\n <TRTable.Cell>\n <TRBadge\n className=\"whitespace-nowrap\"\n uiSize=\"md\"\n variant={\n managedUser.managed_by === 'config' ? 'warning' : 'info'\n }\n >\n {formatManagedBy(t, managedUser.managed_by)}\n </TRBadge>\n </TRTable.Cell>\n <TRTable.Cell>\n {managedUser.email_verified ? t('common.yes') : t('common.no')}\n </TRTable.Cell>\n <TRTable.Cell>\n {managedUser.totp_registered\n ? t('admin.users.secondFactorTotp')\n : managedUser.passkey_count > 0\n ? t(\n managedUser.passkey_count === 1\n ? 'admin.users.secondFactorPasskey'\n : 'admin.users.secondFactorPasskeys',\n { count: managedUser.passkey_count },\n )\n : t('common.none')}\n </TRTable.Cell>\n <TRTable.Cell>\n {/*\n `variant` here is a test contract: the directory test reads\n `[data-variant=\"success\"]` out of the row to assert the\n status. Changing these tones breaks it.\n */}\n <TRBadge\n className=\"whitespace-nowrap\"\n uiSize=\"md\"\n variant={managedUser.deleted_at ? 'danger' : 'success'}\n >\n {managedUser.deleted_at\n ? t('admin.users.deleted')\n : t('admin.users.active')}\n </TRBadge>\n </TRTable.Cell>\n <TRTable.Cell>\n {managedUser.managed_by === 'database' &&\n !managedUser.deleted_at ? (\n <div className=\"inline-flex items-center whitespace-nowrap rounded-tinyrack-md border border-tinyrack-border bg-tinyrack-surface-muted\">\n <TRButton\n appearance=\"ghost\"\n aria-label={t('admin.users.editUser', {\n email: managedUser.email,\n })}\n onClick={() => onEdit(managedUser)}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('admin.users.edit')}\n </TRButton>\n <TRButton\n appearance=\"outline\"\n aria-label={t('admin.users.deleteUser', {\n email: managedUser.email,\n })}\n intent=\"danger\"\n onClick={() => onDelete(managedUser)}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('admin.users.delete')}\n </TRButton>\n </div>\n ) : (\n <TRBadge className=\"whitespace-nowrap\" uiSize=\"md\">\n {t('admin.users.readonly')}\n </TRBadge>\n )}\n </TRTable.Cell>\n </TRTable.Row>\n ))}\n {users.length === 0 ? (\n <TRTable.Row>\n <TRTable.Cell\n className=\"py-tinyrack-3xl text-center text-tinyrack-text-muted\"\n colSpan={7}\n >\n {t('admin.users.emptyFiltered')}\n </TRTable.Cell>\n </TRTable.Row>\n ) : null}\n </TRTable.Body>\n </TRTable.Root>\n </div>\n );\n}\n","import { TRButton } from '@tinyrack/ui/components/button';\nimport { TRCard } from '@tinyrack/ui/components/card';\nimport { TRCheckbox } from '@tinyrack/ui/components/checkbox';\nimport { TRField } from '@tinyrack/ui/components/field';\nimport { TRInput } from '@tinyrack/ui/components/input';\nimport { TRText } from '@tinyrack/ui/components/text';\nimport { PlusIcon, SearchIcon, UsersIcon } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport type { QuickFilter } from '#frontend/features/admin/users/admin-users-filters.ts';\n\ntype AdminUsersToolbarProps = {\n total: number;\n draftQuery: string;\n onDraftQueryChange: (value: string) => void;\n draftIncludeDeleted: boolean;\n onDraftIncludeDeletedChange: (value: boolean) => void;\n onSearch: () => void;\n onCreate: () => void;\n activeQuickFilter: QuickFilter;\n onQuickFilter: (filter: QuickFilter) => void;\n};\n\nconst QUICK_FILTERS: QuickFilter[] = ['all', 'database', 'config', 'admins'];\n\nexport function AdminUsersToolbar({\n total,\n draftQuery,\n onDraftQueryChange,\n draftIncludeDeleted,\n onDraftIncludeDeletedChange,\n onSearch,\n onCreate,\n activeQuickFilter,\n onQuickFilter,\n}: AdminUsersToolbarProps) {\n const { t } = useTranslation();\n\n return (\n <div className=\"flex flex-col gap-tinyrack-lg border-tinyrack-border border-b-tinyrack-default bg-tinyrack-surface-muted p-tinyrack-xl xl:flex-row xl:items-end xl:justify-between\">\n <div className=\"flex flex-col gap-tinyrack-sm\">\n <div className=\"flex items-center gap-tinyrack-sm\">\n <UsersIcon\n aria-hidden\n className=\"size-tinyrack-lg text-tinyrack-success\"\n />\n <TRText color=\"muted\" variant=\"label\">\n {t('admin.users.directoryEyebrow')}\n </TRText>\n </div>\n <TRCard.Title>{t('admin.users.directory')}</TRCard.Title>\n <TRCard.Description className=\"text-tinyrack-sm\">\n {t('admin.users.total', { count: total })}\n </TRCard.Description>\n </div>\n\n <div className=\"flex flex-col gap-tinyrack-md xl:items-end\">\n <div className=\"flex flex-col gap-tinyrack-sm lg:flex-row lg:items-center\">\n <TRInput\n aria-label={t('admin.users.searchPlaceholder')}\n className=\"w-full lg:w-tinyrack-overlay-width-sm\"\n onChange={(event) => onDraftQueryChange(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') onSearch();\n }}\n placeholder={t('admin.users.searchPlaceholder')}\n type=\"search\"\n uiSize=\"sm\"\n value={draftQuery}\n />\n\n {/*\n `aria-label` rather than relying on the label association: the\n design system's checkbox is a `button[role=checkbox]`, and the\n accessible-name path through `Field.Label` for a non-input control\n is not something to gamble a test contract on.\n */}\n <TRField.Root>\n <div className=\"flex items-center gap-tinyrack-sm rounded-tinyrack-md border border-tinyrack-border bg-tinyrack-surface px-tinyrack-md py-tinyrack-sm\">\n <TRCheckbox.Root\n aria-label={t('admin.users.includeDeleted')}\n checked={draftIncludeDeleted}\n onCheckedChange={(checked) =>\n onDraftIncludeDeletedChange(checked === true)\n }\n uiSize=\"md\"\n >\n <TRCheckbox.Indicator />\n </TRCheckbox.Root>\n <TRField.Label className=\"cursor-pointer\">\n {t('admin.users.includeDeleted')}\n </TRField.Label>\n </div>\n </TRField.Root>\n\n <TRButton\n appearance=\"outline\"\n onClick={onSearch}\n type=\"button\"\n uiSize=\"sm\"\n >\n <SearchIcon aria-hidden className=\"size-tinyrack-lg\" />\n {t('admin.users.search')}\n </TRButton>\n <TRButton\n intent=\"primary\"\n onClick={onCreate}\n type=\"button\"\n uiSize=\"sm\"\n >\n <PlusIcon aria-hidden className=\"size-tinyrack-lg\" />\n {t('admin.users.create')}\n </TRButton>\n </div>\n\n <div className=\"inline-flex items-center gap-tinyrack-3xs rounded-tinyrack-md border border-tinyrack-border bg-tinyrack-surface-muted p-tinyrack-xs\">\n {QUICK_FILTERS.map((filter) => (\n <TRButton\n appearance={activeQuickFilter === filter ? 'solid' : 'ghost'}\n intent={activeQuickFilter === filter ? 'primary' : undefined}\n key={filter}\n onClick={() => onQuickFilter(filter)}\n type=\"button\"\n uiSize=\"sm\"\n >\n {t(`admin.users.filter.${filter}`)}\n </TRButton>\n ))}\n </div>\n </div>\n </div>\n );\n}\n","import {\n useMutation,\n useQueryClient,\n useSuspenseQuery,\n} from '@tanstack/react-query';\nimport { createFileRoute, redirect } from '@tanstack/react-router';\nimport { TRBadge } from '@tinyrack/ui/components/badge';\nimport { TRButton } from '@tinyrack/ui/components/button';\nimport { TRCard } from '@tinyrack/ui/components/card';\nimport { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { AdminGateScreen } from '#frontend/features/admin/admin-gate-screen.tsx';\nimport { AdminShell } from '#frontend/features/admin/admin-shell.tsx';\nimport { AdminUserFormModal } from '#frontend/features/admin/users/admin-user-form-modal.tsx';\nimport { AdminUsersFilterBar } from '#frontend/features/admin/users/admin-users-filter-bar.tsx';\nimport {\n getActiveQuickFilter,\n type NoticeState,\n type QuickFilter,\n type UserModalState,\n} from '#frontend/features/admin/users/admin-users-filters.ts';\nimport { AdminUsersNotice } from '#frontend/features/admin/users/admin-users-notice.tsx';\nimport { AdminUsersSummary } from '#frontend/features/admin/users/admin-users-summary.tsx';\nimport { AdminUsersTable } from '#frontend/features/admin/users/admin-users-table.tsx';\nimport { AdminUsersToolbar } from '#frontend/features/admin/users/admin-users-toolbar.tsx';\nimport {\n adminUsersQueryOptions,\n createAdminUser,\n deleteAdminUser,\n normalizeAdminUsersQuery,\n updateAdminUser,\n} from '#frontend/queries/admin-users.ts';\nimport { appConfigQueryOptions } from '#frontend/queries/config.ts';\nimport type { SessionUser } from '#frontend/queries/session.ts';\n\nexport const Route = createFileRoute('/admin/users/')({\n component: AdminUsersPage,\n beforeLoad: async ({ context }) => {\n if (!context.user) {\n throw redirect({ to: '/login' });\n }\n },\n});\n\nfunction AdminUsersPage() {\n const user = Route.useRouteContext({ select: (context) => context.user });\n\n if (user?.role !== 'admin') {\n return <AdminGateScreen reason=\"access-required\" />;\n }\n\n return <AdminUsersGate user={user} />;\n}\n\nfunction AdminUsersGate({ user }: { user: SessionUser }) {\n const { data: config } = useSuspenseQuery(appConfigQueryOptions);\n if (!config.admin.enabled) {\n return <AdminGateScreen reason=\"console-disabled\" />;\n }\n return <AdminUsersContent user={user} />;\n}\n\nfunction AdminUsersContent({ user }: { user: SessionUser }) {\n const { t } = useTranslation();\n const queryClient = useQueryClient();\n const [draftQuery, setDraftQuery] = useState('');\n const [draftIncludeDeleted, setDraftIncludeDeleted] = useState(false);\n const [filters, setFilters] = useState(() => normalizeAdminUsersQuery());\n const [notice, setNotice] = useState<NoticeState>(null);\n const [modal, setModal] = useState<UserModalState>(null);\n const { data } = useSuspenseQuery(adminUsersQueryOptions(filters));\n\n const activeUsers = data.users.filter(\n (managedUser) => !managedUser.deleted_at,\n ).length;\n const configUsers = data.users.filter(\n (managedUser) => managedUser.managed_by === 'config',\n ).length;\n const databaseUsers = data.users.filter(\n (managedUser) => managedUser.managed_by === 'database',\n ).length;\n const activeQuickFilter = getActiveQuickFilter(filters);\n const hasActiveFilters =\n filters.query !== '' ||\n filters.includeDeleted ||\n filters.managedBy !== undefined ||\n filters.role !== undefined;\n const pageStart =\n data.pagination.total === 0\n ? 0\n : (data.pagination.page - 1) * data.pagination.page_size + 1;\n const pageEnd = Math.min(\n data.pagination.page * data.pagination.page_size,\n data.pagination.total,\n );\n\n const noticeOn = (message: string) => setNotice({ tone: 'success', message });\n const noticeFail = () =>\n setNotice({ tone: 'error', message: t('admin.users.operationFailed') });\n\n const createMutation = useMutation({\n mutationFn: createAdminUser,\n onSuccess: ({ user: nextUser }) => {\n void queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });\n noticeOn(t('admin.users.createdNotice', { email: nextUser.email }));\n setModal(null);\n },\n onError: noticeFail,\n });\n\n const updateMutation = useMutation({\n mutationFn: updateAdminUser,\n onSuccess: ({ user: nextUser }) => {\n void queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });\n noticeOn(t('admin.users.updatedNotice', { email: nextUser.email }));\n setModal(null);\n },\n onError: noticeFail,\n });\n\n const deleteMutation = useMutation({\n mutationFn: deleteAdminUser,\n onSuccess: ({ user: nextUser }) => {\n void queryClient.invalidateQueries({ queryKey: ['admin', 'users'] });\n noticeOn(t('admin.users.deletedNotice', { email: nextUser.email }));\n setModal(null);\n },\n onError: noticeFail,\n });\n\n const isMutating =\n createMutation.isPending ||\n updateMutation.isPending ||\n deleteMutation.isPending;\n\n const applySearch = () => {\n setFilters((current) => ({\n ...current,\n query: draftQuery.trim(),\n includeDeleted: draftIncludeDeleted,\n page: 1,\n }));\n };\n\n const clearFilters = () => {\n setDraftQuery('');\n setDraftIncludeDeleted(false);\n setFilters(normalizeAdminUsersQuery());\n };\n\n const applyQuickFilter = (nextFilter: QuickFilter) => {\n setFilters((current) => ({\n ...current,\n page: 1,\n managedBy:\n nextFilter === 'database'\n ? 'database'\n : nextFilter === 'config'\n ? 'config'\n : undefined,\n role: nextFilter === 'admins' ? 'admin' : undefined,\n }));\n };\n\n return (\n <AdminShell\n current=\"users\"\n description={t('admin.users.description')}\n title={t('admin.users.title')}\n user={user}\n >\n <AdminUsersSummary\n active={activeUsers}\n config={configUsers}\n database={databaseUsers}\n />\n\n {notice ? (\n <AdminUsersNotice notice={notice} onDismiss={() => setNotice(null)} />\n ) : null}\n\n <TRCard.Root\n className=\"overflow-hidden shadow-tinyrack-raised\"\n data-testid=\"admin-users-directory\"\n variant=\"outlined\"\n >\n <TRCard.Content className=\"gap-tinyrack-lg p-0\">\n <AdminUsersToolbar\n activeQuickFilter={activeQuickFilter}\n draftIncludeDeleted={draftIncludeDeleted}\n draftQuery={draftQuery}\n onCreate={() => setModal({ type: 'create' })}\n onDraftIncludeDeletedChange={setDraftIncludeDeleted}\n onDraftQueryChange={setDraftQuery}\n onQuickFilter={applyQuickFilter}\n onSearch={applySearch}\n total={data.pagination.total}\n />\n\n <AdminUsersFilterBar\n activeQuickFilter={activeQuickFilter}\n hasActiveFilters={hasActiveFilters}\n includeDeleted={filters.includeDeleted}\n onClearFilters={clearFilters}\n onPageSizeChange={(pageSize) =>\n setFilters((current) => ({ ...current, page: 1, pageSize }))\n }\n pageEnd={pageEnd}\n pageSize={filters.pageSize}\n pageStart={pageStart}\n query={filters.query}\n total={data.pagination.total}\n />\n\n <AdminUsersTable\n onDelete={(managedUser) =>\n setModal({ type: 'delete', user: managedUser })\n }\n onEdit={(managedUser) =>\n setModal({ type: 'edit', user: managedUser })\n }\n users={data.users}\n />\n\n <div className=\"flex items-center justify-between border-tinyrack-border border-t-tinyrack-default bg-tinyrack-surface-muted p-tinyrack-lg\">\n <TRButton\n appearance=\"outline\"\n disabled={filters.page <= 1}\n onClick={() =>\n setFilters((current) => ({\n ...current,\n page: current.page - 1,\n }))\n }\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('admin.users.previous')}\n </TRButton>\n <TRBadge uiSize=\"md\">\n {t('admin.users.page', { page: data.pagination.page })}\n </TRBadge>\n <TRButton\n appearance=\"outline\"\n disabled={\n data.pagination.page * data.pagination.page_size >=\n data.pagination.total\n }\n onClick={() =>\n setFilters((current) => ({\n ...current,\n page: current.page + 1,\n }))\n }\n type=\"button\"\n uiSize=\"sm\"\n >\n {t('admin.users.next')}\n </TRButton>\n </div>\n </TRCard.Content>\n </TRCard.Root>\n\n <AdminUserFormModal\n isMutating={isMutating}\n modal={modal}\n onClose={() => setModal(null)}\n onCreate={(values) => createMutation.mutate(values)}\n onDelete={(sub) => deleteMutation.mutate(sub)}\n onUpdate={(values) => updateMutation.mutate(values)}\n />\n </AdminShell>\n );\n}\n"],"x_google_ignoreList":[0,6,7,8,9,10,11,12,13,14],"mappings":"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"}
|
package/public/index.html
CHANGED
|
@@ -18,11 +18,10 @@
|
|
|
18
18
|
<!-- Preload critical API data for faster initial render -->
|
|
19
19
|
<link rel="preload" href="/api/config" as="fetch" crossorigin="anonymous" />
|
|
20
20
|
<link rel="preload" href="/api/user/session" as="fetch" crossorigin="anonymous" />
|
|
21
|
-
<script type="module" crossorigin src="/assets/index-
|
|
21
|
+
<script type="module" crossorigin src="/assets/index-CS23Ozt6.js"></script>
|
|
22
22
|
<link rel="modulepreload" crossorigin href="/assets/createLucideIcon-BPpAIXR_.js">
|
|
23
|
-
<link rel="modulepreload" crossorigin href="/assets/config-
|
|
24
|
-
<link rel="modulepreload" crossorigin href="/assets/mutationOptions-
|
|
25
|
-
<link rel="modulepreload" crossorigin href="/assets/link-BN90emXr.js">
|
|
23
|
+
<link rel="modulepreload" crossorigin href="/assets/config-DTQCUlfZ.js">
|
|
24
|
+
<link rel="modulepreload" crossorigin href="/assets/mutationOptions-DyYFUbyn.js">
|
|
26
25
|
<link rel="modulepreload" crossorigin href="/assets/zod-C87S6Tec.js">
|
|
27
26
|
<link rel="stylesheet" crossorigin href="/assets/index-DZyHRhbQ.css">
|
|
28
27
|
</head>
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { AppEnv } from '../../../../../lib/app-env.ts';
|
|
2
|
-
export declare const authPasswordResetRequiredPost: import("hono/hono-base").HonoBase<AppEnv, {
|
|
3
|
-
"/auth/password/reset-required": {
|
|
4
|
-
$post: {
|
|
5
|
-
input: {
|
|
6
|
-
json: {
|
|
7
|
-
password: string;
|
|
8
|
-
};
|
|
9
|
-
};
|
|
10
|
-
output: {
|
|
11
|
-
message: string;
|
|
12
|
-
};
|
|
13
|
-
outputFormat: "json";
|
|
14
|
-
status: 200;
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
}, "/", "/auth/password/reset-required">;
|
|
18
|
-
//# sourceMappingURL=post.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"post.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/api/auth/password/reset-required/post.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAO5D,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;wCA0CzC,CAAC"}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { Hono } from 'hono';
|
|
2
|
-
import { describeRoute, resolver, validator } from 'hono-openapi';
|
|
3
|
-
import { z } from 'zod';
|
|
4
|
-
import { TAGS } from "../../../../../lib/swagger-tags.js";
|
|
5
|
-
import { verifyPasswordResetUser } from "../../../../../middleware/auth.js";
|
|
6
|
-
import { e } from "../../../../../schemas/error.js";
|
|
7
|
-
import { f } from "../../../../../schemas/field.js";
|
|
8
|
-
import { r } from "../../../../../schemas/response.js";
|
|
9
|
-
export const authPasswordResetRequiredPost = new Hono().post('/auth/password/reset-required', describeRoute({
|
|
10
|
-
tags: [TAGS.AUTH],
|
|
11
|
-
summary: 'Set a replacement password',
|
|
12
|
-
description: 'Sets a new password after passkey verification retired a legacy password. Does not create a user session.',
|
|
13
|
-
responses: {
|
|
14
|
-
200: {
|
|
15
|
-
content: {
|
|
16
|
-
'application/json': { schema: resolver(r.MessageResponse) },
|
|
17
|
-
},
|
|
18
|
-
description: 'Password replaced; a fresh login is required',
|
|
19
|
-
},
|
|
20
|
-
400: {
|
|
21
|
-
content: {
|
|
22
|
-
'application/json': { schema: resolver(e.ValidationError.Schema) },
|
|
23
|
-
},
|
|
24
|
-
description: 'Password policy validation failed',
|
|
25
|
-
},
|
|
26
|
-
401: {
|
|
27
|
-
content: {
|
|
28
|
-
'application/json': { schema: resolver(e.Unauthorized.Schema) },
|
|
29
|
-
},
|
|
30
|
-
description: 'Restricted password-reset session required',
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
}), validator('json', z.object({ password: f.newUserPassword })), verifyPasswordResetUser(), async (c) => {
|
|
34
|
-
const user = c.var.verifiedPasswordResetUser;
|
|
35
|
-
await c.var.services.passwordAuthService.replacePassword(user, c.req.valid('json').password);
|
|
36
|
-
c.var.session.delete();
|
|
37
|
-
return c.json({ message: 'Password has been set. Sign in with the new password.' }, 200);
|
|
38
|
-
});
|
|
39
|
-
//# sourceMappingURL=post.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"post.js","sourceRoot":"","sources":["../../../../../../src/routes/api/auth/password/reset-required/post.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,CAAC,EAAE,MAAM,iCAAiC,CAAC;AACpD,OAAO,EAAE,CAAC,EAAE,MAAM,iCAAiC,CAAC;AACpD,OAAO,EAAE,CAAC,EAAE,MAAM,oCAAoC,CAAC;AAEvD,MAAM,CAAC,MAAM,6BAA6B,GAAG,IAAI,IAAI,EAAU,CAAC,IAAI,CAClE,+BAA+B,EAC/B,aAAa,CAAC;IACZ,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;IACjB,OAAO,EAAE,4BAA4B;IACrC,WAAW,EACT,2GAA2G;IAC7G,SAAS,EAAE;QACT,GAAG,EAAE;YACH,OAAO,EAAE;gBACP,kBAAkB,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,EAAE;aAC5D;YACD,WAAW,EAAE,8CAA8C;SAC5D;QACD,GAAG,EAAE;YACH,OAAO,EAAE;gBACP,kBAAkB,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE;aACnE;YACD,WAAW,EAAE,mCAAmC;SACjD;QACD,GAAG,EAAE;YACH,OAAO,EAAE;gBACP,kBAAkB,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE;aAChE;YACD,WAAW,EAAE,4CAA4C;SAC1D;KACF;CACF,CAAC,EACF,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,EAC5D,uBAAuB,EAAE,EACzB,KAAK,EAAE,CAAC,EAAE,EAAE;IACV,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,yBAAyB,CAAC;IAC7C,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,mBAAmB,CAAC,eAAe,CACtD,IAAI,EACJ,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,QAAQ,CAC7B,CAAC;IACF,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;IACvB,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,OAAO,EAAE,uDAAuD,EAAE,EACpE,GAAG,CACJ,CAAC;AACJ,CAAC,CACF,CAAC"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { IssuaryRuntimeConfig } from '../lib/config/index.ts';
|
|
2
|
-
import type { Logger } from '../lib/logger.ts';
|
|
3
|
-
import type { MikroService } from './mikro.service.ts';
|
|
4
|
-
export interface LegacyCredentialCounts {
|
|
5
|
-
passwords: number;
|
|
6
|
-
clientSecrets: number;
|
|
7
|
-
recoveryCodes: number;
|
|
8
|
-
oauthCodes: number;
|
|
9
|
-
deviceCodes: number;
|
|
10
|
-
}
|
|
11
|
-
export declare class LegacyCredentialRetirementService {
|
|
12
|
-
private readonly config;
|
|
13
|
-
private readonly mikro;
|
|
14
|
-
private readonly logger;
|
|
15
|
-
constructor(config: IssuaryRuntimeConfig, mikro: MikroService, logger: Logger);
|
|
16
|
-
count(): Promise<LegacyCredentialCounts>;
|
|
17
|
-
countPasswordResetRequired(): Promise<number>;
|
|
18
|
-
retireIfEnabled(): Promise<LegacyCredentialCounts>;
|
|
19
|
-
}
|
|
20
|
-
//# sourceMappingURL=legacy-credential-retirement.service.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"legacy-credential-retirement.service.d.ts","sourceRoot":"","sources":["../../src/services/legacy-credential-retirement.service.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKvD,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,iCAAiC;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAG9B,MAAM,EAAE,oBAAoB,EAC5B,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,MAAM;IAOH,KAAK,IAAI,OAAO,CAAC,sBAAsB,CAAC;IA2BxC,0BAA0B,IAAI,OAAO,CAAC,MAAM,CAAC;IAM7C,eAAe,IAAI,OAAO,CAAC,sBAAsB,CAAC;CA+DhE"}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { OAuthClientEntitySchema } from "../entities/oauth-client.entity.js";
|
|
2
|
-
import { OAuthCodeEntitySchema } from "../entities/oauth-code.entity.js";
|
|
3
|
-
import { OAuthDeviceCodeEntitySchema } from "../entities/oauth-device-code.entity.js";
|
|
4
|
-
import { UserEntity } from "../entities/user.entity.js";
|
|
5
|
-
import { UserTotpRecoveryCodeEntitySchema } from "../entities/user-totp-recovery-code.entity.js";
|
|
6
|
-
const LEGACY_HASH_PATTERN = '%$v=1$%';
|
|
7
|
-
const RETIRED_CLIENT_SECRET_HASH = 'retired-legacy-v1-client-secret';
|
|
8
|
-
export class LegacyCredentialRetirementService {
|
|
9
|
-
config;
|
|
10
|
-
mikro;
|
|
11
|
-
logger;
|
|
12
|
-
constructor(config, mikro, logger) {
|
|
13
|
-
this.config = config;
|
|
14
|
-
this.mikro = mikro;
|
|
15
|
-
this.logger = logger;
|
|
16
|
-
}
|
|
17
|
-
async count() {
|
|
18
|
-
const em = this.mikro.orm.em.fork();
|
|
19
|
-
const [passwords, clientSecrets, recoveryCodes, oauthCodes, deviceCodes] = await Promise.all([
|
|
20
|
-
em.count(UserEntity, {
|
|
21
|
-
password_hash: { $like: LEGACY_HASH_PATTERN },
|
|
22
|
-
}),
|
|
23
|
-
em.count(OAuthClientEntitySchema, {
|
|
24
|
-
clientSecretHash: { $like: LEGACY_HASH_PATTERN },
|
|
25
|
-
}),
|
|
26
|
-
em.count(UserTotpRecoveryCodeEntitySchema, {
|
|
27
|
-
code_hash: { $like: LEGACY_HASH_PATTERN },
|
|
28
|
-
}),
|
|
29
|
-
em.count(OAuthCodeEntitySchema, {
|
|
30
|
-
codeHash: { $like: LEGACY_HASH_PATTERN },
|
|
31
|
-
}),
|
|
32
|
-
em.count(OAuthDeviceCodeEntitySchema, {
|
|
33
|
-
$or: [
|
|
34
|
-
{ deviceCodeHash: { $like: LEGACY_HASH_PATTERN } },
|
|
35
|
-
{ userCodeHash: { $like: LEGACY_HASH_PATTERN } },
|
|
36
|
-
],
|
|
37
|
-
}),
|
|
38
|
-
]);
|
|
39
|
-
return { passwords, clientSecrets, recoveryCodes, oauthCodes, deviceCodes };
|
|
40
|
-
}
|
|
41
|
-
async countPasswordResetRequired() {
|
|
42
|
-
return this.mikro.orm.em.fork().count(UserEntity, {
|
|
43
|
-
password_reset_required: true,
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
async retireIfEnabled() {
|
|
47
|
-
const before = await this.count();
|
|
48
|
-
if (!this.config.security.retire_legacy_v1_credentials) {
|
|
49
|
-
return before;
|
|
50
|
-
}
|
|
51
|
-
const em = this.mikro.orm.em.fork();
|
|
52
|
-
const configManagedPasswordCount = await em.count(UserEntity, {
|
|
53
|
-
managed_by: 'config',
|
|
54
|
-
password_hash: { $like: LEGACY_HASH_PATTERN },
|
|
55
|
-
});
|
|
56
|
-
if (configManagedPasswordCount > 0) {
|
|
57
|
-
throw new Error('Config-managed users still have v1 password hashes after config seeding.');
|
|
58
|
-
}
|
|
59
|
-
await em.transactional(async (tx) => {
|
|
60
|
-
await tx.nativeUpdate(UserEntity, {
|
|
61
|
-
managed_by: 'database',
|
|
62
|
-
password_hash: { $like: LEGACY_HASH_PATTERN },
|
|
63
|
-
}, { password_hash: null, password_reset_required: true });
|
|
64
|
-
await tx.nativeUpdate(OAuthClientEntitySchema, { clientSecretHash: { $like: LEGACY_HASH_PATTERN } }, {
|
|
65
|
-
enabled: false,
|
|
66
|
-
clientSecretHash: RETIRED_CLIENT_SECRET_HASH,
|
|
67
|
-
});
|
|
68
|
-
await tx.nativeDelete(UserTotpRecoveryCodeEntitySchema, {
|
|
69
|
-
code_hash: { $like: LEGACY_HASH_PATTERN },
|
|
70
|
-
});
|
|
71
|
-
await tx.nativeDelete(OAuthCodeEntitySchema, {
|
|
72
|
-
codeHash: { $like: LEGACY_HASH_PATTERN },
|
|
73
|
-
});
|
|
74
|
-
await tx.nativeDelete(OAuthDeviceCodeEntitySchema, {
|
|
75
|
-
$or: [
|
|
76
|
-
{ deviceCodeHash: { $like: LEGACY_HASH_PATTERN } },
|
|
77
|
-
{ userCodeHash: { $like: LEGACY_HASH_PATTERN } },
|
|
78
|
-
],
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
const remaining = await this.count();
|
|
82
|
-
const remainingTotal = Object.values(remaining).reduce((total, value) => total + value, 0);
|
|
83
|
-
if (remainingTotal > 0) {
|
|
84
|
-
throw new Error('Legacy v1 credential retirement did not reach zero.');
|
|
85
|
-
}
|
|
86
|
-
this.logger.warn({ retiredLegacyCredentials: before }, 'Legacy v1 credentials were irreversibly retired');
|
|
87
|
-
return remaining;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
//# sourceMappingURL=legacy-credential-retirement.service.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"legacy-credential-retirement.service.js","sourceRoot":"","sources":["../../src/services/legacy-credential-retirement.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{i as e,q as t}from"./createLucideIcon-BPpAIXR_.js";import{t as n}from"./config-v3-oy_ef.js";import{tt as r}from"./shell-header-bar-C9AB5lT-.js";import{t as i}from"./link-BN90emXr.js";import{t as a}from"./fingerprint-pattern-DP62Vk8x.js";import{t as o}from"./shield-check-D_p8H0ni.js";import{N as s,f as c}from"./index-gliHKncz.js";import{t as l}from"./auth-choice-row-BlSsUI7d.js";import{t as u}from"./auth-page-header-CIs08f5Y.js";import{t as d}from"./auth-layout-CoeqNhTT.js";import{n as f,t as p}from"./auth-footer-Cz5ivsDc.js";var m=t();function h(){let{t}=e(),h=s(c.useSearch()),{data:g}=r(n);return(0,m.jsxs)(d,{children:[(0,m.jsx)(u,{subtitle:t(`verify2fa.subtitle`),title:t(`verify2fa.title`)}),(0,m.jsxs)(`div`,{className:`flex flex-col gap-tinyrack-sm`,children:[g.auth.password.enabled&&g.auth.password.totp.enabled&&(0,m.jsx)(l,{description:t(`verify2fa.totp.description`),icon:o,label:t(`verify2fa.totp.title`),render:(0,m.jsx)(i,{search:h,to:`/verify/totp`})}),g.auth.passkey.enabled&&(0,m.jsx)(l,{description:t(`verify2fa.passkey.description`),icon:a,label:t(`verify2fa.passkey.title`),render:(0,m.jsx)(i,{search:h,to:`/verify/passkey`})})]}),(0,m.jsx)(p,{children:(0,m.jsx)(f,{link:(0,m.jsx)(i,{search:h,to:`/login`,children:t(`verify2fa.backToLogin`)})})})]})}export{h as component};
|
|
2
|
-
//# sourceMappingURL=2fa-BgveHSB_.js.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{i as e,q as t}from"./createLucideIcon-BPpAIXR_.js";import{t as n}from"./config-v3-oy_ef.js";import{tt as r}from"./shell-header-bar-C9AB5lT-.js";import{t as i}from"./link-BN90emXr.js";import{t as a}from"./fingerprint-pattern-DP62Vk8x.js";import{t as o}from"./shield-check-D_p8H0ni.js";import{N as s,l as c}from"./index-gliHKncz.js";import{t as l}from"./auth-choice-row-BlSsUI7d.js";import{t as u}from"./auth-page-header-CIs08f5Y.js";import{t as d}from"./alert-leqyvHOp.js";import{t as f}from"./auth-layout-CoeqNhTT.js";import{n as p,t as m}from"./auth-footer-Cz5ivsDc.js";var h=t();function g(){let{t}=e(),g=c.useSearch(),{data:_}=r(n),v=s(g);return(0,h.jsxs)(f,{children:[(0,h.jsx)(u,{subtitle:t(`setup2fa.subtitle`),title:t(`setup2fa.title`)}),(0,h.jsx)(d,{icon:o,type:`info`,children:t(`setup2fa.required`)}),(0,h.jsxs)(`div`,{className:`flex flex-col gap-tinyrack-sm`,children:[_.auth.password.enabled&&_.auth.password.totp.enabled&&(0,h.jsx)(l,{description:t(`setup2fa.totp.description`),icon:o,label:t(`setup2fa.totp.title`),render:(0,h.jsx)(i,{search:v,to:`/setup/totp`})}),_.auth.passkey.enabled&&(0,h.jsx)(l,{description:t(`setup2fa.passkey.description`),icon:a,label:t(`setup2fa.passkey.title`),render:(0,h.jsx)(i,{search:{...v,passkey_name:`default`},to:`/setup/passkey`})})]}),(0,h.jsx)(m,{children:(0,h.jsx)(p,{link:(0,h.jsx)(i,{search:v,to:`/login`,children:t(`setup2fa.backToLogin`)})})})]})}export{g as component};
|
|
2
|
-
//# sourceMappingURL=2fa-kiqzGSz2.js.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{i as e,n as t,q as n,t as r}from"./createLucideIcon-BPpAIXR_.js";import{t as i}from"./config-v3-oy_ef.js";import{tt as a}from"./shell-header-bar-C9AB5lT-.js";import{t as o}from"./link-BN90emXr.js";import{c as s,l as c,o as l,s as u,t as d,u as f}from"./admin-users-CwTJdiih.js";import{B as p,H as m,g as h,z as g}from"./index-gliHKncz.js";import{t as _}from"./badge-CsOfUji0.js";var v=r(`network`,[[`rect`,{x:`16`,y:`16`,width:`6`,height:`6`,rx:`1`,key:`4q2zg0`}],[`rect`,{x:`2`,y:`16`,width:`6`,height:`6`,rx:`1`,key:`8cvhb9`}],[`rect`,{x:`9`,y:`2`,width:`6`,height:`6`,rx:`1`,key:`1egb70`}],[`path`,{d:`M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3`,key:`1jsf9p`}],[`path`,{d:`M12 12V8`,key:`2874zd`}]]),y=n();function b(){let e=h.useRouteContext({select:e=>e.user});return e?.role===`admin`?(0,y.jsx)(x,{user:e}):(0,y.jsx)(f,{reason:`access-required`})}function x({user:e}){let{data:t}=a(i);return t.admin.enabled?(0,y.jsx)(S,{user:e}):(0,y.jsx)(f,{reason:`console-disabled`})}function S({user:n}){let{t:r}=e(),[i,a,f,h]=m({queries:[d(),d({pageSize:1,role:`admin`}),d({managedBy:`config`,pageSize:1}),d({managedBy:`database`,pageSize:1})]}),b=i.data,x=f.data.pagination.total,S=h.data.pagination.total,w=a.data.pagination.total;return(0,y.jsxs)(u,{current:`dashboard`,description:r(`admin.dashboardDescription`),title:r(`admin.dashboardTitle`),user:n,children:[(0,y.jsxs)(`div`,{className:`flex flex-col divide-y divide-tinyrack-border overflow-hidden rounded-tinyrack-lg border border-tinyrack-border bg-tinyrack-surface shadow-tinyrack-raised lg:flex-row lg:divide-x lg:divide-y-0`,children:[(0,y.jsx)(l,{accent:`bg-tinyrack-primary`,hint:r(`admin.metrics.totalUsersHint`),label:r(`admin.metrics.totalUsers`),value:b.pagination.total}),(0,y.jsx)(l,{accent:`bg-tinyrack-success`,hint:r(`admin.metrics.adminsHint`),label:r(`admin.metrics.admins`),value:w}),(0,y.jsx)(l,{accent:`bg-tinyrack-info`,hint:r(`admin.metrics.databaseUsersHint`),label:r(`admin.metrics.databaseUsers`),value:S})]}),(0,y.jsxs)(`div`,{className:`grid gap-tinyrack-xl xl:grid-cols-3`,children:[(0,y.jsx)(p.Root,{className:`overflow-hidden border-tinyrack-border shadow-tinyrack-raised xl:col-span-2`,variant:`outlined`,children:(0,y.jsxs)(p.Content,{className:`p-0`,children:[(0,y.jsxs)(`div`,{className:`flex flex-col gap-tinyrack-lg border-tinyrack-border border-b-tinyrack-default p-tinyrack-xl sm:flex-row sm:items-center sm:justify-between`,children:[(0,y.jsxs)(`div`,{className:`flex flex-col gap-tinyrack-sm`,children:[(0,y.jsxs)(`div`,{className:`flex items-center gap-tinyrack-sm`,children:[(0,y.jsx)(v,{"aria-hidden":!0,className:`size-tinyrack-lg text-tinyrack-primary`}),(0,y.jsx)(t,{color:`muted`,variant:`label`,children:r(`admin.identityGraph`)})]}),(0,y.jsx)(p.Title,{children:r(`admin.users.title`)}),(0,y.jsx)(p.Description,{className:`text-tinyrack-sm`,children:r(`admin.users.description`)})]}),(0,y.jsx)(g,{intent:`primary`,render:(0,y.jsx)(o,{to:`/admin/users`}),uiSize:`sm`,children:r(`admin.users.open`)})]}),(0,y.jsx)(`div`,{className:`grid divide-y divide-tinyrack-border [gap:0] md:grid-cols-2 md:divide-x md:divide-y-0`,children:b.users.slice(0,4).map(e=>(0,y.jsxs)(o,{className:`group flex flex-col gap-tinyrack-lg bg-tinyrack-surface p-tinyrack-lg transition hover:bg-tinyrack-surface-hover`,to:`/admin/users`,children:[(0,y.jsxs)(`div`,{className:`flex items-start justify-between gap-tinyrack-lg`,children:[(0,y.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-tinyrack-xs`,children:[(0,y.jsx)(t,{as:`p`,truncate:!0,variant:`bodySm`,weight:`medium`,children:e.email}),(0,y.jsx)(t,{as:`p`,color:`muted`,truncate:!0,variant:`caption`,children:(0,y.jsx)(`span`,{className:`font-tinyrack-mono`,children:e.sub})})]}),(0,y.jsx)(_,{className:`shrink-0`,uiSize:`md`,variant:e.role===`admin`?`neutral`:void 0,children:s(r,e.role)})]}),(0,y.jsxs)(`div`,{className:`flex items-center justify-between gap-tinyrack-sm`,children:[(0,y.jsx)(_,{uiSize:`md`,children:c(r,e.managed_by)}),(0,y.jsxs)(t,{color:`muted`,variant:`caption`,children:[r(`admin.users.verifiedLabel`),` `,e.email_verified?r(`common.yes`):r(`common.no`)]})]})]},e.sub))})]})}),(0,y.jsx)(p.Root,{className:`overflow-hidden border-tinyrack-border shadow-tinyrack-raised`,variant:`outlined`,children:(0,y.jsxs)(p.Content,{className:`flex flex-col items-start gap-tinyrack-md`,children:[(0,y.jsx)(_,{uiSize:`md`,variant:`neutral`,children:r(`admin.policy.title`)}),(0,y.jsx)(p.Title,{className:`text-tinyrack-xl`,children:r(`admin.policy.heading`)}),(0,y.jsx)(p.Description,{className:`text-tinyrack-sm`,children:r(`admin.policy.description`)}),(0,y.jsxs)(`div`,{className:`flex w-full flex-col gap-tinyrack-md`,children:[(0,y.jsx)(C,{label:r(`admin.metrics.configUsers`),value:x}),(0,y.jsx)(C,{label:r(`admin.metrics.databaseUsers`),value:S}),(0,y.jsx)(C,{label:r(`admin.policy.configReadonly`),value:r(`common.on`)})]})]})})]})]})}function C({label:e,value:n}){return(0,y.jsxs)(`div`,{className:`flex items-center justify-between gap-tinyrack-sm rounded-tinyrack-md border border-tinyrack-border bg-tinyrack-surface-muted px-tinyrack-lg py-tinyrack-md`,children:[(0,y.jsx)(t,{color:`muted`,variant:`bodySm`,children:e}),(0,y.jsx)(_,{uiSize:`md`,variant:`neutral`,children:n})]})}export{b as component};
|
|
2
|
-
//# sourceMappingURL=admin-DbDuu6AI.js.map
|