@betterportal/config-manager 0.0.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 (154) hide show
  1. package/README.md +3 -0
  2. package/bsb-plugin.json +23 -0
  3. package/bsb-tests.json +14 -0
  4. package/lib/.bsb/clients/service-betterportal-config-manager.d.ts +37 -0
  5. package/lib/.bsb/clients/service-betterportal-config-manager.d.ts.map +1 -0
  6. package/lib/.bsb/clients/service-betterportal-config-manager.js +40 -0
  7. package/lib/.bsb/clients/service-betterportal-config-manager.js.map +1 -0
  8. package/lib/index.d.ts +2 -0
  9. package/lib/index.d.ts.map +1 -0
  10. package/lib/index.js +2 -0
  11. package/lib/index.js.map +1 -0
  12. package/lib/plugins/service-betterportal-config-manager/.bp-generated/registry.d.ts +3 -0
  13. package/lib/plugins/service-betterportal-config-manager/.bp-generated/registry.d.ts.map +1 -0
  14. package/lib/plugins/service-betterportal-config-manager/.bp-generated/registry.js +235 -0
  15. package/lib/plugins/service-betterportal-config-manager/.bp-generated/registry.js.map +1 -0
  16. package/lib/plugins/service-betterportal-config-manager/adminApi.d.ts +4 -0
  17. package/lib/plugins/service-betterportal-config-manager/adminApi.d.ts.map +1 -0
  18. package/lib/plugins/service-betterportal-config-manager/adminApi.js +2319 -0
  19. package/lib/plugins/service-betterportal-config-manager/adminApi.js.map +1 -0
  20. package/lib/plugins/service-betterportal-config-manager/bootstrapEndpoint.d.ts +21 -0
  21. package/lib/plugins/service-betterportal-config-manager/bootstrapEndpoint.d.ts.map +1 -0
  22. package/lib/plugins/service-betterportal-config-manager/bootstrapEndpoint.js +269 -0
  23. package/lib/plugins/service-betterportal-config-manager/bootstrapEndpoint.js.map +1 -0
  24. package/lib/plugins/service-betterportal-config-manager/bootstrapWizardHtml.d.ts +19 -0
  25. package/lib/plugins/service-betterportal-config-manager/bootstrapWizardHtml.d.ts.map +1 -0
  26. package/lib/plugins/service-betterportal-config-manager/bootstrapWizardHtml.js +329 -0
  27. package/lib/plugins/service-betterportal-config-manager/bootstrapWizardHtml.js.map +1 -0
  28. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/_theme.bootstrap1/index.d.ts +4 -0
  29. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/_theme.bootstrap1/index.d.ts.map +1 -0
  30. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/_theme.bootstrap1/index.js +38 -0
  31. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/_theme.bootstrap1/index.js.map +1 -0
  32. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/index.d.ts +96 -0
  33. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/index.d.ts.map +1 -0
  34. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/index.js +78 -0
  35. package/lib/plugins/service-betterportal-config-manager/bp-routes/auth/index.js.map +1 -0
  36. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.bootstrap1/index.d.ts +4 -0
  37. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.bootstrap1/index.d.ts.map +1 -0
  38. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.bootstrap1/index.js +62 -0
  39. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.bootstrap1/index.js.map +1 -0
  40. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.embedded.d.ts +5 -0
  41. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.embedded.d.ts.map +1 -0
  42. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.embedded.js +5 -0
  43. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/_theme.embedded.js.map +1 -0
  44. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/index.d.ts +43 -0
  45. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/index.d.ts.map +1 -0
  46. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/index.js +68 -0
  47. package/lib/plugins/service-betterportal-config-manager/bp-routes/config/index.js.map +1 -0
  48. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/_theme.bootstrap1/index.d.ts +5 -0
  49. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/_theme.bootstrap1/index.d.ts.map +1 -0
  50. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/_theme.bootstrap1/index.js +11 -0
  51. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/_theme.bootstrap1/index.js.map +1 -0
  52. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/index.d.ts +32 -0
  53. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/index.d.ts.map +1 -0
  54. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/index.js +32 -0
  55. package/lib/plugins/service-betterportal-config-manager/bp-routes/fragments/index.js.map +1 -0
  56. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/_theme.bootstrap1/index.d.ts +4 -0
  57. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/_theme.bootstrap1/index.d.ts.map +1 -0
  58. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/_theme.bootstrap1/index.js +170 -0
  59. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/_theme.bootstrap1/index.js.map +1 -0
  60. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/index.d.ts +60 -0
  61. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/index.d.ts.map +1 -0
  62. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/index.js +48 -0
  63. package/lib/plugins/service-betterportal-config-manager/bp-routes/menu/index.js.map +1 -0
  64. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/_theme.bootstrap1/index.d.ts +4 -0
  65. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/_theme.bootstrap1/index.d.ts.map +1 -0
  66. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/_theme.bootstrap1/index.js +28 -0
  67. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/_theme.bootstrap1/index.js.map +1 -0
  68. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/index.d.ts +48 -0
  69. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/index.d.ts.map +1 -0
  70. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/index.js +40 -0
  71. package/lib/plugins/service-betterportal-config-manager/bp-routes/preview/index.js.map +1 -0
  72. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/_theme.bootstrap1/index.d.ts +5 -0
  73. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/_theme.bootstrap1/index.d.ts.map +1 -0
  74. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/_theme.bootstrap1/index.js +194 -0
  75. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/_theme.bootstrap1/index.js.map +1 -0
  76. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/index.d.ts +80 -0
  77. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/index.d.ts.map +1 -0
  78. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/index.js +59 -0
  79. package/lib/plugins/service-betterportal-config-manager/bp-routes/routes/index.js.map +1 -0
  80. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_theme.bootstrap1/index.d.ts +5 -0
  81. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_theme.bootstrap1/index.d.ts.map +1 -0
  82. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_theme.bootstrap1/index.js +167 -0
  83. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/_theme.bootstrap1/index.js.map +1 -0
  84. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/index.d.ts +128 -0
  85. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/index.d.ts.map +1 -0
  86. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/index.js +89 -0
  87. package/lib/plugins/service-betterportal-config-manager/bp-routes/services/index.js.map +1 -0
  88. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/_theme.bootstrap1/index.d.ts +5 -0
  89. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/_theme.bootstrap1/index.d.ts.map +1 -0
  90. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/_theme.bootstrap1/index.js +8 -0
  91. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/_theme.bootstrap1/index.js.map +1 -0
  92. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/index.d.ts +89 -0
  93. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/index.d.ts.map +1 -0
  94. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/index.js +93 -0
  95. package/lib/plugins/service-betterportal-config-manager/bp-routes/settings/index.js.map +1 -0
  96. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/_theme.bootstrap1/index.d.ts +4 -0
  97. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/_theme.bootstrap1/index.d.ts.map +1 -0
  98. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/_theme.bootstrap1/index.js +61 -0
  99. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/_theme.bootstrap1/index.js.map +1 -0
  100. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/index.d.ts +180 -0
  101. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/index.d.ts.map +1 -0
  102. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/index.js +405 -0
  103. package/lib/plugins/service-betterportal-config-manager/bp-routes/tenants/index.js.map +1 -0
  104. package/lib/plugins/service-betterportal-config-manager/cpBootstrap.d.ts +26 -0
  105. package/lib/plugins/service-betterportal-config-manager/cpBootstrap.d.ts.map +1 -0
  106. package/lib/plugins/service-betterportal-config-manager/cpBootstrap.js +58 -0
  107. package/lib/plugins/service-betterportal-config-manager/cpBootstrap.js.map +1 -0
  108. package/lib/plugins/service-betterportal-config-manager/fragmentsEditor.d.ts +3 -0
  109. package/lib/plugins/service-betterportal-config-manager/fragmentsEditor.d.ts.map +1 -0
  110. package/lib/plugins/service-betterportal-config-manager/fragmentsEditor.js +365 -0
  111. package/lib/plugins/service-betterportal-config-manager/fragmentsEditor.js.map +1 -0
  112. package/lib/plugins/service-betterportal-config-manager/index.d.ts +143 -0
  113. package/lib/plugins/service-betterportal-config-manager/index.d.ts.map +1 -0
  114. package/lib/plugins/service-betterportal-config-manager/index.js +696 -0
  115. package/lib/plugins/service-betterportal-config-manager/index.js.map +1 -0
  116. package/lib/plugins/service-betterportal-config-manager/menuEditor.d.ts +3 -0
  117. package/lib/plugins/service-betterportal-config-manager/menuEditor.d.ts.map +1 -0
  118. package/lib/plugins/service-betterportal-config-manager/menuEditor.js +823 -0
  119. package/lib/plugins/service-betterportal-config-manager/menuEditor.js.map +1 -0
  120. package/lib/plugins/service-betterportal-config-manager/routeContext.d.ts +10 -0
  121. package/lib/plugins/service-betterportal-config-manager/routeContext.d.ts.map +1 -0
  122. package/lib/plugins/service-betterportal-config-manager/routeContext.js +11 -0
  123. package/lib/plugins/service-betterportal-config-manager/routeContext.js.map +1 -0
  124. package/lib/plugins/service-betterportal-config-manager/setupTokens.d.ts +18 -0
  125. package/lib/plugins/service-betterportal-config-manager/setupTokens.d.ts.map +1 -0
  126. package/lib/plugins/service-betterportal-config-manager/setupTokens.js +245 -0
  127. package/lib/plugins/service-betterportal-config-manager/setupTokens.js.map +1 -0
  128. package/lib/plugins/service-betterportal-config-manager/storage/core.d.ts +41 -0
  129. package/lib/plugins/service-betterportal-config-manager/storage/core.d.ts.map +1 -0
  130. package/lib/plugins/service-betterportal-config-manager/storage/core.js +396 -0
  131. package/lib/plugins/service-betterportal-config-manager/storage/core.js.map +1 -0
  132. package/lib/plugins/service-betterportal-config-manager/storage/file.d.ts +10 -0
  133. package/lib/plugins/service-betterportal-config-manager/storage/file.d.ts.map +1 -0
  134. package/lib/plugins/service-betterportal-config-manager/storage/file.js +30 -0
  135. package/lib/plugins/service-betterportal-config-manager/storage/file.js.map +1 -0
  136. package/lib/plugins/service-betterportal-config-manager/storage/index.d.ts +36 -0
  137. package/lib/plugins/service-betterportal-config-manager/storage/index.d.ts.map +1 -0
  138. package/lib/plugins/service-betterportal-config-manager/storage/index.js +52 -0
  139. package/lib/plugins/service-betterportal-config-manager/storage/index.js.map +1 -0
  140. package/lib/plugins/service-betterportal-config-manager/storage/postgres.d.ts +15 -0
  141. package/lib/plugins/service-betterportal-config-manager/storage/postgres.d.ts.map +1 -0
  142. package/lib/plugins/service-betterportal-config-manager/storage/postgres.js +60 -0
  143. package/lib/plugins/service-betterportal-config-manager/storage/postgres.js.map +1 -0
  144. package/lib/plugins/service-betterportal-config-manager/syncApi.d.ts +44 -0
  145. package/lib/plugins/service-betterportal-config-manager/syncApi.d.ts.map +1 -0
  146. package/lib/plugins/service-betterportal-config-manager/syncApi.js +280 -0
  147. package/lib/plugins/service-betterportal-config-manager/syncApi.js.map +1 -0
  148. package/lib/plugins/service-betterportal-config-manager/webhooks.d.ts +6 -0
  149. package/lib/plugins/service-betterportal-config-manager/webhooks.d.ts.map +1 -0
  150. package/lib/plugins/service-betterportal-config-manager/webhooks.js +372 -0
  151. package/lib/plugins/service-betterportal-config-manager/webhooks.js.map +1 -0
  152. package/lib/schemas/service-betterportal-config-manager.json +157 -0
  153. package/lib/schemas/service-betterportal-config-manager.plugin.json +135 -0
  154. package/package.json +69 -0
@@ -0,0 +1,329 @@
1
+ /**
2
+ * Vanilla HTML bootstrap wizard. No theme dependency.
3
+ *
4
+ * Flow (browser-side):
5
+ * 1. Operator enters bootstrap key + admin tenant/app + theme URL + auth URL.
6
+ * 2. Browser:
7
+ * a) POST /.well-known/bp/bootstrap/commit -> registers admin tenant/app in CP DB
8
+ * b) For each of {theme, auth}:
9
+ * - POST /.well-known/bp/admin/services/begin-install -> get setupToken
10
+ * - POST {serviceUrl}/.well-known/bp/install with {setupToken, cpUrl}
11
+ * c) Redirect to admin app URL
12
+ * 3. Admin app's login flow redirects to /register while the auth service has
13
+ * zero users; the operator creates the first admin THERE (app origin, so
14
+ * tenant/app context resolves from the request). Then logs in.
15
+ */
16
+ export function renderBootstrapWizardHtml(input) {
17
+ const cpIssuerSafe = JSON.stringify(input.cpIssuer);
18
+ return `<!doctype html>
19
+ <html lang="en">
20
+ <head>
21
+ <meta charset="utf-8">
22
+ <meta name="viewport" content="width=device-width,initial-scale=1">
23
+ <title>BetterPortal Bootstrap</title>
24
+ <style>
25
+ :root { color-scheme: light dark; --bg:#0e1116; --fg:#e6edf3; --muted:#7d8590; --accent:#2f81f7; --ok:#3fb950; --err:#f85149; --card:#161b22; --border:#30363d; --input:#0d1117; }
26
+ @media (prefers-color-scheme: light) {
27
+ :root { --bg:#f6f8fa; --fg:#1f2328; --muted:#656d76; --accent:#0969da; --ok:#1a7f37; --err:#cf222e; --card:#ffffff; --border:#d0d7de; --input:#ffffff; }
28
+ }
29
+ *,*::before,*::after { box-sizing: border-box; }
30
+ body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; background: var(--bg); color: var(--fg); min-height: 100vh; padding: 2rem 1rem; }
31
+ .wrap { max-width: 720px; margin: 0 auto; }
32
+ h1 { margin: 0 0 0.5rem; font-size: 1.8rem; letter-spacing: -0.02em; }
33
+ p.lead { color: var(--muted); margin: 0 0 2rem; line-height: 1.6; }
34
+ .card { background: var(--card); border: 1px solid var(--border); border-radius: 12px; padding: 1.5rem; margin-bottom: 1rem; }
35
+ .card h2 { margin: 0 0 0.25rem; font-size: 1rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); }
36
+ .card p.hint { margin: 0.25rem 0 1rem; color: var(--muted); font-size: 0.9rem; }
37
+ label { display: block; margin: 0.75rem 0 0.25rem; font-size: 0.85rem; font-weight: 600; }
38
+ input { width: 100%; padding: 0.6rem 0.75rem; font: inherit; background: var(--input); color: var(--fg); border: 1px solid var(--border); border-radius: 6px; }
39
+ input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent); }
40
+ .row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
41
+ button { width: 100%; padding: 0.75rem; font: inherit; font-weight: 600; background: var(--accent); color: white; border: 0; border-radius: 8px; cursor: pointer; }
42
+ button:hover { filter: brightness(1.1); }
43
+ button:disabled { opacity: 0.5; cursor: not-allowed; }
44
+ pre { background: var(--input); border: 1px solid var(--border); padding: 0.75rem; border-radius: 6px; overflow-x: auto; font-size: 0.85rem; white-space: pre-wrap; word-break: break-all; }
45
+ .step { display: flex; align-items: center; padding: 0.5rem 0; gap: 0.75rem; color: var(--muted); font-size: 0.9rem; }
46
+ .step.done { color: var(--ok); }
47
+ .step.err { color: var(--err); }
48
+ .step .marker { width: 1.2rem; text-align: center; }
49
+ .alert-err { background: color-mix(in srgb, var(--err) 12%, transparent); color: var(--err); border: 1px solid var(--err); padding: 0.75rem; border-radius: 6px; margin-top: 1rem; }
50
+ .alert-ok { background: color-mix(in srgb, var(--ok) 12%, transparent); color: var(--ok); border: 1px solid var(--ok); padding: 0.75rem; border-radius: 6px; margin-top: 1rem; }
51
+ .modal-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.55); display: none; align-items: center; justify-content: center; z-index: 1000; padding: 1rem; }
52
+ .modal-backdrop.open { display: flex; }
53
+ .modal { background: var(--card); border: 1px solid var(--border); border-radius: 12px; max-width: 560px; width: 100%; max-height: 80vh; display: flex; flex-direction: column; box-shadow: 0 20px 50px rgba(0,0,0,0.4); }
54
+ .modal-header { display: flex; align-items: center; justify-content: space-between; padding: 1rem 1.5rem; border-bottom: 1px solid var(--border); }
55
+ .modal-header h2 { margin: 0; font-size: 1rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); }
56
+ .modal-close { background: transparent; color: var(--muted); border: 0; font-size: 1.25rem; line-height: 1; padding: 0.25rem 0.5rem; cursor: pointer; border-radius: 4px; }
57
+ .modal-close:hover { color: var(--fg); background: var(--input); }
58
+ .modal-body { padding: 1rem 1.5rem; overflow-y: auto; flex: 1; }
59
+ </style>
60
+ </head>
61
+ <body>
62
+ <div class="wrap">
63
+ <h1>BetterPortal Bootstrap</h1>
64
+ <p class="lead">First-time setup. Enter the bootstrap key from your config-manager stdout, then point at your theme + auth service URLs and create the first admin user.</p>
65
+
66
+ <form id="wizard">
67
+ <div class="card">
68
+ <h2>1. Bootstrap key</h2>
69
+ <p class="hint">Logged to config-manager stdout on startup. Valid 15 minutes.</p>
70
+ <label>Key</label>
71
+ <input id="bootstrapKey" name="bootstrapKey" autocomplete="off" required placeholder="bootstrap-...">
72
+ </div>
73
+
74
+ <div class="card">
75
+ <h2>2. Admin tenant + app</h2>
76
+ <p class="hint">The product itself. This is where you log in to manage other tenants. IDs are auto-generated.</p>
77
+ <label>Tenant title</label>
78
+ <input name="adminTenant.title" value="BetterPortal" required>
79
+ <label>App title</label>
80
+ <input name="adminApp.title" value="Admin Portal" required>
81
+ <label>App URL (where you'll log in)</label>
82
+ <input name="adminApp.hostname" placeholder="http://localhost:3100" required>
83
+ </div>
84
+
85
+ <div class="card">
86
+ <h2>3. Theme service</h2>
87
+ <p class="hint">Renders the admin UI. Identity (UUIDv7) is auto-generated.</p>
88
+ <label>Title</label>
89
+ <input name="themeService.title" value="Bootstrap1" required>
90
+ <label>Theme URL</label>
91
+ <input name="themeService.hostname" placeholder="http://localhost:3100" required>
92
+ </div>
93
+
94
+ <div class="card">
95
+ <h2>4. Auth service</h2>
96
+ <p class="hint">Issues login tokens. Must publish /.well-known/bp/manifest. Identity (UUIDv7) is auto-generated.</p>
97
+ <label>Title</label>
98
+ <input name="authService.title" value="Auth Default" required>
99
+ <label>Auth URL</label>
100
+ <input name="authService.hostname" placeholder="http://localhost:3210" required>
101
+ </div>
102
+
103
+ <p class="hint">No admin user is created here. After setup you'll be redirected to the admin app, which walks you through creating the first admin account (open only while the auth service has zero users).</p>
104
+
105
+ <button type="submit" id="submitBtn">Run setup</button>
106
+ </form>
107
+
108
+ </div>
109
+
110
+ <div class="modal-backdrop" id="progressModal" role="dialog" aria-modal="true" aria-labelledby="progressModalTitle">
111
+ <div class="modal" role="document">
112
+ <div class="modal-header">
113
+ <h2 id="progressModalTitle">Setup progress</h2>
114
+ <button type="button" class="modal-close" id="progressModalClose" aria-label="Close">&times;</button>
115
+ </div>
116
+ <div class="modal-body" id="steps"></div>
117
+ </div>
118
+ </div>
119
+
120
+ <script>
121
+ const CP_ISSUER = ${cpIssuerSafe};
122
+
123
+ function getValue(form, name) { return form.elements.namedItem(name) ? form.elements.namedItem(name).value : ""; }
124
+ async function readJson(res, label) {
125
+ const contentType = res.headers.get("content-type") || "";
126
+ if (contentType.includes("application/json")) return res.json();
127
+ let text = "";
128
+ try { text = await res.text(); } catch (_) {}
129
+ throw new Error(label + " returned " + (contentType || "non-JSON") + " HTTP " + res.status + (text ? ": " + text.slice(0, 160) : ""));
130
+ }
131
+
132
+ function step(id, label) {
133
+ const wrap = document.getElementById("steps");
134
+ const div = document.createElement("div");
135
+ div.className = "step";
136
+ div.id = id;
137
+ div.innerHTML = '<span class="marker">...</span><span>' + label + '</span>';
138
+ wrap.appendChild(div);
139
+ return {
140
+ done() { div.classList.add("done"); div.querySelector(".marker").textContent = "OK"; },
141
+ fail(msg) { div.classList.add("err"); div.querySelector(".marker").textContent = "X"; if (msg) div.querySelector("span:last-child").textContent = label + " - " + msg; }
142
+ };
143
+ }
144
+
145
+ async function postJson(url, body) {
146
+ const res = await fetch(url, { method: "POST", headers: { "content-type": "application/json", "accept": "application/json" }, body: JSON.stringify(body) });
147
+ if (!res.ok) {
148
+ let text = "";
149
+ try { text = await res.text(); } catch (_) {}
150
+ throw new Error("HTTP " + res.status + " " + (text || res.statusText));
151
+ }
152
+ return readJson(res, "POST " + url);
153
+ }
154
+
155
+ async function getJson(url) {
156
+ const res = await fetch(url, { headers: { accept: "application/json" } });
157
+ if (!res.ok) throw new Error("HTTP " + res.status);
158
+ return readJson(res, "GET " + url);
159
+ }
160
+
161
+ async function installService(label, serviceUrl, scope, options) {
162
+ const s = step("install-" + label, "Install " + label + " service");
163
+ try {
164
+ const beginRes = await postJson(CP_ISSUER + "/.well-known/bp/admin/services/begin-install", {
165
+ serviceUrl,
166
+ ...(scope || {}),
167
+ ...(options && options.instanceId ? { instanceId: options.instanceId } : {}),
168
+ ...(options && options.sharedServiceId ? { sharedServiceId: options.sharedServiceId } : {})
169
+ });
170
+ const installRes = await postJson(serviceUrl.replace(/\\/+$/, "") + "/.well-known/bp/install", {
171
+ setupToken: beginRes.setupToken,
172
+ cpUrl: CP_ISSUER
173
+ });
174
+ s.done();
175
+ return installRes;
176
+ } catch (e) {
177
+ s.fail(e.message);
178
+ throw e;
179
+ }
180
+ }
181
+
182
+ async function buildAdminRole(adminAppId, payload, commit) {
183
+ const s = step("admin-role", "Build admin role from service manifests");
184
+ try {
185
+ // Fetch each known service's manifest to discover view-level permission requirements.
186
+ // serviceId in grants MUST be the UUIDv7 instance id (matches routes/fragments
187
+ // and what the framework auth resolver compares against), NOT the pluginId.
188
+ const sources = [
189
+ { instanceId: commit.cmInstanceId, url: CP_ISSUER },
190
+ { instanceId: commit.authActivationId, url: payload.authService.hostname }
191
+ ];
192
+ if (payload.themeService && payload.themeService.hostname && commit.themeActivationId) {
193
+ sources.push({ instanceId: commit.themeActivationId, url: payload.themeService.hostname });
194
+ }
195
+ const ACTIONS = ["read", "create", "update", "delete"];
196
+ const grants = [];
197
+ for (const src of sources) {
198
+ try {
199
+ const m = await getJson(src.url.replace(/\\/+$/, "") + "/.well-known/bp/manifest");
200
+ const views = Array.isArray(m.views) ? m.views : [];
201
+ for (const v of views) {
202
+ if (!v.viewId) continue;
203
+ grants.push({
204
+ serviceId: src.instanceId,
205
+ viewId: v.viewId,
206
+ permissions: ACTIONS.slice()
207
+ });
208
+ }
209
+ } catch (e) {
210
+ // Manifest fetch can fail in race with install. Continue with whatever we have.
211
+ // (silent - surface only via the wizard's overall failure step if all manifests miss)
212
+ }
213
+ }
214
+
215
+ // POST admin role with all gathered grants
216
+ const res = await postJson(CP_ISSUER + "/.well-known/bp/admin/apps/" + encodeURIComponent(adminAppId) + "/auth/roles", {
217
+ id: "admin",
218
+ title: "Administrator",
219
+ description: "Full access to all services and views. Auto-created during bootstrap.",
220
+ permissions: grants
221
+ });
222
+ s.done();
223
+ return res;
224
+ } catch (e) {
225
+ s.fail(e.message);
226
+ throw e;
227
+ }
228
+ }
229
+
230
+ async function commitBootstrap(payload) {
231
+ const s = step("commit", "Register admin tenant/app");
232
+ try {
233
+ const r = await postJson(CP_ISSUER + "/.well-known/bp/bootstrap/commit", payload);
234
+ s.done();
235
+ return r;
236
+ } catch (e) {
237
+ s.fail(e.message);
238
+ throw e;
239
+ }
240
+ }
241
+
242
+ const progressModal = document.getElementById("progressModal");
243
+ const stepsEl = document.getElementById("steps");
244
+ function openProgressModal() {
245
+ stepsEl.innerHTML = "";
246
+ progressModal.classList.add("open");
247
+ document.body.style.overflow = "hidden";
248
+ }
249
+ function closeProgressModal() {
250
+ progressModal.classList.remove("open");
251
+ document.body.style.overflow = "";
252
+ stepsEl.innerHTML = "";
253
+ document.getElementById("submitBtn").disabled = false;
254
+ }
255
+ document.getElementById("progressModalClose").addEventListener("click", closeProgressModal);
256
+ progressModal.addEventListener("click", (e) => { if (e.target === progressModal) closeProgressModal(); });
257
+ document.addEventListener("keydown", (e) => {
258
+ if (e.key === "Escape" && progressModal.classList.contains("open")) closeProgressModal();
259
+ });
260
+
261
+ document.getElementById("wizard").addEventListener("submit", async (evt) => {
262
+ evt.preventDefault();
263
+ const form = evt.currentTarget;
264
+ document.getElementById("submitBtn").disabled = true;
265
+ openProgressModal();
266
+
267
+ const payload = {
268
+ bootstrapKey: getValue(form, "bootstrapKey"),
269
+ adminTenant: {
270
+ title: getValue(form, "adminTenant.title")
271
+ },
272
+ adminApp: {
273
+ title: getValue(form, "adminApp.title"),
274
+ hostname: getValue(form, "adminApp.hostname")
275
+ },
276
+ themeService: {
277
+ hostname: getValue(form, "themeService.hostname"),
278
+ title: getValue(form, "themeService.title")
279
+ },
280
+ authService: {
281
+ hostname: getValue(form, "authService.hostname"),
282
+ title: getValue(form, "authService.title")
283
+ }
284
+ };
285
+
286
+ try {
287
+ // 1. Commit admin tenant + app to CP (CM generates UUIDv7 ids and returns them)
288
+ const commit = await commitBootstrap(payload);
289
+
290
+ // 2. Install auth + theme services via setup-token handshake (browser dispatches).
291
+ // instanceIds from commit response -> match pre-created tenant.services placeholders.
292
+ await installService(
293
+ "auth",
294
+ payload.authService.hostname,
295
+ { tenantId: commit.adminTenantId, appId: commit.adminAppId },
296
+ { sharedServiceId: commit.authSharedServiceId }
297
+ );
298
+ if (payload.themeService && payload.themeService.hostname) {
299
+ await installService(
300
+ "theme",
301
+ payload.themeService.hostname,
302
+ { tenantId: commit.adminTenantId, appId: commit.adminAppId },
303
+ { sharedServiceId: commit.themeSharedServiceId }
304
+ );
305
+ }
306
+
307
+ // 3. Build admin role with all permissions from every registered service's manifest.
308
+ await buildAdminRole(commit.adminAppId, payload, commit);
309
+
310
+ // 4. Redirect to admin app. First admin user is created THERE: the app's
311
+ // login flow redirects to /register while the auth service has zero
312
+ // users, so the request originates from the app origin and tenant/app
313
+ // context resolves naturally.
314
+ const okStep = step("done", "Bootstrap complete - redirecting to " + payload.adminApp.hostname + " to create the first admin");
315
+ okStep.done();
316
+ setTimeout(() => { window.location.href = payload.adminApp.hostname; }, 2000);
317
+ } catch (e) {
318
+ const note = document.createElement("div");
319
+ note.className = "alert-err";
320
+ note.textContent = "Setup failed: " + e.message;
321
+ stepsEl.appendChild(note);
322
+ document.getElementById("submitBtn").disabled = false;
323
+ }
324
+ });
325
+ </script>
326
+ </body>
327
+ </html>`;
328
+ }
329
+ //# sourceMappingURL=bootstrapWizardHtml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrapWizardHtml.js","sourceRoot":"","sources":["../../../src/plugins/service-betterportal-config-manager/bootstrapWizardHtml.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,yBAAyB,CAAC,KAA2B;IACnE,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACpD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAuGW,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA8MxB,CAAC;AACT,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { HtmlRenderable } from "@betterportal/framework";
2
+ import type { ResponseData } from "../index.js";
3
+ export declare function render(data: ResponseData): HtmlRenderable;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/plugins/service-betterportal-config-manager/bp-routes/auth/_theme.bootstrap1/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA+BhD,wBAAgB,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,cAAc,CAqOzD"}
@@ -0,0 +1,38 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "jsx-htmx/jsx-runtime";
2
+ /** @jsxImportSource jsx-htmx */
3
+ import { js } from "jsx-htmx";
4
+ function permsScript(apiBase, serviceUrl, selectedAppId) {
5
+ return js(`(() => {
6
+ const apiBase = ${JSON.stringify(apiBase)};
7
+ const appId = ${JSON.stringify(selectedAppId ?? "")};
8
+
9
+ if (!appId) return;
10
+
11
+ document.querySelectorAll("[data-bp-edit-role]").forEach((btn) => {
12
+ btn.addEventListener("click", () => {
13
+ const role = JSON.parse(btn.dataset.bpEditRole);
14
+ const form = document.getElementById("bp-edit-role-form");
15
+ if (!form) return;
16
+ form.setAttribute("hx-put", apiBase + "/apps/" + encodeURIComponent(appId) + "/auth/roles/" + encodeURIComponent(role.id));
17
+ form.querySelector("[name=roleId]").value = role.id;
18
+ form.querySelector("[name=title]").value = role.title;
19
+ form.querySelector("[name=description]").value = role.description || "";
20
+ form.querySelectorAll("[data-bp-grant]").forEach((box) => {
21
+ const [sid, vid, action] = box.dataset.bpGrant.split("|");
22
+ const grant = role.permissions.find((p) => p.serviceId === sid && p.viewId === vid);
23
+ box.checked = !!(grant && grant.permissions.includes(action));
24
+ });
25
+ if (window.htmx) window.htmx.process(form);
26
+ });
27
+ });
28
+ })()`);
29
+ }
30
+ const ACTIONS = ["read", "create", "update", "delete"];
31
+ export function render(data) {
32
+ const serviceUrl = data.serviceBaseUrl ?? "";
33
+ const apiBase = serviceUrl + data.adminApiBase;
34
+ const authPath = `${serviceUrl}/auth`;
35
+ const selectedApp = data.apps.find((a) => a.id === data.selectedAppId);
36
+ return (_jsxs("div", { class: "container-fluid px-0", children: [_jsxs("div", { class: "d-flex justify-content-between align-items-center mb-4", children: [_jsxs("div", { children: [_jsx("h2", { class: "mb-1", children: data.title }), _jsx("p", { class: "text-secondary mb-0", children: "Define roles + permission grants per app. Services advertise per-view requirements via manifest." })] }), selectedApp && data.authConfigured ? (_jsx("button", { class: "btn btn-primary", "data-bs-toggle": "offcanvas", "data-bs-target": "#bp-add-role-panel", children: "+ Add Role" })) : null] }), _jsxs("div", { class: "mb-4", children: [_jsx("label", { class: "form-label", children: "App" }), _jsxs("select", { class: "form-select", id: "bp-app-select", name: "appId", "hx-get": authPath, "hx-trigger": "change", "hx-target": "#bp-main", "hx-swap": "innerHTML", "hx-push-url": "true", children: [_jsx("option", { value: "", children: "Select app..." }), data.apps.map((a) => (_jsx("option", { value: a.id, selected: a.id === data.selectedAppId ? true : undefined, children: a.title })))] })] }), !selectedApp ? (_jsxs("div", { class: "alert alert-secondary", children: ["Select an app to manage its roles. No apps? Create one in ", _jsx("strong", { children: "Tenants & Apps" }), "."] })) : !data.authConfigured ? (_jsx("div", { class: "alert alert-warning", children: "Configure an auth provider for this app before creating roles." })) : (_jsxs("div", { class: "row g-4", children: [_jsx("div", { class: "col-lg-7", children: _jsx("div", { class: "card border-0 shadow-sm", children: _jsxs("div", { class: "card-body", children: [_jsxs("h5", { class: "card-title mb-3", children: ["Roles for ", selectedApp.title, " (", data.currentRoles.length, ")"] }), data.currentRoles.length === 0 ? (_jsx("div", { class: "alert alert-secondary mb-0", children: "No roles defined. Click \"Add Role\" to create one." })) : (_jsx("div", { class: "table-responsive", children: _jsxs("table", { class: "table table-sm align-middle", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "ID" }), _jsx("th", { children: "Title" }), _jsx("th", { children: "Grants" }), _jsx("th", {})] }) }), _jsx("tbody", { children: data.currentRoles.map((r) => (_jsxs("tr", { children: [_jsx("td", { class: "font-monospace small", children: r.id }), _jsxs("td", { children: [_jsx("div", { children: r.title }), r.description ? _jsx("div", { class: "small text-secondary", children: r.description }) : null] }), _jsx("td", { children: _jsxs("span", { class: "badge text-bg-secondary", children: [r.permissions.length, " grant", r.permissions.length === 1 ? "" : "s"] }) }), _jsx("td", { children: _jsxs("div", { class: "btn-group btn-group-sm", children: [_jsx("button", { class: "btn btn-outline-primary", "data-bs-toggle": "offcanvas", "data-bs-target": "#bp-edit-role-panel", "data-bp-edit-role": JSON.stringify(r), children: "Edit" }), _jsx("button", { class: "btn btn-outline-danger", "hx-delete": `${apiBase}/apps/${selectedApp.id}/auth/roles/${r.id}`, "hx-confirm": `Delete role ${r.id}?`, "hx-target": "#bp-main", "hx-swap": "innerHTML", children: "x" })] }) })] }))) })] }) }))] }) }) }), _jsx("div", { class: "col-lg-5", children: _jsx("div", { class: "card border-0 shadow-sm", children: _jsxs("div", { class: "card-body", children: [_jsx("h5", { class: "card-title mb-3", children: "Available services & views" }), data.servicePermissions.length === 0 ? (_jsx("div", { class: "text-secondary small", children: "No services registered yet." })) : (data.servicePermissions.map((s) => (_jsxs("div", { class: "mb-3", children: [_jsx("div", { class: "fw-semibold", children: s.title }), _jsxs("div", { class: "font-monospace small text-secondary mb-1", children: [s.serviceId, s.manifestVersion ? ` - v${s.manifestVersion}` : " - manifest pending"] }), s.views.length === 0 ? (_jsx("div", { class: "small text-secondary fst-italic", children: "No views in manifest cache." })) : (_jsx("ul", { class: "list-unstyled small mb-0", children: s.views.map((v) => (_jsxs("li", { class: "ms-2", children: [_jsx("code", { children: v.viewId }), _jsxs("span", { class: "text-secondary", children: [" ", v.path] }), v.role ? _jsx("span", { class: "badge text-bg-info ms-1", children: v.role }) : null] }))) }))] }))))] }) }) })] })), selectedApp && data.authConfigured ? (_jsxs("div", { class: "offcanvas offcanvas-end", tabindex: -1, id: "bp-add-role-panel", children: [_jsxs("div", { class: "offcanvas-header", children: [_jsx("h5", { class: "offcanvas-title", children: "Add Role" }), _jsx("button", { type: "button", class: "btn-close", "data-bs-dismiss": "offcanvas" })] }), _jsx("div", { class: "offcanvas-body", children: _jsxs("form", { id: "bp-add-role-form", "hx-post": `${apiBase}/apps/${selectedApp.id}/auth/roles`, "hx-target": "#bp-main", "hx-swap": "innerHTML", children: [_jsxs("div", { class: "mb-3", children: [_jsx("label", { class: "form-label", children: "Title" }), _jsx("input", { type: "text", class: "form-control", name: "title", placeholder: "Administrator", required: true })] }), _jsxs("div", { class: "mb-3", children: [_jsx("label", { class: "form-label", children: "Description (optional)" }), _jsx("textarea", { class: "form-control", name: "description", rows: 2 })] }), _jsx("div", { class: "alert alert-danger d-none", id: "bp-add-role-error" }), _jsx("button", { type: "submit", class: "btn btn-primary w-100", children: "Create Role" }), _jsx("p", { class: "text-secondary small mt-2 mb-0", children: "Grants are set via the Edit panel after creation." })] }) })] })) : null, selectedApp && data.authConfigured ? (_jsxs("div", { class: "offcanvas offcanvas-end", tabindex: -1, id: "bp-edit-role-panel", style: "--bs-offcanvas-width: 600px;", children: [_jsxs("div", { class: "offcanvas-header", children: [_jsx("h5", { class: "offcanvas-title", children: "Edit Role" }), _jsx("button", { type: "button", class: "btn-close", "data-bs-dismiss": "offcanvas" })] }), _jsx("div", { class: "offcanvas-body", children: _jsxs("form", { id: "bp-edit-role-form", "hx-target": "#bp-main", "hx-swap": "innerHTML", children: [_jsx("input", { type: "hidden", name: "roleId" }), _jsxs("div", { class: "mb-3", children: [_jsx("label", { class: "form-label", children: "Title" }), _jsx("input", { type: "text", class: "form-control", name: "title", required: true })] }), _jsxs("div", { class: "mb-3", children: [_jsx("label", { class: "form-label", children: "Description" }), _jsx("textarea", { class: "form-control", name: "description", rows: 2 })] }), _jsx("h6", { class: "mt-4 mb-2", children: "Permission grants" }), _jsx("p", { class: "small text-secondary", children: "Check actions this role grants for each service view." }), data.servicePermissions.length === 0 || data.servicePermissions.every((s) => s.views.length === 0) ? (_jsx("div", { class: "alert alert-secondary small mb-3", children: "No services or views in manifest cache yet. Services will appear here once they push their manifest (next poll cycle)." })) : (data.servicePermissions.map((s) => (s.views.length === 0 ? null : (_jsxs("div", { class: "mb-3", children: [_jsx("div", { class: "fw-semibold small", children: s.title }), _jsx("div", { class: "table-responsive", children: _jsxs("table", { class: "table table-sm align-middle mb-0", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { class: "small", children: "View" }), ACTIONS.map((a) => (_jsx("th", { class: "text-center small", children: a })))] }) }), _jsx("tbody", { children: s.views.map((v) => (_jsxs("tr", { children: [_jsx("td", { class: "font-monospace small", children: v.viewId }), ACTIONS.map((a) => (_jsx("td", { class: "text-center", children: _jsx("input", { type: "checkbox", class: "form-check-input", name: "grant", value: `${s.serviceId}|${v.viewId}|${a}`, "data-bp-grant": `${s.serviceId}|${v.viewId}|${a}` }) })))] }))) })] }) })] }))))), _jsx("div", { class: "alert alert-danger d-none", id: "bp-edit-role-error" }), _jsx("button", { type: "submit", class: "btn btn-primary w-100", children: "Save Role" })] }) })] })) : null, _jsx("script", { children: permsScript(apiBase, serviceUrl, data.selectedAppId) })] }));
37
+ }
38
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/plugins/service-betterportal-config-manager/bp-routes/auth/_theme.bootstrap1/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ import * as av from "anyvali";
2
+ import type { Infer } from "anyvali";
3
+ import { type ApiAuthRequirement, type CacheHints } from "@betterportal/framework";
4
+ export declare const QuerySchema: av.ObjectSchema<{
5
+ appId: av.OptionalSchema<av.StringSchema>;
6
+ }>;
7
+ export declare const HeadersSchema: av.ObjectSchema<{}>;
8
+ export declare const RequestSchema: av.ObjectSchema<{}>;
9
+ export declare const ResponseSchema: av.ObjectSchema<{
10
+ title: av.StringSchema;
11
+ apps: av.ArraySchema<av.ObjectSchema<{
12
+ id: av.StringSchema;
13
+ tenantId: av.StringSchema;
14
+ title: av.StringSchema;
15
+ }>>;
16
+ selectedAppId: av.OptionalSchema<av.StringSchema>;
17
+ selectedTenantId: av.OptionalSchema<av.StringSchema>;
18
+ authConfigured: av.BoolSchema;
19
+ servicePermissions: av.ArraySchema<av.ObjectSchema<{
20
+ serviceId: av.StringSchema;
21
+ title: av.StringSchema;
22
+ hostname: av.StringSchema;
23
+ manifestVersion: av.OptionalSchema<av.StringSchema>;
24
+ views: av.ArraySchema<av.ObjectSchema<{
25
+ viewId: av.StringSchema;
26
+ path: av.StringSchema;
27
+ methods: av.ArraySchema<av.StringSchema>;
28
+ role: av.OptionalSchema<av.StringSchema>;
29
+ requiredPermissions: av.ArraySchema<av.ObjectSchema<{
30
+ serviceId: av.StringSchema;
31
+ viewId: av.StringSchema;
32
+ permissions: av.ArraySchema<av.StringSchema>;
33
+ }>>;
34
+ }>>;
35
+ }>>;
36
+ currentRoles: av.ArraySchema<av.ObjectSchema<{
37
+ id: av.StringSchema;
38
+ title: av.StringSchema;
39
+ description: av.OptionalSchema<av.StringSchema>;
40
+ permissions: av.ArraySchema<av.ObjectSchema<{
41
+ serviceId: av.StringSchema;
42
+ viewId: av.StringSchema;
43
+ permissions: av.ArraySchema<av.EnumSchema<readonly ["read", "create", "update", "delete"]>>;
44
+ }>>;
45
+ }>>;
46
+ adminApiBase: av.StringSchema;
47
+ serviceBaseUrl: av.OptionalSchema<av.StringSchema>;
48
+ }>;
49
+ export type ResponseData = Infer<typeof ResponseSchema>;
50
+ export declare const title = "Permission Manager";
51
+ export declare const description = "Define role -> permission grants per app. Services advertise per-view permission requirements via their manifest.";
52
+ export declare const auth: ApiAuthRequirement;
53
+ export declare const cacheHints: CacheHints;
54
+ export declare const handleGet: import("@betterportal/framework").RouteHandler<Record<string, string>, {
55
+ appId?: string | undefined;
56
+ }, Record<string, string>, Record<string, unknown>, {
57
+ title: string;
58
+ apps: {
59
+ id: string;
60
+ tenantId: string;
61
+ title: string;
62
+ }[];
63
+ authConfigured: boolean;
64
+ servicePermissions: {
65
+ serviceId: string;
66
+ title: string;
67
+ hostname: string;
68
+ views: {
69
+ viewId: string;
70
+ path: string;
71
+ methods: string[];
72
+ requiredPermissions: {
73
+ serviceId: string;
74
+ viewId: string;
75
+ permissions: string[];
76
+ }[];
77
+ role?: string | undefined;
78
+ }[];
79
+ manifestVersion?: string | undefined;
80
+ }[];
81
+ currentRoles: {
82
+ id: string;
83
+ title: string;
84
+ permissions: {
85
+ serviceId: string;
86
+ viewId: string;
87
+ permissions: ("read" | "create" | "update" | "delete")[];
88
+ }[];
89
+ description?: string | undefined;
90
+ }[];
91
+ adminApiBase: string;
92
+ selectedAppId?: string | undefined;
93
+ selectedTenantId?: string | undefined;
94
+ serviceBaseUrl?: string | undefined;
95
+ }, unknown, Record<string, unknown>>;
96
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/service-betterportal-config-manager/bp-routes/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,UAAU,EAChB,MAAM,yBAAyB,CAAC;AA2CjC,eAAO,MAAM,WAAW;;EAEI,CAAC;AAE7B,eAAO,MAAM,aAAa,qBAA0C,CAAC;AAErE,eAAO,MAAM,aAAa,qBAA0C,CAAC;AAErE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAUC,CAAC;AAC7B,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAExD,eAAO,MAAM,KAAK,uBAAuB,CAAC;AAC1C,eAAO,MAAM,WAAW,sHAAsH,CAAC;AAE/I,eAAO,MAAM,IAAI,EAAE,kBAKlB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,UAGxB,CAAC;AAEF,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oCAarB,CAAC"}
@@ -0,0 +1,78 @@
1
+ import * as av from "anyvali";
2
+ import { createHandler } from "@betterportal/framework";
3
+ const PermissionActionSchema = av.enum_(["read", "create", "update", "delete"]);
4
+ const ViewWithPermsSchema = av.object({
5
+ viewId: av.string().minLength(1),
6
+ path: av.string().minLength(1),
7
+ methods: av.array(av.string()).default([]),
8
+ role: av.optional(av.string()),
9
+ requiredPermissions: av.array(av.object({
10
+ serviceId: av.string().minLength(1),
11
+ viewId: av.string().minLength(1),
12
+ permissions: av.array(av.string())
13
+ }, { unknownKeys: "strip" })).default([])
14
+ }, { unknownKeys: "strip" });
15
+ const ServiceWithViewsSchema = av.object({
16
+ serviceId: av.string().minLength(1),
17
+ title: av.string().minLength(1),
18
+ hostname: av.string(),
19
+ manifestVersion: av.optional(av.string()),
20
+ views: av.array(ViewWithPermsSchema).default([])
21
+ }, { unknownKeys: "strip" });
22
+ const RolePermissionGrantSchema = av.object({
23
+ serviceId: av.string().minLength(1),
24
+ viewId: av.string().minLength(1),
25
+ permissions: av.array(PermissionActionSchema).minItems(1)
26
+ }, { unknownKeys: "strip" });
27
+ const AppRoleSchema = av.object({
28
+ id: av.string().minLength(1),
29
+ title: av.string().minLength(1),
30
+ description: av.optional(av.string()),
31
+ permissions: av.array(RolePermissionGrantSchema).default([])
32
+ }, { unknownKeys: "strip" });
33
+ const AppSummarySchema = av.object({
34
+ id: av.string().minLength(1),
35
+ tenantId: av.string().minLength(1),
36
+ title: av.string().minLength(1)
37
+ }, { unknownKeys: "strip" });
38
+ export const QuerySchema = av.object({
39
+ appId: av.optional(av.string().minLength(1))
40
+ }, { unknownKeys: "strip" });
41
+ export const HeadersSchema = av.object({}, { unknownKeys: "strip" });
42
+ export const RequestSchema = av.object({}, { unknownKeys: "strip" });
43
+ export const ResponseSchema = av.object({
44
+ title: av.string().minLength(1),
45
+ apps: av.array(AppSummarySchema).default([]),
46
+ selectedAppId: av.optional(av.string()),
47
+ selectedTenantId: av.optional(av.string()),
48
+ authConfigured: av.bool().default(false),
49
+ servicePermissions: av.array(ServiceWithViewsSchema).default([]),
50
+ currentRoles: av.array(AppRoleSchema).default([]),
51
+ adminApiBase: av.string().default("/.well-known/bp/admin"),
52
+ serviceBaseUrl: av.optional(av.string())
53
+ }, { unknownKeys: "strip" });
54
+ export const title = "Permission Manager";
55
+ export const description = "Define role -> permission grants per app. Services advertise per-view permission requirements via their manifest.";
56
+ export const auth = {
57
+ required: true,
58
+ permissions: [
59
+ { serviceId: "service.betterportal.config-manager", viewId: "auth.index", permissions: ["read", "create", "update", "delete"] }
60
+ ]
61
+ };
62
+ export const cacheHints = {
63
+ ttlSeconds: 0,
64
+ varyBy: ["accept", "origin"]
65
+ };
66
+ export const handleGet = createHandler({ response: ResponseSchema, query: QuerySchema }, (ctx) => {
67
+ if (ctx.responseModel)
68
+ return ctx.responseModel;
69
+ return {
70
+ title: "Permission Manager",
71
+ apps: [],
72
+ authConfigured: false,
73
+ servicePermissions: [],
74
+ currentRoles: [],
75
+ adminApiBase: "/.well-known/bp/admin"
76
+ };
77
+ });
78
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/plugins/service-betterportal-config-manager/bp-routes/auth/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { HtmlRenderable } from "@betterportal/framework";
2
+ import type { ResponseData } from "../index.js";
3
+ export declare function render(data: ResponseData): HtmlRenderable;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/plugins/service-betterportal-config-manager/bp-routes/config/_theme.bootstrap1/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA0DhD,wBAAgB,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,cAAc,CA+DzD"}