@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,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
3
|
+
var chunkLFAQUR7P_cjs = require('./chunk-LFAQUR7P.cjs');
|
|
4
|
+
var chunkB2ASV5RD_cjs = require('./chunk-B2ASV5RD.cjs');
|
|
5
|
+
var chunk6BVLPACH_cjs = require('./chunk-6BVLPACH.cjs');
|
|
6
|
+
var chunkDE5YTNCD_cjs = require('./chunk-DE5YTNCD.cjs');
|
|
7
7
|
var chunkLTKV7AE5_cjs = require('./chunk-LTKV7AE5.cjs');
|
|
8
8
|
var chunk6FHNRRJ3_cjs = require('./chunk-6FHNRRJ3.cjs');
|
|
9
|
-
var
|
|
9
|
+
var chunkQLPFENZ2_cjs = require('./chunk-QLPFENZ2.cjs');
|
|
10
10
|
var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
|
|
11
11
|
var chunkMNWKYY5E_cjs = require('./chunk-MNWKYY5E.cjs');
|
|
12
12
|
var hono = require('hono');
|
|
@@ -61,6 +61,69 @@ function normalizePublicContentFilter(filter, userRole) {
|
|
|
61
61
|
});
|
|
62
62
|
return normalizedFilter;
|
|
63
63
|
}
|
|
64
|
+
|
|
65
|
+
// src/plugins/core-plugins/global-variables-plugin/variable-resolver.ts
|
|
66
|
+
var TOKEN_PATTERN = /\{([a-z0-9_]+)\}/g;
|
|
67
|
+
function resolveVariables(text, variables) {
|
|
68
|
+
if (!text || variables.size === 0) return text;
|
|
69
|
+
return text.replace(TOKEN_PATTERN, (match, key) => {
|
|
70
|
+
const value = variables.get(key);
|
|
71
|
+
return value !== void 0 ? value : match;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function resolveVariablesInObject(obj, variables) {
|
|
75
|
+
if (!obj || variables.size === 0) return obj;
|
|
76
|
+
if (typeof obj === "string") {
|
|
77
|
+
return resolveVariables(obj, variables);
|
|
78
|
+
}
|
|
79
|
+
if (Array.isArray(obj)) {
|
|
80
|
+
return obj.map((item) => resolveVariablesInObject(item, variables));
|
|
81
|
+
}
|
|
82
|
+
if (typeof obj === "object") {
|
|
83
|
+
const result = {};
|
|
84
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
85
|
+
result[key] = resolveVariablesInObject(value, variables);
|
|
86
|
+
}
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
return obj;
|
|
90
|
+
}
|
|
91
|
+
var variableCache = null;
|
|
92
|
+
var cacheTimestamp = 0;
|
|
93
|
+
var CACHE_TTL_MS = 3e5;
|
|
94
|
+
function getVariablesCached() {
|
|
95
|
+
const now = Date.now();
|
|
96
|
+
if (variableCache && now - cacheTimestamp < CACHE_TTL_MS) {
|
|
97
|
+
return variableCache;
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
function setVariablesCache(map) {
|
|
102
|
+
variableCache = map;
|
|
103
|
+
cacheTimestamp = Date.now();
|
|
104
|
+
}
|
|
105
|
+
async function resolveContentVariables(contentData, db) {
|
|
106
|
+
if (!db || !contentData) return contentData;
|
|
107
|
+
try {
|
|
108
|
+
let variables = getVariablesCached();
|
|
109
|
+
if (!variables) {
|
|
110
|
+
const { results } = await db.prepare(
|
|
111
|
+
"SELECT key, value FROM global_variables WHERE is_active = 1"
|
|
112
|
+
).all();
|
|
113
|
+
variables = /* @__PURE__ */ new Map();
|
|
114
|
+
for (const row of results || []) {
|
|
115
|
+
variables.set(row.key, row.value);
|
|
116
|
+
}
|
|
117
|
+
setVariablesCache(variables);
|
|
118
|
+
}
|
|
119
|
+
if (variables.size === 0) return contentData;
|
|
120
|
+
return resolveVariablesInObject(contentData, variables);
|
|
121
|
+
} catch {
|
|
122
|
+
return contentData;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/routes/api-content-crud.ts
|
|
64
127
|
var apiContentCrudRoutes = new hono.Hono();
|
|
65
128
|
apiContentCrudRoutes.get("/check-slug", async (c) => {
|
|
66
129
|
try {
|
|
@@ -112,6 +175,10 @@ apiContentCrudRoutes.get("/:id", async (c) => {
|
|
|
112
175
|
created_at: content.created_at,
|
|
113
176
|
updated_at: content.updated_at
|
|
114
177
|
};
|
|
178
|
+
const resolveVars = c.req.query("resolve_variables") !== "false";
|
|
179
|
+
if (resolveVars) {
|
|
180
|
+
transformedContent.data = await resolveContentVariables(transformedContent.data, db);
|
|
181
|
+
}
|
|
115
182
|
return c.json({ data: transformedContent });
|
|
116
183
|
} catch (error) {
|
|
117
184
|
console.error("Error fetching content:", error);
|
|
@@ -121,7 +188,7 @@ apiContentCrudRoutes.get("/:id", async (c) => {
|
|
|
121
188
|
}, 500);
|
|
122
189
|
}
|
|
123
190
|
});
|
|
124
|
-
apiContentCrudRoutes.post("/",
|
|
191
|
+
apiContentCrudRoutes.post("/", chunkB2ASV5RD_cjs.requireAuth(), chunkB2ASV5RD_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
125
192
|
try {
|
|
126
193
|
const db = c.env.DB;
|
|
127
194
|
const user = c.get("user");
|
|
@@ -162,7 +229,7 @@ apiContentCrudRoutes.post("/", chunkIT2TC4ZD_cjs.requireAuth(), chunkIT2TC4ZD_cj
|
|
|
162
229
|
now,
|
|
163
230
|
now
|
|
164
231
|
).run();
|
|
165
|
-
const cache =
|
|
232
|
+
const cache = chunkLFAQUR7P_cjs.getCacheService(chunkLFAQUR7P_cjs.CACHE_CONFIGS.api);
|
|
166
233
|
await cache.invalidate(`content:list:${collectionId}:*`);
|
|
167
234
|
await cache.invalidate("content-filtered:*");
|
|
168
235
|
const getStmt = db.prepare("SELECT * FROM content WHERE id = ?");
|
|
@@ -187,7 +254,7 @@ apiContentCrudRoutes.post("/", chunkIT2TC4ZD_cjs.requireAuth(), chunkIT2TC4ZD_cj
|
|
|
187
254
|
}, 500);
|
|
188
255
|
}
|
|
189
256
|
});
|
|
190
|
-
apiContentCrudRoutes.put("/:id",
|
|
257
|
+
apiContentCrudRoutes.put("/:id", chunkB2ASV5RD_cjs.requireAuth(), chunkB2ASV5RD_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
191
258
|
try {
|
|
192
259
|
const id = c.req.param("id");
|
|
193
260
|
const db = c.env.DB;
|
|
@@ -225,7 +292,7 @@ apiContentCrudRoutes.put("/:id", chunkIT2TC4ZD_cjs.requireAuth(), chunkIT2TC4ZD_
|
|
|
225
292
|
WHERE id = ?
|
|
226
293
|
`);
|
|
227
294
|
await updateStmt.bind(...params).run();
|
|
228
|
-
const cache =
|
|
295
|
+
const cache = chunkLFAQUR7P_cjs.getCacheService(chunkLFAQUR7P_cjs.CACHE_CONFIGS.api);
|
|
229
296
|
await cache.delete(cache.generateKey("content", id));
|
|
230
297
|
await cache.invalidate(`content:list:${existing.collection_id}:*`);
|
|
231
298
|
await cache.invalidate("content-filtered:*");
|
|
@@ -251,7 +318,7 @@ apiContentCrudRoutes.put("/:id", chunkIT2TC4ZD_cjs.requireAuth(), chunkIT2TC4ZD_
|
|
|
251
318
|
}, 500);
|
|
252
319
|
}
|
|
253
320
|
});
|
|
254
|
-
apiContentCrudRoutes.delete("/:id",
|
|
321
|
+
apiContentCrudRoutes.delete("/:id", chunkB2ASV5RD_cjs.requireAuth(), chunkB2ASV5RD_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
255
322
|
try {
|
|
256
323
|
const id = c.req.param("id");
|
|
257
324
|
const db = c.env.DB;
|
|
@@ -262,7 +329,7 @@ apiContentCrudRoutes.delete("/:id", chunkIT2TC4ZD_cjs.requireAuth(), chunkIT2TC4
|
|
|
262
329
|
}
|
|
263
330
|
const deleteStmt = db.prepare("DELETE FROM content WHERE id = ?");
|
|
264
331
|
await deleteStmt.bind(id).run();
|
|
265
|
-
const cache =
|
|
332
|
+
const cache = chunkLFAQUR7P_cjs.getCacheService(chunkLFAQUR7P_cjs.CACHE_CONFIGS.api);
|
|
266
333
|
await cache.delete(cache.generateKey("content", id));
|
|
267
334
|
await cache.invalidate(`content:list:${existing.collection_id}:*`);
|
|
268
335
|
await cache.invalidate("content-filtered:*");
|
|
@@ -287,7 +354,7 @@ apiRoutes.use("*", async (c, next) => {
|
|
|
287
354
|
c.header("X-Response-Time", `${totalTime}ms`);
|
|
288
355
|
});
|
|
289
356
|
apiRoutes.use("*", async (c, next) => {
|
|
290
|
-
const cacheEnabled = await
|
|
357
|
+
const cacheEnabled = await chunkB2ASV5RD_cjs.isPluginActive(c.env.DB, "core-cache");
|
|
291
358
|
c.set("cacheEnabled", cacheEnabled);
|
|
292
359
|
await next();
|
|
293
360
|
});
|
|
@@ -724,7 +791,7 @@ apiRoutes.get("/collections", async (c) => {
|
|
|
724
791
|
try {
|
|
725
792
|
const db = c.env.DB;
|
|
726
793
|
const cacheEnabled = c.get("cacheEnabled");
|
|
727
|
-
const cache =
|
|
794
|
+
const cache = chunkLFAQUR7P_cjs.getCacheService(chunkLFAQUR7P_cjs.CACHE_CONFIGS.api);
|
|
728
795
|
const cacheKey = cache.generateKey("collections", "all");
|
|
729
796
|
if (cacheEnabled) {
|
|
730
797
|
const cacheResult = await cache.getWithSource(cacheKey);
|
|
@@ -750,7 +817,7 @@ apiRoutes.get("/collections", async (c) => {
|
|
|
750
817
|
}
|
|
751
818
|
c.header("X-Cache-Status", "MISS");
|
|
752
819
|
c.header("X-Cache-Source", "database");
|
|
753
|
-
const stmt = db.prepare("SELECT * FROM collections WHERE is_active = 1");
|
|
820
|
+
const stmt = db.prepare("SELECT * FROM collections WHERE is_active = 1 AND (source_type IS NULL OR source_type = 'user')");
|
|
754
821
|
const { results } = await stmt.all();
|
|
755
822
|
const transformedResults = results.map((row) => ({
|
|
756
823
|
...row,
|
|
@@ -778,7 +845,7 @@ apiRoutes.get("/collections", async (c) => {
|
|
|
778
845
|
return c.json({ error: "Failed to fetch collections" }, 500);
|
|
779
846
|
}
|
|
780
847
|
});
|
|
781
|
-
apiRoutes.get("/content",
|
|
848
|
+
apiRoutes.get("/content", chunkB2ASV5RD_cjs.optionalAuth(), async (c) => {
|
|
782
849
|
const executionStart = Date.now();
|
|
783
850
|
try {
|
|
784
851
|
const db = c.env.DB;
|
|
@@ -801,13 +868,13 @@ apiRoutes.get("/content", chunkIT2TC4ZD_cjs.optionalAuth(), async (c) => {
|
|
|
801
868
|
});
|
|
802
869
|
}
|
|
803
870
|
}
|
|
804
|
-
const filter =
|
|
871
|
+
const filter = chunkQLPFENZ2_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
|
|
805
872
|
const normalizedFilter = normalizePublicContentFilter(filter, c.get("user")?.role);
|
|
806
873
|
if (!normalizedFilter.limit) {
|
|
807
874
|
normalizedFilter.limit = 50;
|
|
808
875
|
}
|
|
809
876
|
normalizedFilter.limit = Math.min(normalizedFilter.limit, 1e3);
|
|
810
|
-
const builder3 = new
|
|
877
|
+
const builder3 = new chunkQLPFENZ2_cjs.QueryFilterBuilder();
|
|
811
878
|
const queryResult = builder3.build("content", normalizedFilter);
|
|
812
879
|
if (queryResult.errors.length > 0) {
|
|
813
880
|
return c.json({
|
|
@@ -816,7 +883,7 @@ apiRoutes.get("/content", chunkIT2TC4ZD_cjs.optionalAuth(), async (c) => {
|
|
|
816
883
|
}, 400);
|
|
817
884
|
}
|
|
818
885
|
const cacheEnabled = c.get("cacheEnabled");
|
|
819
|
-
const cache =
|
|
886
|
+
const cache = chunkLFAQUR7P_cjs.getCacheService(chunkLFAQUR7P_cjs.CACHE_CONFIGS.api);
|
|
820
887
|
const cacheKey = cache.generateKey("content-filtered", JSON.stringify({ filter: normalizedFilter, query: queryResult.sql }));
|
|
821
888
|
if (cacheEnabled) {
|
|
822
889
|
const cacheResult = await cache.getWithSource(cacheKey);
|
|
@@ -879,7 +946,7 @@ apiRoutes.get("/content", chunkIT2TC4ZD_cjs.optionalAuth(), async (c) => {
|
|
|
879
946
|
}, 500);
|
|
880
947
|
}
|
|
881
948
|
});
|
|
882
|
-
apiRoutes.get("/collections/:collection/content",
|
|
949
|
+
apiRoutes.get("/collections/:collection/content", chunkB2ASV5RD_cjs.optionalAuth(), async (c) => {
|
|
883
950
|
const executionStart = Date.now();
|
|
884
951
|
try {
|
|
885
952
|
const collection = c.req.param("collection");
|
|
@@ -890,7 +957,7 @@ apiRoutes.get("/collections/:collection/content", chunkIT2TC4ZD_cjs.optionalAuth
|
|
|
890
957
|
if (!collectionResult) {
|
|
891
958
|
return c.json({ error: "Collection not found" }, 404);
|
|
892
959
|
}
|
|
893
|
-
const filter =
|
|
960
|
+
const filter = chunkQLPFENZ2_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
|
|
894
961
|
const normalizedFilter = normalizePublicContentFilter(filter, c.get("user")?.role);
|
|
895
962
|
if (!normalizedFilter.where) {
|
|
896
963
|
normalizedFilter.where = { and: [] };
|
|
@@ -907,7 +974,7 @@ apiRoutes.get("/collections/:collection/content", chunkIT2TC4ZD_cjs.optionalAuth
|
|
|
907
974
|
normalizedFilter.limit = 50;
|
|
908
975
|
}
|
|
909
976
|
normalizedFilter.limit = Math.min(normalizedFilter.limit, 1e3);
|
|
910
|
-
const builder3 = new
|
|
977
|
+
const builder3 = new chunkQLPFENZ2_cjs.QueryFilterBuilder();
|
|
911
978
|
const queryResult = builder3.build("content", normalizedFilter);
|
|
912
979
|
if (queryResult.errors.length > 0) {
|
|
913
980
|
return c.json({
|
|
@@ -916,7 +983,7 @@ apiRoutes.get("/collections/:collection/content", chunkIT2TC4ZD_cjs.optionalAuth
|
|
|
916
983
|
}, 400);
|
|
917
984
|
}
|
|
918
985
|
const cacheEnabled = c.get("cacheEnabled");
|
|
919
|
-
const cache =
|
|
986
|
+
const cache = chunkLFAQUR7P_cjs.getCacheService(chunkLFAQUR7P_cjs.CACHE_CONFIGS.api);
|
|
920
987
|
const cacheKey = cache.generateKey("collection-content-filtered", `${collection}:${JSON.stringify({ filter: normalizedFilter, query: queryResult.sql })}`);
|
|
921
988
|
if (cacheEnabled) {
|
|
922
989
|
const cacheResult = await cache.getWithSource(cacheKey);
|
|
@@ -1028,7 +1095,7 @@ var fileValidationSchema = zod.z.object({
|
|
|
1028
1095
|
// 50MB max
|
|
1029
1096
|
});
|
|
1030
1097
|
var apiMediaRoutes = new hono.Hono();
|
|
1031
|
-
apiMediaRoutes.use("*",
|
|
1098
|
+
apiMediaRoutes.use("*", chunkB2ASV5RD_cjs.requireAuth());
|
|
1032
1099
|
apiMediaRoutes.post("/upload", async (c) => {
|
|
1033
1100
|
try {
|
|
1034
1101
|
const user = c.get("user");
|
|
@@ -1772,14 +1839,14 @@ apiSystemRoutes.get("/env", (c) => {
|
|
|
1772
1839
|
});
|
|
1773
1840
|
var api_system_default = apiSystemRoutes;
|
|
1774
1841
|
var adminApiRoutes = new hono.Hono();
|
|
1775
|
-
adminApiRoutes.use("*",
|
|
1776
|
-
adminApiRoutes.use("*",
|
|
1842
|
+
adminApiRoutes.use("*", chunkB2ASV5RD_cjs.requireAuth());
|
|
1843
|
+
adminApiRoutes.use("*", chunkB2ASV5RD_cjs.requireRole(["admin", "editor"]));
|
|
1777
1844
|
adminApiRoutes.get("/stats", async (c) => {
|
|
1778
1845
|
try {
|
|
1779
1846
|
const db = c.env.DB;
|
|
1780
1847
|
let collectionsCount = 0;
|
|
1781
1848
|
try {
|
|
1782
|
-
const collectionsStmt = db.prepare("SELECT COUNT(*) as count FROM collections WHERE is_active = 1");
|
|
1849
|
+
const collectionsStmt = db.prepare("SELECT COUNT(*) as count FROM collections WHERE is_active = 1 AND (source_type IS NULL OR source_type = 'user')");
|
|
1783
1850
|
const collectionsResult = await collectionsStmt.first();
|
|
1784
1851
|
collectionsCount = collectionsResult?.count || 0;
|
|
1785
1852
|
} catch (error) {
|
|
@@ -1787,7 +1854,7 @@ adminApiRoutes.get("/stats", async (c) => {
|
|
|
1787
1854
|
}
|
|
1788
1855
|
let contentCount = 0;
|
|
1789
1856
|
try {
|
|
1790
|
-
const contentStmt = db.prepare("SELECT COUNT(*) as count FROM content WHERE deleted_at IS NULL");
|
|
1857
|
+
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')");
|
|
1791
1858
|
const contentResult = await contentStmt.first();
|
|
1792
1859
|
contentCount = contentResult?.count || 0;
|
|
1793
1860
|
} catch (error) {
|
|
@@ -1929,6 +1996,7 @@ adminApiRoutes.get("/collections", async (c) => {
|
|
|
1929
1996
|
SELECT id, name, display_name, description, created_at, updated_at, is_active, managed
|
|
1930
1997
|
FROM collections
|
|
1931
1998
|
WHERE ${includeInactive ? "1=1" : "is_active = 1"}
|
|
1999
|
+
AND (source_type IS NULL OR source_type = 'user')
|
|
1932
2000
|
AND (name LIKE ? OR display_name LIKE ? OR description LIKE ?)
|
|
1933
2001
|
ORDER BY created_at DESC
|
|
1934
2002
|
`);
|
|
@@ -1939,7 +2007,8 @@ adminApiRoutes.get("/collections", async (c) => {
|
|
|
1939
2007
|
stmt = db.prepare(`
|
|
1940
2008
|
SELECT id, name, display_name, description, created_at, updated_at, is_active, managed
|
|
1941
2009
|
FROM collections
|
|
1942
|
-
|
|
2010
|
+
WHERE (source_type IS NULL OR source_type = 'user')
|
|
2011
|
+
${includeInactive ? "" : "AND is_active = 1"}
|
|
1943
2012
|
ORDER BY created_at DESC
|
|
1944
2013
|
`);
|
|
1945
2014
|
const queryResults = await stmt.all();
|
|
@@ -2283,7 +2352,7 @@ adminApiRoutes.delete("/collections/:id", async (c) => {
|
|
|
2283
2352
|
});
|
|
2284
2353
|
adminApiRoutes.get("/migrations/status", async (c) => {
|
|
2285
2354
|
try {
|
|
2286
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
2355
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-VNYOSUNE.cjs');
|
|
2287
2356
|
const db = c.env.DB;
|
|
2288
2357
|
const migrationService = new MigrationService2(db);
|
|
2289
2358
|
const status = await migrationService.getMigrationStatus();
|
|
@@ -2308,7 +2377,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
|
|
|
2308
2377
|
error: "Unauthorized. Admin access required."
|
|
2309
2378
|
}, 403);
|
|
2310
2379
|
}
|
|
2311
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
2380
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-VNYOSUNE.cjs');
|
|
2312
2381
|
const db = c.env.DB;
|
|
2313
2382
|
const migrationService = new MigrationService2(db);
|
|
2314
2383
|
const result = await migrationService.runPendingMigrations();
|
|
@@ -2327,7 +2396,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
|
|
|
2327
2396
|
});
|
|
2328
2397
|
adminApiRoutes.get("/migrations/validate", async (c) => {
|
|
2329
2398
|
try {
|
|
2330
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
2399
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-VNYOSUNE.cjs');
|
|
2331
2400
|
const db = c.env.DB;
|
|
2332
2401
|
const migrationService = new MigrationService2(db);
|
|
2333
2402
|
const validation = await migrationService.validateSchema();
|
|
@@ -2738,7 +2807,7 @@ var JWT_SECRET_FALLBACK = "your-super-secret-jwt-key-change-in-production";
|
|
|
2738
2807
|
async function setCsrfCookie(c) {
|
|
2739
2808
|
const secret = c.env?.JWT_SECRET || JWT_SECRET_FALLBACK;
|
|
2740
2809
|
const isDev = c.env?.ENVIRONMENT === "development" || !c.env?.ENVIRONMENT;
|
|
2741
|
-
const csrfToken = await
|
|
2810
|
+
const csrfToken = await chunkB2ASV5RD_cjs.generateCsrfToken(secret);
|
|
2742
2811
|
cookie.setCookie(c, "csrf_token", csrfToken, {
|
|
2743
2812
|
httpOnly: false,
|
|
2744
2813
|
secure: !isDev,
|
|
@@ -2795,7 +2864,7 @@ var loginSchema = zod.z.object({
|
|
|
2795
2864
|
});
|
|
2796
2865
|
authRoutes.post(
|
|
2797
2866
|
"/register",
|
|
2798
|
-
|
|
2867
|
+
chunkB2ASV5RD_cjs.rateLimit({ max: 3, windowMs: 60 * 1e3, keyPrefix: "register" }),
|
|
2799
2868
|
async (c) => {
|
|
2800
2869
|
try {
|
|
2801
2870
|
const db = c.env.DB;
|
|
@@ -2832,7 +2901,7 @@ authRoutes.post(
|
|
|
2832
2901
|
if (existingUser) {
|
|
2833
2902
|
return c.json({ error: "User with this email or username already exists" }, 400);
|
|
2834
2903
|
}
|
|
2835
|
-
const passwordHash = await
|
|
2904
|
+
const passwordHash = await chunkB2ASV5RD_cjs.AuthManager.hashPassword(password);
|
|
2836
2905
|
const userId = crypto.randomUUID();
|
|
2837
2906
|
const now = /* @__PURE__ */ new Date();
|
|
2838
2907
|
await db.prepare(`
|
|
@@ -2852,7 +2921,7 @@ authRoutes.post(
|
|
|
2852
2921
|
now.getTime(),
|
|
2853
2922
|
now.getTime()
|
|
2854
2923
|
).run();
|
|
2855
|
-
const token = await
|
|
2924
|
+
const token = await chunkB2ASV5RD_cjs.AuthManager.generateToken(userId, normalizedEmail, "viewer", c.env.JWT_SECRET);
|
|
2856
2925
|
cookie.setCookie(c, "auth_token", token, {
|
|
2857
2926
|
httpOnly: true,
|
|
2858
2927
|
secure: true,
|
|
@@ -2886,7 +2955,7 @@ authRoutes.post(
|
|
|
2886
2955
|
);
|
|
2887
2956
|
authRoutes.post(
|
|
2888
2957
|
"/login",
|
|
2889
|
-
|
|
2958
|
+
chunkB2ASV5RD_cjs.rateLimit({ max: 5, windowMs: 60 * 1e3, keyPrefix: "login" }),
|
|
2890
2959
|
async (c) => {
|
|
2891
2960
|
try {
|
|
2892
2961
|
const body = await c.req.json();
|
|
@@ -2897,7 +2966,7 @@ authRoutes.post(
|
|
|
2897
2966
|
const { email, password } = validation.data;
|
|
2898
2967
|
const db = c.env.DB;
|
|
2899
2968
|
const normalizedEmail = email.toLowerCase();
|
|
2900
|
-
const cache =
|
|
2969
|
+
const cache = chunkLFAQUR7P_cjs.getCacheService(chunkLFAQUR7P_cjs.CACHE_CONFIGS.user);
|
|
2901
2970
|
let user = await cache.get(cache.generateKey("user", `email:${normalizedEmail}`));
|
|
2902
2971
|
if (!user) {
|
|
2903
2972
|
user = await db.prepare("SELECT * FROM users WHERE email = ? AND is_active = 1").bind(normalizedEmail).first();
|
|
@@ -2909,19 +2978,19 @@ authRoutes.post(
|
|
|
2909
2978
|
if (!user) {
|
|
2910
2979
|
return c.json({ error: "Invalid email or password" }, 401);
|
|
2911
2980
|
}
|
|
2912
|
-
const isValidPassword = await
|
|
2981
|
+
const isValidPassword = await chunkB2ASV5RD_cjs.AuthManager.verifyPassword(password, user.password_hash);
|
|
2913
2982
|
if (!isValidPassword) {
|
|
2914
2983
|
return c.json({ error: "Invalid email or password" }, 401);
|
|
2915
2984
|
}
|
|
2916
|
-
if (
|
|
2985
|
+
if (chunkB2ASV5RD_cjs.AuthManager.isLegacyHash(user.password_hash)) {
|
|
2917
2986
|
try {
|
|
2918
|
-
const newHash = await
|
|
2987
|
+
const newHash = await chunkB2ASV5RD_cjs.AuthManager.hashPassword(password);
|
|
2919
2988
|
await db.prepare("UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?").bind(newHash, Date.now(), user.id).run();
|
|
2920
2989
|
} catch (rehashError) {
|
|
2921
2990
|
console.error("Password rehash failed (non-fatal):", rehashError);
|
|
2922
2991
|
}
|
|
2923
2992
|
}
|
|
2924
|
-
const token = await
|
|
2993
|
+
const token = await chunkB2ASV5RD_cjs.AuthManager.generateToken(user.id, user.email, user.role, c.env.JWT_SECRET);
|
|
2925
2994
|
cookie.setCookie(c, "auth_token", token, {
|
|
2926
2995
|
httpOnly: true,
|
|
2927
2996
|
secure: true,
|
|
@@ -2974,7 +3043,7 @@ authRoutes.get("/logout", (c) => {
|
|
|
2974
3043
|
clearCsrfCookie(c);
|
|
2975
3044
|
return c.redirect("/auth/login?message=You have been logged out successfully");
|
|
2976
3045
|
});
|
|
2977
|
-
authRoutes.get("/me",
|
|
3046
|
+
authRoutes.get("/me", chunkB2ASV5RD_cjs.requireAuth(), async (c) => {
|
|
2978
3047
|
try {
|
|
2979
3048
|
const user = c.get("user");
|
|
2980
3049
|
if (!user) {
|
|
@@ -2991,13 +3060,13 @@ authRoutes.get("/me", chunkIT2TC4ZD_cjs.requireAuth(), async (c) => {
|
|
|
2991
3060
|
return c.json({ error: "Failed to get user" }, 500);
|
|
2992
3061
|
}
|
|
2993
3062
|
});
|
|
2994
|
-
authRoutes.post("/refresh",
|
|
3063
|
+
authRoutes.post("/refresh", chunkB2ASV5RD_cjs.requireAuth(), async (c) => {
|
|
2995
3064
|
try {
|
|
2996
3065
|
const user = c.get("user");
|
|
2997
3066
|
if (!user) {
|
|
2998
3067
|
return c.json({ error: "Not authenticated" }, 401);
|
|
2999
3068
|
}
|
|
3000
|
-
const token = await
|
|
3069
|
+
const token = await chunkB2ASV5RD_cjs.AuthManager.generateToken(user.userId, user.email, user.role, c.env.JWT_SECRET);
|
|
3001
3070
|
cookie.setCookie(c, "auth_token", token, {
|
|
3002
3071
|
httpOnly: true,
|
|
3003
3072
|
secure: true,
|
|
@@ -3014,7 +3083,7 @@ authRoutes.post("/refresh", chunkIT2TC4ZD_cjs.requireAuth(), async (c) => {
|
|
|
3014
3083
|
});
|
|
3015
3084
|
authRoutes.post(
|
|
3016
3085
|
"/register/form",
|
|
3017
|
-
|
|
3086
|
+
chunkB2ASV5RD_cjs.rateLimit({ max: 3, windowMs: 60 * 1e3, keyPrefix: "register" }),
|
|
3018
3087
|
async (c) => {
|
|
3019
3088
|
try {
|
|
3020
3089
|
const db = c.env.DB;
|
|
@@ -3061,7 +3130,7 @@ authRoutes.post(
|
|
|
3061
3130
|
</div>
|
|
3062
3131
|
`);
|
|
3063
3132
|
}
|
|
3064
|
-
const passwordHash = await
|
|
3133
|
+
const passwordHash = await chunkB2ASV5RD_cjs.AuthManager.hashPassword(password);
|
|
3065
3134
|
const role = isFirstUser ? "admin" : "viewer";
|
|
3066
3135
|
const userId = crypto.randomUUID();
|
|
3067
3136
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -3081,7 +3150,7 @@ authRoutes.post(
|
|
|
3081
3150
|
now.getTime(),
|
|
3082
3151
|
now.getTime()
|
|
3083
3152
|
).run();
|
|
3084
|
-
const token = await
|
|
3153
|
+
const token = await chunkB2ASV5RD_cjs.AuthManager.generateToken(userId, normalizedEmail, role, c.env.JWT_SECRET);
|
|
3085
3154
|
cookie.setCookie(c, "auth_token", token, {
|
|
3086
3155
|
httpOnly: true,
|
|
3087
3156
|
secure: false,
|
|
@@ -3114,7 +3183,7 @@ authRoutes.post(
|
|
|
3114
3183
|
);
|
|
3115
3184
|
authRoutes.post(
|
|
3116
3185
|
"/login/form",
|
|
3117
|
-
|
|
3186
|
+
chunkB2ASV5RD_cjs.rateLimit({ max: 5, windowMs: 60 * 1e3, keyPrefix: "login" }),
|
|
3118
3187
|
async (c) => {
|
|
3119
3188
|
try {
|
|
3120
3189
|
const formData = await c.req.formData();
|
|
@@ -3138,7 +3207,7 @@ authRoutes.post(
|
|
|
3138
3207
|
</div>
|
|
3139
3208
|
`);
|
|
3140
3209
|
}
|
|
3141
|
-
const isValidPassword = await
|
|
3210
|
+
const isValidPassword = await chunkB2ASV5RD_cjs.AuthManager.verifyPassword(password, user.password_hash);
|
|
3142
3211
|
if (!isValidPassword) {
|
|
3143
3212
|
return c.html(html.html`
|
|
3144
3213
|
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded">
|
|
@@ -3146,15 +3215,15 @@ authRoutes.post(
|
|
|
3146
3215
|
</div>
|
|
3147
3216
|
`);
|
|
3148
3217
|
}
|
|
3149
|
-
if (
|
|
3218
|
+
if (chunkB2ASV5RD_cjs.AuthManager.isLegacyHash(user.password_hash)) {
|
|
3150
3219
|
try {
|
|
3151
|
-
const newHash = await
|
|
3220
|
+
const newHash = await chunkB2ASV5RD_cjs.AuthManager.hashPassword(password);
|
|
3152
3221
|
await db.prepare("UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?").bind(newHash, Date.now(), user.id).run();
|
|
3153
3222
|
} catch (rehashError) {
|
|
3154
3223
|
console.error("Password rehash failed (non-fatal):", rehashError);
|
|
3155
3224
|
}
|
|
3156
3225
|
}
|
|
3157
|
-
const token = await
|
|
3226
|
+
const token = await chunkB2ASV5RD_cjs.AuthManager.generateToken(user.id, user.email, user.role, c.env.JWT_SECRET);
|
|
3158
3227
|
cookie.setCookie(c, "auth_token", token, {
|
|
3159
3228
|
httpOnly: true,
|
|
3160
3229
|
secure: false,
|
|
@@ -3196,7 +3265,7 @@ authRoutes.post(
|
|
|
3196
3265
|
);
|
|
3197
3266
|
authRoutes.post(
|
|
3198
3267
|
"/seed-admin",
|
|
3199
|
-
|
|
3268
|
+
chunkB2ASV5RD_cjs.rateLimit({ max: 2, windowMs: 60 * 1e3, keyPrefix: "seed-admin" }),
|
|
3200
3269
|
async (c) => {
|
|
3201
3270
|
try {
|
|
3202
3271
|
const db = c.env.DB;
|
|
@@ -3218,7 +3287,7 @@ authRoutes.post(
|
|
|
3218
3287
|
`).run();
|
|
3219
3288
|
const existingAdmin = await db.prepare("SELECT id FROM users WHERE email = ? OR username = ?").bind("admin@sonicjs.com", "admin").first();
|
|
3220
3289
|
if (existingAdmin) {
|
|
3221
|
-
const passwordHash2 = await
|
|
3290
|
+
const passwordHash2 = await chunkB2ASV5RD_cjs.AuthManager.hashPassword("sonicjs!");
|
|
3222
3291
|
await db.prepare("UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?").bind(passwordHash2, Date.now(), existingAdmin.id).run();
|
|
3223
3292
|
return c.json({
|
|
3224
3293
|
message: "Admin user already exists (password updated)",
|
|
@@ -3230,7 +3299,7 @@ authRoutes.post(
|
|
|
3230
3299
|
}
|
|
3231
3300
|
});
|
|
3232
3301
|
}
|
|
3233
|
-
const passwordHash = await
|
|
3302
|
+
const passwordHash = await chunkB2ASV5RD_cjs.AuthManager.hashPassword("sonicjs!");
|
|
3234
3303
|
const userId = "admin-user-id";
|
|
3235
3304
|
const now = Date.now();
|
|
3236
3305
|
const adminEmail = "admin@sonicjs.com".toLowerCase();
|
|
@@ -3451,7 +3520,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
3451
3520
|
if (existingUsername) {
|
|
3452
3521
|
return c.json({ error: "Username is already taken" }, 400);
|
|
3453
3522
|
}
|
|
3454
|
-
const passwordHash = await
|
|
3523
|
+
const passwordHash = await chunkB2ASV5RD_cjs.AuthManager.hashPassword(password);
|
|
3455
3524
|
const updateStmt = db.prepare(`
|
|
3456
3525
|
UPDATE users SET
|
|
3457
3526
|
username = ?,
|
|
@@ -3470,7 +3539,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
3470
3539
|
Date.now(),
|
|
3471
3540
|
invitedUser.id
|
|
3472
3541
|
).run();
|
|
3473
|
-
const authToken = await
|
|
3542
|
+
const authToken = await chunkB2ASV5RD_cjs.AuthManager.generateToken(invitedUser.id, invitedUser.email, invitedUser.role, c.env.JWT_SECRET);
|
|
3474
3543
|
cookie.setCookie(c, "auth_token", authToken, {
|
|
3475
3544
|
httpOnly: true,
|
|
3476
3545
|
secure: true,
|
|
@@ -3487,7 +3556,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
3487
3556
|
});
|
|
3488
3557
|
authRoutes.post(
|
|
3489
3558
|
"/request-password-reset",
|
|
3490
|
-
|
|
3559
|
+
chunkB2ASV5RD_cjs.rateLimit({ max: 3, windowMs: 15 * 60 * 1e3, keyPrefix: "password-reset" }),
|
|
3491
3560
|
async (c) => {
|
|
3492
3561
|
try {
|
|
3493
3562
|
const formData = await c.req.formData();
|
|
@@ -3705,7 +3774,7 @@ authRoutes.post("/reset-password", async (c) => {
|
|
|
3705
3774
|
if (Date.now() > user.password_reset_expires) {
|
|
3706
3775
|
return c.json({ error: "Reset token has expired" }, 400);
|
|
3707
3776
|
}
|
|
3708
|
-
const newPasswordHash = await
|
|
3777
|
+
const newPasswordHash = await chunkB2ASV5RD_cjs.AuthManager.hashPassword(password);
|
|
3709
3778
|
try {
|
|
3710
3779
|
const historyStmt = db.prepare(`
|
|
3711
3780
|
INSERT INTO password_history (id, user_id, password_hash, created_at)
|
|
@@ -8139,7 +8208,15 @@ function renderContentFormPage(data) {
|
|
|
8139
8208
|
fetch(\`/admin/content/\${contentId}/versions\`)
|
|
8140
8209
|
.then(response => response.text())
|
|
8141
8210
|
.then(html => {
|
|
8142
|
-
document.getElementById('version-history-content')
|
|
8211
|
+
const container = document.getElementById('version-history-content');
|
|
8212
|
+
container.innerHTML = html;
|
|
8213
|
+
// Script tags inserted via innerHTML are not executed by the browser,
|
|
8214
|
+
// so we need to manually create and append them for execution.
|
|
8215
|
+
container.querySelectorAll('script').forEach(oldScript => {
|
|
8216
|
+
const newScript = document.createElement('script');
|
|
8217
|
+
newScript.textContent = oldScript.textContent;
|
|
8218
|
+
oldScript.replaceWith(newScript);
|
|
8219
|
+
});
|
|
8143
8220
|
})
|
|
8144
8221
|
.catch(error => {
|
|
8145
8222
|
console.error('Error loading version history:', error);
|
|
@@ -9168,9 +9245,9 @@ function parseFieldValue(field, formData, options = {}) {
|
|
|
9168
9245
|
const { skipValidation = false } = options;
|
|
9169
9246
|
const value = formData.get(field.field_name);
|
|
9170
9247
|
const errors = [];
|
|
9171
|
-
const blocksConfig =
|
|
9248
|
+
const blocksConfig = chunkQLPFENZ2_cjs.getBlocksFieldConfig(field.field_options);
|
|
9172
9249
|
if (blocksConfig) {
|
|
9173
|
-
const parsed =
|
|
9250
|
+
const parsed = chunkQLPFENZ2_cjs.parseBlocksValue(value, blocksConfig);
|
|
9174
9251
|
if (!skipValidation && field.is_required && parsed.value.length === 0) {
|
|
9175
9252
|
parsed.errors.push(`${field.field_label} is required`);
|
|
9176
9253
|
}
|
|
@@ -9280,9 +9357,9 @@ function extractFieldData(fields, formData, options = {}) {
|
|
|
9280
9357
|
}
|
|
9281
9358
|
return { data, errors };
|
|
9282
9359
|
}
|
|
9283
|
-
adminContentRoutes.use("*",
|
|
9360
|
+
adminContentRoutes.use("*", chunkB2ASV5RD_cjs.requireAuth());
|
|
9284
9361
|
async function getCollectionFields(db, collectionId) {
|
|
9285
|
-
const cache =
|
|
9362
|
+
const cache = chunkLFAQUR7P_cjs.getCacheService(chunkLFAQUR7P_cjs.CACHE_CONFIGS.collection);
|
|
9286
9363
|
return cache.getOrSet(
|
|
9287
9364
|
cache.generateKey("fields", collectionId),
|
|
9288
9365
|
async () => {
|
|
@@ -9331,7 +9408,7 @@ async function getCollectionFields(db, collectionId) {
|
|
|
9331
9408
|
);
|
|
9332
9409
|
}
|
|
9333
9410
|
async function getCollection(db, collectionId) {
|
|
9334
|
-
const cache =
|
|
9411
|
+
const cache = chunkLFAQUR7P_cjs.getCacheService(chunkLFAQUR7P_cjs.CACHE_CONFIGS.collection);
|
|
9335
9412
|
return cache.getOrSet(
|
|
9336
9413
|
cache.generateKey("collection", collectionId),
|
|
9337
9414
|
async () => {
|
|
@@ -9359,7 +9436,7 @@ adminContentRoutes.get("/", async (c) => {
|
|
|
9359
9436
|
const status = url.searchParams.get("status") || "all";
|
|
9360
9437
|
const search = url.searchParams.get("search") || "";
|
|
9361
9438
|
const offset = (page - 1) * limit;
|
|
9362
|
-
const collectionsStmt = db.prepare("SELECT id, name, display_name FROM collections WHERE is_active = 1 ORDER BY display_name");
|
|
9439
|
+
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");
|
|
9363
9440
|
const { results: collectionsResults } = await collectionsStmt.all();
|
|
9364
9441
|
const models = (collectionsResults || []).map((row) => ({
|
|
9365
9442
|
name: row.name,
|
|
@@ -9367,6 +9444,7 @@ adminContentRoutes.get("/", async (c) => {
|
|
|
9367
9444
|
}));
|
|
9368
9445
|
const conditions = [];
|
|
9369
9446
|
const params = [];
|
|
9447
|
+
conditions.push("(col.source_type IS NULL OR col.source_type = 'user')");
|
|
9370
9448
|
if (status !== "deleted") {
|
|
9371
9449
|
conditions.push("c.status != 'deleted'");
|
|
9372
9450
|
}
|
|
@@ -9495,7 +9573,7 @@ adminContentRoutes.get("/new", async (c) => {
|
|
|
9495
9573
|
const collectionId = url.searchParams.get("collection");
|
|
9496
9574
|
if (!collectionId) {
|
|
9497
9575
|
const db2 = c.env.DB;
|
|
9498
|
-
const collectionsStmt = db2.prepare("SELECT id, name, display_name, description FROM collections WHERE is_active = 1 ORDER BY display_name");
|
|
9576
|
+
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");
|
|
9499
9577
|
const { results } = await collectionsStmt.all();
|
|
9500
9578
|
const collections = (results || []).map((row) => ({
|
|
9501
9579
|
id: row.id,
|
|
@@ -9556,21 +9634,21 @@ adminContentRoutes.get("/new", async (c) => {
|
|
|
9556
9634
|
const tinymceEnabled = await isPluginActive2(db, "tinymce-plugin");
|
|
9557
9635
|
let tinymceSettings;
|
|
9558
9636
|
if (tinymceEnabled) {
|
|
9559
|
-
const pluginService = new
|
|
9637
|
+
const pluginService = new chunk6BVLPACH_cjs.PluginService(db);
|
|
9560
9638
|
const tinymcePlugin2 = await pluginService.getPlugin("tinymce-plugin");
|
|
9561
9639
|
tinymceSettings = tinymcePlugin2?.settings;
|
|
9562
9640
|
}
|
|
9563
9641
|
const quillEnabled = await isPluginActive2(db, "quill-editor");
|
|
9564
9642
|
let quillSettings;
|
|
9565
9643
|
if (quillEnabled) {
|
|
9566
|
-
const pluginService = new
|
|
9644
|
+
const pluginService = new chunk6BVLPACH_cjs.PluginService(db);
|
|
9567
9645
|
const quillPlugin = await pluginService.getPlugin("quill-editor");
|
|
9568
9646
|
quillSettings = quillPlugin?.settings;
|
|
9569
9647
|
}
|
|
9570
9648
|
const mdxeditorEnabled = await isPluginActive2(db, "easy-mdx");
|
|
9571
9649
|
let mdxeditorSettings;
|
|
9572
9650
|
if (mdxeditorEnabled) {
|
|
9573
|
-
const pluginService = new
|
|
9651
|
+
const pluginService = new chunk6BVLPACH_cjs.PluginService(db);
|
|
9574
9652
|
const mdxeditorPlugin = await pluginService.getPlugin("easy-mdx");
|
|
9575
9653
|
mdxeditorSettings = mdxeditorPlugin?.settings;
|
|
9576
9654
|
}
|
|
@@ -9620,7 +9698,7 @@ adminContentRoutes.get("/:id/edit", async (c) => {
|
|
|
9620
9698
|
const db = c.env.DB;
|
|
9621
9699
|
const url = new URL(c.req.url);
|
|
9622
9700
|
const referrerParams = url.searchParams.get("ref") || "";
|
|
9623
|
-
const cache =
|
|
9701
|
+
const cache = chunkLFAQUR7P_cjs.getCacheService(chunkLFAQUR7P_cjs.CACHE_CONFIGS.content);
|
|
9624
9702
|
const content = await cache.getOrSet(
|
|
9625
9703
|
cache.generateKey("content", id),
|
|
9626
9704
|
async () => {
|
|
@@ -9661,21 +9739,21 @@ adminContentRoutes.get("/:id/edit", async (c) => {
|
|
|
9661
9739
|
const tinymceEnabled = await isPluginActive2(db, "tinymce-plugin");
|
|
9662
9740
|
let tinymceSettings;
|
|
9663
9741
|
if (tinymceEnabled) {
|
|
9664
|
-
const pluginService = new
|
|
9742
|
+
const pluginService = new chunk6BVLPACH_cjs.PluginService(db);
|
|
9665
9743
|
const tinymcePlugin2 = await pluginService.getPlugin("tinymce-plugin");
|
|
9666
9744
|
tinymceSettings = tinymcePlugin2?.settings;
|
|
9667
9745
|
}
|
|
9668
9746
|
const quillEnabled = await isPluginActive2(db, "quill-editor");
|
|
9669
9747
|
let quillSettings;
|
|
9670
9748
|
if (quillEnabled) {
|
|
9671
|
-
const pluginService = new
|
|
9749
|
+
const pluginService = new chunk6BVLPACH_cjs.PluginService(db);
|
|
9672
9750
|
const quillPlugin = await pluginService.getPlugin("quill-editor");
|
|
9673
9751
|
quillSettings = quillPlugin?.settings;
|
|
9674
9752
|
}
|
|
9675
9753
|
const mdxeditorEnabled = await isPluginActive2(db, "easy-mdx");
|
|
9676
9754
|
let mdxeditorSettings;
|
|
9677
9755
|
if (mdxeditorEnabled) {
|
|
9678
|
-
const pluginService = new
|
|
9756
|
+
const pluginService = new chunk6BVLPACH_cjs.PluginService(db);
|
|
9679
9757
|
const mdxeditorPlugin = await pluginService.getPlugin("easy-mdx");
|
|
9680
9758
|
mdxeditorSettings = mdxeditorPlugin?.settings;
|
|
9681
9759
|
}
|
|
@@ -9796,7 +9874,7 @@ adminContentRoutes.post("/", async (c) => {
|
|
|
9796
9874
|
now,
|
|
9797
9875
|
now
|
|
9798
9876
|
).run();
|
|
9799
|
-
const cache =
|
|
9877
|
+
const cache = chunkLFAQUR7P_cjs.getCacheService(chunkLFAQUR7P_cjs.CACHE_CONFIGS.content);
|
|
9800
9878
|
await cache.invalidate(`content:list:${collectionId}:*`);
|
|
9801
9879
|
const versionStmt = db.prepare(`
|
|
9802
9880
|
INSERT INTO content_versions (id, content_id, version, data, author_id, created_at)
|
|
@@ -9915,7 +9993,7 @@ adminContentRoutes.put("/:id", async (c) => {
|
|
|
9915
9993
|
now,
|
|
9916
9994
|
id
|
|
9917
9995
|
).run();
|
|
9918
|
-
const cache =
|
|
9996
|
+
const cache = chunkLFAQUR7P_cjs.getCacheService(chunkLFAQUR7P_cjs.CACHE_CONFIGS.content);
|
|
9919
9997
|
await cache.delete(cache.generateKey("content", id));
|
|
9920
9998
|
await cache.invalidate(`content:list:${existingContent.collection_id}:*`);
|
|
9921
9999
|
const existingData = JSON.parse(existingContent.data || "{}");
|
|
@@ -9970,7 +10048,7 @@ adminContentRoutes.put("/:id", async (c) => {
|
|
|
9970
10048
|
`);
|
|
9971
10049
|
}
|
|
9972
10050
|
});
|
|
9973
|
-
adminContentRoutes.post("/preview",
|
|
10051
|
+
adminContentRoutes.post("/preview", chunkB2ASV5RD_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
9974
10052
|
try {
|
|
9975
10053
|
const formData = await c.req.formData();
|
|
9976
10054
|
const collectionId = formData.get("collection_id");
|
|
@@ -10192,7 +10270,7 @@ adminContentRoutes.post("/bulk-action", async (c) => {
|
|
|
10192
10270
|
} else {
|
|
10193
10271
|
return c.json({ success: false, error: "Invalid action" });
|
|
10194
10272
|
}
|
|
10195
|
-
const cache =
|
|
10273
|
+
const cache = chunkLFAQUR7P_cjs.getCacheService(chunkLFAQUR7P_cjs.CACHE_CONFIGS.content);
|
|
10196
10274
|
for (const contentId of ids) {
|
|
10197
10275
|
await cache.delete(cache.generateKey("content", contentId));
|
|
10198
10276
|
}
|
|
@@ -10220,7 +10298,7 @@ adminContentRoutes.delete("/:id", async (c) => {
|
|
|
10220
10298
|
WHERE id = ?
|
|
10221
10299
|
`);
|
|
10222
10300
|
await deleteStmt.bind(now, id).run();
|
|
10223
|
-
const cache =
|
|
10301
|
+
const cache = chunkLFAQUR7P_cjs.getCacheService(chunkLFAQUR7P_cjs.CACHE_CONFIGS.content);
|
|
10224
10302
|
await cache.delete(cache.generateKey("content", id));
|
|
10225
10303
|
await cache.invalidate("content:list:*");
|
|
10226
10304
|
return c.html(`
|
|
@@ -10348,7 +10426,7 @@ adminContentRoutes.post("/:id/restore/:version", async (c) => {
|
|
|
10348
10426
|
return c.json({ success: false, error: "Failed to restore version" });
|
|
10349
10427
|
}
|
|
10350
10428
|
});
|
|
10351
|
-
adminContentRoutes.get("/:id/version/:version/preview",
|
|
10429
|
+
adminContentRoutes.get("/:id/version/:version/preview", chunkB2ASV5RD_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
10352
10430
|
try {
|
|
10353
10431
|
const id = c.req.param("id");
|
|
10354
10432
|
const version = parseInt(c.req.param("version") || "0");
|
|
@@ -11419,6 +11497,36 @@ function renderUserEditPage(data) {
|
|
|
11419
11497
|
</div>
|
|
11420
11498
|
</div>
|
|
11421
11499
|
|
|
11500
|
+
<!-- Set Password -->
|
|
11501
|
+
<div class="mb-8">
|
|
11502
|
+
<h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Set Password</h3>
|
|
11503
|
+
<p class="text-sm text-zinc-500 dark:text-zinc-400 mb-4">Leave blank to keep the current password</p>
|
|
11504
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
11505
|
+
<div>
|
|
11506
|
+
<label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">New Password</label>
|
|
11507
|
+
<input
|
|
11508
|
+
type="password"
|
|
11509
|
+
name="new_password"
|
|
11510
|
+
minlength="8"
|
|
11511
|
+
placeholder="Minimum 8 characters"
|
|
11512
|
+
autocomplete="new-password"
|
|
11513
|
+
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"
|
|
11514
|
+
/>
|
|
11515
|
+
</div>
|
|
11516
|
+
<div>
|
|
11517
|
+
<label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Confirm Password</label>
|
|
11518
|
+
<input
|
|
11519
|
+
type="password"
|
|
11520
|
+
name="confirm_password"
|
|
11521
|
+
minlength="8"
|
|
11522
|
+
placeholder="Repeat new password"
|
|
11523
|
+
autocomplete="new-password"
|
|
11524
|
+
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"
|
|
11525
|
+
/>
|
|
11526
|
+
</div>
|
|
11527
|
+
</div>
|
|
11528
|
+
</div>
|
|
11529
|
+
|
|
11422
11530
|
<!-- Account Status -->
|
|
11423
11531
|
<div class="mb-8">
|
|
11424
11532
|
<h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-4">Account Status</h3>
|
|
@@ -12315,14 +12423,14 @@ function renderUsersListPage(data) {
|
|
|
12315
12423
|
|
|
12316
12424
|
// src/routes/admin-users.ts
|
|
12317
12425
|
var userRoutes = new hono.Hono();
|
|
12318
|
-
userRoutes.use("*",
|
|
12319
|
-
userRoutes.use("/users/*",
|
|
12320
|
-
userRoutes.use("/users",
|
|
12321
|
-
userRoutes.use("/invite-user",
|
|
12322
|
-
userRoutes.use("/resend-invitation/*",
|
|
12323
|
-
userRoutes.use("/cancel-invitation/*",
|
|
12324
|
-
userRoutes.use("/activity-logs",
|
|
12325
|
-
userRoutes.use("/activity-logs/*",
|
|
12426
|
+
userRoutes.use("*", chunkB2ASV5RD_cjs.requireAuth());
|
|
12427
|
+
userRoutes.use("/users/*", chunkB2ASV5RD_cjs.requireRole(["admin"]));
|
|
12428
|
+
userRoutes.use("/users", chunkB2ASV5RD_cjs.requireRole(["admin"]));
|
|
12429
|
+
userRoutes.use("/invite-user", chunkB2ASV5RD_cjs.requireRole(["admin"]));
|
|
12430
|
+
userRoutes.use("/resend-invitation/*", chunkB2ASV5RD_cjs.requireRole(["admin"]));
|
|
12431
|
+
userRoutes.use("/cancel-invitation/*", chunkB2ASV5RD_cjs.requireRole(["admin"]));
|
|
12432
|
+
userRoutes.use("/activity-logs", chunkB2ASV5RD_cjs.requireRole(["admin"]));
|
|
12433
|
+
userRoutes.use("/activity-logs/*", chunkB2ASV5RD_cjs.requireRole(["admin"]));
|
|
12326
12434
|
userRoutes.get("/", (c) => {
|
|
12327
12435
|
return c.redirect("/admin/dashboard");
|
|
12328
12436
|
});
|
|
@@ -12477,7 +12585,7 @@ userRoutes.put("/profile", async (c) => {
|
|
|
12477
12585
|
Date.now(),
|
|
12478
12586
|
user.userId
|
|
12479
12587
|
).run();
|
|
12480
|
-
await
|
|
12588
|
+
await chunkB2ASV5RD_cjs.logActivity(
|
|
12481
12589
|
db,
|
|
12482
12590
|
user.userId,
|
|
12483
12591
|
"profile.update",
|
|
@@ -12540,7 +12648,7 @@ userRoutes.post("/profile/avatar", async (c) => {
|
|
|
12540
12648
|
SELECT first_name, last_name FROM users WHERE id = ?
|
|
12541
12649
|
`);
|
|
12542
12650
|
const userData = await userStmt.bind(user.userId).first();
|
|
12543
|
-
await
|
|
12651
|
+
await chunkB2ASV5RD_cjs.logActivity(
|
|
12544
12652
|
db,
|
|
12545
12653
|
user.userId,
|
|
12546
12654
|
"profile.avatar_update",
|
|
@@ -12611,7 +12719,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
12611
12719
|
dismissible: true
|
|
12612
12720
|
}));
|
|
12613
12721
|
}
|
|
12614
|
-
const validPassword = await
|
|
12722
|
+
const validPassword = await chunkB2ASV5RD_cjs.AuthManager.verifyPassword(currentPassword, userData.password_hash);
|
|
12615
12723
|
if (!validPassword) {
|
|
12616
12724
|
return c.html(renderAlert2({
|
|
12617
12725
|
type: "error",
|
|
@@ -12619,7 +12727,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
12619
12727
|
dismissible: true
|
|
12620
12728
|
}));
|
|
12621
12729
|
}
|
|
12622
|
-
const newPasswordHash = await
|
|
12730
|
+
const newPasswordHash = await chunkB2ASV5RD_cjs.AuthManager.hashPassword(newPassword);
|
|
12623
12731
|
const historyStmt = db.prepare(`
|
|
12624
12732
|
INSERT INTO password_history (id, user_id, password_hash, created_at)
|
|
12625
12733
|
VALUES (?, ?, ?, ?)
|
|
@@ -12635,7 +12743,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
12635
12743
|
WHERE id = ?
|
|
12636
12744
|
`);
|
|
12637
12745
|
await updateStmt.bind(newPasswordHash, Date.now(), user.userId).run();
|
|
12638
|
-
await
|
|
12746
|
+
await chunkB2ASV5RD_cjs.logActivity(
|
|
12639
12747
|
db,
|
|
12640
12748
|
user.userId,
|
|
12641
12749
|
"profile.password_change",
|
|
@@ -12702,7 +12810,7 @@ userRoutes.get("/users", async (c) => {
|
|
|
12702
12810
|
`);
|
|
12703
12811
|
const countResult = await countStmt.bind(...params).first();
|
|
12704
12812
|
const totalUsers = countResult?.total || 0;
|
|
12705
|
-
await
|
|
12813
|
+
await chunkB2ASV5RD_cjs.logActivity(
|
|
12706
12814
|
db,
|
|
12707
12815
|
user.userId,
|
|
12708
12816
|
"users.list_view",
|
|
@@ -12740,6 +12848,7 @@ userRoutes.get("/users", async (c) => {
|
|
|
12740
12848
|
formattedLastLogin: u.last_login_at ? new Date(u.last_login_at).toLocaleDateString() : void 0,
|
|
12741
12849
|
formattedCreatedAt: new Date(u.created_at).toLocaleDateString()
|
|
12742
12850
|
}));
|
|
12851
|
+
const successMessage = c.req.query("success") || void 0;
|
|
12743
12852
|
const pageData = {
|
|
12744
12853
|
users,
|
|
12745
12854
|
currentPage: page,
|
|
@@ -12748,6 +12857,7 @@ userRoutes.get("/users", async (c) => {
|
|
|
12748
12857
|
searchFilter: search,
|
|
12749
12858
|
roleFilter,
|
|
12750
12859
|
statusFilter,
|
|
12860
|
+
success: successMessage,
|
|
12751
12861
|
pagination: {
|
|
12752
12862
|
currentPage: page,
|
|
12753
12863
|
totalPages: Math.ceil(totalUsers / limit),
|
|
@@ -12858,7 +12968,7 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
12858
12968
|
dismissible: true
|
|
12859
12969
|
}));
|
|
12860
12970
|
}
|
|
12861
|
-
const passwordHash = await
|
|
12971
|
+
const passwordHash = await chunkB2ASV5RD_cjs.AuthManager.hashPassword(password);
|
|
12862
12972
|
const userId = crypto.randomUUID();
|
|
12863
12973
|
const createStmt = db.prepare(`
|
|
12864
12974
|
INSERT INTO users (
|
|
@@ -12881,7 +12991,7 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
12881
12991
|
Date.now(),
|
|
12882
12992
|
Date.now()
|
|
12883
12993
|
).run();
|
|
12884
|
-
await
|
|
12994
|
+
await chunkB2ASV5RD_cjs.logActivity(
|
|
12885
12995
|
db,
|
|
12886
12996
|
user.userId,
|
|
12887
12997
|
"user!.create",
|
|
@@ -12891,7 +13001,8 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
12891
13001
|
c.req.header("x-forwarded-for") || c.req.header("cf-connecting-ip"),
|
|
12892
13002
|
c.req.header("user-agent")
|
|
12893
13003
|
);
|
|
12894
|
-
|
|
13004
|
+
c.header("HX-Redirect", "/admin/users?success=User created successfully");
|
|
13005
|
+
return c.body(null, 200);
|
|
12895
13006
|
} catch (error) {
|
|
12896
13007
|
console.error("User creation error:", error);
|
|
12897
13008
|
return c.html(renderAlert2({
|
|
@@ -12919,7 +13030,7 @@ userRoutes.get("/users/:id", async (c) => {
|
|
|
12919
13030
|
if (!userRecord) {
|
|
12920
13031
|
return c.json({ error: "User not found" }, 404);
|
|
12921
13032
|
}
|
|
12922
|
-
await
|
|
13033
|
+
await chunkB2ASV5RD_cjs.logActivity(
|
|
12923
13034
|
db,
|
|
12924
13035
|
user.userId,
|
|
12925
13036
|
"user!.view",
|
|
@@ -13037,6 +13148,8 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
13037
13148
|
const role = validRoles.includes(roleInput) ? roleInput : "viewer";
|
|
13038
13149
|
const isActive = formData.get("is_active") === "1";
|
|
13039
13150
|
const emailVerified = formData.get("email_verified") === "1";
|
|
13151
|
+
const newPassword = formData.get("new_password")?.toString() || "";
|
|
13152
|
+
const confirmPassword = formData.get("confirm_password")?.toString() || "";
|
|
13040
13153
|
const profileDisplayName = chunkMNWKYY5E_cjs.sanitizeInput(formData.get("profile_display_name")?.toString()) || null;
|
|
13041
13154
|
const profileBio = chunkMNWKYY5E_cjs.sanitizeInput(formData.get("profile_bio")?.toString()) || null;
|
|
13042
13155
|
const profileCompany = chunkMNWKYY5E_cjs.sanitizeInput(formData.get("profile_company")?.toString()) || null;
|
|
@@ -13060,6 +13173,22 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
13060
13173
|
dismissible: true
|
|
13061
13174
|
}));
|
|
13062
13175
|
}
|
|
13176
|
+
if (newPassword) {
|
|
13177
|
+
if (newPassword.length < 8) {
|
|
13178
|
+
return c.html(renderAlert2({
|
|
13179
|
+
type: "error",
|
|
13180
|
+
message: "Password must be at least 8 characters long.",
|
|
13181
|
+
dismissible: true
|
|
13182
|
+
}));
|
|
13183
|
+
}
|
|
13184
|
+
if (newPassword !== confirmPassword) {
|
|
13185
|
+
return c.html(renderAlert2({
|
|
13186
|
+
type: "error",
|
|
13187
|
+
message: "Passwords do not match.",
|
|
13188
|
+
dismissible: true
|
|
13189
|
+
}));
|
|
13190
|
+
}
|
|
13191
|
+
}
|
|
13063
13192
|
if (profileWebsite) {
|
|
13064
13193
|
try {
|
|
13065
13194
|
new URL(profileWebsite);
|
|
@@ -13102,6 +13231,13 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
13102
13231
|
Date.now(),
|
|
13103
13232
|
userId
|
|
13104
13233
|
).run();
|
|
13234
|
+
if (newPassword) {
|
|
13235
|
+
const passwordHash = await chunkB2ASV5RD_cjs.AuthManager.hashPassword(newPassword);
|
|
13236
|
+
const updatePasswordStmt = db.prepare(`
|
|
13237
|
+
UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?
|
|
13238
|
+
`);
|
|
13239
|
+
await updatePasswordStmt.bind(passwordHash, Date.now(), userId).run();
|
|
13240
|
+
}
|
|
13105
13241
|
const hasProfileData = profileDisplayName || profileBio || profileCompany || profileJobTitle || profileWebsite || profileLocation || profileDateOfBirth;
|
|
13106
13242
|
if (hasProfileData) {
|
|
13107
13243
|
const now = Date.now();
|
|
@@ -13146,13 +13282,13 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
13146
13282
|
).run();
|
|
13147
13283
|
}
|
|
13148
13284
|
}
|
|
13149
|
-
await
|
|
13285
|
+
await chunkB2ASV5RD_cjs.logActivity(
|
|
13150
13286
|
db,
|
|
13151
13287
|
user.userId,
|
|
13152
13288
|
"user.update",
|
|
13153
13289
|
"users",
|
|
13154
13290
|
userId,
|
|
13155
|
-
{ fields: ["first_name", "last_name", "username", "email", "phone", "role", "is_active", "email_verified", "profile"] },
|
|
13291
|
+
{ fields: ["first_name", "last_name", "username", "email", "phone", "role", "is_active", "email_verified", "profile", ...newPassword ? ["password"] : []] },
|
|
13156
13292
|
c.req.header("x-forwarded-for") || c.req.header("cf-connecting-ip"),
|
|
13157
13293
|
c.req.header("user-agent")
|
|
13158
13294
|
);
|
|
@@ -13191,7 +13327,7 @@ userRoutes.post("/users/:id/toggle", async (c) => {
|
|
|
13191
13327
|
UPDATE users SET is_active = ?, updated_at = ? WHERE id = ?
|
|
13192
13328
|
`);
|
|
13193
13329
|
await toggleStmt.bind(active ? 1 : 0, Date.now(), userId).run();
|
|
13194
|
-
await
|
|
13330
|
+
await chunkB2ASV5RD_cjs.logActivity(
|
|
13195
13331
|
db,
|
|
13196
13332
|
user.userId,
|
|
13197
13333
|
active ? "user.activate" : "user.deactivate",
|
|
@@ -13232,7 +13368,7 @@ userRoutes.delete("/users/:id", async (c) => {
|
|
|
13232
13368
|
DELETE FROM users WHERE id = ?
|
|
13233
13369
|
`);
|
|
13234
13370
|
await deleteStmt.bind(userId).run();
|
|
13235
|
-
await
|
|
13371
|
+
await chunkB2ASV5RD_cjs.logActivity(
|
|
13236
13372
|
db,
|
|
13237
13373
|
user.userId,
|
|
13238
13374
|
"user!.hard_delete",
|
|
@@ -13251,7 +13387,7 @@ userRoutes.delete("/users/:id", async (c) => {
|
|
|
13251
13387
|
UPDATE users SET is_active = 0, updated_at = ? WHERE id = ?
|
|
13252
13388
|
`);
|
|
13253
13389
|
await deleteStmt.bind(Date.now(), userId).run();
|
|
13254
|
-
await
|
|
13390
|
+
await chunkB2ASV5RD_cjs.logActivity(
|
|
13255
13391
|
db,
|
|
13256
13392
|
user.userId,
|
|
13257
13393
|
"user!.soft_delete",
|
|
@@ -13317,7 +13453,7 @@ userRoutes.post("/invite-user", async (c) => {
|
|
|
13317
13453
|
Date.now(),
|
|
13318
13454
|
Date.now()
|
|
13319
13455
|
).run();
|
|
13320
|
-
await
|
|
13456
|
+
await chunkB2ASV5RD_cjs.logActivity(
|
|
13321
13457
|
db,
|
|
13322
13458
|
user.userId,
|
|
13323
13459
|
"user!.invite_sent",
|
|
@@ -13374,7 +13510,7 @@ userRoutes.post("/resend-invitation/:id", async (c) => {
|
|
|
13374
13510
|
Date.now(),
|
|
13375
13511
|
userId
|
|
13376
13512
|
).run();
|
|
13377
|
-
await
|
|
13513
|
+
await chunkB2ASV5RD_cjs.logActivity(
|
|
13378
13514
|
db,
|
|
13379
13515
|
user.userId,
|
|
13380
13516
|
"user!.invitation_resent",
|
|
@@ -13410,7 +13546,7 @@ userRoutes.delete("/cancel-invitation/:id", async (c) => {
|
|
|
13410
13546
|
}
|
|
13411
13547
|
const deleteStmt = db.prepare(`DELETE FROM users WHERE id = ?`);
|
|
13412
13548
|
await deleteStmt.bind(userId).run();
|
|
13413
|
-
await
|
|
13549
|
+
await chunkB2ASV5RD_cjs.logActivity(
|
|
13414
13550
|
db,
|
|
13415
13551
|
user.userId,
|
|
13416
13552
|
"user!.invitation_cancelled",
|
|
@@ -13493,7 +13629,7 @@ userRoutes.get("/activity-logs", async (c) => {
|
|
|
13493
13629
|
...log,
|
|
13494
13630
|
details: log.details ? JSON.parse(log.details) : null
|
|
13495
13631
|
}));
|
|
13496
|
-
await
|
|
13632
|
+
await chunkB2ASV5RD_cjs.logActivity(
|
|
13497
13633
|
db,
|
|
13498
13634
|
user.userId,
|
|
13499
13635
|
"activity.logs_viewed",
|
|
@@ -13600,7 +13736,7 @@ userRoutes.get("/activity-logs/export", async (c) => {
|
|
|
13600
13736
|
csvRows.push(row.join(","));
|
|
13601
13737
|
}
|
|
13602
13738
|
const csvContent = csvRows.join("\n");
|
|
13603
|
-
await
|
|
13739
|
+
await chunkB2ASV5RD_cjs.logActivity(
|
|
13604
13740
|
db,
|
|
13605
13741
|
user.userId,
|
|
13606
13742
|
"activity.logs_exported",
|
|
@@ -14939,7 +15075,7 @@ var fileValidationSchema2 = zod.z.object({
|
|
|
14939
15075
|
// 50MB max
|
|
14940
15076
|
});
|
|
14941
15077
|
var adminMediaRoutes = new hono.Hono();
|
|
14942
|
-
adminMediaRoutes.use("*",
|
|
15078
|
+
adminMediaRoutes.use("*", chunkB2ASV5RD_cjs.requireAuth());
|
|
14943
15079
|
adminMediaRoutes.get("/", async (c) => {
|
|
14944
15080
|
try {
|
|
14945
15081
|
const user = c.get("user");
|
|
@@ -15525,7 +15661,7 @@ adminMediaRoutes.put("/:id", async (c) => {
|
|
|
15525
15661
|
`);
|
|
15526
15662
|
}
|
|
15527
15663
|
});
|
|
15528
|
-
adminMediaRoutes.delete("/cleanup",
|
|
15664
|
+
adminMediaRoutes.delete("/cleanup", chunkB2ASV5RD_cjs.requireRole("admin"), async (c) => {
|
|
15529
15665
|
try {
|
|
15530
15666
|
const db = c.env.DB;
|
|
15531
15667
|
const allMediaStmt = db.prepare("SELECT id, r2_key, filename FROM media WHERE deleted_at IS NULL");
|
|
@@ -17252,6 +17388,7 @@ function renderOTPLoginSettingsContent(plugin, settings) {
|
|
|
17252
17388
|
const maxAttempts = settings.maxAttempts || 3;
|
|
17253
17389
|
const rateLimitPerHour = settings.rateLimitPerHour || 5;
|
|
17254
17390
|
const allowNewUserRegistration = settings.allowNewUserRegistration || false;
|
|
17391
|
+
const logoUrl = settings.logoUrl || "";
|
|
17255
17392
|
return `
|
|
17256
17393
|
<div class="space-y-6">
|
|
17257
17394
|
<!-- Test OTP Section -->
|
|
@@ -17435,6 +17572,7 @@ function renderOTPLoginSettingsContent(plugin, settings) {
|
|
|
17435
17572
|
|
|
17436
17573
|
<div class="bg-white rounded-lg overflow-hidden shadow-lg">
|
|
17437
17574
|
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px 20px; text-align: center;">
|
|
17575
|
+
${logoUrl ? `<img src="${logoUrl}" alt="Logo" style="max-width: 150px; height: auto; margin: 0 auto 16px;">` : ""}
|
|
17438
17576
|
<h3 style="margin: 0 0 8px 0; font-size: 24px; font-weight: 600;">Your Login Code</h3>
|
|
17439
17577
|
<p style="margin: 0; opacity: 0.95; font-size: 14px;">Enter this code to sign in to ${siteName}</p>
|
|
17440
17578
|
</div>
|
|
@@ -17748,7 +17886,7 @@ function renderEmailSettingsContent(plugin, settings) {
|
|
|
17748
17886
|
|
|
17749
17887
|
// src/routes/admin-plugins.ts
|
|
17750
17888
|
var adminPluginRoutes = new hono.Hono();
|
|
17751
|
-
adminPluginRoutes.use("*",
|
|
17889
|
+
adminPluginRoutes.use("*", chunkB2ASV5RD_cjs.requireAuth());
|
|
17752
17890
|
var AVAILABLE_PLUGINS = [
|
|
17753
17891
|
{
|
|
17754
17892
|
id: "third-party-faq",
|
|
@@ -17875,7 +18013,7 @@ adminPluginRoutes.get("/", async (c) => {
|
|
|
17875
18013
|
if (user?.role !== "admin") {
|
|
17876
18014
|
return c.text("Access denied", 403);
|
|
17877
18015
|
}
|
|
17878
|
-
const pluginService = new
|
|
18016
|
+
const pluginService = new chunk6BVLPACH_cjs.PluginService(db);
|
|
17879
18017
|
let installedPlugins = [];
|
|
17880
18018
|
let stats = { total: 0, active: 0, inactive: 0, errors: 0, uninstalled: 0 };
|
|
17881
18019
|
try {
|
|
@@ -17951,7 +18089,7 @@ adminPluginRoutes.get("/:id", async (c) => {
|
|
|
17951
18089
|
if (user?.role !== "admin") {
|
|
17952
18090
|
return c.redirect("/admin/plugins");
|
|
17953
18091
|
}
|
|
17954
|
-
const pluginService = new
|
|
18092
|
+
const pluginService = new chunk6BVLPACH_cjs.PluginService(db);
|
|
17955
18093
|
const plugin = await pluginService.getPlugin(pluginId);
|
|
17956
18094
|
if (!plugin) {
|
|
17957
18095
|
return c.text("Plugin not found", 404);
|
|
@@ -17959,17 +18097,9 @@ adminPluginRoutes.get("/:id", async (c) => {
|
|
|
17959
18097
|
const activity = await pluginService.getPluginActivity(pluginId, 20);
|
|
17960
18098
|
let enrichedSettings = plugin.settings || {};
|
|
17961
18099
|
if (pluginId === "otp-login") {
|
|
17962
|
-
const
|
|
17963
|
-
|
|
17964
|
-
|
|
17965
|
-
let siteName = "SonicJS";
|
|
17966
|
-
if (generalSettings?.value) {
|
|
17967
|
-
try {
|
|
17968
|
-
const parsed = JSON.parse(generalSettings.value);
|
|
17969
|
-
siteName = parsed.siteName || "SonicJS";
|
|
17970
|
-
} catch (e) {
|
|
17971
|
-
}
|
|
17972
|
-
}
|
|
18100
|
+
const settingsService = new chunkLFAQUR7P_cjs.SettingsService(db);
|
|
18101
|
+
const generalSettings = await settingsService.getGeneralSettings();
|
|
18102
|
+
const siteName = generalSettings.siteName || "SonicJS";
|
|
17973
18103
|
const emailPlugin = await db.prepare(`
|
|
17974
18104
|
SELECT settings FROM plugins WHERE id = 'email'
|
|
17975
18105
|
`).first();
|
|
@@ -18035,7 +18165,7 @@ adminPluginRoutes.post("/:id/activate", async (c) => {
|
|
|
18035
18165
|
if (user?.role !== "admin") {
|
|
18036
18166
|
return c.json({ error: "Access denied" }, 403);
|
|
18037
18167
|
}
|
|
18038
|
-
const pluginService = new
|
|
18168
|
+
const pluginService = new chunk6BVLPACH_cjs.PluginService(db);
|
|
18039
18169
|
await pluginService.activatePlugin(pluginId);
|
|
18040
18170
|
return c.json({ success: true });
|
|
18041
18171
|
} catch (error) {
|
|
@@ -18052,7 +18182,7 @@ adminPluginRoutes.post("/:id/deactivate", async (c) => {
|
|
|
18052
18182
|
if (user?.role !== "admin") {
|
|
18053
18183
|
return c.json({ error: "Access denied" }, 403);
|
|
18054
18184
|
}
|
|
18055
|
-
const pluginService = new
|
|
18185
|
+
const pluginService = new chunk6BVLPACH_cjs.PluginService(db);
|
|
18056
18186
|
await pluginService.deactivatePlugin(pluginId);
|
|
18057
18187
|
return c.json({ success: true });
|
|
18058
18188
|
} catch (error) {
|
|
@@ -18069,7 +18199,7 @@ adminPluginRoutes.post("/install", async (c) => {
|
|
|
18069
18199
|
return c.json({ error: "Access denied" }, 403);
|
|
18070
18200
|
}
|
|
18071
18201
|
const body = await c.req.json();
|
|
18072
|
-
const pluginService = new
|
|
18202
|
+
const pluginService = new chunk6BVLPACH_cjs.PluginService(db);
|
|
18073
18203
|
if (body.name === "faq-plugin") {
|
|
18074
18204
|
const faqPlugin = await pluginService.installPlugin({
|
|
18075
18205
|
id: "third-party-faq",
|
|
@@ -18339,7 +18469,7 @@ adminPluginRoutes.post("/:id/uninstall", async (c) => {
|
|
|
18339
18469
|
if (user?.role !== "admin") {
|
|
18340
18470
|
return c.json({ error: "Access denied" }, 403);
|
|
18341
18471
|
}
|
|
18342
|
-
const pluginService = new
|
|
18472
|
+
const pluginService = new chunk6BVLPACH_cjs.PluginService(db);
|
|
18343
18473
|
await pluginService.uninstallPlugin(pluginId);
|
|
18344
18474
|
return c.json({ success: true });
|
|
18345
18475
|
} catch (error) {
|
|
@@ -18357,7 +18487,7 @@ adminPluginRoutes.post("/:id/settings", async (c) => {
|
|
|
18357
18487
|
return c.json({ error: "Access denied" }, 403);
|
|
18358
18488
|
}
|
|
18359
18489
|
const settings = await c.req.json();
|
|
18360
|
-
const pluginService = new
|
|
18490
|
+
const pluginService = new chunk6BVLPACH_cjs.PluginService(db);
|
|
18361
18491
|
await pluginService.updatePluginSettings(pluginId, settings);
|
|
18362
18492
|
if (pluginId === "core-auth") {
|
|
18363
18493
|
try {
|
|
@@ -19165,11 +19295,11 @@ function renderLogConfigPage(data) {
|
|
|
19165
19295
|
|
|
19166
19296
|
// src/routes/admin-logs.ts
|
|
19167
19297
|
var adminLogsRoutes = new hono.Hono();
|
|
19168
|
-
adminLogsRoutes.use("*",
|
|
19298
|
+
adminLogsRoutes.use("*", chunkB2ASV5RD_cjs.requireAuth());
|
|
19169
19299
|
adminLogsRoutes.get("/", async (c) => {
|
|
19170
19300
|
try {
|
|
19171
19301
|
const user = c.get("user");
|
|
19172
|
-
const logger =
|
|
19302
|
+
const logger = chunkLFAQUR7P_cjs.getLogger(c.env.DB);
|
|
19173
19303
|
const query = c.req.query();
|
|
19174
19304
|
const page = parseInt(query.page || "1");
|
|
19175
19305
|
const limit = parseInt(query.limit || "50");
|
|
@@ -19249,7 +19379,7 @@ adminLogsRoutes.get("/:id", async (c) => {
|
|
|
19249
19379
|
try {
|
|
19250
19380
|
const id = c.req.param("id");
|
|
19251
19381
|
const user = c.get("user");
|
|
19252
|
-
const logger =
|
|
19382
|
+
const logger = chunkLFAQUR7P_cjs.getLogger(c.env.DB);
|
|
19253
19383
|
const { logs } = await logger.getLogs({
|
|
19254
19384
|
limit: 1,
|
|
19255
19385
|
offset: 0,
|
|
@@ -19286,7 +19416,7 @@ adminLogsRoutes.get("/:id", async (c) => {
|
|
|
19286
19416
|
adminLogsRoutes.get("/config", async (c) => {
|
|
19287
19417
|
try {
|
|
19288
19418
|
const user = c.get("user");
|
|
19289
|
-
const logger =
|
|
19419
|
+
const logger = chunkLFAQUR7P_cjs.getLogger(c.env.DB);
|
|
19290
19420
|
const configs = await logger.getAllConfigs();
|
|
19291
19421
|
const pageData = {
|
|
19292
19422
|
configs,
|
|
@@ -19310,7 +19440,7 @@ adminLogsRoutes.post("/config/:category", async (c) => {
|
|
|
19310
19440
|
const level = formData.get("level");
|
|
19311
19441
|
const retention = parseInt(formData.get("retention"));
|
|
19312
19442
|
const maxSize = parseInt(formData.get("max_size"));
|
|
19313
|
-
const logger =
|
|
19443
|
+
const logger = chunkLFAQUR7P_cjs.getLogger(c.env.DB);
|
|
19314
19444
|
await logger.updateConfig(category, {
|
|
19315
19445
|
enabled,
|
|
19316
19446
|
level,
|
|
@@ -19339,7 +19469,7 @@ adminLogsRoutes.get("/export", async (c) => {
|
|
|
19339
19469
|
const category = query.category;
|
|
19340
19470
|
const startDate = query.start_date;
|
|
19341
19471
|
const endDate = query.end_date;
|
|
19342
|
-
const logger =
|
|
19472
|
+
const logger = chunkLFAQUR7P_cjs.getLogger(c.env.DB);
|
|
19343
19473
|
const filter = {
|
|
19344
19474
|
limit: 1e4,
|
|
19345
19475
|
// Export up to 10k logs
|
|
@@ -19420,7 +19550,7 @@ adminLogsRoutes.post("/cleanup", async (c) => {
|
|
|
19420
19550
|
error: "Unauthorized. Admin access required."
|
|
19421
19551
|
}, 403);
|
|
19422
19552
|
}
|
|
19423
|
-
const logger =
|
|
19553
|
+
const logger = chunkLFAQUR7P_cjs.getLogger(c.env.DB);
|
|
19424
19554
|
await logger.cleanupByRetention();
|
|
19425
19555
|
return c.html(html.html`
|
|
19426
19556
|
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded">
|
|
@@ -19442,7 +19572,7 @@ adminLogsRoutes.post("/search", async (c) => {
|
|
|
19442
19572
|
const search = formData.get("search");
|
|
19443
19573
|
const level = formData.get("level");
|
|
19444
19574
|
const category = formData.get("category");
|
|
19445
|
-
const logger =
|
|
19575
|
+
const logger = chunkLFAQUR7P_cjs.getLogger(c.env.DB);
|
|
19446
19576
|
const filter = {
|
|
19447
19577
|
limit: 20,
|
|
19448
19578
|
offset: 0,
|
|
@@ -21493,9 +21623,9 @@ function renderStorageUsage(databaseSizeBytes, mediaSizeBytes) {
|
|
|
21493
21623
|
}
|
|
21494
21624
|
|
|
21495
21625
|
// src/routes/admin-dashboard.ts
|
|
21496
|
-
var VERSION =
|
|
21626
|
+
var VERSION = chunkQLPFENZ2_cjs.getCoreVersion();
|
|
21497
21627
|
var router = new hono.Hono();
|
|
21498
|
-
router.use("*",
|
|
21628
|
+
router.use("*", chunkB2ASV5RD_cjs.requireAuth());
|
|
21499
21629
|
router.get("/", async (c) => {
|
|
21500
21630
|
const user = c.get("user");
|
|
21501
21631
|
try {
|
|
@@ -21526,7 +21656,7 @@ router.get("/stats", async (c) => {
|
|
|
21526
21656
|
const db = c.env.DB;
|
|
21527
21657
|
let collectionsCount = 0;
|
|
21528
21658
|
try {
|
|
21529
|
-
const collectionsStmt = db.prepare("SELECT COUNT(*) as count FROM collections WHERE is_active = 1");
|
|
21659
|
+
const collectionsStmt = db.prepare("SELECT COUNT(*) as count FROM collections WHERE is_active = 1 AND (source_type IS NULL OR source_type = 'user')");
|
|
21530
21660
|
const collectionsResult = await collectionsStmt.first();
|
|
21531
21661
|
collectionsCount = collectionsResult?.count || 0;
|
|
21532
21662
|
} catch (error) {
|
|
@@ -21534,7 +21664,7 @@ router.get("/stats", async (c) => {
|
|
|
21534
21664
|
}
|
|
21535
21665
|
let contentCount = 0;
|
|
21536
21666
|
try {
|
|
21537
|
-
const contentStmt = db.prepare("SELECT COUNT(*) as count FROM content");
|
|
21667
|
+
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')");
|
|
21538
21668
|
const contentResult = await contentStmt.first();
|
|
21539
21669
|
contentCount = contentResult?.count || 0;
|
|
21540
21670
|
} catch (error) {
|
|
@@ -23314,10 +23444,10 @@ function renderCollectionFormPage(data) {
|
|
|
23314
23444
|
|
|
23315
23445
|
// src/routes/admin-collections.ts
|
|
23316
23446
|
var adminCollectionsRoutes = new hono.Hono();
|
|
23317
|
-
adminCollectionsRoutes.use("*",
|
|
23318
|
-
adminCollectionsRoutes.post("*",
|
|
23319
|
-
adminCollectionsRoutes.put("*",
|
|
23320
|
-
adminCollectionsRoutes.delete("*",
|
|
23447
|
+
adminCollectionsRoutes.use("*", chunkB2ASV5RD_cjs.requireAuth());
|
|
23448
|
+
adminCollectionsRoutes.post("*", chunkB2ASV5RD_cjs.requireRole(["admin"]));
|
|
23449
|
+
adminCollectionsRoutes.put("*", chunkB2ASV5RD_cjs.requireRole(["admin"]));
|
|
23450
|
+
adminCollectionsRoutes.delete("*", chunkB2ASV5RD_cjs.requireRole(["admin"]));
|
|
23321
23451
|
adminCollectionsRoutes.get("/", async (c) => {
|
|
23322
23452
|
try {
|
|
23323
23453
|
const user = c.get("user");
|
|
@@ -23331,6 +23461,7 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
23331
23461
|
SELECT id, name, display_name, description, created_at, managed, schema
|
|
23332
23462
|
FROM collections
|
|
23333
23463
|
WHERE is_active = 1
|
|
23464
|
+
AND (source_type IS NULL OR source_type = 'user')
|
|
23334
23465
|
AND (name LIKE ? OR display_name LIKE ? OR description LIKE ?)
|
|
23335
23466
|
ORDER BY created_at DESC
|
|
23336
23467
|
`);
|
|
@@ -23338,7 +23469,7 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
23338
23469
|
const queryResults = await stmt.bind(searchParam, searchParam, searchParam).all();
|
|
23339
23470
|
results = queryResults.results;
|
|
23340
23471
|
} else {
|
|
23341
|
-
stmt = db.prepare("SELECT id, name, display_name, description, created_at, managed, schema FROM collections WHERE is_active = 1 ORDER BY created_at DESC");
|
|
23472
|
+
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");
|
|
23342
23473
|
const queryResults = await stmt.all();
|
|
23343
23474
|
results = queryResults.results;
|
|
23344
23475
|
}
|
|
@@ -25512,7 +25643,7 @@ function renderDatabaseToolsSettings(settings) {
|
|
|
25512
25643
|
|
|
25513
25644
|
// src/routes/admin-settings.ts
|
|
25514
25645
|
var adminSettingsRoutes = new hono.Hono();
|
|
25515
|
-
adminSettingsRoutes.use("*",
|
|
25646
|
+
adminSettingsRoutes.use("*", chunkB2ASV5RD_cjs.requireAuth());
|
|
25516
25647
|
function getMockSettings(user) {
|
|
25517
25648
|
return {
|
|
25518
25649
|
general: {
|
|
@@ -25577,7 +25708,7 @@ adminSettingsRoutes.get("/", (c) => {
|
|
|
25577
25708
|
adminSettingsRoutes.get("/general", async (c) => {
|
|
25578
25709
|
const user = c.get("user");
|
|
25579
25710
|
const db = c.env.DB;
|
|
25580
|
-
const settingsService = new
|
|
25711
|
+
const settingsService = new chunkLFAQUR7P_cjs.SettingsService(db);
|
|
25581
25712
|
const generalSettings = await settingsService.getGeneralSettings(user?.email);
|
|
25582
25713
|
const mockSettings = getMockSettings(user);
|
|
25583
25714
|
mockSettings.general = generalSettings;
|
|
@@ -25680,7 +25811,7 @@ adminSettingsRoutes.get("/database-tools", (c) => {
|
|
|
25680
25811
|
adminSettingsRoutes.get("/api/migrations/status", async (c) => {
|
|
25681
25812
|
try {
|
|
25682
25813
|
const db = c.env.DB;
|
|
25683
|
-
const migrationService = new
|
|
25814
|
+
const migrationService = new chunkDE5YTNCD_cjs.MigrationService(db);
|
|
25684
25815
|
const status = await migrationService.getMigrationStatus();
|
|
25685
25816
|
return c.json({
|
|
25686
25817
|
success: true,
|
|
@@ -25704,7 +25835,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
|
|
|
25704
25835
|
}, 403);
|
|
25705
25836
|
}
|
|
25706
25837
|
const db = c.env.DB;
|
|
25707
|
-
const migrationService = new
|
|
25838
|
+
const migrationService = new chunkDE5YTNCD_cjs.MigrationService(db);
|
|
25708
25839
|
const result = await migrationService.runPendingMigrations();
|
|
25709
25840
|
return c.json({
|
|
25710
25841
|
success: result.success,
|
|
@@ -25722,7 +25853,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
|
|
|
25722
25853
|
adminSettingsRoutes.get("/api/migrations/validate", async (c) => {
|
|
25723
25854
|
try {
|
|
25724
25855
|
const db = c.env.DB;
|
|
25725
|
-
const migrationService = new
|
|
25856
|
+
const migrationService = new chunkDE5YTNCD_cjs.MigrationService(db);
|
|
25726
25857
|
const validation = await migrationService.validateSchema();
|
|
25727
25858
|
return c.json({
|
|
25728
25859
|
success: true,
|
|
@@ -25891,7 +26022,7 @@ adminSettingsRoutes.post("/general", async (c) => {
|
|
|
25891
26022
|
}
|
|
25892
26023
|
const formData = await c.req.formData();
|
|
25893
26024
|
const db = c.env.DB;
|
|
25894
|
-
const settingsService = new
|
|
26025
|
+
const settingsService = new chunkLFAQUR7P_cjs.SettingsService(db);
|
|
25895
26026
|
const settings = {
|
|
25896
26027
|
siteName: formData.get("siteName"),
|
|
25897
26028
|
siteDescription: formData.get("siteDescription"),
|
|
@@ -27612,7 +27743,7 @@ function renderFormCreatePage(data) {
|
|
|
27612
27743
|
|
|
27613
27744
|
// src/routes/admin-forms.ts
|
|
27614
27745
|
var adminFormsRoutes = new hono.Hono();
|
|
27615
|
-
adminFormsRoutes.use("*",
|
|
27746
|
+
adminFormsRoutes.use("*", chunkB2ASV5RD_cjs.requireAuth());
|
|
27616
27747
|
adminFormsRoutes.get("/", async (c) => {
|
|
27617
27748
|
try {
|
|
27618
27749
|
const user = c.get("user");
|
|
@@ -28410,14 +28541,36 @@ publicFormsRoutes.post("/:identifier/submit", async (c) => {
|
|
|
28410
28541
|
now
|
|
28411
28542
|
).run();
|
|
28412
28543
|
await db.prepare(`
|
|
28413
|
-
UPDATE forms
|
|
28544
|
+
UPDATE forms
|
|
28414
28545
|
SET submission_count = submission_count + 1,
|
|
28415
28546
|
updated_at = ?
|
|
28416
28547
|
WHERE id = ?
|
|
28417
28548
|
`).bind(now, form.id).run();
|
|
28549
|
+
let contentId = null;
|
|
28550
|
+
try {
|
|
28551
|
+
contentId = await chunk6BVLPACH_cjs.createContentFromSubmission(
|
|
28552
|
+
db,
|
|
28553
|
+
sanitizedData,
|
|
28554
|
+
{ id: form.id, name: form.name, display_name: form.display_name },
|
|
28555
|
+
submissionId,
|
|
28556
|
+
{
|
|
28557
|
+
ipAddress: c.req.header("cf-connecting-ip") || null,
|
|
28558
|
+
userAgent: c.req.header("user-agent") || null,
|
|
28559
|
+
userEmail: sanitizedData?.email || null,
|
|
28560
|
+
userId: null
|
|
28561
|
+
// anonymous submission
|
|
28562
|
+
}
|
|
28563
|
+
);
|
|
28564
|
+
if (!contentId) {
|
|
28565
|
+
console.warn("[FormSubmit] Content creation returned null for submission:", submissionId);
|
|
28566
|
+
}
|
|
28567
|
+
} catch (contentError) {
|
|
28568
|
+
console.error("[FormSubmit] Error creating content from submission:", contentError);
|
|
28569
|
+
}
|
|
28418
28570
|
return c.json({
|
|
28419
28571
|
success: true,
|
|
28420
28572
|
submissionId,
|
|
28573
|
+
contentId,
|
|
28421
28574
|
message: "Form submitted successfully"
|
|
28422
28575
|
});
|
|
28423
28576
|
} catch (error) {
|
|
@@ -28569,7 +28722,7 @@ function renderAPIReferencePage(data) {
|
|
|
28569
28722
|
>
|
|
28570
28723
|
<option value="">All Categories</option>
|
|
28571
28724
|
${categories.map((category) => {
|
|
28572
|
-
const info =
|
|
28725
|
+
const info = chunkLFAQUR7P_cjs.CATEGORY_INFO[category];
|
|
28573
28726
|
const title = info ? info.title : category;
|
|
28574
28727
|
return `<option value="${category}">${title}</option>`;
|
|
28575
28728
|
}).join("\n ")}
|
|
@@ -28586,7 +28739,7 @@ function renderAPIReferencePage(data) {
|
|
|
28586
28739
|
<!-- API Categories -->
|
|
28587
28740
|
<div class="space-y-6">
|
|
28588
28741
|
${Object.entries(endpointsByCategory).map(([category, endpoints]) => {
|
|
28589
|
-
const info =
|
|
28742
|
+
const info = chunkLFAQUR7P_cjs.CATEGORY_INFO[category] || { title: category, description: "", icon: "📋" };
|
|
28590
28743
|
return `
|
|
28591
28744
|
<div class="api-category" data-category="${category}">
|
|
28592
28745
|
<div class="rounded-lg bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 overflow-hidden">
|
|
@@ -28763,14 +28916,14 @@ function renderAPIReferencePage(data) {
|
|
|
28763
28916
|
}
|
|
28764
28917
|
|
|
28765
28918
|
// src/routes/admin-api-reference.ts
|
|
28766
|
-
var VERSION2 =
|
|
28919
|
+
var VERSION2 = chunkQLPFENZ2_cjs.getCoreVersion();
|
|
28767
28920
|
var router2 = new hono.Hono();
|
|
28768
|
-
router2.use("*",
|
|
28921
|
+
router2.use("*", chunkB2ASV5RD_cjs.requireAuth());
|
|
28769
28922
|
router2.get("/", async (c) => {
|
|
28770
28923
|
const user = c.get("user");
|
|
28771
28924
|
try {
|
|
28772
|
-
const app2 =
|
|
28773
|
-
const endpoints =
|
|
28925
|
+
const app2 = chunkLFAQUR7P_cjs.getAppInstance();
|
|
28926
|
+
const endpoints = chunkLFAQUR7P_cjs.buildRouteList(app2);
|
|
28774
28927
|
const pageData = {
|
|
28775
28928
|
endpoints,
|
|
28776
28929
|
user: user ? {
|
|
@@ -28852,5 +29005,5 @@ exports.router = router;
|
|
|
28852
29005
|
exports.router2 = router2;
|
|
28853
29006
|
exports.test_cleanup_default = test_cleanup_default;
|
|
28854
29007
|
exports.userRoutes = userRoutes;
|
|
28855
|
-
//# sourceMappingURL=chunk-
|
|
28856
|
-
//# sourceMappingURL=chunk-
|
|
29008
|
+
//# sourceMappingURL=chunk-ASAEJ4B7.cjs.map
|
|
29009
|
+
//# sourceMappingURL=chunk-ASAEJ4B7.cjs.map
|