@ackplus/nest-auth 0.1.50 → 1.1.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/README.md +6 -513
- package/eslint.config.mjs +59 -0
- package/jest.config.ts +10 -0
- package/package.json +14 -44
- package/project.json +86 -0
- package/src/index.ts +30 -0
- package/src/lib/admin-console/admin-console.module.ts +62 -0
- package/src/lib/admin-console/controllers/admin-auth.controller.ts +339 -0
- package/src/lib/admin-console/controllers/admin-console.controller.ts +82 -0
- package/src/lib/admin-console/controllers/admin-permissions.controller.ts +180 -0
- package/src/lib/admin-console/controllers/admin-roles.controller.ts +89 -0
- package/src/lib/admin-console/controllers/admin-tenants.controller.ts +68 -0
- package/src/lib/admin-console/controllers/admin-users.controller.ts +379 -0
- package/src/lib/admin-console/decorators/current-admin.decorator.ts +9 -0
- package/src/lib/admin-console/dto/admin-permission.dto.ts +106 -0
- package/src/lib/admin-console/dto/admin-role.dto.ts +45 -0
- package/src/lib/admin-console/dto/admin-tenant.dto.ts +43 -0
- package/src/lib/admin-console/dto/admin-user.dto.ts +87 -0
- package/src/lib/admin-console/dto/create-dashboard-admin.dto.ts +34 -0
- package/src/lib/admin-console/dto/login.dto.ts +10 -0
- package/src/lib/admin-console/dto/reset-password.dto.ts +21 -0
- package/src/lib/admin-console/dto/setup-admin.dto.ts +23 -0
- package/src/lib/admin-console/dto/signup.dto.ts +51 -0
- package/src/lib/admin-console/entities/admin-user.entity.ts +74 -0
- package/src/lib/admin-console/guards/admin-session.guard.ts +47 -0
- package/src/lib/admin-console/services/admin-auth.service.ts +82 -0
- package/src/lib/admin-console/services/admin-console-config.service.ts +62 -0
- package/src/lib/admin-console/services/admin-session.service.ts +106 -0
- package/src/lib/admin-console/services/admin-user.service.ts +96 -0
- package/src/lib/admin-console/static/index.html +771 -0
- package/src/lib/auth/auth.module.ts +58 -0
- package/src/lib/auth/controllers/auth.controller.ts +393 -0
- package/src/lib/auth/controllers/mfa.controller.ts +200 -0
- package/src/lib/auth/dto/credentials/email-credentials.dto.ts +24 -0
- package/src/lib/auth/dto/credentials/phone-credentials.dto.ts +24 -0
- package/src/lib/auth/dto/credentials/social-credentials.dto.ts +15 -0
- package/src/lib/auth/dto/index.ts +1 -0
- package/src/lib/auth/dto/requests/change-password.request.dto.ts +34 -0
- package/src/lib/auth/dto/requests/forgot-password.request.dto.ts +30 -0
- package/src/lib/auth/dto/requests/initialize-admin.request.dto.ts +51 -0
- package/src/lib/auth/dto/requests/login.request.dto.ts +65 -0
- package/src/lib/auth/dto/requests/refresh-token.request.dto.ts +12 -0
- package/src/lib/auth/dto/requests/reset-password-with-token.request.dto.ts +22 -0
- package/src/lib/auth/dto/requests/reset-password.request.dto.ts +50 -0
- package/src/lib/auth/dto/requests/send-email-verification.request.dto.ts +12 -0
- package/src/lib/auth/dto/requests/send-mfa-code.request.dto.ts +19 -0
- package/src/lib/auth/dto/requests/signup.request.dto.ts +42 -0
- package/src/lib/auth/dto/requests/toggle-mfa.request.dto.ts +12 -0
- package/src/lib/auth/dto/requests/verify-2fa.request.dto.ts +24 -0
- package/src/lib/auth/dto/requests/verify-email.request.dto.ts +22 -0
- package/src/lib/auth/dto/requests/verify-forgot-password-otp-request-dto.ts +41 -0
- package/src/lib/auth/dto/requests/verify-totp-setup.request.dto.ts +22 -0
- package/src/lib/auth/dto/responses/auth-cookie.response.dto.ts +58 -0
- package/src/lib/auth/dto/responses/auth-success.response.dto.ts +58 -0
- package/src/lib/auth/dto/responses/auth.response.dto.ts +99 -0
- package/src/lib/auth/dto/responses/client-config.response.dto.ts +153 -0
- package/src/lib/auth/dto/responses/initialize-admin.response.dto.ts +22 -0
- package/src/lib/auth/dto/responses/mfa-code-response.dto.ts +27 -0
- package/src/lib/auth/dto/responses/mfa-status.response.dto.ts +89 -0
- package/src/lib/auth/dto/responses/verify-otp.response.dto.ts +9 -0
- package/src/lib/auth/entities/mfa-secret.entity.ts +33 -0
- package/src/lib/auth/entities/otp.entity.ts +33 -0
- package/src/lib/auth/events/{logged-out-all.event.d.ts → logged-out-all.event.ts} +6 -3
- package/src/lib/auth/events/{logged-out.event.d.ts → logged-out.event.ts} +5 -3
- package/src/lib/auth/events/{password-reset-requested.event.d.ts → password-reset-requested.event.ts} +6 -3
- package/src/lib/auth/events/{password-reset.event.d.ts → password-reset.event.ts} +6 -3
- package/src/lib/auth/events/{user-2fa-verified.event.d.ts → user-2fa-verified.event.ts} +6 -3
- package/src/lib/auth/events/{user-logged-in.event.d.ts → user-logged-in.event.ts} +7 -3
- package/src/lib/auth/events/{user-refresh-token.event.d.ts → user-refresh-token.event.ts} +6 -3
- package/src/lib/auth/events/{user-registered.event.d.ts → user-registered.event.ts} +7 -3
- package/src/lib/auth/guards/auth.guard.ts +386 -0
- package/src/lib/auth/{index.d.ts → index.ts} +28 -1
- package/src/lib/auth/interceptors/refresh-token.interceptor.ts +117 -0
- package/src/lib/auth/services/auth.service.ts +947 -0
- package/src/lib/auth/services/client-config.service.ts +157 -0
- package/src/lib/auth/services/cookie.service.ts +43 -0
- package/src/lib/auth/services/mfa.service.ts +391 -0
- package/src/lib/auth.constants.ts +63 -0
- package/src/lib/core/core.module.ts +50 -0
- package/src/lib/core/decorators/auth.decorator.ts +38 -0
- package/src/lib/core/decorators/permissions.decorator.ts +17 -0
- package/src/lib/core/decorators/public.decorator.ts +33 -0
- package/src/lib/core/decorators/role.decorator.ts +12 -0
- package/src/lib/core/decorators/skip-mfa.decorator.ts +4 -0
- package/src/lib/core/dto/message.response.dto.ts +6 -0
- package/src/lib/core/{entities.d.ts → entities.ts} +18 -1
- package/src/lib/core/{index.d.ts → index.ts} +17 -0
- package/src/lib/core/interfaces/auth-module-options.interface.ts +211 -0
- package/src/lib/core/interfaces/mfa-options.interface.ts +46 -0
- package/src/lib/core/interfaces/otp.interface.ts +6 -0
- package/src/lib/core/interfaces/session-options.interface.ts +19 -0
- package/src/lib/core/interfaces/{token-payload.interface.d.ts → token-payload.interface.ts} +4 -1
- package/src/lib/core/providers/apple-auth.provider.ts +61 -0
- package/src/lib/core/providers/base-auth.provider.ts +74 -0
- package/src/lib/core/providers/email-auth.provider.ts +71 -0
- package/src/lib/core/providers/facebook-auth.provider.ts +55 -0
- package/src/lib/core/providers/github-auth.provider.ts +79 -0
- package/src/lib/core/providers/google-auth.provider.ts +61 -0
- package/src/lib/core/providers/jwt-auth.provider.ts +50 -0
- package/src/lib/core/providers/phone-auth.provider.ts +45 -0
- package/src/lib/core/services/auth-config.service.ts +184 -0
- package/src/lib/core/services/auth-provider-registry.service.ts +93 -0
- package/src/lib/core/services/{debug-logger.service.js → debug-logger.service.ts} +92 -59
- package/src/lib/core/services/initialization.service.ts +29 -0
- package/src/lib/core/services/jwt.service.ts +137 -0
- package/src/lib/nest-auth.module.ts +152 -0
- package/src/lib/permission/entities/permission.entity.ts +56 -0
- package/src/lib/permission/index.ts +4 -0
- package/src/lib/permission/permission.module.ts +14 -0
- package/src/lib/permission/services/permission.service.ts +233 -0
- package/src/lib/request-context/index.ts +2 -0
- package/src/lib/request-context/request-context.middleware.ts +13 -0
- package/src/lib/request-context/{request-context.js → request-context.ts} +51 -27
- package/src/lib/role/entities/role.entity.ts +103 -0
- package/src/lib/role/{index.d.ts → index.ts} +2 -0
- package/src/lib/role/role.module.ts +15 -0
- package/src/lib/role/services/{role.service.js → role.service.ts} +117 -52
- package/src/lib/session/entities/session.entity.ts +54 -0
- package/src/lib/session/index.ts +20 -0
- package/src/lib/session/interfaces/session-repository.interface.ts +58 -0
- package/src/lib/session/repositories/base-session.repository.ts +74 -0
- package/src/lib/session/repositories/memory-session.repository.ts +153 -0
- package/src/lib/session/repositories/redis-session.repository.ts +171 -0
- package/src/lib/session/repositories/typeorm-session.repository.ts +86 -0
- package/src/lib/session/services/session-manager.service.ts +261 -0
- package/src/lib/session/session.module.ts +102 -0
- package/src/lib/session/utils/session.util.ts +166 -0
- package/src/lib/tenant/entities/tenant.entity.ts +40 -0
- package/src/lib/tenant/events/tenant-created.event.ts +9 -0
- package/src/lib/tenant/events/tenant-deleted.event.ts +11 -0
- package/src/lib/tenant/events/{tenant-updated.event.d.ts → tenant-updated.event.ts} +6 -3
- package/src/lib/tenant/index.ts +9 -0
- package/src/lib/tenant/services/tenant.service.ts +336 -0
- package/src/lib/tenant/tenant.module.ts +19 -0
- package/src/lib/types/express.d.ts +14 -0
- package/src/lib/user/dto/requests/update-user.dto.ts +15 -0
- package/src/lib/user/entities/access-key.entity.ts +53 -0
- package/src/lib/user/entities/identity.entity.ts +31 -0
- package/src/lib/user/entities/user.entity.ts +212 -0
- package/src/lib/user/events/{user-created.event.d.ts → user-created.event.ts} +4 -3
- package/src/lib/user/events/{user-deleted.event.d.ts → user-deleted.event.ts} +6 -3
- package/src/lib/user/events/{user-updated.event.d.ts → user-updated.event.ts} +6 -3
- package/src/lib/user/index.ts +11 -0
- package/src/lib/user/services/access-key.service.ts +145 -0
- package/src/lib/user/services/{user.service.js → user.service.ts} +199 -95
- package/src/lib/user/user.module.ts +26 -0
- package/src/lib/utils/database.utils.ts +6 -0
- package/src/lib/utils/date.util.ts +106 -0
- package/src/lib/utils/device.util.ts +111 -0
- package/src/lib/utils/index.ts +6 -0
- package/src/lib/utils/otp.ts +3 -0
- package/src/lib/utils/security.util.ts +27 -0
- package/src/lib/utils/slug.util.ts +58 -0
- package/src/types/ms.d.ts +1 -0
- package/test/access-key.service.spec.ts +204 -0
- package/test/auth.service.spec.ts +541 -0
- package/test/mfa.service.spec.ts +359 -0
- package/test/role.service.spec.ts +418 -0
- package/test/tenant.service.spec.ts +218 -0
- package/test/test.setup.ts +66 -0
- package/test/user.service.spec.ts +374 -0
- package/tsconfig.json +17 -0
- package/tsconfig.lib.json +15 -0
- package/tsconfig.spec.json +15 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/ui/.env +1 -0
- package/ui/.env.example +1 -0
- package/ui/.eslintignore +7 -0
- package/ui/README.md +288 -0
- package/ui/index.html +17 -0
- package/ui/package.json +34 -0
- package/ui/postcss.config.js +6 -0
- package/ui/src/App.tsx +245 -0
- package/ui/src/components/AuthGuard.tsx +59 -0
- package/ui/src/components/AuthProvider.tsx +76 -0
- package/ui/src/components/Button.tsx +37 -0
- package/ui/src/components/Card.tsx +37 -0
- package/ui/src/components/ErrorMessage.tsx +15 -0
- package/ui/src/components/FormDialog.tsx +61 -0
- package/ui/src/components/FormFooter.tsx +37 -0
- package/ui/src/components/Layout.tsx +112 -0
- package/ui/src/components/LoadingMessage.tsx +11 -0
- package/ui/src/components/Modal.tsx +97 -0
- package/ui/src/components/MultiSelect.tsx +145 -0
- package/ui/src/components/PageHeader.tsx +42 -0
- package/ui/src/components/PanelHeader.tsx +28 -0
- package/ui/src/components/PermissionInput.tsx +473 -0
- package/ui/src/components/SearchInput.tsx +69 -0
- package/ui/src/components/Select.tsx +51 -0
- package/ui/src/components/SwaggerUIWrapper.tsx +316 -0
- package/ui/src/components/Table.tsx +207 -0
- package/ui/src/components/Tag.tsx +9 -0
- package/ui/src/components/TagsInput.tsx +96 -0
- package/ui/src/components/admin/AdminForm.tsx +170 -0
- package/ui/src/components/admin/CreateAdminDialog.tsx +38 -0
- package/ui/src/components/auth/LoginFooter.tsx +17 -0
- package/ui/src/components/auth/LoginHeader.tsx +14 -0
- package/ui/src/components/auth/components/CodeBlock.tsx +43 -0
- package/ui/src/components/auth/components/CreateAccountCodeExamples.tsx +60 -0
- package/ui/src/components/auth/components/PasswordRequirements.tsx +16 -0
- package/ui/src/components/auth/components/PasswordStrengthIndicator.tsx +48 -0
- package/ui/src/components/auth/components/ResetPasswordCodeExamples.tsx +76 -0
- package/ui/src/components/auth/components/Tabs.tsx +32 -0
- package/ui/src/components/auth/dialogs/CreateAccountDialog.tsx +79 -0
- package/ui/src/components/auth/dialogs/ForgotPasswordDialog.tsx +79 -0
- package/ui/src/components/auth/forms/CreateAccountForm.tsx +226 -0
- package/ui/src/components/auth/forms/LoginForm.tsx +149 -0
- package/ui/src/components/auth/forms/ResetPasswordForm.tsx +202 -0
- package/ui/src/components/auth/types.ts +17 -0
- package/ui/src/components/auth/utils/security.ts +82 -0
- package/ui/src/components/auth/utils/utils.ts +25 -0
- package/ui/src/components/form/EmailField.tsx +25 -0
- package/ui/src/components/form/FormField.tsx +102 -0
- package/ui/src/components/form/FormMultiSelect.tsx +46 -0
- package/ui/src/components/form/FormSelect.tsx +60 -0
- package/ui/src/components/form/FormTagsInput.tsx +42 -0
- package/ui/src/components/form/FormTextarea.tsx +42 -0
- package/ui/src/components/form/PasswordField.tsx +93 -0
- package/ui/src/components/form/SecretKeyField.tsx +49 -0
- package/ui/src/components/permission/CreatePermissionDialog.tsx +44 -0
- package/ui/src/components/permission/EditPermissionDialog.tsx +55 -0
- package/ui/src/components/permission/PermissionForm.tsx +251 -0
- package/ui/src/components/role/CreateRoleDialog.tsx +45 -0
- package/ui/src/components/role/EditRoleDialog.tsx +55 -0
- package/ui/src/components/role/RoleDialog.tsx +252 -0
- package/ui/src/components/role/RoleForm.tsx +246 -0
- package/ui/src/components/tenant/CreateTenantDialog.tsx +41 -0
- package/ui/src/components/tenant/EditTenantDialog.tsx +52 -0
- package/ui/src/components/tenant/TenantForm.tsx +160 -0
- package/ui/src/components/user/CreateUserDialog.tsx +45 -0
- package/ui/src/components/user/UserDetailModal.tsx +815 -0
- package/ui/src/components/user/UserForm.tsx +191 -0
- package/ui/src/data/nest-auth.json +1687 -0
- package/ui/src/hooks/useApi.ts +69 -0
- package/ui/src/hooks/useAuth.ts +100 -0
- package/ui/src/hooks/useConfirm.tsx +105 -0
- package/ui/src/hooks/useFormFooter.tsx +42 -0
- package/ui/src/hooks/usePagination.ts +69 -0
- package/ui/src/index.css +59 -0
- package/ui/src/main.tsx +13 -0
- package/ui/src/pages/AdminsPage.tsx +178 -0
- package/ui/src/pages/ApiPage.tsx +89 -0
- package/ui/src/pages/DashboardPage.tsx +281 -0
- package/ui/src/pages/LoginPage.tsx +39 -0
- package/ui/src/pages/PermissionsPage.tsx +376 -0
- package/ui/src/pages/RolesPage.tsx +274 -0
- package/ui/src/pages/TenantsPage.tsx +221 -0
- package/ui/src/pages/UsersPage.tsx +387 -0
- package/ui/src/services/api.ts +115 -0
- package/ui/src/types/index.ts +136 -0
- package/ui/src/vite-env.d.ts +9 -0
- package/ui/tailwind.config.js +45 -0
- package/ui/tsconfig.json +24 -0
- package/ui/tsconfig.node.json +10 -0
- package/ui/vite.config.ts +37 -0
- package/ui/yarn.lock +3137 -0
- package/src/index.d.ts +0 -11
- package/src/index.js +0 -18
- package/src/index.js.map +0 -1
- package/src/lib/auth/auth.module.d.ts +0 -2
- package/src/lib/auth/auth.module.js +0 -54
- package/src/lib/auth/auth.module.js.map +0 -1
- package/src/lib/auth/controllers/auth.controller.d.ts +0 -29
- package/src/lib/auth/controllers/auth.controller.js +0 -206
- package/src/lib/auth/controllers/auth.controller.js.map +0 -1
- package/src/lib/auth/controllers/mfa.controller.d.ts +0 -23
- package/src/lib/auth/controllers/mfa.controller.js +0 -131
- package/src/lib/auth/controllers/mfa.controller.js.map +0 -1
- package/src/lib/auth/dto/index.d.ts +0 -0
- package/src/lib/auth/dto/index.js +0 -1
- package/src/lib/auth/dto/index.js.map +0 -1
- package/src/lib/auth/dto/requests/forgot-password.request.dto.d.ts +0 -5
- package/src/lib/auth/dto/requests/forgot-password.request.dto.js +0 -30
- package/src/lib/auth/dto/requests/forgot-password.request.dto.js.map +0 -1
- package/src/lib/auth/dto/requests/login.request.dto.d.ts +0 -6
- package/src/lib/auth/dto/requests/login.request.dto.js +0 -38
- package/src/lib/auth/dto/requests/login.request.dto.js.map +0 -1
- package/src/lib/auth/dto/requests/refresh-token.request.dto.d.ts +0 -3
- package/src/lib/auth/dto/requests/refresh-token.request.dto.js +0 -15
- package/src/lib/auth/dto/requests/refresh-token.request.dto.js.map +0 -1
- package/src/lib/auth/dto/requests/reset-password.request.dto.d.ts +0 -7
- package/src/lib/auth/dto/requests/reset-password.request.dto.js +0 -42
- package/src/lib/auth/dto/requests/reset-password.request.dto.js.map +0 -1
- package/src/lib/auth/dto/requests/send-mfa-code.request.dto.d.ts +0 -4
- package/src/lib/auth/dto/requests/send-mfa-code.request.dto.js +0 -16
- package/src/lib/auth/dto/requests/send-mfa-code.request.dto.js.map +0 -1
- package/src/lib/auth/dto/requests/signup.request.dto.d.ts +0 -7
- package/src/lib/auth/dto/requests/signup.request.dto.js +0 -37
- package/src/lib/auth/dto/requests/signup.request.dto.js.map +0 -1
- package/src/lib/auth/dto/requests/social-login.request.dto.d.ts +0 -3
- package/src/lib/auth/dto/requests/social-login.request.dto.js +0 -16
- package/src/lib/auth/dto/requests/social-login.request.dto.js.map +0 -1
- package/src/lib/auth/dto/requests/verify-2fa.request.dto.d.ts +0 -5
- package/src/lib/auth/dto/requests/verify-2fa.request.dto.js +0 -21
- package/src/lib/auth/dto/requests/verify-2fa.request.dto.js.map +0 -1
- package/src/lib/auth/dto/requests/verify-forgot-password-otp-request-dto.d.ts +0 -6
- package/src/lib/auth/dto/requests/verify-forgot-password-otp-request-dto.js +0 -35
- package/src/lib/auth/dto/requests/verify-forgot-password-otp-request-dto.js.map +0 -1
- package/src/lib/auth/dto/requests/verify-totp-setup.request.dto.d.ts +0 -4
- package/src/lib/auth/dto/requests/verify-totp-setup.request.dto.js +0 -20
- package/src/lib/auth/dto/requests/verify-totp-setup.request.dto.js.map +0 -1
- package/src/lib/auth/dto/responses/auth.response.dto.d.ts +0 -16
- package/src/lib/auth/dto/responses/auth.response.dto.js +0 -50
- package/src/lib/auth/dto/responses/auth.response.dto.js.map +0 -1
- package/src/lib/auth/entities/mfa-secret.entity.d.ts +0 -12
- package/src/lib/auth/entities/mfa-secret.entity.js +0 -50
- package/src/lib/auth/entities/mfa-secret.entity.js.map +0 -1
- package/src/lib/auth/entities/otp.entity.d.ts +0 -13
- package/src/lib/auth/entities/otp.entity.js +0 -50
- package/src/lib/auth/entities/otp.entity.js.map +0 -1
- package/src/lib/auth/events/logged-out-all.event.js +0 -10
- package/src/lib/auth/events/logged-out-all.event.js.map +0 -1
- package/src/lib/auth/events/logged-out.event.js +0 -10
- package/src/lib/auth/events/logged-out.event.js.map +0 -1
- package/src/lib/auth/events/password-reset-requested.event.js +0 -10
- package/src/lib/auth/events/password-reset-requested.event.js.map +0 -1
- package/src/lib/auth/events/password-reset.event.js +0 -10
- package/src/lib/auth/events/password-reset.event.js.map +0 -1
- package/src/lib/auth/events/user-2fa-verified.event.js +0 -10
- package/src/lib/auth/events/user-2fa-verified.event.js.map +0 -1
- package/src/lib/auth/events/user-logged-in.event.js +0 -10
- package/src/lib/auth/events/user-logged-in.event.js.map +0 -1
- package/src/lib/auth/events/user-refresh-token.event.js +0 -10
- package/src/lib/auth/events/user-refresh-token.event.js.map +0 -1
- package/src/lib/auth/events/user-registered.event.js +0 -10
- package/src/lib/auth/events/user-registered.event.js.map +0 -1
- package/src/lib/auth/guards/auth.guard.d.ts +0 -28
- package/src/lib/auth/guards/auth.guard.js +0 -304
- package/src/lib/auth/guards/auth.guard.js.map +0 -1
- package/src/lib/auth/index.js +0 -31
- package/src/lib/auth/index.js.map +0 -1
- package/src/lib/auth/services/auth.service.d.ts +0 -53
- package/src/lib/auth/services/auth.service.js +0 -522
- package/src/lib/auth/services/auth.service.js.map +0 -1
- package/src/lib/auth/services/cookie.service.d.ts +0 -9
- package/src/lib/auth/services/cookie.service.js +0 -43
- package/src/lib/auth/services/cookie.service.js.map +0 -1
- package/src/lib/auth/services/mfa.service.d.ts +0 -38
- package/src/lib/auth/services/mfa.service.js +0 -254
- package/src/lib/auth/services/mfa.service.js.map +0 -1
- package/src/lib/auth.constants.d.ts +0 -39
- package/src/lib/auth.constants.js +0 -43
- package/src/lib/auth.constants.js.map +0 -1
- package/src/lib/core/core.module.d.ts +0 -2
- package/src/lib/core/core.module.js +0 -53
- package/src/lib/core/core.module.js.map +0 -1
- package/src/lib/core/decorators/auth.decorator.d.ts +0 -1
- package/src/lib/core/decorators/auth.decorator.js +0 -8
- package/src/lib/core/decorators/auth.decorator.js.map +0 -1
- package/src/lib/core/decorators/permissions.decorator.d.ts +0 -2
- package/src/lib/core/decorators/permissions.decorator.js +0 -14
- package/src/lib/core/decorators/permissions.decorator.js.map +0 -1
- package/src/lib/core/decorators/role.decorator.d.ts +0 -3
- package/src/lib/core/decorators/role.decorator.js +0 -14
- package/src/lib/core/decorators/role.decorator.js.map +0 -1
- package/src/lib/core/decorators/skip-mfa.decorator.d.ts +0 -2
- package/src/lib/core/decorators/skip-mfa.decorator.js +0 -8
- package/src/lib/core/decorators/skip-mfa.decorator.js.map +0 -1
- package/src/lib/core/dto/message.response.dto.d.ts +0 -3
- package/src/lib/core/dto/message.response.dto.js +0 -13
- package/src/lib/core/dto/message.response.dto.js.map +0 -1
- package/src/lib/core/entities.js +0 -31
- package/src/lib/core/entities.js.map +0 -1
- package/src/lib/core/index.js +0 -27
- package/src/lib/core/index.js.map +0 -1
- package/src/lib/core/interfaces/auth-module-options.interface.d.ts +0 -62
- package/src/lib/core/interfaces/auth-module-options.interface.js +0 -3
- package/src/lib/core/interfaces/auth-module-options.interface.js.map +0 -1
- package/src/lib/core/interfaces/mfa-options.interface.d.ts +0 -25
- package/src/lib/core/interfaces/mfa-options.interface.js +0 -10
- package/src/lib/core/interfaces/mfa-options.interface.js.map +0 -1
- package/src/lib/core/interfaces/otp.interface.d.ts +0 -5
- package/src/lib/core/interfaces/otp.interface.js +0 -10
- package/src/lib/core/interfaces/otp.interface.js.map +0 -1
- package/src/lib/core/interfaces/session-options.interface.d.ts +0 -12
- package/src/lib/core/interfaces/session-options.interface.js +0 -9
- package/src/lib/core/interfaces/session-options.interface.js.map +0 -1
- package/src/lib/core/interfaces/token-payload.interface.js +0 -3
- package/src/lib/core/interfaces/token-payload.interface.js.map +0 -1
- package/src/lib/core/providers/apple-auth.provider.d.ts +0 -18
- package/src/lib/core/providers/apple-auth.provider.js +0 -57
- package/src/lib/core/providers/apple-auth.provider.js.map +0 -1
- package/src/lib/core/providers/base-auth.provider.d.ts +0 -26
- package/src/lib/core/providers/base-auth.provider.js +0 -43
- package/src/lib/core/providers/base-auth.provider.js.map +0 -1
- package/src/lib/core/providers/email-auth.provider.d.ts +0 -17
- package/src/lib/core/providers/email-auth.provider.js +0 -40
- package/src/lib/core/providers/email-auth.provider.js.map +0 -1
- package/src/lib/core/providers/facebook-auth.provider.d.ts +0 -18
- package/src/lib/core/providers/facebook-auth.provider.js +0 -56
- package/src/lib/core/providers/facebook-auth.provider.js.map +0 -1
- package/src/lib/core/providers/google-auth.provider.d.ts +0 -21
- package/src/lib/core/providers/google-auth.provider.js +0 -58
- package/src/lib/core/providers/google-auth.provider.js.map +0 -1
- package/src/lib/core/providers/jwt-auth.provider.d.ts +0 -33
- package/src/lib/core/providers/jwt-auth.provider.js +0 -50
- package/src/lib/core/providers/jwt-auth.provider.js.map +0 -1
- package/src/lib/core/providers/phone-auth.provider.d.ts +0 -18
- package/src/lib/core/providers/phone-auth.provider.js +0 -43
- package/src/lib/core/providers/phone-auth.provider.js.map +0 -1
- package/src/lib/core/services/auth-config.service.d.ts +0 -12
- package/src/lib/core/services/auth-config.service.js +0 -79
- package/src/lib/core/services/auth-config.service.js.map +0 -1
- package/src/lib/core/services/auth-provider-registry.service.d.ts +0 -24
- package/src/lib/core/services/auth-provider-registry.service.js +0 -71
- package/src/lib/core/services/auth-provider-registry.service.js.map +0 -1
- package/src/lib/core/services/debug-logger.service.d.ts +0 -38
- package/src/lib/core/services/debug-logger.service.js.map +0 -1
- package/src/lib/core/services/initialization.service.d.ts +0 -10
- package/src/lib/core/services/initialization.service.js +0 -34
- package/src/lib/core/services/initialization.service.js.map +0 -1
- package/src/lib/core/services/jwt.service.d.ts +0 -14
- package/src/lib/core/services/jwt.service.js +0 -92
- package/src/lib/core/services/jwt.service.js.map +0 -1
- package/src/lib/nest-auth.module.d.ts +0 -11
- package/src/lib/nest-auth.module.js +0 -177
- package/src/lib/nest-auth.module.js.map +0 -1
- package/src/lib/request-context/request-context.d.ts +0 -22
- package/src/lib/request-context/request-context.js.map +0 -1
- package/src/lib/request-context/request-context.middleware.d.ts +0 -4
- package/src/lib/request-context/request-context.middleware.js +0 -16
- package/src/lib/request-context/request-context.middleware.js.map +0 -1
- package/src/lib/role/entities/role.entity.d.ts +0 -20
- package/src/lib/role/entities/role.entity.js +0 -110
- package/src/lib/role/entities/role.entity.js.map +0 -1
- package/src/lib/role/index.js +0 -5
- package/src/lib/role/index.js.map +0 -1
- package/src/lib/role/role.module.d.ts +0 -2
- package/src/lib/role/role.module.js +0 -23
- package/src/lib/role/role.module.js.map +0 -1
- package/src/lib/role/services/role.service.d.ts +0 -20
- package/src/lib/role/services/role.service.js.map +0 -1
- package/src/lib/session/entities/session.entity.d.ts +0 -16
- package/src/lib/session/entities/session.entity.js +0 -63
- package/src/lib/session/entities/session.entity.js.map +0 -1
- package/src/lib/session/index.d.ts +0 -3
- package/src/lib/session/index.js +0 -7
- package/src/lib/session/index.js.map +0 -1
- package/src/lib/session/services/base-session.service.d.ts +0 -23
- package/src/lib/session/services/base-session.service.js +0 -64
- package/src/lib/session/services/base-session.service.js.map +0 -1
- package/src/lib/session/services/database-session.service.d.ts +0 -17
- package/src/lib/session/services/database-session.service.js +0 -51
- package/src/lib/session/services/database-session.service.js.map +0 -1
- package/src/lib/session/services/redis-session.service.d.ts +0 -20
- package/src/lib/session/services/redis-session.service.js +0 -117
- package/src/lib/session/services/redis-session.service.js.map +0 -1
- package/src/lib/session/session.module.d.ts +0 -2
- package/src/lib/session/session.module.js +0 -33
- package/src/lib/session/session.module.js.map +0 -1
- package/src/lib/tenant/entities/tenant.entity.d.ts +0 -10
- package/src/lib/tenant/entities/tenant.entity.js +0 -44
- package/src/lib/tenant/entities/tenant.entity.js.map +0 -1
- package/src/lib/tenant/events/tenant-created.event.d.ts +0 -8
- package/src/lib/tenant/events/tenant-created.event.js +0 -10
- package/src/lib/tenant/events/tenant-created.event.js.map +0 -1
- package/src/lib/tenant/events/tenant-deleted.event.d.ts +0 -8
- package/src/lib/tenant/events/tenant-deleted.event.js +0 -10
- package/src/lib/tenant/events/tenant-deleted.event.js.map +0 -1
- package/src/lib/tenant/events/tenant-updated.event.js +0 -10
- package/src/lib/tenant/events/tenant-updated.event.js.map +0 -1
- package/src/lib/tenant/index.d.ts +0 -1
- package/src/lib/tenant/index.js +0 -5
- package/src/lib/tenant/index.js.map +0 -1
- package/src/lib/tenant/services/tenant.service.d.ts +0 -26
- package/src/lib/tenant/services/tenant.service.js +0 -200
- package/src/lib/tenant/services/tenant.service.js.map +0 -1
- package/src/lib/tenant/tenant.module.d.ts +0 -2
- package/src/lib/tenant/tenant.module.js +0 -27
- package/src/lib/tenant/tenant.module.js.map +0 -1
- package/src/lib/user/dto/requests/update-user.dto.d.ts +0 -5
- package/src/lib/user/dto/requests/update-user.dto.js +0 -24
- package/src/lib/user/dto/requests/update-user.dto.js.map +0 -1
- package/src/lib/user/entities/access-key.entity.d.ts +0 -16
- package/src/lib/user/entities/access-key.entity.js +0 -63
- package/src/lib/user/entities/access-key.entity.js.map +0 -1
- package/src/lib/user/entities/identity.entity.d.ts +0 -12
- package/src/lib/user/entities/identity.entity.js +0 -47
- package/src/lib/user/entities/identity.entity.js.map +0 -1
- package/src/lib/user/entities/user.entity.d.ts +0 -39
- package/src/lib/user/entities/user.entity.js +0 -201
- package/src/lib/user/entities/user.entity.js.map +0 -1
- package/src/lib/user/events/user-created.event.js +0 -10
- package/src/lib/user/events/user-created.event.js.map +0 -1
- package/src/lib/user/events/user-deleted.event.js +0 -10
- package/src/lib/user/events/user-deleted.event.js.map +0 -1
- package/src/lib/user/events/user-updated.event.js +0 -10
- package/src/lib/user/events/user-updated.event.js.map +0 -1
- package/src/lib/user/index.d.ts +0 -3
- package/src/lib/user/index.js +0 -7
- package/src/lib/user/index.js.map +0 -1
- package/src/lib/user/services/access-key.service.d.ts +0 -19
- package/src/lib/user/services/access-key.service.js +0 -119
- package/src/lib/user/services/access-key.service.js.map +0 -1
- package/src/lib/user/services/user.service.d.ts +0 -24
- package/src/lib/user/services/user.service.js.map +0 -1
- package/src/lib/user/user.module.d.ts +0 -2
- package/src/lib/user/user.module.js +0 -34
- package/src/lib/user/user.module.js.map +0 -1
- package/src/lib/utils/database.utils.d.ts +0 -2
- package/src/lib/utils/database.utils.js +0 -8
- package/src/lib/utils/database.utils.js.map +0 -1
- package/src/lib/utils/otp.d.ts +0 -1
- package/src/lib/utils/otp.js +0 -7
- package/src/lib/utils/otp.js.map +0 -1
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
import { DataSource, Repository } from 'typeorm';
|
|
2
|
+
import { RoleService } from '../src/lib/role/services/role.service';
|
|
3
|
+
import { NestAuthRole } from '../src/lib/role/entities/role.entity';
|
|
4
|
+
import { NestAuthTenant } from '../src/lib/tenant/entities/tenant.entity';
|
|
5
|
+
import { getRepositoryToken } from '@nestjs/typeorm';
|
|
6
|
+
import { createTestApp } from './test.setup';
|
|
7
|
+
import { ConflictException, NotFoundException } from '@nestjs/common';
|
|
8
|
+
import { DEFAULT_GUARD_NAME } from '../src/lib/auth.constants';
|
|
9
|
+
|
|
10
|
+
describe('RoleService', () => {
|
|
11
|
+
let service: RoleService;
|
|
12
|
+
let roleRepository: Repository<NestAuthRole>;
|
|
13
|
+
let tenantRepository: Repository<NestAuthTenant>;
|
|
14
|
+
let dataSource: DataSource;
|
|
15
|
+
let tenant1: NestAuthTenant;
|
|
16
|
+
let tenant2: NestAuthTenant;
|
|
17
|
+
|
|
18
|
+
beforeEach(async () => {
|
|
19
|
+
const app = await createTestApp();
|
|
20
|
+
|
|
21
|
+
service = app.get<RoleService>(RoleService);
|
|
22
|
+
dataSource = app.get<DataSource>(DataSource);
|
|
23
|
+
roleRepository = dataSource.getRepository(NestAuthRole);
|
|
24
|
+
tenantRepository = dataSource.getRepository(NestAuthTenant);
|
|
25
|
+
|
|
26
|
+
// Create test tenants
|
|
27
|
+
[tenant1, tenant2] = await tenantRepository.save([
|
|
28
|
+
{ name: 'Tenant 1', domain: 'tenant-1' },
|
|
29
|
+
{ name: 'Tenant 2', domain: 'tenant-2' }
|
|
30
|
+
]);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
afterEach(async () => {
|
|
34
|
+
// Clean up database after each test
|
|
35
|
+
await dataSource.synchronize(true);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
afterAll(async () => {
|
|
39
|
+
// Close the connection after all tests
|
|
40
|
+
await dataSource.destroy();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe('createRole', () => {
|
|
44
|
+
it('should create a new role successfully', async () => {
|
|
45
|
+
const result = await service.createRole('test-role', DEFAULT_GUARD_NAME, tenant1.id);
|
|
46
|
+
|
|
47
|
+
expect(result).toBeDefined();
|
|
48
|
+
expect(result.name).toBe('test-role');
|
|
49
|
+
expect(result.guard).toBe(DEFAULT_GUARD_NAME);
|
|
50
|
+
expect(result.tenantId).toBe(tenant1.id);
|
|
51
|
+
expect(result.isSystem).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should throw ConflictException if role already exists', async () => {
|
|
55
|
+
await service.createRole('test-role', DEFAULT_GUARD_NAME, tenant1.id);
|
|
56
|
+
|
|
57
|
+
await expect(
|
|
58
|
+
service.createRole('test-role', DEFAULT_GUARD_NAME, tenant1.id)
|
|
59
|
+
).rejects.toThrow(ConflictException);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should throw ConflictException if role name conflicts with system role', async () => {
|
|
63
|
+
await service.createRole('system-role', DEFAULT_GUARD_NAME, null, true);
|
|
64
|
+
|
|
65
|
+
await expect(
|
|
66
|
+
service.createRole('system-role', DEFAULT_GUARD_NAME, tenant1.id)
|
|
67
|
+
).rejects.toThrow(ConflictException);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe('getRoleById', () => {
|
|
72
|
+
it('should return role by id', async () => {
|
|
73
|
+
const role = await service.createRole('test-role', DEFAULT_GUARD_NAME, tenant1.id);
|
|
74
|
+
|
|
75
|
+
const result = await service.getRoleById(role.id);
|
|
76
|
+
|
|
77
|
+
expect(result).toBeDefined();
|
|
78
|
+
expect(result?.id).toBe(role.id);
|
|
79
|
+
expect(result?.name).toBe('test-role');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should return null if role not found', async () => {
|
|
83
|
+
const result = await service.getRoleById('non-existent-id');
|
|
84
|
+
|
|
85
|
+
expect(result).toBeNull();
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
describe('getRoleByName', () => {
|
|
90
|
+
it('should return role by name and guard', async () => {
|
|
91
|
+
await service.createRole('test-role', DEFAULT_GUARD_NAME, tenant1.id);
|
|
92
|
+
|
|
93
|
+
const result = await service.getRoleByName('test-role', DEFAULT_GUARD_NAME, tenant1.id);
|
|
94
|
+
|
|
95
|
+
expect(result).toBeDefined();
|
|
96
|
+
expect(result?.name).toBe('test-role');
|
|
97
|
+
expect(result?.guard).toBe(DEFAULT_GUARD_NAME);
|
|
98
|
+
expect(result?.tenantId).toBe(tenant1.id);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should return null if role not found', async () => {
|
|
102
|
+
const result = await service.getRoleByName('non-existent', DEFAULT_GUARD_NAME, tenant1.id);
|
|
103
|
+
|
|
104
|
+
expect(result).toBeNull();
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe('getRolesByGuard', () => {
|
|
109
|
+
it('should return roles by guard', async () => {
|
|
110
|
+
await service.createRole('test-role-1', DEFAULT_GUARD_NAME, tenant1.id);
|
|
111
|
+
await service.createRole('test-role-2', DEFAULT_GUARD_NAME, tenant1.id);
|
|
112
|
+
|
|
113
|
+
const result = await service.getRolesByGuard(DEFAULT_GUARD_NAME, tenant1.id);
|
|
114
|
+
|
|
115
|
+
expect(result).toHaveLength(2);
|
|
116
|
+
expect(result[0].guard).toBe(DEFAULT_GUARD_NAME);
|
|
117
|
+
expect(result[1].guard).toBe(DEFAULT_GUARD_NAME);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('should return empty array if guard is not provided', async () => {
|
|
121
|
+
const result = await service.getRolesByGuard('');
|
|
122
|
+
|
|
123
|
+
expect(result).toEqual([]);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe('getRolesByTenant', () => {
|
|
128
|
+
it('should return roles by tenant including system roles', async () => {
|
|
129
|
+
await service.createRole('system-role', DEFAULT_GUARD_NAME, null, true);
|
|
130
|
+
await service.createRole('tenant-role-1', DEFAULT_GUARD_NAME, tenant1.id);
|
|
131
|
+
await service.createRole('tenant-role-2', DEFAULT_GUARD_NAME, tenant1.id);
|
|
132
|
+
|
|
133
|
+
const result = await service.getRolesByTenant(tenant1.id);
|
|
134
|
+
|
|
135
|
+
expect(result).toHaveLength(3);
|
|
136
|
+
expect(result.some(role => role.name === 'system-role')).toBe(true);
|
|
137
|
+
expect(result.some(role => role.name === 'tenant-role-1')).toBe(true);
|
|
138
|
+
expect(result.some(role => role.name === 'tenant-role-2')).toBe(true);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('should return empty array if tenantId is not provided', async () => {
|
|
142
|
+
const result = await service.getRolesByTenant('');
|
|
143
|
+
|
|
144
|
+
expect(result).toEqual([]);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('updateRole', () => {
|
|
149
|
+
it('should update role successfully', async () => {
|
|
150
|
+
const role = await service.createRole('test-role', DEFAULT_GUARD_NAME, tenant1.id);
|
|
151
|
+
|
|
152
|
+
const result = await service.updateRole(role.id, { name: 'updated-role' });
|
|
153
|
+
|
|
154
|
+
expect(result.name).toBe('updated-role');
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('should throw NotFoundException if role not found', async () => {
|
|
158
|
+
await expect(
|
|
159
|
+
service.updateRole('non-existent-id', { name: 'updated-role' })
|
|
160
|
+
).rejects.toThrow(NotFoundException);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('should throw BadRequestException if trying to update system role', async () => {
|
|
164
|
+
const systemRole = await service.createRole('system-role', DEFAULT_GUARD_NAME, null, true);
|
|
165
|
+
|
|
166
|
+
await expect(
|
|
167
|
+
service.updateRole(systemRole.id, { name: 'updated-role' })
|
|
168
|
+
).rejects.toThrow('Cannot update system role');
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
describe('updateRolePermissions', () => {
|
|
173
|
+
it('should update role permissions successfully', async () => {
|
|
174
|
+
const role = await service.createRole('test-role', DEFAULT_GUARD_NAME, tenant1.id);
|
|
175
|
+
|
|
176
|
+
const result = await service.updateRolePermissions(role.id, ['permission-1', 'permission-2']);
|
|
177
|
+
|
|
178
|
+
expect(result).toBeDefined();
|
|
179
|
+
expect(result.permissions).toHaveLength(2);
|
|
180
|
+
expect(result.permissions).toContain('permission-1');
|
|
181
|
+
expect(result.permissions).toContain('permission-2');
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should throw NotFoundException if role not found', async () => {
|
|
185
|
+
await expect(
|
|
186
|
+
service.updateRolePermissions('non-existent-id', ['permission-1'])
|
|
187
|
+
).rejects.toThrow(NotFoundException);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('should throw BadRequestException if trying to update system role permissions', async () => {
|
|
191
|
+
const systemRole = await service.createRole('system-role', DEFAULT_GUARD_NAME, null, true);
|
|
192
|
+
|
|
193
|
+
await expect(
|
|
194
|
+
service.updateRolePermissions(systemRole.id, ['permission-1'])
|
|
195
|
+
).rejects.toThrow('Cannot update system role');
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
describe('deleteRole', () => {
|
|
200
|
+
it('should delete role successfully', async () => {
|
|
201
|
+
const role = await service.createRole('test-role', DEFAULT_GUARD_NAME, tenant1.id);
|
|
202
|
+
|
|
203
|
+
await service.deleteRole(role.id);
|
|
204
|
+
|
|
205
|
+
const deletedRole = await service.getRoleById(role.id);
|
|
206
|
+
expect(deletedRole).toBeNull();
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('should throw NotFoundException if role not found', async () => {
|
|
210
|
+
await expect(
|
|
211
|
+
service.deleteRole('non-existent-id')
|
|
212
|
+
).rejects.toThrow(NotFoundException);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('should throw BadRequestException if trying to delete system role', async () => {
|
|
216
|
+
const systemRole = await service.createRole('system-role', DEFAULT_GUARD_NAME, null, true);
|
|
217
|
+
|
|
218
|
+
await expect(
|
|
219
|
+
service.deleteRole(systemRole.id)
|
|
220
|
+
).rejects.toThrow('Cannot delete system role');
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
describe('deleteSystemRole', () => {
|
|
225
|
+
it('should delete system role successfully', async () => {
|
|
226
|
+
const systemRole = await service.createRole('system-role', DEFAULT_GUARD_NAME, null, true);
|
|
227
|
+
|
|
228
|
+
await service.deleteSystemRole(systemRole.id);
|
|
229
|
+
|
|
230
|
+
const deletedRole = await service.getRoleById(systemRole.id);
|
|
231
|
+
expect(deletedRole).toBeNull();
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it('should not throw error if role not found', async () => {
|
|
235
|
+
await expect(service.deleteSystemRole('non-existent-id')).resolves.not.toThrow();
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('should not delete if role is not a system role', async () => {
|
|
239
|
+
const role = await service.createRole('test-role', DEFAULT_GUARD_NAME, tenant1.id);
|
|
240
|
+
|
|
241
|
+
await service.deleteSystemRole(role.id);
|
|
242
|
+
|
|
243
|
+
const existingRole = await service.getRoleById(role.id);
|
|
244
|
+
expect(existingRole).toBeDefined();
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
describe('Multiple Tenants and Guards', () => {
|
|
249
|
+
it('should allow same role name across different tenants', async () => {
|
|
250
|
+
// Create role in tenant-1
|
|
251
|
+
const role1 = await service.createRole('admin', DEFAULT_GUARD_NAME, tenant1.id);
|
|
252
|
+
expect(role1.name).toBe('admin');
|
|
253
|
+
expect(role1.tenantId).toBe(tenant1.id);
|
|
254
|
+
|
|
255
|
+
// Create same role in tenant-2
|
|
256
|
+
const role2 = await service.createRole('admin', DEFAULT_GUARD_NAME, tenant2.id);
|
|
257
|
+
expect(role2.name).toBe('admin');
|
|
258
|
+
expect(role2.tenantId).toBe(tenant2.id);
|
|
259
|
+
|
|
260
|
+
// Verify both roles exist
|
|
261
|
+
const roles = await service.getRolesByGuard(DEFAULT_GUARD_NAME, tenant1.id);
|
|
262
|
+
expect(roles).toHaveLength(1);
|
|
263
|
+
expect(roles[0].name).toBe('admin');
|
|
264
|
+
expect(roles[0].tenantId).toBe(tenant1.id);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('should allow same role name across different guards in same tenant', async () => {
|
|
268
|
+
// Create role with web guard
|
|
269
|
+
const webRole = await service.createRole('admin', 'web', tenant1.id);
|
|
270
|
+
expect(webRole.name).toBe('admin');
|
|
271
|
+
expect(webRole.guard).toBe('web');
|
|
272
|
+
|
|
273
|
+
// Create same role with api guard
|
|
274
|
+
const apiRole = await service.createRole('admin', 'api', tenant1.id);
|
|
275
|
+
expect(apiRole.name).toBe('admin');
|
|
276
|
+
expect(apiRole.guard).toBe('api');
|
|
277
|
+
|
|
278
|
+
// Verify both roles exist
|
|
279
|
+
const webRoles = await service.getRolesByGuard('web', tenant1.id);
|
|
280
|
+
expect(webRoles).toHaveLength(1);
|
|
281
|
+
expect(webRoles[0].name).toBe('admin');
|
|
282
|
+
|
|
283
|
+
const apiRoles = await service.getRolesByGuard('api', tenant1.id);
|
|
284
|
+
expect(apiRoles).toHaveLength(1);
|
|
285
|
+
expect(apiRoles[0].name).toBe('admin');
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('should prevent role name conflicts within same tenant and guard', async () => {
|
|
289
|
+
// Create initial role
|
|
290
|
+
await service.createRole('admin', 'web', tenant1.id);
|
|
291
|
+
|
|
292
|
+
// Try to create same role in same tenant and guard
|
|
293
|
+
await expect(
|
|
294
|
+
service.createRole('admin', 'web', tenant1.id)
|
|
295
|
+
).rejects.toThrow(ConflictException);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('should prevent role name conflicts with system roles across all tenants', async () => {
|
|
299
|
+
// Create system role
|
|
300
|
+
await service.createRole('super-admin', DEFAULT_GUARD_NAME, null, true);
|
|
301
|
+
|
|
302
|
+
// Try to create same role in different tenants
|
|
303
|
+
await expect(
|
|
304
|
+
service.createRole('super-admin', DEFAULT_GUARD_NAME, tenant1.id)
|
|
305
|
+
).rejects.toThrow(ConflictException);
|
|
306
|
+
|
|
307
|
+
await expect(
|
|
308
|
+
service.createRole('super-admin', DEFAULT_GUARD_NAME, tenant2.id)
|
|
309
|
+
).rejects.toThrow(ConflictException);
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
describe('Role Update Restrictions', () => {
|
|
314
|
+
it('should prevent updating system role properties', async () => {
|
|
315
|
+
const systemRole = await service.createRole('system-role', DEFAULT_GUARD_NAME, null, true);
|
|
316
|
+
|
|
317
|
+
// Try to update various properties
|
|
318
|
+
await expect(
|
|
319
|
+
service.updateRole(systemRole.id, { name: 'new-name' })
|
|
320
|
+
).rejects.toThrow('Cannot update system role');
|
|
321
|
+
|
|
322
|
+
await expect(
|
|
323
|
+
service.updateRole(systemRole.id, { guard: 'new-guard' })
|
|
324
|
+
).rejects.toThrow('Cannot update system role');
|
|
325
|
+
|
|
326
|
+
await expect(
|
|
327
|
+
service.updateRole(systemRole.id, { isSystem: false })
|
|
328
|
+
).rejects.toThrow('Cannot update system role');
|
|
329
|
+
|
|
330
|
+
await expect(
|
|
331
|
+
service.updateRole(systemRole.id, { tenantId: tenant1.id })
|
|
332
|
+
).rejects.toThrow('Cannot update system role');
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
it('should prevent updating role to conflict with existing roles', async () => {
|
|
336
|
+
// Create two roles
|
|
337
|
+
const role1 = await service.createRole('role1', 'web', tenant1.id);
|
|
338
|
+
await service.createRole('role2', 'web', tenant1.id);
|
|
339
|
+
|
|
340
|
+
// Try to update role1 to conflict with role2
|
|
341
|
+
await expect(
|
|
342
|
+
service.updateRole(role1.id, { name: 'role2' })
|
|
343
|
+
).rejects.toThrow(ConflictException);
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
it('should prevent updating role to conflict with system roles', async () => {
|
|
347
|
+
// Create system role
|
|
348
|
+
await service.createRole('system-role', DEFAULT_GUARD_NAME, null, true);
|
|
349
|
+
|
|
350
|
+
// Create regular role
|
|
351
|
+
const regularRole = await service.createRole('regular-role', DEFAULT_GUARD_NAME, tenant1.id);
|
|
352
|
+
|
|
353
|
+
// Try to update regular role to system role name
|
|
354
|
+
await expect(
|
|
355
|
+
service.updateRole(regularRole.id, { name: 'system-role' })
|
|
356
|
+
).rejects.toThrow(ConflictException);
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
it('should allow updating role name to a new unique name', async () => {
|
|
360
|
+
const role = await service.createRole('old-name', 'web', tenant1.id);
|
|
361
|
+
|
|
362
|
+
const updatedRole = await service.updateRole(role.id, { name: 'new-name' });
|
|
363
|
+
|
|
364
|
+
expect(updatedRole.name).toBe('new-name');
|
|
365
|
+
expect(updatedRole.guard).toBe('web');
|
|
366
|
+
expect(updatedRole.tenantId).toBe(tenant1.id);
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it('should allow updating role guard if name remains unique', async () => {
|
|
370
|
+
const role = await service.createRole('admin', 'web', tenant1.id);
|
|
371
|
+
|
|
372
|
+
const updatedRole = await service.updateRole(role.id, { guard: 'api' });
|
|
373
|
+
|
|
374
|
+
expect(updatedRole.name).toBe('admin');
|
|
375
|
+
expect(updatedRole.guard).toBe('api');
|
|
376
|
+
expect(updatedRole.tenantId).toBe(tenant1.id);
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
describe('Role Permissions Management', () => {
|
|
381
|
+
it('should handle permissions across multiple tenants', async () => {
|
|
382
|
+
// Create roles in different tenants
|
|
383
|
+
const role1 = await service.createRole('admin', 'web', tenant1.id);
|
|
384
|
+
const role2 = await service.createRole('admin', 'web', tenant2.id);
|
|
385
|
+
|
|
386
|
+
// Update permissions for each role
|
|
387
|
+
const updatedRole1 = await service.updateRolePermissions(role1.id, ['permission-1', 'permission-2']);
|
|
388
|
+
const updatedRole2 = await service.updateRolePermissions(role2.id, ['permission-3', 'permission-4']);
|
|
389
|
+
|
|
390
|
+
// Verify permissions are set correctly
|
|
391
|
+
expect(updatedRole1.permissions).toHaveLength(2);
|
|
392
|
+
expect(updatedRole1.permissions).toContain('permission-1');
|
|
393
|
+
expect(updatedRole1.permissions).toContain('permission-2');
|
|
394
|
+
|
|
395
|
+
expect(updatedRole2.permissions).toHaveLength(2);
|
|
396
|
+
expect(updatedRole2.permissions).toContain('permission-3');
|
|
397
|
+
expect(updatedRole2.permissions).toContain('permission-4');
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
it('should prevent updating permissions for system roles', async () => {
|
|
401
|
+
const systemRole = await service.createRole('system-role', DEFAULT_GUARD_NAME, null, true);
|
|
402
|
+
|
|
403
|
+
await expect(
|
|
404
|
+
service.updateRolePermissions(systemRole.id, ['permission-1'])
|
|
405
|
+
).rejects.toThrow('Cannot update system role');
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
it('should allow updating permissions for regular roles', async () => {
|
|
409
|
+
const role = await service.createRole('regular-role', 'web', tenant1.id);
|
|
410
|
+
|
|
411
|
+
const updatedRole = await service.updateRolePermissions(role.id, ['permission-1', 'permission-2']);
|
|
412
|
+
|
|
413
|
+
expect(updatedRole.permissions).toHaveLength(2);
|
|
414
|
+
expect(updatedRole.permissions).toContain('permission-1');
|
|
415
|
+
expect(updatedRole.permissions).toContain('permission-2');
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
});
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { DataSource, Repository } from 'typeorm';
|
|
2
|
+
import { TenantService } from '../src/lib/tenant/services/tenant.service';
|
|
3
|
+
import { NestAuthTenant } from '../src/lib/tenant/entities/tenant.entity';
|
|
4
|
+
import { getRepositoryToken } from '@nestjs/typeorm';
|
|
5
|
+
import { createTestApp } from './test.setup';
|
|
6
|
+
import { ConflictException, NotFoundException } from '@nestjs/common';
|
|
7
|
+
|
|
8
|
+
describe('TenantService', () => {
|
|
9
|
+
let service: TenantService;
|
|
10
|
+
let tenantRepository: Repository<NestAuthTenant>;
|
|
11
|
+
let dataSource: DataSource;
|
|
12
|
+
|
|
13
|
+
beforeEach(async () => {
|
|
14
|
+
const app = await createTestApp();
|
|
15
|
+
|
|
16
|
+
service = app.get<TenantService>(TenantService);
|
|
17
|
+
dataSource = app.get<DataSource>(DataSource);
|
|
18
|
+
tenantRepository = dataSource.getRepository(NestAuthTenant);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
afterEach(async () => {
|
|
22
|
+
// Clean up database after each test
|
|
23
|
+
await dataSource.synchronize(true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
afterAll(async () => {
|
|
27
|
+
// Close the connection after all tests
|
|
28
|
+
await dataSource.destroy();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('createTenant', () => {
|
|
32
|
+
it('should create a new tenant successfully', async () => {
|
|
33
|
+
const createData = {
|
|
34
|
+
name: 'Test Tenant',
|
|
35
|
+
domain: 'test.example.com',
|
|
36
|
+
description: 'Test tenant description'
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const result = await service.createTenant(createData);
|
|
40
|
+
|
|
41
|
+
expect(result).toBeDefined();
|
|
42
|
+
expect(result.name).toBe(createData.name);
|
|
43
|
+
expect(result.domain).toBe(createData.domain);
|
|
44
|
+
expect(result.description).toBe(createData.description);
|
|
45
|
+
expect(result.isActive).toBe(true);
|
|
46
|
+
expect(result.metadata).toEqual({});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should throw ConflictException if tenant with same domain exists', async () => {
|
|
50
|
+
const createData = {
|
|
51
|
+
name: 'Test Tenant',
|
|
52
|
+
domain: 'test.example.com'
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
await service.createTenant(createData);
|
|
56
|
+
|
|
57
|
+
await expect(service.createTenant(createData)).rejects.toThrow(ConflictException);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('getTenantById', () => {
|
|
62
|
+
it('should return tenant by id', async () => {
|
|
63
|
+
const tenant = await service.createTenant({
|
|
64
|
+
name: 'Test Tenant',
|
|
65
|
+
domain: 'test.example.com'
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const result = await service.getTenantById(tenant.id);
|
|
69
|
+
|
|
70
|
+
expect(result).toBeDefined();
|
|
71
|
+
expect(result?.id).toBe(tenant.id);
|
|
72
|
+
expect(result?.name).toBe('Test Tenant');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should return null if tenant not found', async () => {
|
|
76
|
+
const result = await service.getTenantById('non-existent-id');
|
|
77
|
+
|
|
78
|
+
expect(result).toBeNull();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe('getTenantByDomain', () => {
|
|
83
|
+
it('should return tenant by domain', async () => {
|
|
84
|
+
const tenant = await service.createTenant({
|
|
85
|
+
name: 'Test Tenant',
|
|
86
|
+
domain: 'test.example.com'
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const result = await service.getTenantByDomain('test.example.com');
|
|
90
|
+
|
|
91
|
+
expect(result).toBeDefined();
|
|
92
|
+
expect(result?.domain).toBe('test.example.com');
|
|
93
|
+
expect(result?.id).toBe(tenant.id);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should return null if tenant not found', async () => {
|
|
97
|
+
const result = await service.getTenantByDomain('non-existent.com');
|
|
98
|
+
|
|
99
|
+
expect(result).toBeNull();
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
describe('updateTenant', () => {
|
|
104
|
+
it('should update tenant successfully', async () => {
|
|
105
|
+
const tenant = await service.createTenant({
|
|
106
|
+
name: 'Test Tenant',
|
|
107
|
+
domain: 'test.example.com'
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const updateData = {
|
|
111
|
+
name: 'Updated Tenant',
|
|
112
|
+
description: 'Updated description'
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const result = await service.updateTenant(tenant.id, updateData);
|
|
116
|
+
|
|
117
|
+
expect(result.name).toBe(updateData.name);
|
|
118
|
+
expect(result.description).toBe(updateData.description);
|
|
119
|
+
expect(result.domain).toBe('test.example.com'); // Domain should remain unchanged
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('should throw NotFoundException if tenant not found', async () => {
|
|
123
|
+
await expect(
|
|
124
|
+
service.updateTenant('non-existent-id', { name: 'Updated Tenant' })
|
|
125
|
+
).rejects.toThrow(NotFoundException);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe('deleteTenant', () => {
|
|
130
|
+
it('should delete tenant successfully', async () => {
|
|
131
|
+
const tenant = await service.createTenant({
|
|
132
|
+
name: 'Test Tenant',
|
|
133
|
+
domain: 'test.example.com'
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
await service.deleteTenant(tenant.id);
|
|
137
|
+
|
|
138
|
+
const deletedTenant = await service.getTenantById(tenant.id);
|
|
139
|
+
expect(deletedTenant).toBeNull();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should throw NotFoundException if tenant not found', async () => {
|
|
143
|
+
await expect(
|
|
144
|
+
service.deleteTenant('non-existent-id')
|
|
145
|
+
).rejects.toThrow(NotFoundException);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
describe('updateTenantStatus', () => {
|
|
150
|
+
it('should update tenant status successfully', async () => {
|
|
151
|
+
const tenant = await service.createTenant({
|
|
152
|
+
name: 'Test Tenant',
|
|
153
|
+
domain: 'test.example.com'
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const result = await service.updateTenantStatus(tenant.id, false);
|
|
157
|
+
|
|
158
|
+
expect(result.isActive).toBe(false);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('should throw NotFoundException if tenant not found', async () => {
|
|
162
|
+
await expect(
|
|
163
|
+
service.updateTenantStatus('non-existent-id', false)
|
|
164
|
+
).rejects.toThrow(NotFoundException);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
describe('updateTenantMetadata', () => {
|
|
169
|
+
it('should update tenant metadata successfully', async () => {
|
|
170
|
+
const tenant = await service.createTenant({
|
|
171
|
+
name: 'Test Tenant',
|
|
172
|
+
domain: 'test.example.com'
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const metadata = { key: 'value', nested: { data: 'test' } };
|
|
176
|
+
const result = await service.updateTenantMetadata(tenant.id, metadata);
|
|
177
|
+
|
|
178
|
+
expect(result.metadata).toEqual(metadata);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('should throw NotFoundException if tenant not found', async () => {
|
|
182
|
+
await expect(
|
|
183
|
+
service.updateTenantMetadata('non-existent-id', { key: 'value' })
|
|
184
|
+
).rejects.toThrow(NotFoundException);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe('Multiple Tenants', () => {
|
|
189
|
+
it('should allow multiple tenants with different domains', async () => {
|
|
190
|
+
const tenant1 = await service.createTenant({
|
|
191
|
+
name: 'Tenant 1',
|
|
192
|
+
domain: 'tenant1.example.com'
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const tenant2 = await service.createTenant({
|
|
196
|
+
name: 'Tenant 2',
|
|
197
|
+
domain: 'tenant2.example.com'
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
expect(tenant1.id).not.toBe(tenant2.id);
|
|
201
|
+
expect(tenant1.domain).not.toBe(tenant2.domain);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('should prevent duplicate domains across tenants', async () => {
|
|
205
|
+
await service.createTenant({
|
|
206
|
+
name: 'Tenant 1',
|
|
207
|
+
domain: 'example.com'
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
await expect(
|
|
211
|
+
service.createTenant({
|
|
212
|
+
name: 'Tenant 2',
|
|
213
|
+
domain: 'example.com'
|
|
214
|
+
})
|
|
215
|
+
).rejects.toThrow(ConflictException);
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
});
|