@intranefr/superbackend 1.5.3 → 1.6.3
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/cookies.txt +6 -0
- package/cookies1.txt +6 -0
- package/cookies2.txt +6 -0
- package/cookies3.txt +6 -0
- package/cookies4.txt +5 -0
- package/cookies_old.txt +5 -0
- package/cookies_old_test.txt +6 -0
- package/cookies_super.txt +5 -0
- package/cookies_super_test.txt +6 -0
- package/cookies_test.txt +6 -0
- package/index.js +7 -0
- package/package.json +3 -1
- package/plugins/core-waiting-list-migration/README.md +118 -0
- package/plugins/core-waiting-list-migration/index.js +438 -0
- package/plugins/global-settings-presets/index.js +20 -0
- package/plugins/hello-cli/index.js +17 -0
- package/plugins/ui-components-seeder/components/suiAlert.js +212 -0
- package/plugins/ui-components-seeder/components/suiToast.js +186 -0
- package/plugins/ui-components-seeder/index.js +31 -0
- package/public/js/admin-ui-components-preview.js +281 -0
- package/public/js/admin-ui-components.js +408 -0
- package/public/js/llm-provider-model-picker.js +193 -0
- package/public/test-iframe-fix.html +63 -0
- package/public/test-iframe.html +14 -0
- package/src/admin/endpointRegistry.js +68 -0
- package/src/controllers/admin.controller.js +25 -5
- package/src/controllers/adminDataCleanup.controller.js +45 -0
- package/src/controllers/adminLlm.controller.js +0 -8
- package/src/controllers/adminLogin.controller.js +269 -0
- package/src/controllers/adminPlugins.controller.js +55 -0
- package/src/controllers/adminRegistry.controller.js +106 -0
- package/src/controllers/adminStats.controller.js +4 -4
- package/src/controllers/registry.controller.js +32 -0
- package/src/controllers/waitingList.controller.js +52 -74
- package/src/middleware/auth.js +71 -1
- package/src/middleware/rbac.js +62 -0
- package/src/middleware.js +454 -153
- package/src/models/GlobalSetting.js +11 -1
- package/src/models/UiComponent.js +2 -0
- package/src/models/User.js +1 -1
- package/src/routes/admin.routes.js +3 -3
- package/src/routes/adminAgents.routes.js +2 -2
- package/src/routes/adminAssets.routes.js +11 -11
- package/src/routes/adminBlog.routes.js +2 -2
- package/src/routes/adminBlogAi.routes.js +2 -2
- package/src/routes/adminBlogAutomation.routes.js +2 -2
- package/src/routes/adminCache.routes.js +2 -2
- package/src/routes/adminConsoleManager.routes.js +2 -2
- package/src/routes/adminCrons.routes.js +2 -2
- package/src/routes/adminDataCleanup.routes.js +26 -0
- package/src/routes/adminDbBrowser.routes.js +2 -2
- package/src/routes/adminEjsVirtual.routes.js +2 -2
- package/src/routes/adminFeatureFlags.routes.js +6 -6
- package/src/routes/adminHeadless.routes.js +2 -2
- package/src/routes/adminHealthChecks.routes.js +2 -2
- package/src/routes/adminI18n.routes.js +2 -2
- package/src/routes/adminJsonConfigs.routes.js +8 -8
- package/src/routes/adminLlm.routes.js +8 -8
- package/src/routes/adminLogin.routes.js +23 -0
- package/src/routes/adminMarkdowns.routes.js +3 -9
- package/src/routes/adminMigration.routes.js +12 -12
- package/src/routes/adminPages.routes.js +2 -2
- package/src/routes/adminPlugins.routes.js +15 -0
- package/src/routes/adminProxy.routes.js +2 -2
- package/src/routes/adminRateLimits.routes.js +8 -8
- package/src/routes/adminRbac.routes.js +2 -2
- package/src/routes/adminRegistry.routes.js +24 -0
- package/src/routes/adminScripts.routes.js +2 -2
- package/src/routes/adminSeoConfig.routes.js +10 -10
- package/src/routes/adminTelegram.routes.js +2 -2
- package/src/routes/adminTerminals.routes.js +2 -2
- package/src/routes/adminUiComponents.routes.js +2 -2
- package/src/routes/adminUploadNamespaces.routes.js +7 -7
- package/src/routes/blogInternal.routes.js +2 -2
- package/src/routes/experiments.routes.js +2 -2
- package/src/routes/formsAdmin.routes.js +6 -6
- package/src/routes/globalSettings.routes.js +8 -8
- package/src/routes/internalExperiments.routes.js +2 -2
- package/src/routes/notificationAdmin.routes.js +7 -7
- package/src/routes/orgAdmin.routes.js +16 -16
- package/src/routes/pages.routes.js +3 -3
- package/src/routes/registry.routes.js +11 -0
- package/src/routes/stripeAdmin.routes.js +12 -12
- package/src/routes/userAdmin.routes.js +7 -7
- package/src/routes/waitingListAdmin.routes.js +2 -2
- package/src/routes/workflows.routes.js +3 -3
- package/src/services/dataCleanup.service.js +286 -0
- package/src/services/jsonConfigs.service.js +262 -0
- package/src/services/plugins.service.js +348 -0
- package/src/services/registry.service.js +452 -0
- package/src/services/uiComponents.service.js +180 -0
- package/src/services/waitingListJson.service.js +401 -0
- package/src/utils/rbac/rightsRegistry.js +118 -0
- package/test-access.js +63 -0
- package/test-iframe-fix.html +63 -0
- package/test-iframe.html +14 -0
- package/views/admin-403.ejs +92 -0
- package/views/admin-dashboard-home.ejs +52 -2
- package/views/admin-dashboard.ejs +143 -2
- package/views/admin-data-cleanup.ejs +357 -0
- package/views/admin-login.ejs +286 -0
- package/views/admin-plugins-system.ejs +223 -0
- package/views/admin-ui-components.ejs +82 -402
- package/views/admin-users.ejs +207 -11
- package/views/partials/dashboard/nav-items.ejs +2 -0
- package/views/partials/llm-provider-model-picker.ejs +0 -161
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Plugins system</title>
|
|
7
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
8
|
+
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
|
|
9
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@latest/dist/tabler-icons.min.css">
|
|
10
|
+
</head>
|
|
11
|
+
<body class="bg-gray-100">
|
|
12
|
+
<div id="app" class="min-h-screen p-6">
|
|
13
|
+
<div class="max-w-6xl mx-auto space-y-6">
|
|
14
|
+
<header class="bg-white rounded-xl border border-gray-200 p-6">
|
|
15
|
+
<h1 class="text-2xl font-bold text-gray-900 flex items-center gap-2">
|
|
16
|
+
<i class="ti ti-puzzle text-blue-600"></i>
|
|
17
|
+
Plugins system
|
|
18
|
+
</h1>
|
|
19
|
+
<p class="text-gray-600 mt-2">Enable, disable, and install local CommonJS plugins from <code class="text-sm bg-gray-100 px-1.5 py-0.5 rounded">cwd/plugins/*</code>.</p>
|
|
20
|
+
</header>
|
|
21
|
+
|
|
22
|
+
<section class="bg-white rounded-xl border border-gray-200 p-6">
|
|
23
|
+
<div class="flex items-center justify-between mb-4">
|
|
24
|
+
<h2 class="text-lg font-semibold text-gray-800">Available plugins</h2>
|
|
25
|
+
<button @click="loadPlugins" class="px-3 py-2 rounded-lg bg-blue-600 text-white hover:bg-blue-700 text-sm">
|
|
26
|
+
Refresh
|
|
27
|
+
</button>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<p v-if="error" class="mb-4 text-sm text-red-600">{{ error }}</p>
|
|
31
|
+
|
|
32
|
+
<div v-if="loading" class="text-sm text-gray-500">Loading plugins...</div>
|
|
33
|
+
|
|
34
|
+
<div v-else-if="plugins.length === 0" class="text-sm text-gray-500 border border-dashed border-gray-300 rounded-lg p-4">
|
|
35
|
+
No plugins discovered. Create folders under <code>plugins/</code> with an <code>index.js</code> CommonJS export.
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div v-else class="space-y-3">
|
|
39
|
+
<article v-for="plugin in plugins" :key="plugin.id" class="border border-gray-200 rounded-lg p-4 bg-gray-50">
|
|
40
|
+
<div class="flex items-start justify-between gap-4">
|
|
41
|
+
<div>
|
|
42
|
+
<h3 class="font-semibold text-gray-900">{{ plugin.name }} <span class="text-xs text-gray-500">({{ plugin.id }})</span></h3>
|
|
43
|
+
<p class="text-sm text-gray-600 mt-1">{{ plugin.description || 'No description provided.' }}</p>
|
|
44
|
+
<div class="mt-2 flex flex-wrap gap-2 text-xs">
|
|
45
|
+
<span class="px-2 py-1 rounded bg-white border border-gray-200">version: {{ plugin.version }}</span>
|
|
46
|
+
<span class="px-2 py-1 rounded bg-white border border-gray-200">bootstrap: {{ plugin.hooks.bootstrap ? 'yes' : 'no' }}</span>
|
|
47
|
+
<span class="px-2 py-1 rounded bg-white border border-gray-200">install: {{ plugin.hooks.install ? 'yes' : 'no' }}</span>
|
|
48
|
+
<span class="px-2 py-1 rounded" :class="plugin.enabled ? 'bg-green-100 text-green-800 border border-green-200' : 'bg-gray-200 text-gray-700 border border-gray-300'">
|
|
49
|
+
{{ plugin.enabled ? 'enabled' : 'disabled' }}
|
|
50
|
+
</span>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<div class="flex flex-col gap-2 min-w-[170px]">
|
|
55
|
+
<button
|
|
56
|
+
v-if="!plugin.enabled"
|
|
57
|
+
@click="enablePlugin(plugin.id)"
|
|
58
|
+
class="px-3 py-2 rounded-lg bg-green-600 text-white hover:bg-green-700 text-sm"
|
|
59
|
+
>Enable</button>
|
|
60
|
+
<button
|
|
61
|
+
v-else
|
|
62
|
+
@click="disablePlugin(plugin.id)"
|
|
63
|
+
class="px-3 py-2 rounded-lg bg-gray-700 text-white hover:bg-gray-800 text-sm"
|
|
64
|
+
>Disable</button>
|
|
65
|
+
<button
|
|
66
|
+
@click="installPlugin(plugin.id)"
|
|
67
|
+
class="px-3 py-2 rounded-lg bg-indigo-600 text-white hover:bg-indigo-700 text-sm"
|
|
68
|
+
>Run install</button>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</article>
|
|
72
|
+
</div>
|
|
73
|
+
</section>
|
|
74
|
+
|
|
75
|
+
<section class="bg-white rounded-xl border border-gray-200 p-6 space-y-3">
|
|
76
|
+
<h2 class="text-lg font-semibold text-gray-800">How to create and use plugins</h2>
|
|
77
|
+
|
|
78
|
+
<details class="border border-gray-200 rounded-lg p-4">
|
|
79
|
+
<summary class="cursor-pointer font-medium text-gray-900">Add a new plugin</summary>
|
|
80
|
+
<pre class="mt-3 text-xs bg-gray-900 text-gray-100 p-3 rounded overflow-auto">plugins/my-plugin/index.js
|
|
81
|
+
|
|
82
|
+
module.exports = {
|
|
83
|
+
meta: {
|
|
84
|
+
id: 'my-plugin',
|
|
85
|
+
name: 'My Plugin',
|
|
86
|
+
version: '1.0.0',
|
|
87
|
+
description: 'Example plugin',
|
|
88
|
+
tags: ['example']
|
|
89
|
+
},
|
|
90
|
+
hooks: {
|
|
91
|
+
bootstrap(ctx) {
|
|
92
|
+
console.log('[my-plugin] bootstrap', Object.keys(ctx.services || {}));
|
|
93
|
+
},
|
|
94
|
+
install(ctx) {
|
|
95
|
+
console.log('[my-plugin] install');
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};</pre>
|
|
99
|
+
</details>
|
|
100
|
+
|
|
101
|
+
<details class="border border-gray-200 rounded-lg p-4">
|
|
102
|
+
<summary class="cursor-pointer font-medium text-gray-900">Permissive contract supported</summary>
|
|
103
|
+
<pre class="mt-3 text-xs bg-gray-900 text-gray-100 p-3 rounded overflow-auto">module.exports = {
|
|
104
|
+
id: 'top-level-contract',
|
|
105
|
+
name: 'Top level contract plugin',
|
|
106
|
+
bootstrap(ctx) {
|
|
107
|
+
console.log('bootstrap hook with fallback contract');
|
|
108
|
+
},
|
|
109
|
+
install(ctx) {
|
|
110
|
+
console.log('install hook with fallback contract');
|
|
111
|
+
}
|
|
112
|
+
};</pre>
|
|
113
|
+
</details>
|
|
114
|
+
|
|
115
|
+
<details class="border border-gray-200 rounded-lg p-4">
|
|
116
|
+
<summary class="cursor-pointer font-medium text-gray-900">Expose helpers/services programmatically</summary>
|
|
117
|
+
<pre class="mt-3 text-xs bg-gray-900 text-gray-100 p-3 rounded overflow-auto">module.exports = {
|
|
118
|
+
meta: { id: 'tools', name: 'Tools plugin' },
|
|
119
|
+
services: {
|
|
120
|
+
myService() {
|
|
121
|
+
return 'hello';
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
helpers: {
|
|
125
|
+
formatLabel(input) {
|
|
126
|
+
return String(input || '').toUpperCase();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// then available in runtime after enable/bootstrap:
|
|
132
|
+
// superbackend.services.pluginsRuntime.myService()
|
|
133
|
+
// superbackend.helpers.pluginsRuntime.formatLabel('demo')</pre>
|
|
134
|
+
</details>
|
|
135
|
+
</section>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
|
|
139
|
+
<script>
|
|
140
|
+
const { createApp, ref, onMounted } = Vue;
|
|
141
|
+
|
|
142
|
+
createApp({
|
|
143
|
+
setup() {
|
|
144
|
+
const baseUrl = '<%= baseUrl %>';
|
|
145
|
+
const plugins = ref([]);
|
|
146
|
+
const loading = ref(false);
|
|
147
|
+
const error = ref('');
|
|
148
|
+
|
|
149
|
+
const loadPlugins = async () => {
|
|
150
|
+
loading.value = true;
|
|
151
|
+
error.value = '';
|
|
152
|
+
try {
|
|
153
|
+
const response = await fetch(baseUrl + '/api/admin/plugins');
|
|
154
|
+
const payload = await response.json();
|
|
155
|
+
if (!response.ok) throw new Error(payload.error || 'Failed to load plugins');
|
|
156
|
+
plugins.value = payload.items || [];
|
|
157
|
+
} catch (err) {
|
|
158
|
+
error.value = err.message || 'Failed to load plugins';
|
|
159
|
+
} finally {
|
|
160
|
+
loading.value = false;
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const enablePlugin = async (id) => {
|
|
165
|
+
error.value = '';
|
|
166
|
+
try {
|
|
167
|
+
const response = await fetch(baseUrl + '/api/admin/plugins/' + encodeURIComponent(id) + '/enable', {
|
|
168
|
+
method: 'POST',
|
|
169
|
+
headers: { 'Content-Type': 'application/json' }
|
|
170
|
+
});
|
|
171
|
+
const payload = await response.json();
|
|
172
|
+
if (!response.ok) throw new Error(payload.error || 'Enable failed');
|
|
173
|
+
await loadPlugins();
|
|
174
|
+
} catch (err) {
|
|
175
|
+
error.value = err.message || 'Enable failed';
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const disablePlugin = async (id) => {
|
|
180
|
+
error.value = '';
|
|
181
|
+
try {
|
|
182
|
+
const response = await fetch(baseUrl + '/api/admin/plugins/' + encodeURIComponent(id) + '/disable', {
|
|
183
|
+
method: 'POST',
|
|
184
|
+
headers: { 'Content-Type': 'application/json' }
|
|
185
|
+
});
|
|
186
|
+
const payload = await response.json();
|
|
187
|
+
if (!response.ok) throw new Error(payload.error || 'Disable failed');
|
|
188
|
+
await loadPlugins();
|
|
189
|
+
} catch (err) {
|
|
190
|
+
error.value = err.message || 'Disable failed';
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
const installPlugin = async (id) => {
|
|
195
|
+
error.value = '';
|
|
196
|
+
try {
|
|
197
|
+
const response = await fetch(baseUrl + '/api/admin/plugins/' + encodeURIComponent(id) + '/install', {
|
|
198
|
+
method: 'POST',
|
|
199
|
+
headers: { 'Content-Type': 'application/json' }
|
|
200
|
+
});
|
|
201
|
+
const payload = await response.json();
|
|
202
|
+
if (!response.ok) throw new Error(payload.error || 'Install failed');
|
|
203
|
+
} catch (err) {
|
|
204
|
+
error.value = err.message || 'Install failed';
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
onMounted(loadPlugins);
|
|
209
|
+
|
|
210
|
+
return {
|
|
211
|
+
plugins,
|
|
212
|
+
loading,
|
|
213
|
+
error,
|
|
214
|
+
loadPlugins,
|
|
215
|
+
enablePlugin,
|
|
216
|
+
disablePlugin,
|
|
217
|
+
installPlugin,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
}).mount('#app');
|
|
221
|
+
</script>
|
|
222
|
+
</body>
|
|
223
|
+
</html>
|