hazo_auth 4.6.3 → 5.1.1

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.
Files changed (264) hide show
  1. package/README.md +28 -3
  2. package/SETUP_CHECKLIST.md +82 -4
  3. package/bin/hazo_auth.mjs +0 -0
  4. package/cli-src/cli/index.ts +12 -0
  5. package/cli-src/cli/init_permissions.ts +164 -0
  6. package/cli-src/cli/init_users.ts +92 -2
  7. package/cli-src/lib/app_user_data_config.server.ts +191 -0
  8. package/cli-src/lib/auth/auth_types.ts +12 -53
  9. package/cli-src/lib/auth/auth_utils.server.ts +6 -6
  10. package/cli-src/lib/auth/hazo_get_auth.server.ts +52 -163
  11. package/cli-src/lib/auth/scope_cache.ts +15 -23
  12. package/cli-src/lib/auth/server_auth.ts +3 -3
  13. package/cli-src/lib/branding_config.server.ts +130 -0
  14. package/cli-src/lib/config/default_config.ts +4 -17
  15. package/cli-src/lib/index.ts +2 -0
  16. package/cli-src/lib/scope_hierarchy_config.server.ts +19 -76
  17. package/cli-src/lib/services/branding_service.ts +405 -0
  18. package/cli-src/lib/services/firm_service.ts +320 -0
  19. package/cli-src/lib/services/index.ts +7 -0
  20. package/cli-src/lib/services/invitation_service.ts +542 -0
  21. package/cli-src/lib/services/login_service.ts +2 -2
  22. package/cli-src/lib/services/oauth_service.ts +1 -1
  23. package/cli-src/lib/services/post_verification_service.ts +231 -0
  24. package/cli-src/lib/services/registration_service.ts +1 -1
  25. package/cli-src/lib/services/scope_service.ts +371 -249
  26. package/cli-src/lib/services/user_scope_service.ts +189 -158
  27. package/dist/cli/index.js +11 -0
  28. package/dist/cli/init_permissions.d.ts +11 -0
  29. package/dist/cli/init_permissions.d.ts.map +1 -0
  30. package/dist/cli/init_permissions.js +138 -0
  31. package/dist/cli/init_users.d.ts.map +1 -1
  32. package/dist/cli/init_users.js +78 -2
  33. package/dist/client.d.ts +2 -0
  34. package/dist/client.d.ts.map +1 -1
  35. package/dist/client.js +1 -0
  36. package/dist/components/layouts/create_firm/hooks/use_create_firm_form.d.ts +32 -0
  37. package/dist/components/layouts/create_firm/hooks/use_create_firm_form.d.ts.map +1 -0
  38. package/dist/components/layouts/create_firm/hooks/use_create_firm_form.js +99 -0
  39. package/dist/components/layouts/create_firm/index.d.ts +44 -0
  40. package/dist/components/layouts/create_firm/index.d.ts.map +1 -0
  41. package/dist/components/layouts/create_firm/index.js +40 -0
  42. package/dist/components/layouts/scope_management/components/branding_editor.d.ts +16 -0
  43. package/dist/components/layouts/scope_management/components/branding_editor.d.ts.map +1 -0
  44. package/dist/components/layouts/scope_management/components/branding_editor.js +189 -0
  45. package/dist/components/layouts/shared/components/auth_navbar.js +1 -1
  46. package/dist/components/layouts/shared/components/form_action_buttons.d.ts +5 -3
  47. package/dist/components/layouts/shared/components/form_action_buttons.d.ts.map +1 -1
  48. package/dist/components/layouts/shared/components/form_action_buttons.js +3 -3
  49. package/dist/components/layouts/shared/components/standalone_layout_wrapper.d.ts.map +1 -1
  50. package/dist/components/layouts/shared/components/standalone_layout_wrapper.js +3 -6
  51. package/dist/components/layouts/shared/hooks/use_firm_branding.d.ts +66 -0
  52. package/dist/components/layouts/shared/hooks/use_firm_branding.d.ts.map +1 -0
  53. package/dist/components/layouts/shared/hooks/use_firm_branding.js +177 -0
  54. package/dist/components/layouts/user_management/components/app_user_data_editor.d.ts +12 -0
  55. package/dist/components/layouts/user_management/components/app_user_data_editor.d.ts.map +1 -0
  56. package/dist/components/layouts/user_management/components/app_user_data_editor.js +204 -0
  57. package/dist/components/layouts/user_management/components/scope_hierarchy_tab.d.ts +1 -2
  58. package/dist/components/layouts/user_management/components/scope_hierarchy_tab.d.ts.map +1 -1
  59. package/dist/components/layouts/user_management/components/scope_hierarchy_tab.js +53 -92
  60. package/dist/components/layouts/user_management/components/user_scopes_tab.d.ts.map +1 -1
  61. package/dist/components/layouts/user_management/components/user_scopes_tab.js +12 -27
  62. package/dist/components/layouts/user_management/index.d.ts +1 -3
  63. package/dist/components/layouts/user_management/index.d.ts.map +1 -1
  64. package/dist/components/layouts/user_management/index.js +28 -199
  65. package/dist/lib/app_user_data_config.server.d.ts +57 -0
  66. package/dist/lib/app_user_data_config.server.d.ts.map +1 -0
  67. package/dist/lib/app_user_data_config.server.js +132 -0
  68. package/dist/lib/auth/auth_types.d.ts +10 -46
  69. package/dist/lib/auth/auth_types.d.ts.map +1 -1
  70. package/dist/lib/auth/auth_types.js +4 -16
  71. package/dist/lib/auth/auth_utils.server.js +6 -6
  72. package/dist/lib/auth/hazo_get_auth.server.d.ts +2 -2
  73. package/dist/lib/auth/hazo_get_auth.server.d.ts.map +1 -1
  74. package/dist/lib/auth/hazo_get_auth.server.js +21 -120
  75. package/dist/lib/auth/scope_cache.d.ts +6 -8
  76. package/dist/lib/auth/scope_cache.d.ts.map +1 -1
  77. package/dist/lib/auth/scope_cache.js +13 -14
  78. package/dist/lib/auth/server_auth.js +3 -3
  79. package/dist/lib/branding_config.server.d.ts +39 -0
  80. package/dist/lib/branding_config.server.d.ts.map +1 -0
  81. package/dist/lib/branding_config.server.js +61 -0
  82. package/dist/lib/config/default_config.d.ts +8 -28
  83. package/dist/lib/config/default_config.d.ts.map +1 -1
  84. package/dist/lib/config/default_config.js +4 -16
  85. package/dist/lib/index.d.ts +2 -0
  86. package/dist/lib/index.d.ts.map +1 -1
  87. package/dist/lib/index.js +1 -0
  88. package/dist/lib/scope_hierarchy_config.server.d.ts +5 -12
  89. package/dist/lib/scope_hierarchy_config.server.d.ts.map +1 -1
  90. package/dist/lib/scope_hierarchy_config.server.js +6 -57
  91. package/dist/lib/services/branding_service.d.ts +50 -0
  92. package/dist/lib/services/branding_service.d.ts.map +1 -0
  93. package/dist/lib/services/branding_service.js +320 -0
  94. package/dist/lib/services/firm_service.d.ts +38 -0
  95. package/dist/lib/services/firm_service.d.ts.map +1 -0
  96. package/dist/lib/services/firm_service.js +261 -0
  97. package/dist/lib/services/index.d.ts +7 -0
  98. package/dist/lib/services/index.d.ts.map +1 -1
  99. package/dist/lib/services/index.js +7 -0
  100. package/dist/lib/services/invitation_service.d.ts +66 -0
  101. package/dist/lib/services/invitation_service.d.ts.map +1 -0
  102. package/dist/lib/services/invitation_service.js +422 -0
  103. package/dist/lib/services/login_service.js +2 -2
  104. package/dist/lib/services/oauth_service.js +1 -1
  105. package/dist/lib/services/post_verification_service.d.ts +45 -0
  106. package/dist/lib/services/post_verification_service.d.ts.map +1 -0
  107. package/dist/lib/services/post_verification_service.js +164 -0
  108. package/dist/lib/services/registration_service.js +1 -1
  109. package/dist/lib/services/scope_service.d.ts +84 -57
  110. package/dist/lib/services/scope_service.d.ts.map +1 -1
  111. package/dist/lib/services/scope_service.js +313 -181
  112. package/dist/lib/services/user_scope_service.d.ts +39 -21
  113. package/dist/lib/services/user_scope_service.d.ts.map +1 -1
  114. package/dist/lib/services/user_scope_service.js +146 -112
  115. package/dist/page_components/create_firm.d.ts +7 -0
  116. package/dist/page_components/create_firm.d.ts.map +1 -0
  117. package/dist/page_components/create_firm.js +31 -0
  118. package/dist/page_components/index.d.ts +1 -1
  119. package/dist/page_components/index.d.ts.map +1 -1
  120. package/dist/page_components/index.js +1 -1
  121. package/dist/server/routes/create_firm.d.ts +2 -0
  122. package/dist/server/routes/create_firm.d.ts.map +1 -0
  123. package/dist/server/routes/create_firm.js +2 -0
  124. package/dist/server/routes/index.d.ts +2 -1
  125. package/dist/server/routes/index.d.ts.map +1 -1
  126. package/dist/server/routes/index.js +4 -2
  127. package/dist/server/routes/invitations.d.ts +2 -0
  128. package/dist/server/routes/invitations.d.ts.map +1 -0
  129. package/dist/server/routes/invitations.js +2 -0
  130. package/hazo_auth_config.example.ini +35 -9
  131. package/package.json +12 -8
  132. package/public/hazo_auth/images/new_firm_default.jpg +0 -0
  133. package/dist/app/api/hazo_auth/app_user_data/route.d.ts +0 -64
  134. package/dist/app/api/hazo_auth/app_user_data/route.d.ts.map +0 -1
  135. package/dist/app/api/hazo_auth/app_user_data/route.js +0 -208
  136. package/dist/app/api/hazo_auth/change_password/route.d.ts +0 -8
  137. package/dist/app/api/hazo_auth/change_password/route.d.ts.map +0 -1
  138. package/dist/app/api/hazo_auth/change_password/route.js +0 -98
  139. package/dist/app/api/hazo_auth/forgot_password/route.d.ts +0 -8
  140. package/dist/app/api/hazo_auth/forgot_password/route.d.ts.map +0 -1
  141. package/dist/app/api/hazo_auth/forgot_password/route.js +0 -93
  142. package/dist/app/api/hazo_auth/get_auth/route.d.ts +0 -10
  143. package/dist/app/api/hazo_auth/get_auth/route.d.ts.map +0 -1
  144. package/dist/app/api/hazo_auth/get_auth/route.js +0 -63
  145. package/dist/app/api/hazo_auth/invalidate_cache/route.d.ts +0 -14
  146. package/dist/app/api/hazo_auth/invalidate_cache/route.d.ts.map +0 -1
  147. package/dist/app/api/hazo_auth/invalidate_cache/route.js +0 -96
  148. package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.d.ts +0 -9
  149. package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.d.ts.map +0 -1
  150. package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.js +0 -82
  151. package/dist/app/api/hazo_auth/library_photos/route.d.ts +0 -22
  152. package/dist/app/api/hazo_auth/library_photos/route.d.ts.map +0 -1
  153. package/dist/app/api/hazo_auth/library_photos/route.js +0 -80
  154. package/dist/app/api/hazo_auth/login/route.d.ts +0 -12
  155. package/dist/app/api/hazo_auth/login/route.d.ts.map +0 -1
  156. package/dist/app/api/hazo_auth/login/route.js +0 -156
  157. package/dist/app/api/hazo_auth/logout/route.d.ts +0 -8
  158. package/dist/app/api/hazo_auth/logout/route.d.ts.map +0 -1
  159. package/dist/app/api/hazo_auth/logout/route.js +0 -103
  160. package/dist/app/api/hazo_auth/me/route.d.ts +0 -36
  161. package/dist/app/api/hazo_auth/me/route.d.ts.map +0 -1
  162. package/dist/app/api/hazo_auth/me/route.js +0 -132
  163. package/dist/app/api/hazo_auth/org_management/orgs/route.d.ts +0 -26
  164. package/dist/app/api/hazo_auth/org_management/orgs/route.d.ts.map +0 -1
  165. package/dist/app/api/hazo_auth/org_management/orgs/route.js +0 -315
  166. package/dist/app/api/hazo_auth/profile_picture/[filename]/route.d.ts +0 -7
  167. package/dist/app/api/hazo_auth/profile_picture/[filename]/route.d.ts.map +0 -1
  168. package/dist/app/api/hazo_auth/profile_picture/[filename]/route.js +0 -43
  169. package/dist/app/api/hazo_auth/register/route.d.ts +0 -9
  170. package/dist/app/api/hazo_auth/register/route.d.ts.map +0 -1
  171. package/dist/app/api/hazo_auth/register/route.js +0 -80
  172. package/dist/app/api/hazo_auth/remove_profile_picture/route.d.ts +0 -8
  173. package/dist/app/api/hazo_auth/remove_profile_picture/route.d.ts.map +0 -1
  174. package/dist/app/api/hazo_auth/remove_profile_picture/route.js +0 -64
  175. package/dist/app/api/hazo_auth/resend_verification/route.d.ts +0 -8
  176. package/dist/app/api/hazo_auth/resend_verification/route.d.ts.map +0 -1
  177. package/dist/app/api/hazo_auth/resend_verification/route.js +0 -79
  178. package/dist/app/api/hazo_auth/reset_password/route.d.ts +0 -8
  179. package/dist/app/api/hazo_auth/reset_password/route.d.ts.map +0 -1
  180. package/dist/app/api/hazo_auth/reset_password/route.js +0 -76
  181. package/dist/app/api/hazo_auth/update_user/route.d.ts +0 -9
  182. package/dist/app/api/hazo_auth/update_user/route.d.ts.map +0 -1
  183. package/dist/app/api/hazo_auth/update_user/route.js +0 -98
  184. package/dist/app/api/hazo_auth/upload_profile_picture/route.d.ts +0 -9
  185. package/dist/app/api/hazo_auth/upload_profile_picture/route.d.ts.map +0 -1
  186. package/dist/app/api/hazo_auth/upload_profile_picture/route.js +0 -204
  187. package/dist/app/api/hazo_auth/user_management/permissions/route.d.ts +0 -50
  188. package/dist/app/api/hazo_auth/user_management/permissions/route.d.ts.map +0 -1
  189. package/dist/app/api/hazo_auth/user_management/permissions/route.js +0 -257
  190. package/dist/app/api/hazo_auth/user_management/roles/route.d.ts +0 -40
  191. package/dist/app/api/hazo_auth/user_management/roles/route.d.ts.map +0 -1
  192. package/dist/app/api/hazo_auth/user_management/roles/route.js +0 -352
  193. package/dist/app/api/hazo_auth/user_management/users/roles/route.d.ts +0 -37
  194. package/dist/app/api/hazo_auth/user_management/users/roles/route.d.ts.map +0 -1
  195. package/dist/app/api/hazo_auth/user_management/users/roles/route.js +0 -276
  196. package/dist/app/api/hazo_auth/user_management/users/route.d.ts +0 -50
  197. package/dist/app/api/hazo_auth/user_management/users/route.d.ts.map +0 -1
  198. package/dist/app/api/hazo_auth/user_management/users/route.js +0 -293
  199. package/dist/app/api/hazo_auth/validate_reset_token/route.d.ts +0 -6
  200. package/dist/app/api/hazo_auth/validate_reset_token/route.d.ts.map +0 -1
  201. package/dist/app/api/hazo_auth/validate_reset_token/route.js +0 -58
  202. package/dist/app/api/hazo_auth/verify_email/route.d.ts +0 -11
  203. package/dist/app/api/hazo_auth/verify_email/route.d.ts.map +0 -1
  204. package/dist/app/api/hazo_auth/verify_email/route.js +0 -63
  205. package/dist/components/layouts/app_user_data_test/index.d.ts +0 -6
  206. package/dist/components/layouts/app_user_data_test/index.d.ts.map +0 -1
  207. package/dist/components/layouts/app_user_data_test/index.js +0 -145
  208. package/dist/components/layouts/org_management/index.d.ts +0 -26
  209. package/dist/components/layouts/org_management/index.d.ts.map +0 -1
  210. package/dist/components/layouts/org_management/index.js +0 -75
  211. package/dist/components/layouts/profile_stamp_test/index.d.ts +0 -10
  212. package/dist/components/layouts/profile_stamp_test/index.d.ts.map +0 -1
  213. package/dist/components/layouts/profile_stamp_test/index.js +0 -51
  214. package/dist/components/layouts/rbac_test/index.d.ts +0 -13
  215. package/dist/components/layouts/rbac_test/index.d.ts.map +0 -1
  216. package/dist/components/layouts/rbac_test/index.js +0 -378
  217. package/dist/components/layouts/user_management/components/org_hierarchy_tab.d.ts +0 -13
  218. package/dist/components/layouts/user_management/components/org_hierarchy_tab.d.ts.map +0 -1
  219. package/dist/components/layouts/user_management/components/org_hierarchy_tab.js +0 -276
  220. package/dist/components/layouts/user_management/components/scope_labels_tab.d.ts +0 -14
  221. package/dist/components/layouts/user_management/components/scope_labels_tab.d.ts.map +0 -1
  222. package/dist/components/layouts/user_management/components/scope_labels_tab.js +0 -186
  223. package/dist/lib/auth/org_cache.d.ts +0 -65
  224. package/dist/lib/auth/org_cache.d.ts.map +0 -1
  225. package/dist/lib/auth/org_cache.js +0 -103
  226. package/dist/lib/multi_tenancy_config.server.d.ts +0 -30
  227. package/dist/lib/multi_tenancy_config.server.d.ts.map +0 -1
  228. package/dist/lib/multi_tenancy_config.server.js +0 -41
  229. package/dist/lib/services/org_service.d.ts +0 -191
  230. package/dist/lib/services/org_service.d.ts.map +0 -1
  231. package/dist/lib/services/org_service.js +0 -746
  232. package/dist/lib/services/scope_labels_service.d.ts +0 -48
  233. package/dist/lib/services/scope_labels_service.d.ts.map +0 -1
  234. package/dist/lib/services/scope_labels_service.js +0 -277
  235. package/dist/page_components/org_management.d.ts +0 -27
  236. package/dist/page_components/org_management.d.ts.map +0 -1
  237. package/dist/page_components/org_management.js +0 -18
  238. package/dist/pages/forgot_password.d.ts +0 -52
  239. package/dist/pages/forgot_password.d.ts.map +0 -1
  240. package/dist/pages/forgot_password.js +0 -41
  241. package/dist/pages/index.d.ts +0 -33
  242. package/dist/pages/index.d.ts.map +0 -1
  243. package/dist/pages/index.js +0 -28
  244. package/dist/pages/login.d.ts +0 -43
  245. package/dist/pages/login.d.ts.map +0 -1
  246. package/dist/pages/login.js +0 -45
  247. package/dist/pages/my_settings.d.ts +0 -54
  248. package/dist/pages/my_settings.d.ts.map +0 -1
  249. package/dist/pages/my_settings.js +0 -57
  250. package/dist/pages/register.d.ts +0 -44
  251. package/dist/pages/register.d.ts.map +0 -1
  252. package/dist/pages/register.js +0 -46
  253. package/dist/pages/reset_password.d.ts +0 -43
  254. package/dist/pages/reset_password.d.ts.map +0 -1
  255. package/dist/pages/reset_password.js +0 -42
  256. package/dist/pages/verify_email.d.ts +0 -52
  257. package/dist/pages/verify_email.d.ts.map +0 -1
  258. package/dist/pages/verify_email.js +0 -41
  259. package/dist/server/logging/logger_service.d.ts +0 -3
  260. package/dist/server/logging/logger_service.d.ts.map +0 -1
  261. package/dist/server/logging/logger_service.js +0 -37
  262. package/dist/server/routes/org_management_orgs.d.ts +0 -2
  263. package/dist/server/routes/org_management_orgs.d.ts.map +0 -1
  264. package/dist/server/routes/org_management_orgs.js +0 -2
package/README.md CHANGED
@@ -2,7 +2,34 @@
2
2
 
3
3
  A reusable authentication UI component package powered by Next.js, TailwindCSS, and shadcn. It integrates `hazo_config` for configuration management and `hazo_connect` for data access, enabling future components to stay aligned with platform conventions.
4
4
 
5
- ### What's New in v2.0 🚀
5
+ ### What's New in v5.0 🚀
6
+
7
+ **BREAKING CHANGE: Scope-Based Multi-Tenancy** - Complete architectural redesign for simpler, more flexible multi-tenancy!
8
+
9
+ - ✅ **Unified Scope System** - Single `hazo_scopes` table replaces 8 separate tables (1 org + 7 scope levels)
10
+ - ✅ **Membership-Based** - Users assigned to scopes via `hazo_user_scopes` (not org_id on user record)
11
+ - ✅ **Invitation System** - Built-in invitation flow for onboarding new users to existing scopes
12
+ - ✅ **Create Firm Flow** - New users create their own firm (scope) after email verification
13
+ - ✅ **Post-Verification Routing** - Smart routing after email verification: invitations → create firm → default redirect
14
+ - ✅ **Unlimited Hierarchy** - Flexible parent-child relationships, no fixed depth limit
15
+ - ✅ **Simpler Architecture** - Fewer tables, fewer joins, easier to understand
16
+ - ✅ **New CLI Command** - `npx hazo_auth init-permissions` for flexible permission setup
17
+
18
+ **Migrating from v4.x?** This is a breaking change. Run the migration:
19
+
20
+ ```bash
21
+ # 1. Backup your database first!
22
+ # 2. Run the scope consolidation migration
23
+ npm run migrate migrations/009_scope_consolidation.sql
24
+
25
+ # 3. Update configuration (remove org settings, add invitation/create firm settings)
26
+ # 4. Update code (remove org-related API calls and components)
27
+ # 5. Test thoroughly
28
+ ```
29
+
30
+ See [CHANGE_LOG.md](./CHANGE_LOG.md) for detailed migration guide, rationale, and breaking changes.
31
+
32
+ ### What's New in v2.0
6
33
 
7
34
  **Zero-Config Server Components** - Authentication pages now work out-of-the-box with ZERO configuration required!
8
35
 
@@ -12,8 +39,6 @@ A reusable authentication UI component package powered by Next.js, TailwindCSS,
12
39
  - ✅ **Embeddable Components** - MySettings and UserManagement adapt to any layout
13
40
  - ✅ **Sensible Defaults** - INI files are now optional, defaults built-in
14
41
 
15
- **Migrating from v1.x?** See [MIGRATION.md](./MIGRATION.md) for a complete upgrade guide.
16
-
17
42
  ### Also Includes (v1.6.6+)
18
43
 
19
44
  - **JWT Session Tokens for Edge-Compatible Authentication**: Secure Edge Runtime authentication in Next.js proxy/middleware files. See [Proxy/Middleware Authentication](#proxymiddleware-authentication) for details.
@@ -18,9 +18,16 @@ npx hazo_auth generate-routes --pages
18
18
 
19
19
  # 4. Set up environment variables
20
20
  cp .env.local.example .env.local
21
- # Edit .env.local and add ZEPTOMAIL_API_KEY
21
+ # Edit .env.local and add ZEPTOMAIL_API_KEY and JWT_SECRET
22
22
 
23
- # 5. Start dev server and test
23
+ # 5. Configure navbar logo and company name (IMPORTANT)
24
+ # Edit hazo_auth_config.ini and set:
25
+ # [hazo_auth__navbar]
26
+ # logo_path = /logo.png
27
+ # company_name = My Company
28
+ # Note: Copy your logo to public/logo.png
29
+
30
+ # 6. Start dev server and test
24
31
  npm run dev
25
32
  # Visit http://localhost:3000/hazo_auth/login
26
33
  ```
@@ -98,7 +105,48 @@ export default function RootLayout({ children }) {
98
105
  }
99
106
  ```
100
107
 
101
- ### Step 1.4: Enable Dark Mode Support (Optional)
108
+ ### Step 1.4: Configure Navbar (Logo and Company Name)
109
+
110
+ The navbar appears on all auth pages (login, register, etc.) when using standalone layout mode. **By default, the logo and company name are NOT displayed** - you must configure them.
111
+
112
+ **Edit `hazo_auth_config.ini`:**
113
+ ```ini
114
+ [hazo_auth__navbar]
115
+ # Enable navbar (default: true)
116
+ enable_navbar = true
117
+
118
+ # Logo - place your logo in public folder and set the path
119
+ logo_path = /logo.png
120
+
121
+ # Logo size (default: 28x28 - fits slim 48px navbar)
122
+ logo_width = 28
123
+ logo_height = 28
124
+
125
+ # Company name displayed next to logo
126
+ company_name = My Company
127
+
128
+ # Home link (right side of navbar)
129
+ show_home_link = true
130
+ home_path = /
131
+ home_label = Home
132
+
133
+ # Navbar height (default: 48px for slim appearance)
134
+ height = 48
135
+ ```
136
+
137
+ **Important:**
138
+ - If `logo_path` is empty, no logo will be displayed
139
+ - If `company_name` is empty, no company name will be displayed
140
+ - The default navbar height is 48px (slim design)
141
+
142
+ **Checklist:**
143
+ - [ ] Logo file exists in `public/` folder (e.g., `public/logo.png`)
144
+ - [ ] `logo_path` configured in `hazo_auth_config.ini`
145
+ - [ ] `company_name` configured in `hazo_auth_config.ini`
146
+
147
+ ---
148
+
149
+ ### Step 1.5: Enable Dark Mode Support (Optional)
102
150
 
103
151
  hazo_auth components support dark mode via CSS custom properties. Add the CSS variables to your global styles:
104
152
 
@@ -1708,6 +1756,34 @@ sqlite3 data/hazo_auth.sqlite ".tables" | grep -E "hazo_scopes|hazo_user_scopes|
1708
1756
  2. Check cookies are being set (inspect browser devtools > Application > Cookies)
1709
1757
  3. Ensure API routes are on same domain (no CORS issues)
1710
1758
 
1759
+ ### Issue: Navbar logo or company name not showing
1760
+
1761
+ **Symptoms:** Navbar appears but logo and/or company name are missing.
1762
+
1763
+ **Solutions:**
1764
+ 1. **Configure logo and company name in `hazo_auth_config.ini`:**
1765
+ ```ini
1766
+ [hazo_auth__navbar]
1767
+ logo_path = /logo.png
1768
+ company_name = My Company
1769
+ ```
1770
+
1771
+ 2. **Ensure logo file exists:**
1772
+ - Place your logo in the `public/` folder
1773
+ - The path should be relative to public (e.g., `/logo.png` for `public/logo.png`)
1774
+
1775
+ 3. **Verify config is being read:**
1776
+ - Config file must be in project root (where `process.cwd()` points)
1777
+ - Restart the dev server after changing config
1778
+
1779
+ 4. **Check if navbar is enabled:**
1780
+ ```ini
1781
+ [hazo_auth__navbar]
1782
+ enable_navbar = true
1783
+ ```
1784
+
1785
+ **Note:** By default, `logo_path` and `company_name` are empty strings, so nothing displays until you configure them.
1786
+
1711
1787
  ---
1712
1788
 
1713
1789
  ## Final Checklist
@@ -1715,7 +1791,8 @@ sqlite3 data/hazo_auth.sqlite ".tables" | grep -E "hazo_scopes|hazo_user_scopes|
1715
1791
  **Configuration:**
1716
1792
  - [ ] `hazo_auth_config.ini` configured
1717
1793
  - [ ] `hazo_notify_config.ini` configured
1718
- - [ ] `.env.local` with all required variables
1794
+ - [ ] `.env.local` with all required variables (ZEPTOMAIL_API_KEY, JWT_SECRET)
1795
+ - [ ] Navbar configured with logo and company name (see Step 1.4)
1719
1796
 
1720
1797
  **Database:**
1721
1798
  - [ ] Database created and accessible
@@ -1728,6 +1805,7 @@ sqlite3 data/hazo_auth.sqlite ".tables" | grep -E "hazo_scopes|hazo_user_scopes|
1728
1805
  **Pages:**
1729
1806
  - [ ] All 6 auth pages created
1730
1807
  - [ ] Pages render without errors
1808
+ - [ ] Navbar displays with logo and company name
1731
1809
 
1732
1810
  **Features:**
1733
1811
  - [ ] Registration works
package/bin/hazo_auth.mjs CHANGED
File without changes
@@ -7,6 +7,7 @@ import { run_validation } from "./validate.js";
7
7
  import { generate_routes, type GenerateOptions } from "./generate.js";
8
8
  import { handle_init } from "./init.js";
9
9
  import { handle_init_users, show_init_users_help } from "./init_users.js";
10
+ import { handle_init_permissions, show_init_permissions_help } from "./init_permissions.js";
10
11
 
11
12
  // section: constants
12
13
  const VERSION = "1.6.0";
@@ -18,6 +19,7 @@ Usage: hazo_auth <command> [options]
18
19
 
19
20
  Commands:
20
21
  init Initialize hazo_auth in your project (creates directories, copies config)
22
+ init-permissions Create default permissions from config (no user required)
21
23
  init-users Initialize permissions, roles, and super user from config
22
24
  validate Check your hazo_auth setup and configuration
23
25
  generate-routes Generate API route files and pages in your project
@@ -28,6 +30,7 @@ Options:
28
30
 
29
31
  Examples:
30
32
  npx hazo_auth init
33
+ npx hazo_auth init-permissions
31
34
  npx hazo_auth init-users
32
35
  npx hazo_auth validate
33
36
  npx hazo_auth generate-routes
@@ -154,6 +157,15 @@ Actions:
154
157
  handle_init();
155
158
  break;
156
159
 
160
+ case "init-permissions": {
161
+ if (help) {
162
+ show_init_permissions_help();
163
+ return;
164
+ }
165
+ await handle_init_permissions();
166
+ break;
167
+ }
168
+
157
169
  case "init-users": {
158
170
  if (help) {
159
171
  show_init_users_help();
@@ -0,0 +1,164 @@
1
+ // file_description: CLI command to initialize permissions from configuration
2
+ // section: imports
3
+ import { randomUUID } from "crypto";
4
+ import { get_hazo_connect_instance } from "../lib/hazo_connect_instance.server.js";
5
+ import { createCrudService } from "hazo_connect/server";
6
+ import { get_user_management_config } from "../lib/user_management_config.server.js";
7
+ import { create_app_logger } from "../lib/app_logger.js";
8
+
9
+ // section: types
10
+ type InitPermissionsSummary = {
11
+ inserted: string[];
12
+ existing: string[];
13
+ };
14
+
15
+ // section: helpers
16
+ /**
17
+ * Prints a summary of what was inserted vs what already existed
18
+ */
19
+ function print_summary(summary: InitPermissionsSummary): void {
20
+ console.log("=".repeat(60));
21
+ console.log("INITIALIZATION SUMMARY");
22
+ console.log("=".repeat(60));
23
+ console.log();
24
+
25
+ if (summary.inserted.length > 0) {
26
+ console.log(`✓ Inserted (${summary.inserted.length}):`);
27
+ summary.inserted.forEach((name) => console.log(` - ${name}`));
28
+ }
29
+
30
+ if (summary.existing.length > 0) {
31
+ console.log(`⊙ Already existed (${summary.existing.length}):`);
32
+ summary.existing.forEach((name) => console.log(` - ${name}`));
33
+ }
34
+
35
+ if (summary.inserted.length === 0 && summary.existing.length === 0) {
36
+ console.log("No permissions found in configuration.");
37
+ }
38
+
39
+ console.log();
40
+ console.log("=".repeat(60));
41
+ }
42
+
43
+ // section: main_function
44
+ /**
45
+ * Initializes permissions from configuration
46
+ * This function reads from hazo_auth_config.ini and sets up permissions
47
+ * without requiring any users to exist.
48
+ */
49
+ export async function handle_init_permissions(): Promise<void> {
50
+ const logger = create_app_logger();
51
+ const summary: InitPermissionsSummary = {
52
+ inserted: [],
53
+ existing: [],
54
+ };
55
+
56
+ try {
57
+ console.log("\n🐸 hazo_auth init-permissions\n");
58
+ console.log("Creating permissions from configuration...\n");
59
+
60
+ // Get hazo_connect instance
61
+ const hazoConnect = get_hazo_connect_instance();
62
+ const permissions_service = createCrudService(hazoConnect, "hazo_permissions");
63
+
64
+ // Get permissions from config
65
+ const config = get_user_management_config();
66
+ const permission_names = config.application_permission_list_defaults || [];
67
+
68
+ if (permission_names.length === 0) {
69
+ console.log("⚠ No permissions found in configuration.");
70
+ console.log(" Add permissions to [hazo_auth__user_management] application_permission_list_defaults\n");
71
+ return;
72
+ }
73
+
74
+ console.log(`Found ${permission_names.length} permission(s) in configuration:`);
75
+ permission_names.forEach((name) => console.log(` - ${name}`));
76
+ console.log();
77
+
78
+ // Add permissions to hazo_permissions table
79
+ const now = new Date().toISOString();
80
+
81
+ for (const permission_name of permission_names) {
82
+ const trimmed_name = permission_name.trim();
83
+ if (!trimmed_name) continue;
84
+
85
+ // Check if permission already exists
86
+ const existing_permissions = await permissions_service.findBy({
87
+ permission_name: trimmed_name,
88
+ });
89
+
90
+ if (Array.isArray(existing_permissions) && existing_permissions.length > 0) {
91
+ const existing_permission = existing_permissions[0];
92
+ const perm_id = existing_permission.id as string;
93
+ summary.existing.push(trimmed_name);
94
+ console.log(`⊙ Permission already exists: ${trimmed_name} (ID: ${perm_id})`);
95
+ } else {
96
+ // Insert new permission with generated UUID
97
+ const perm_id = randomUUID();
98
+ await permissions_service.insert({
99
+ id: perm_id,
100
+ permission_name: trimmed_name,
101
+ description: `Permission for ${trimmed_name}`,
102
+ created_at: now,
103
+ changed_at: now,
104
+ });
105
+
106
+ summary.inserted.push(trimmed_name);
107
+ console.log(`✓ Inserted permission: ${trimmed_name} (ID: ${perm_id})`);
108
+ }
109
+ }
110
+
111
+ console.log();
112
+
113
+ // Print summary
114
+ print_summary(summary);
115
+
116
+ logger.info("init_permissions_completed", {
117
+ filename: "init_permissions.ts",
118
+ line_number: 0,
119
+ summary,
120
+ });
121
+ } catch (error) {
122
+ const error_message = error instanceof Error ? error.message : "Unknown error";
123
+ const error_stack = error instanceof Error ? error.stack : undefined;
124
+
125
+ console.error("\n✗ Error initializing permissions:");
126
+ console.error(` ${error_message}`);
127
+ if (error_stack) {
128
+ console.error("\nStack trace:");
129
+ console.error(error_stack);
130
+ }
131
+
132
+ logger.error("init_permissions_failed", {
133
+ filename: "init_permissions.ts",
134
+ line_number: 0,
135
+ error_message,
136
+ error_stack,
137
+ });
138
+
139
+ process.exit(1);
140
+ }
141
+ }
142
+
143
+ // section: help
144
+ /**
145
+ * Shows help for the init-permissions command
146
+ */
147
+ export function show_init_permissions_help(): void {
148
+ console.log(`
149
+ hazo_auth init-permissions
150
+
151
+ Create default permissions from configuration.
152
+
153
+ This command reads permissions from hazo_auth_config.ini and inserts them
154
+ into the hazo_permissions table. Does not require any users to exist.
155
+
156
+ Configuration required in hazo_auth_config.ini:
157
+
158
+ [hazo_auth__user_management]
159
+ application_permission_list_defaults = admin_user_management,admin_role_management,...
160
+
161
+ Usage:
162
+ npx hazo_auth init-permissions
163
+ `);
164
+ }
@@ -5,6 +5,7 @@ import { createCrudService } from "hazo_connect/server";
5
5
  import { get_user_management_config } from "../lib/user_management_config.server.js";
6
6
  import { get_config_value } from "../lib/config/config_loader.server.js";
7
7
  import { create_app_logger } from "../lib/app_logger.js";
8
+ import { SUPER_ADMIN_SCOPE_ID } from "../lib/services/scope_service.js";
8
9
 
9
10
  // section: types
10
11
  type InitSummary = {
@@ -25,6 +26,14 @@ type InitSummary = {
25
26
  inserted: boolean;
26
27
  existing: boolean;
27
28
  };
29
+ super_admin_scope: {
30
+ inserted: boolean;
31
+ existing: boolean;
32
+ };
33
+ user_scope: {
34
+ inserted: boolean;
35
+ existing: boolean;
36
+ };
28
37
  };
29
38
 
30
39
  // section: helpers
@@ -79,6 +88,26 @@ function print_summary(summary: InitSummary): void {
79
88
  }
80
89
  console.log();
81
90
 
91
+ // Super admin scope summary
92
+ console.log("Super Admin Scope:");
93
+ if (summary.super_admin_scope.inserted) {
94
+ console.log(` ✓ Inserted: Super Admin scope (ID: ${SUPER_ADMIN_SCOPE_ID})`);
95
+ }
96
+ if (summary.super_admin_scope.existing) {
97
+ console.log(` ⊙ Already existed: Super Admin scope (ID: ${SUPER_ADMIN_SCOPE_ID})`);
98
+ }
99
+ console.log();
100
+
101
+ // User scope summary
102
+ console.log("User-Scope Assignment:");
103
+ if (summary.user_scope.inserted) {
104
+ console.log(` ✓ Inserted: User assigned to Super Admin scope`);
105
+ }
106
+ if (summary.user_scope.existing) {
107
+ console.log(` ⊙ Already existed: User already in Super Admin scope`);
108
+ }
109
+ console.log();
110
+
82
111
  console.log("=".repeat(60));
83
112
  }
84
113
 
@@ -116,6 +145,14 @@ export async function handle_init_users(options: InitUsersOptions = {}): Promise
116
145
  inserted: false,
117
146
  existing: false,
118
147
  },
148
+ super_admin_scope: {
149
+ inserted: false,
150
+ existing: false,
151
+ },
152
+ user_scope: {
153
+ inserted: false,
154
+ existing: false,
155
+ },
119
156
  };
120
157
 
121
158
  try {
@@ -129,6 +166,12 @@ export async function handle_init_users(options: InitUsersOptions = {}): Promise
129
166
  const role_permissions_service = createCrudService(hazoConnect, "hazo_role_permissions");
130
167
  const users_service = createCrudService(hazoConnect, "hazo_users");
131
168
  const user_roles_service = createCrudService(hazoConnect, "hazo_user_roles");
169
+ const scopes_service = createCrudService(hazoConnect, "hazo_scopes");
170
+ // hazo_user_scopes uses composite primary key (user_id, scope_id), no 'id' column
171
+ const user_scopes_service = createCrudService(hazoConnect, "hazo_user_scopes", {
172
+ primaryKeys: ["user_id", "scope_id"],
173
+ autoId: false,
174
+ });
132
175
 
133
176
  // 1. Get permissions from config
134
177
  const config = get_user_management_config();
@@ -307,7 +350,52 @@ export async function handle_init_users(options: InitUsersOptions = {}): Promise
307
350
 
308
351
  console.log();
309
352
 
310
- // 8. Print summary
353
+ // 8. Ensure super admin scope exists
354
+ const existing_scopes = await scopes_service.findBy({ id: SUPER_ADMIN_SCOPE_ID });
355
+
356
+ if (Array.isArray(existing_scopes) && existing_scopes.length > 0) {
357
+ summary.super_admin_scope.existing = true;
358
+ console.log(`✓ Super Admin scope already exists (ID: ${SUPER_ADMIN_SCOPE_ID})`);
359
+ } else {
360
+ await scopes_service.insert({
361
+ id: SUPER_ADMIN_SCOPE_ID,
362
+ parent_id: null,
363
+ name: "Super Admin",
364
+ level: "system",
365
+ created_at: now,
366
+ changed_at: now,
367
+ });
368
+ summary.super_admin_scope.inserted = true;
369
+ console.log(`✓ Created Super Admin scope (ID: ${SUPER_ADMIN_SCOPE_ID})`);
370
+ }
371
+
372
+ console.log();
373
+
374
+ // 9. Assign user to super admin scope
375
+ const existing_user_scopes = await user_scopes_service.findBy({
376
+ user_id,
377
+ scope_id: SUPER_ADMIN_SCOPE_ID,
378
+ });
379
+
380
+ if (Array.isArray(existing_user_scopes) && existing_user_scopes.length > 0) {
381
+ summary.user_scope.existing = true;
382
+ console.log(`✓ User already assigned to Super Admin scope`);
383
+ } else {
384
+ await user_scopes_service.insert({
385
+ user_id,
386
+ scope_id: SUPER_ADMIN_SCOPE_ID,
387
+ root_scope_id: SUPER_ADMIN_SCOPE_ID,
388
+ role_id,
389
+ created_at: now,
390
+ changed_at: now,
391
+ });
392
+ summary.user_scope.inserted = true;
393
+ console.log(`✓ Assigned user to Super Admin scope`);
394
+ }
395
+
396
+ console.log();
397
+
398
+ // 10. Print summary
311
399
  print_summary(summary);
312
400
 
313
401
  logger.info("init_users_completed", {
@@ -345,7 +433,7 @@ export function show_init_users_help(): void {
345
433
  console.log(`
346
434
  hazo_auth init-users
347
435
 
348
- Initialize users, roles, and permissions from configuration.
436
+ Initialize users, roles, permissions, and super admin scope from configuration.
349
437
 
350
438
  This command reads from hazo_auth_config.ini and:
351
439
  1. Creates permissions from [hazo_auth__user_management] application_permission_list_defaults
@@ -353,6 +441,8 @@ This command reads from hazo_auth_config.ini and:
353
441
  3. Assigns all permissions to the super user role
354
442
  4. Finds user by email (from --email parameter or config)
355
443
  5. Assigns the super user role to that user
444
+ 6. Creates the Super Admin scope (${SUPER_ADMIN_SCOPE_ID})
445
+ 7. Assigns the user to the Super Admin scope
356
446
 
357
447
  Options:
358
448
  --email=<email> Email address of the user to assign super user role