@sonicjs-cms/core 2.10.0 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-CJYFSKH7.js → chunk-2MXF4RYZ.js} +3 -3
- package/dist/{chunk-CJYFSKH7.js.map → chunk-2MXF4RYZ.js.map} +1 -1
- package/dist/{chunk-MNFY6DWY.cjs → chunk-56GUBLJE.cjs} +7 -7
- package/dist/{chunk-MNFY6DWY.cjs.map → chunk-56GUBLJE.cjs.map} +1 -1
- package/dist/{chunk-IIBRG5S5.cjs → chunk-6BVLPACH.cjs} +408 -2
- package/dist/chunk-6BVLPACH.cjs.map +1 -0
- package/dist/{chunk-RCA6R6VE.cjs → chunk-ASAEJ4B7.cjs} +315 -162
- package/dist/chunk-ASAEJ4B7.cjs.map +1 -0
- package/dist/{chunk-IT2TC4ZD.cjs → chunk-B2ASV5RD.cjs} +13 -7
- package/dist/chunk-B2ASV5RD.cjs.map +1 -0
- package/dist/{chunk-IZWNIUJI.js → chunk-BUU2US2Z.js} +3 -3
- package/dist/{chunk-IZWNIUJI.js.map → chunk-BUU2US2Z.js.map} +1 -1
- package/dist/{chunk-ZMVWMJ3S.cjs → chunk-DE5YTNCD.cjs} +9 -2
- package/dist/chunk-DE5YTNCD.cjs.map +1 -0
- package/dist/{chunk-4TTMQQC7.js → chunk-GKRGDJGG.js} +10 -4
- package/dist/chunk-GKRGDJGG.js.map +1 -0
- package/dist/{chunk-6O3RJV3C.js → chunk-H55AYIRI.js} +9 -2
- package/dist/chunk-H55AYIRI.js.map +1 -0
- package/dist/{chunk-JTNUM7JE.js → chunk-JTQBNSZX.js} +187 -34
- package/dist/chunk-JTQBNSZX.js.map +1 -0
- package/dist/{chunk-64APW3DW.cjs → chunk-LFAQUR7P.cjs} +9 -2
- package/dist/chunk-LFAQUR7P.cjs.map +1 -0
- package/dist/{chunk-27AOVQTR.js → chunk-NMLFKXWW.js} +402 -3
- package/dist/chunk-NMLFKXWW.js.map +1 -0
- package/dist/{chunk-EKPLKUZT.cjs → chunk-QLPFENZ2.cjs} +3 -3
- package/dist/{chunk-EKPLKUZT.cjs.map → chunk-QLPFENZ2.cjs.map} +1 -1
- package/dist/{chunk-KYGRJCZM.cjs → chunk-QTFKZBLC.cjs} +3 -2
- package/dist/chunk-QTFKZBLC.cjs.map +1 -0
- package/dist/{chunk-LOUJRBXV.js → chunk-QXOZI5Q2.js} +3 -2
- package/dist/chunk-QXOZI5Q2.js.map +1 -0
- package/dist/{chunk-7JMMLHPQ.js → chunk-VJCLJH3X.js} +9 -2
- package/dist/chunk-VJCLJH3X.js.map +1 -0
- package/dist/index.cjs +751 -152
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +125 -5
- package/dist/index.d.ts +125 -5
- package/dist/index.js +582 -15
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +29 -29
- package/dist/middleware.js +3 -3
- package/dist/migrations-UFVJTPVT.js +4 -0
- package/dist/{migrations-N2C2VPJU.js.map → migrations-UFVJTPVT.js.map} +1 -1
- package/dist/migrations-VNYOSUNE.cjs +13 -0
- package/dist/{migrations-ONIAY6GK.cjs.map → migrations-VNYOSUNE.cjs.map} +1 -1
- package/dist/{plugin-0Xogrln-.d.cts → plugin-DDYetMF-.d.cts} +1 -0
- package/dist/{plugin-0Xogrln-.d.ts → plugin-DDYetMF-.d.ts} +1 -0
- package/dist/{plugin-bootstrap-fpG98Otb.d.cts → plugin-bootstrap-DCXpeQVb.d.cts} +229 -1
- package/dist/{plugin-bootstrap-WmpvYM5w.d.ts → plugin-bootstrap-DXBAYaqM.d.ts} +229 -1
- package/dist/{plugin-manager-GcIeb226.d.cts → plugin-manager-BoM3Q7o7.d.cts} +1 -1
- package/dist/{plugin-manager-Clf2gXwj.d.ts → plugin-manager-Efx9RyDX.d.ts} +1 -1
- package/dist/plugins.cjs +10 -10
- package/dist/plugins.d.cts +2 -2
- package/dist/plugins.d.ts +2 -2
- package/dist/plugins.js +2 -2
- package/dist/routes.cjs +29 -29
- package/dist/routes.js +6 -6
- package/dist/services.cjs +60 -32
- package/dist/services.d.cts +1 -1
- package/dist/services.d.ts +1 -1
- package/dist/services.js +3 -3
- package/dist/types.cjs +2 -2
- package/dist/types.d.cts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utils.cjs +11 -11
- package/dist/utils.js +1 -1
- package/migrations/033_form_content_integration.sql +19 -0
- package/package.json +1 -1
- package/dist/chunk-27AOVQTR.js.map +0 -1
- package/dist/chunk-4TTMQQC7.js.map +0 -1
- package/dist/chunk-64APW3DW.cjs.map +0 -1
- package/dist/chunk-6O3RJV3C.js.map +0 -1
- package/dist/chunk-7JMMLHPQ.js.map +0 -1
- package/dist/chunk-IIBRG5S5.cjs.map +0 -1
- package/dist/chunk-IT2TC4ZD.cjs.map +0 -1
- package/dist/chunk-JTNUM7JE.js.map +0 -1
- package/dist/chunk-KYGRJCZM.cjs.map +0 -1
- package/dist/chunk-LOUJRBXV.js.map +0 -1
- package/dist/chunk-RCA6R6VE.cjs.map +0 -1
- package/dist/chunk-ZMVWMJ3S.cjs.map +0 -1
- package/dist/migrations-N2C2VPJU.js +0 -4
- package/dist/migrations-ONIAY6GK.cjs +0 -13
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { getCacheService, CACHE_CONFIGS,
|
|
2
|
-
import { requireAuth, requireRole, isPluginActive, optionalAuth, rateLimit, AuthManager, logActivity, generateCsrfToken } from './chunk-
|
|
3
|
-
import { PluginService } from './chunk-
|
|
4
|
-
import { MigrationService } from './chunk-
|
|
1
|
+
import { getCacheService, CACHE_CONFIGS, SettingsService, getLogger, getAppInstance, buildRouteList, CATEGORY_INFO } from './chunk-VJCLJH3X.js';
|
|
2
|
+
import { requireAuth, requireRole, isPluginActive, optionalAuth, rateLimit, AuthManager, logActivity, generateCsrfToken } from './chunk-GKRGDJGG.js';
|
|
3
|
+
import { PluginService, createContentFromSubmission } from './chunk-NMLFKXWW.js';
|
|
4
|
+
import { MigrationService } from './chunk-H55AYIRI.js';
|
|
5
5
|
import { init_admin_layout_catalyst_template, renderDesignPage, renderCheckboxPage, renderTestimonialsList, renderCodeExamplesList, renderAlert, renderTable, renderPagination, renderConfirmationDialog, getConfirmationDialogScript, renderAdminLayoutCatalyst, renderAdminLayout, adminLayoutV2, renderForm } from './chunk-JJS7JZCH.js';
|
|
6
6
|
import { PluginBuilder, TurnstileService } from './chunk-J5WGMRSU.js';
|
|
7
|
-
import { QueryFilterBuilder, getCoreVersion, getBlocksFieldConfig, parseBlocksValue } from './chunk-
|
|
7
|
+
import { QueryFilterBuilder, getCoreVersion, getBlocksFieldConfig, parseBlocksValue } from './chunk-BUU2US2Z.js';
|
|
8
8
|
import { metricsTracker } from './chunk-FICTAGD4.js';
|
|
9
9
|
import { escapeHtml, sanitizeRichText, sanitizeInput } from './chunk-TQABQWOP.js';
|
|
10
10
|
import { Hono } from 'hono';
|
|
@@ -59,6 +59,69 @@ function normalizePublicContentFilter(filter, userRole) {
|
|
|
59
59
|
});
|
|
60
60
|
return normalizedFilter;
|
|
61
61
|
}
|
|
62
|
+
|
|
63
|
+
// src/plugins/core-plugins/global-variables-plugin/variable-resolver.ts
|
|
64
|
+
var TOKEN_PATTERN = /\{([a-z0-9_]+)\}/g;
|
|
65
|
+
function resolveVariables(text, variables) {
|
|
66
|
+
if (!text || variables.size === 0) return text;
|
|
67
|
+
return text.replace(TOKEN_PATTERN, (match, key) => {
|
|
68
|
+
const value = variables.get(key);
|
|
69
|
+
return value !== void 0 ? value : match;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function resolveVariablesInObject(obj, variables) {
|
|
73
|
+
if (!obj || variables.size === 0) return obj;
|
|
74
|
+
if (typeof obj === "string") {
|
|
75
|
+
return resolveVariables(obj, variables);
|
|
76
|
+
}
|
|
77
|
+
if (Array.isArray(obj)) {
|
|
78
|
+
return obj.map((item) => resolveVariablesInObject(item, variables));
|
|
79
|
+
}
|
|
80
|
+
if (typeof obj === "object") {
|
|
81
|
+
const result = {};
|
|
82
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
83
|
+
result[key] = resolveVariablesInObject(value, variables);
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
return obj;
|
|
88
|
+
}
|
|
89
|
+
var variableCache = null;
|
|
90
|
+
var cacheTimestamp = 0;
|
|
91
|
+
var CACHE_TTL_MS = 3e5;
|
|
92
|
+
function getVariablesCached() {
|
|
93
|
+
const now = Date.now();
|
|
94
|
+
if (variableCache && now - cacheTimestamp < CACHE_TTL_MS) {
|
|
95
|
+
return variableCache;
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
function setVariablesCache(map) {
|
|
100
|
+
variableCache = map;
|
|
101
|
+
cacheTimestamp = Date.now();
|
|
102
|
+
}
|
|
103
|
+
async function resolveContentVariables(contentData, db) {
|
|
104
|
+
if (!db || !contentData) return contentData;
|
|
105
|
+
try {
|
|
106
|
+
let variables = getVariablesCached();
|
|
107
|
+
if (!variables) {
|
|
108
|
+
const { results } = await db.prepare(
|
|
109
|
+
"SELECT key, value FROM global_variables WHERE is_active = 1"
|
|
110
|
+
).all();
|
|
111
|
+
variables = /* @__PURE__ */ new Map();
|
|
112
|
+
for (const row of results || []) {
|
|
113
|
+
variables.set(row.key, row.value);
|
|
114
|
+
}
|
|
115
|
+
setVariablesCache(variables);
|
|
116
|
+
}
|
|
117
|
+
if (variables.size === 0) return contentData;
|
|
118
|
+
return resolveVariablesInObject(contentData, variables);
|
|
119
|
+
} catch {
|
|
120
|
+
return contentData;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// src/routes/api-content-crud.ts
|
|
62
125
|
var apiContentCrudRoutes = new Hono();
|
|
63
126
|
apiContentCrudRoutes.get("/check-slug", async (c) => {
|
|
64
127
|
try {
|
|
@@ -110,6 +173,10 @@ apiContentCrudRoutes.get("/:id", async (c) => {
|
|
|
110
173
|
created_at: content.created_at,
|
|
111
174
|
updated_at: content.updated_at
|
|
112
175
|
};
|
|
176
|
+
const resolveVars = c.req.query("resolve_variables") !== "false";
|
|
177
|
+
if (resolveVars) {
|
|
178
|
+
transformedContent.data = await resolveContentVariables(transformedContent.data, db);
|
|
179
|
+
}
|
|
113
180
|
return c.json({ data: transformedContent });
|
|
114
181
|
} catch (error) {
|
|
115
182
|
console.error("Error fetching content:", error);
|
|
@@ -748,7 +815,7 @@ apiRoutes.get("/collections", async (c) => {
|
|
|
748
815
|
}
|
|
749
816
|
c.header("X-Cache-Status", "MISS");
|
|
750
817
|
c.header("X-Cache-Source", "database");
|
|
751
|
-
const stmt = db.prepare("SELECT * FROM collections WHERE is_active = 1");
|
|
818
|
+
const stmt = db.prepare("SELECT * FROM collections WHERE is_active = 1 AND (source_type IS NULL OR source_type = 'user')");
|
|
752
819
|
const { results } = await stmt.all();
|
|
753
820
|
const transformedResults = results.map((row) => ({
|
|
754
821
|
...row,
|
|
@@ -1777,7 +1844,7 @@ adminApiRoutes.get("/stats", async (c) => {
|
|
|
1777
1844
|
const db = c.env.DB;
|
|
1778
1845
|
let collectionsCount = 0;
|
|
1779
1846
|
try {
|
|
1780
|
-
const collectionsStmt = db.prepare("SELECT COUNT(*) as count FROM collections WHERE is_active = 1");
|
|
1847
|
+
const collectionsStmt = db.prepare("SELECT COUNT(*) as count FROM collections WHERE is_active = 1 AND (source_type IS NULL OR source_type = 'user')");
|
|
1781
1848
|
const collectionsResult = await collectionsStmt.first();
|
|
1782
1849
|
collectionsCount = collectionsResult?.count || 0;
|
|
1783
1850
|
} catch (error) {
|
|
@@ -1785,7 +1852,7 @@ adminApiRoutes.get("/stats", async (c) => {
|
|
|
1785
1852
|
}
|
|
1786
1853
|
let contentCount = 0;
|
|
1787
1854
|
try {
|
|
1788
|
-
const contentStmt = db.prepare("SELECT COUNT(*) as count FROM content WHERE deleted_at IS NULL");
|
|
1855
|
+
const contentStmt = db.prepare("SELECT COUNT(*) as count FROM content c JOIN collections col ON c.collection_id = col.id WHERE c.deleted_at IS NULL AND (col.source_type IS NULL OR col.source_type = 'user')");
|
|
1789
1856
|
const contentResult = await contentStmt.first();
|
|
1790
1857
|
contentCount = contentResult?.count || 0;
|
|
1791
1858
|
} catch (error) {
|
|
@@ -1927,6 +1994,7 @@ adminApiRoutes.get("/collections", async (c) => {
|
|
|
1927
1994
|
SELECT id, name, display_name, description, created_at, updated_at, is_active, managed
|
|
1928
1995
|
FROM collections
|
|
1929
1996
|
WHERE ${includeInactive ? "1=1" : "is_active = 1"}
|
|
1997
|
+
AND (source_type IS NULL OR source_type = 'user')
|
|
1930
1998
|
AND (name LIKE ? OR display_name LIKE ? OR description LIKE ?)
|
|
1931
1999
|
ORDER BY created_at DESC
|
|
1932
2000
|
`);
|
|
@@ -1937,7 +2005,8 @@ adminApiRoutes.get("/collections", async (c) => {
|
|
|
1937
2005
|
stmt = db.prepare(`
|
|
1938
2006
|
SELECT id, name, display_name, description, created_at, updated_at, is_active, managed
|
|
1939
2007
|
FROM collections
|
|
1940
|
-
|
|
2008
|
+
WHERE (source_type IS NULL OR source_type = 'user')
|
|
2009
|
+
${includeInactive ? "" : "AND is_active = 1"}
|
|
1941
2010
|
ORDER BY created_at DESC
|
|
1942
2011
|
`);
|
|
1943
2012
|
const queryResults = await stmt.all();
|
|
@@ -2281,7 +2350,7 @@ adminApiRoutes.delete("/collections/:id", async (c) => {
|
|
|
2281
2350
|
});
|
|
2282
2351
|
adminApiRoutes.get("/migrations/status", async (c) => {
|
|
2283
2352
|
try {
|
|
2284
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
2353
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-UFVJTPVT.js');
|
|
2285
2354
|
const db = c.env.DB;
|
|
2286
2355
|
const migrationService = new MigrationService2(db);
|
|
2287
2356
|
const status = await migrationService.getMigrationStatus();
|
|
@@ -2306,7 +2375,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
|
|
|
2306
2375
|
error: "Unauthorized. Admin access required."
|
|
2307
2376
|
}, 403);
|
|
2308
2377
|
}
|
|
2309
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
2378
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-UFVJTPVT.js');
|
|
2310
2379
|
const db = c.env.DB;
|
|
2311
2380
|
const migrationService = new MigrationService2(db);
|
|
2312
2381
|
const result = await migrationService.runPendingMigrations();
|
|
@@ -2325,7 +2394,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
|
|
|
2325
2394
|
});
|
|
2326
2395
|
adminApiRoutes.get("/migrations/validate", async (c) => {
|
|
2327
2396
|
try {
|
|
2328
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
2397
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-UFVJTPVT.js');
|
|
2329
2398
|
const db = c.env.DB;
|
|
2330
2399
|
const migrationService = new MigrationService2(db);
|
|
2331
2400
|
const validation = await migrationService.validateSchema();
|
|
@@ -8137,7 +8206,15 @@ function renderContentFormPage(data) {
|
|
|
8137
8206
|
fetch(\`/admin/content/\${contentId}/versions\`)
|
|
8138
8207
|
.then(response => response.text())
|
|
8139
8208
|
.then(html => {
|
|
8140
|
-
document.getElementById('version-history-content')
|
|
8209
|
+
const container = document.getElementById('version-history-content');
|
|
8210
|
+
container.innerHTML = html;
|
|
8211
|
+
// Script tags inserted via innerHTML are not executed by the browser,
|
|
8212
|
+
// so we need to manually create and append them for execution.
|
|
8213
|
+
container.querySelectorAll('script').forEach(oldScript => {
|
|
8214
|
+
const newScript = document.createElement('script');
|
|
8215
|
+
newScript.textContent = oldScript.textContent;
|
|
8216
|
+
oldScript.replaceWith(newScript);
|
|
8217
|
+
});
|
|
8141
8218
|
})
|
|
8142
8219
|
.catch(error => {
|
|
8143
8220
|
console.error('Error loading version history:', error);
|
|
@@ -9357,7 +9434,7 @@ adminContentRoutes.get("/", async (c) => {
|
|
|
9357
9434
|
const status = url.searchParams.get("status") || "all";
|
|
9358
9435
|
const search = url.searchParams.get("search") || "";
|
|
9359
9436
|
const offset = (page - 1) * limit;
|
|
9360
|
-
const collectionsStmt = db.prepare("SELECT id, name, display_name FROM collections WHERE is_active = 1 ORDER BY display_name");
|
|
9437
|
+
const collectionsStmt = db.prepare("SELECT id, name, display_name FROM collections WHERE is_active = 1 AND (source_type IS NULL OR source_type = 'user') ORDER BY display_name");
|
|
9361
9438
|
const { results: collectionsResults } = await collectionsStmt.all();
|
|
9362
9439
|
const models = (collectionsResults || []).map((row) => ({
|
|
9363
9440
|
name: row.name,
|
|
@@ -9365,6 +9442,7 @@ adminContentRoutes.get("/", async (c) => {
|
|
|
9365
9442
|
}));
|
|
9366
9443
|
const conditions = [];
|
|
9367
9444
|
const params = [];
|
|
9445
|
+
conditions.push("(col.source_type IS NULL OR col.source_type = 'user')");
|
|
9368
9446
|
if (status !== "deleted") {
|
|
9369
9447
|
conditions.push("c.status != 'deleted'");
|
|
9370
9448
|
}
|
|
@@ -9493,7 +9571,7 @@ adminContentRoutes.get("/new", async (c) => {
|
|
|
9493
9571
|
const collectionId = url.searchParams.get("collection");
|
|
9494
9572
|
if (!collectionId) {
|
|
9495
9573
|
const db2 = c.env.DB;
|
|
9496
|
-
const collectionsStmt = db2.prepare("SELECT id, name, display_name, description FROM collections WHERE is_active = 1 ORDER BY display_name");
|
|
9574
|
+
const collectionsStmt = db2.prepare("SELECT id, name, display_name, description FROM collections WHERE is_active = 1 AND (source_type IS NULL OR source_type = 'user') ORDER BY display_name");
|
|
9497
9575
|
const { results } = await collectionsStmt.all();
|
|
9498
9576
|
const collections = (results || []).map((row) => ({
|
|
9499
9577
|
id: row.id,
|
|
@@ -11417,6 +11495,36 @@ function renderUserEditPage(data) {
|
|
|
11417
11495
|
</div>
|
|
11418
11496
|
</div>
|
|
11419
11497
|
|
|
11498
|
+
<!-- Set Password -->
|
|
11499
|
+
<div class="mb-8">
|
|
11500
|
+
<h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Set Password</h3>
|
|
11501
|
+
<p class="text-sm text-zinc-500 dark:text-zinc-400 mb-4">Leave blank to keep the current password</p>
|
|
11502
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
11503
|
+
<div>
|
|
11504
|
+
<label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">New Password</label>
|
|
11505
|
+
<input
|
|
11506
|
+
type="password"
|
|
11507
|
+
name="new_password"
|
|
11508
|
+
minlength="8"
|
|
11509
|
+
placeholder="Minimum 8 characters"
|
|
11510
|
+
autocomplete="new-password"
|
|
11511
|
+
class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow"
|
|
11512
|
+
/>
|
|
11513
|
+
</div>
|
|
11514
|
+
<div>
|
|
11515
|
+
<label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Confirm Password</label>
|
|
11516
|
+
<input
|
|
11517
|
+
type="password"
|
|
11518
|
+
name="confirm_password"
|
|
11519
|
+
minlength="8"
|
|
11520
|
+
placeholder="Repeat new password"
|
|
11521
|
+
autocomplete="new-password"
|
|
11522
|
+
class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow"
|
|
11523
|
+
/>
|
|
11524
|
+
</div>
|
|
11525
|
+
</div>
|
|
11526
|
+
</div>
|
|
11527
|
+
|
|
11420
11528
|
<!-- Account Status -->
|
|
11421
11529
|
<div class="mb-8">
|
|
11422
11530
|
<h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Account Status</h3>
|
|
@@ -12738,6 +12846,7 @@ userRoutes.get("/users", async (c) => {
|
|
|
12738
12846
|
formattedLastLogin: u.last_login_at ? new Date(u.last_login_at).toLocaleDateString() : void 0,
|
|
12739
12847
|
formattedCreatedAt: new Date(u.created_at).toLocaleDateString()
|
|
12740
12848
|
}));
|
|
12849
|
+
const successMessage = c.req.query("success") || void 0;
|
|
12741
12850
|
const pageData = {
|
|
12742
12851
|
users,
|
|
12743
12852
|
currentPage: page,
|
|
@@ -12746,6 +12855,7 @@ userRoutes.get("/users", async (c) => {
|
|
|
12746
12855
|
searchFilter: search,
|
|
12747
12856
|
roleFilter,
|
|
12748
12857
|
statusFilter,
|
|
12858
|
+
success: successMessage,
|
|
12749
12859
|
pagination: {
|
|
12750
12860
|
currentPage: page,
|
|
12751
12861
|
totalPages: Math.ceil(totalUsers / limit),
|
|
@@ -12889,7 +12999,8 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
12889
12999
|
c.req.header("x-forwarded-for") || c.req.header("cf-connecting-ip"),
|
|
12890
13000
|
c.req.header("user-agent")
|
|
12891
13001
|
);
|
|
12892
|
-
|
|
13002
|
+
c.header("HX-Redirect", "/admin/users?success=User created successfully");
|
|
13003
|
+
return c.body(null, 200);
|
|
12893
13004
|
} catch (error) {
|
|
12894
13005
|
console.error("User creation error:", error);
|
|
12895
13006
|
return c.html(renderAlert2({
|
|
@@ -13035,6 +13146,8 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
13035
13146
|
const role = validRoles.includes(roleInput) ? roleInput : "viewer";
|
|
13036
13147
|
const isActive = formData.get("is_active") === "1";
|
|
13037
13148
|
const emailVerified = formData.get("email_verified") === "1";
|
|
13149
|
+
const newPassword = formData.get("new_password")?.toString() || "";
|
|
13150
|
+
const confirmPassword = formData.get("confirm_password")?.toString() || "";
|
|
13038
13151
|
const profileDisplayName = sanitizeInput(formData.get("profile_display_name")?.toString()) || null;
|
|
13039
13152
|
const profileBio = sanitizeInput(formData.get("profile_bio")?.toString()) || null;
|
|
13040
13153
|
const profileCompany = sanitizeInput(formData.get("profile_company")?.toString()) || null;
|
|
@@ -13058,6 +13171,22 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
13058
13171
|
dismissible: true
|
|
13059
13172
|
}));
|
|
13060
13173
|
}
|
|
13174
|
+
if (newPassword) {
|
|
13175
|
+
if (newPassword.length < 8) {
|
|
13176
|
+
return c.html(renderAlert2({
|
|
13177
|
+
type: "error",
|
|
13178
|
+
message: "Password must be at least 8 characters long.",
|
|
13179
|
+
dismissible: true
|
|
13180
|
+
}));
|
|
13181
|
+
}
|
|
13182
|
+
if (newPassword !== confirmPassword) {
|
|
13183
|
+
return c.html(renderAlert2({
|
|
13184
|
+
type: "error",
|
|
13185
|
+
message: "Passwords do not match.",
|
|
13186
|
+
dismissible: true
|
|
13187
|
+
}));
|
|
13188
|
+
}
|
|
13189
|
+
}
|
|
13061
13190
|
if (profileWebsite) {
|
|
13062
13191
|
try {
|
|
13063
13192
|
new URL(profileWebsite);
|
|
@@ -13100,6 +13229,13 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
13100
13229
|
Date.now(),
|
|
13101
13230
|
userId
|
|
13102
13231
|
).run();
|
|
13232
|
+
if (newPassword) {
|
|
13233
|
+
const passwordHash = await AuthManager.hashPassword(newPassword);
|
|
13234
|
+
const updatePasswordStmt = db.prepare(`
|
|
13235
|
+
UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?
|
|
13236
|
+
`);
|
|
13237
|
+
await updatePasswordStmt.bind(passwordHash, Date.now(), userId).run();
|
|
13238
|
+
}
|
|
13103
13239
|
const hasProfileData = profileDisplayName || profileBio || profileCompany || profileJobTitle || profileWebsite || profileLocation || profileDateOfBirth;
|
|
13104
13240
|
if (hasProfileData) {
|
|
13105
13241
|
const now = Date.now();
|
|
@@ -13150,7 +13286,7 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
13150
13286
|
"user.update",
|
|
13151
13287
|
"users",
|
|
13152
13288
|
userId,
|
|
13153
|
-
{ fields: ["first_name", "last_name", "username", "email", "phone", "role", "is_active", "email_verified", "profile"] },
|
|
13289
|
+
{ fields: ["first_name", "last_name", "username", "email", "phone", "role", "is_active", "email_verified", "profile", ...newPassword ? ["password"] : []] },
|
|
13154
13290
|
c.req.header("x-forwarded-for") || c.req.header("cf-connecting-ip"),
|
|
13155
13291
|
c.req.header("user-agent")
|
|
13156
13292
|
);
|
|
@@ -17250,6 +17386,7 @@ function renderOTPLoginSettingsContent(plugin, settings) {
|
|
|
17250
17386
|
const maxAttempts = settings.maxAttempts || 3;
|
|
17251
17387
|
const rateLimitPerHour = settings.rateLimitPerHour || 5;
|
|
17252
17388
|
const allowNewUserRegistration = settings.allowNewUserRegistration || false;
|
|
17389
|
+
const logoUrl = settings.logoUrl || "";
|
|
17253
17390
|
return `
|
|
17254
17391
|
<div class="space-y-6">
|
|
17255
17392
|
<!-- Test OTP Section -->
|
|
@@ -17433,6 +17570,7 @@ function renderOTPLoginSettingsContent(plugin, settings) {
|
|
|
17433
17570
|
|
|
17434
17571
|
<div class="bg-white rounded-lg overflow-hidden shadow-lg">
|
|
17435
17572
|
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px 20px; text-align: center;">
|
|
17573
|
+
${logoUrl ? `<img src="${logoUrl}" alt="Logo" style="max-width: 150px; height: auto; margin: 0 auto 16px;">` : ""}
|
|
17436
17574
|
<h3 style="margin: 0 0 8px 0; font-size: 24px; font-weight: 600;">Your Login Code</h3>
|
|
17437
17575
|
<p style="margin: 0; opacity: 0.95; font-size: 14px;">Enter this code to sign in to ${siteName}</p>
|
|
17438
17576
|
</div>
|
|
@@ -17957,17 +18095,9 @@ adminPluginRoutes.get("/:id", async (c) => {
|
|
|
17957
18095
|
const activity = await pluginService.getPluginActivity(pluginId, 20);
|
|
17958
18096
|
let enrichedSettings = plugin.settings || {};
|
|
17959
18097
|
if (pluginId === "otp-login") {
|
|
17960
|
-
const
|
|
17961
|
-
|
|
17962
|
-
|
|
17963
|
-
let siteName = "SonicJS";
|
|
17964
|
-
if (generalSettings?.value) {
|
|
17965
|
-
try {
|
|
17966
|
-
const parsed = JSON.parse(generalSettings.value);
|
|
17967
|
-
siteName = parsed.siteName || "SonicJS";
|
|
17968
|
-
} catch (e) {
|
|
17969
|
-
}
|
|
17970
|
-
}
|
|
18098
|
+
const settingsService = new SettingsService(db);
|
|
18099
|
+
const generalSettings = await settingsService.getGeneralSettings();
|
|
18100
|
+
const siteName = generalSettings.siteName || "SonicJS";
|
|
17971
18101
|
const emailPlugin = await db.prepare(`
|
|
17972
18102
|
SELECT settings FROM plugins WHERE id = 'email'
|
|
17973
18103
|
`).first();
|
|
@@ -21524,7 +21654,7 @@ router.get("/stats", async (c) => {
|
|
|
21524
21654
|
const db = c.env.DB;
|
|
21525
21655
|
let collectionsCount = 0;
|
|
21526
21656
|
try {
|
|
21527
|
-
const collectionsStmt = db.prepare("SELECT COUNT(*) as count FROM collections WHERE is_active = 1");
|
|
21657
|
+
const collectionsStmt = db.prepare("SELECT COUNT(*) as count FROM collections WHERE is_active = 1 AND (source_type IS NULL OR source_type = 'user')");
|
|
21528
21658
|
const collectionsResult = await collectionsStmt.first();
|
|
21529
21659
|
collectionsCount = collectionsResult?.count || 0;
|
|
21530
21660
|
} catch (error) {
|
|
@@ -21532,7 +21662,7 @@ router.get("/stats", async (c) => {
|
|
|
21532
21662
|
}
|
|
21533
21663
|
let contentCount = 0;
|
|
21534
21664
|
try {
|
|
21535
|
-
const contentStmt = db.prepare("SELECT COUNT(*) as count FROM content");
|
|
21665
|
+
const contentStmt = db.prepare("SELECT COUNT(*) as count FROM content c JOIN collections col ON c.collection_id = col.id WHERE (col.source_type IS NULL OR col.source_type = 'user')");
|
|
21536
21666
|
const contentResult = await contentStmt.first();
|
|
21537
21667
|
contentCount = contentResult?.count || 0;
|
|
21538
21668
|
} catch (error) {
|
|
@@ -23329,6 +23459,7 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
23329
23459
|
SELECT id, name, display_name, description, created_at, managed, schema
|
|
23330
23460
|
FROM collections
|
|
23331
23461
|
WHERE is_active = 1
|
|
23462
|
+
AND (source_type IS NULL OR source_type = 'user')
|
|
23332
23463
|
AND (name LIKE ? OR display_name LIKE ? OR description LIKE ?)
|
|
23333
23464
|
ORDER BY created_at DESC
|
|
23334
23465
|
`);
|
|
@@ -23336,7 +23467,7 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
23336
23467
|
const queryResults = await stmt.bind(searchParam, searchParam, searchParam).all();
|
|
23337
23468
|
results = queryResults.results;
|
|
23338
23469
|
} else {
|
|
23339
|
-
stmt = db.prepare("SELECT id, name, display_name, description, created_at, managed, schema FROM collections WHERE is_active = 1 ORDER BY created_at DESC");
|
|
23470
|
+
stmt = db.prepare("SELECT id, name, display_name, description, created_at, managed, schema FROM collections WHERE is_active = 1 AND (source_type IS NULL OR source_type = 'user') ORDER BY created_at DESC");
|
|
23340
23471
|
const queryResults = await stmt.all();
|
|
23341
23472
|
results = queryResults.results;
|
|
23342
23473
|
}
|
|
@@ -28408,14 +28539,36 @@ publicFormsRoutes.post("/:identifier/submit", async (c) => {
|
|
|
28408
28539
|
now
|
|
28409
28540
|
).run();
|
|
28410
28541
|
await db.prepare(`
|
|
28411
|
-
UPDATE forms
|
|
28542
|
+
UPDATE forms
|
|
28412
28543
|
SET submission_count = submission_count + 1,
|
|
28413
28544
|
updated_at = ?
|
|
28414
28545
|
WHERE id = ?
|
|
28415
28546
|
`).bind(now, form.id).run();
|
|
28547
|
+
let contentId = null;
|
|
28548
|
+
try {
|
|
28549
|
+
contentId = await createContentFromSubmission(
|
|
28550
|
+
db,
|
|
28551
|
+
sanitizedData,
|
|
28552
|
+
{ id: form.id, name: form.name, display_name: form.display_name },
|
|
28553
|
+
submissionId,
|
|
28554
|
+
{
|
|
28555
|
+
ipAddress: c.req.header("cf-connecting-ip") || null,
|
|
28556
|
+
userAgent: c.req.header("user-agent") || null,
|
|
28557
|
+
userEmail: sanitizedData?.email || null,
|
|
28558
|
+
userId: null
|
|
28559
|
+
// anonymous submission
|
|
28560
|
+
}
|
|
28561
|
+
);
|
|
28562
|
+
if (!contentId) {
|
|
28563
|
+
console.warn("[FormSubmit] Content creation returned null for submission:", submissionId);
|
|
28564
|
+
}
|
|
28565
|
+
} catch (contentError) {
|
|
28566
|
+
console.error("[FormSubmit] Error creating content from submission:", contentError);
|
|
28567
|
+
}
|
|
28416
28568
|
return c.json({
|
|
28417
28569
|
success: true,
|
|
28418
28570
|
submissionId,
|
|
28571
|
+
contentId,
|
|
28419
28572
|
message: "Form submitted successfully"
|
|
28420
28573
|
});
|
|
28421
28574
|
} catch (error) {
|
|
@@ -28826,5 +28979,5 @@ var ROUTES_INFO = {
|
|
|
28826
28979
|
};
|
|
28827
28980
|
|
|
28828
28981
|
export { ROUTES_INFO, adminCheckboxRoutes, adminCollectionsRoutes, adminDesignRoutes, adminFormsRoutes, adminLogsRoutes, adminMediaRoutes, adminPluginRoutes, adminSettingsRoutes, admin_api_default, admin_code_examples_default, admin_content_default, admin_testimonials_default, api_content_crud_default, api_default, api_media_default, api_system_default, auth_default, getConfirmationDialogScript2 as getConfirmationDialogScript, public_forms_default, renderConfirmationDialog2 as renderConfirmationDialog, router, router2, test_cleanup_default, userRoutes };
|
|
28829
|
-
//# sourceMappingURL=chunk-
|
|
28830
|
-
//# sourceMappingURL=chunk-
|
|
28982
|
+
//# sourceMappingURL=chunk-JTQBNSZX.js.map
|
|
28983
|
+
//# sourceMappingURL=chunk-JTQBNSZX.js.map
|