@sonicjs-cms/core 2.8.2 → 2.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-WI5ESQKT.js → chunk-5XAI2XUF.js} +3 -3
- package/dist/{chunk-WI5ESQKT.js.map → chunk-5XAI2XUF.js.map} +1 -1
- package/dist/{chunk-4Z5BQZT6.js → chunk-CH5UHZVM.js} +160 -23
- package/dist/chunk-CH5UHZVM.js.map +1 -0
- package/dist/{chunk-I6REMSMF.js → chunk-GTFMI24U.js} +2 -2
- package/dist/{chunk-I6REMSMF.js.map → chunk-GTFMI24U.js.map} +1 -1
- package/dist/{chunk-VGSZWZP3.cjs → chunk-HXHVU5GM.cjs} +2 -2
- package/dist/{chunk-VGSZWZP3.cjs.map → chunk-HXHVU5GM.cjs.map} +1 -1
- package/dist/{chunk-JSHIGVIF.cjs → chunk-JDIM5AG7.cjs} +3 -3
- package/dist/{chunk-JSHIGVIF.cjs.map → chunk-JDIM5AG7.cjs.map} +1 -1
- package/dist/{chunk-ZWKCL46S.cjs → chunk-K4Q4SFJJ.cjs} +4 -4
- package/dist/{chunk-ZWKCL46S.cjs.map → chunk-K4Q4SFJJ.cjs.map} +1 -1
- package/dist/{chunk-3U5YHS4G.cjs → chunk-R4WR3VTN.cjs} +238 -101
- package/dist/chunk-R4WR3VTN.cjs.map +1 -0
- package/dist/{chunk-FUUVSYVQ.js → chunk-Y3VMEGY2.js} +3 -3
- package/dist/{chunk-FUUVSYVQ.js.map → chunk-Y3VMEGY2.js.map} +1 -1
- package/dist/{collection-config-BF95LgQb.d.cts → collection-config-i8EaAF7z.d.cts} +2 -1
- package/dist/{collection-config-BF95LgQb.d.ts → collection-config-i8EaAF7z.d.ts} +2 -1
- package/dist/index.cjs +83 -83
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +7 -7
- package/dist/middleware.cjs +28 -28
- package/dist/middleware.js +2 -2
- package/dist/migrations-7X4RPH7O.cjs +13 -0
- package/dist/{migrations-F3G6CTRS.cjs.map → migrations-7X4RPH7O.cjs.map} +1 -1
- package/dist/migrations-KHWFJ2HN.js +4 -0
- package/dist/{migrations-LLNEST75.js.map → migrations-KHWFJ2HN.js.map} +1 -1
- package/dist/{plugin-bootstrap-C7Mj00Ud.d.ts → plugin-bootstrap-CJozpgmI.d.cts} +1 -1
- package/dist/{plugin-bootstrap-DKB5f8-E.d.cts → plugin-bootstrap-DU5VmuHZ.d.ts} +1 -1
- package/dist/routes.cjs +27 -27
- package/dist/routes.js +4 -4
- package/dist/services.cjs +2 -2
- package/dist/services.d.cts +2 -2
- package/dist/services.d.ts +2 -2
- package/dist/services.js +1 -1
- package/dist/types.d.cts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/utils.cjs +11 -11
- package/dist/utils.d.cts +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-3U5YHS4G.cjs.map +0 -1
- package/dist/chunk-4Z5BQZT6.js.map +0 -1
- package/dist/migrations-F3G6CTRS.cjs +0 -13
- package/dist/migrations-LLNEST75.js +0 -4
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunkVNLR35GO_cjs = require('./chunk-VNLR35GO.cjs');
|
|
4
|
-
var
|
|
4
|
+
var chunkK4Q4SFJJ_cjs = require('./chunk-K4Q4SFJJ.cjs');
|
|
5
5
|
var chunkMPT5PA6U_cjs = require('./chunk-MPT5PA6U.cjs');
|
|
6
|
-
var
|
|
6
|
+
var chunkHXHVU5GM_cjs = require('./chunk-HXHVU5GM.cjs');
|
|
7
7
|
var chunkLTKV7AE5_cjs = require('./chunk-LTKV7AE5.cjs');
|
|
8
8
|
var chunk6FHNRRJ3_cjs = require('./chunk-6FHNRRJ3.cjs');
|
|
9
|
-
var
|
|
9
|
+
var chunkJDIM5AG7_cjs = require('./chunk-JDIM5AG7.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');
|
|
@@ -121,7 +121,7 @@ apiContentCrudRoutes.get("/:id", async (c) => {
|
|
|
121
121
|
}, 500);
|
|
122
122
|
}
|
|
123
123
|
});
|
|
124
|
-
apiContentCrudRoutes.post("/",
|
|
124
|
+
apiContentCrudRoutes.post("/", chunkK4Q4SFJJ_cjs.requireAuth(), async (c) => {
|
|
125
125
|
try {
|
|
126
126
|
const db = c.env.DB;
|
|
127
127
|
const user = c.get("user");
|
|
@@ -187,7 +187,7 @@ apiContentCrudRoutes.post("/", chunkZWKCL46S_cjs.requireAuth(), async (c) => {
|
|
|
187
187
|
}, 500);
|
|
188
188
|
}
|
|
189
189
|
});
|
|
190
|
-
apiContentCrudRoutes.put("/:id",
|
|
190
|
+
apiContentCrudRoutes.put("/:id", chunkK4Q4SFJJ_cjs.requireAuth(), async (c) => {
|
|
191
191
|
try {
|
|
192
192
|
const id = c.req.param("id");
|
|
193
193
|
const db = c.env.DB;
|
|
@@ -251,7 +251,7 @@ apiContentCrudRoutes.put("/:id", chunkZWKCL46S_cjs.requireAuth(), async (c) => {
|
|
|
251
251
|
}, 500);
|
|
252
252
|
}
|
|
253
253
|
});
|
|
254
|
-
apiContentCrudRoutes.delete("/:id",
|
|
254
|
+
apiContentCrudRoutes.delete("/:id", chunkK4Q4SFJJ_cjs.requireAuth(), async (c) => {
|
|
255
255
|
try {
|
|
256
256
|
const id = c.req.param("id");
|
|
257
257
|
const db = c.env.DB;
|
|
@@ -287,7 +287,7 @@ apiRoutes.use("*", async (c, next) => {
|
|
|
287
287
|
c.header("X-Response-Time", `${totalTime}ms`);
|
|
288
288
|
});
|
|
289
289
|
apiRoutes.use("*", async (c, next) => {
|
|
290
|
-
const cacheEnabled = await
|
|
290
|
+
const cacheEnabled = await chunkK4Q4SFJJ_cjs.isPluginActive(c.env.DB, "core-cache");
|
|
291
291
|
c.set("cacheEnabled", cacheEnabled);
|
|
292
292
|
await next();
|
|
293
293
|
});
|
|
@@ -778,7 +778,7 @@ apiRoutes.get("/collections", async (c) => {
|
|
|
778
778
|
return c.json({ error: "Failed to fetch collections" }, 500);
|
|
779
779
|
}
|
|
780
780
|
});
|
|
781
|
-
apiRoutes.get("/content",
|
|
781
|
+
apiRoutes.get("/content", chunkK4Q4SFJJ_cjs.optionalAuth(), async (c) => {
|
|
782
782
|
const executionStart = Date.now();
|
|
783
783
|
try {
|
|
784
784
|
const db = c.env.DB;
|
|
@@ -801,13 +801,13 @@ apiRoutes.get("/content", chunkZWKCL46S_cjs.optionalAuth(), async (c) => {
|
|
|
801
801
|
});
|
|
802
802
|
}
|
|
803
803
|
}
|
|
804
|
-
const filter =
|
|
804
|
+
const filter = chunkJDIM5AG7_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
|
|
805
805
|
const normalizedFilter = normalizePublicContentFilter(filter, c.get("user")?.role);
|
|
806
806
|
if (!normalizedFilter.limit) {
|
|
807
807
|
normalizedFilter.limit = 50;
|
|
808
808
|
}
|
|
809
809
|
normalizedFilter.limit = Math.min(normalizedFilter.limit, 1e3);
|
|
810
|
-
const builder3 = new
|
|
810
|
+
const builder3 = new chunkJDIM5AG7_cjs.QueryFilterBuilder();
|
|
811
811
|
const queryResult = builder3.build("content", normalizedFilter);
|
|
812
812
|
if (queryResult.errors.length > 0) {
|
|
813
813
|
return c.json({
|
|
@@ -879,7 +879,7 @@ apiRoutes.get("/content", chunkZWKCL46S_cjs.optionalAuth(), async (c) => {
|
|
|
879
879
|
}, 500);
|
|
880
880
|
}
|
|
881
881
|
});
|
|
882
|
-
apiRoutes.get("/collections/:collection/content",
|
|
882
|
+
apiRoutes.get("/collections/:collection/content", chunkK4Q4SFJJ_cjs.optionalAuth(), async (c) => {
|
|
883
883
|
const executionStart = Date.now();
|
|
884
884
|
try {
|
|
885
885
|
const collection = c.req.param("collection");
|
|
@@ -890,7 +890,7 @@ apiRoutes.get("/collections/:collection/content", chunkZWKCL46S_cjs.optionalAuth
|
|
|
890
890
|
if (!collectionResult) {
|
|
891
891
|
return c.json({ error: "Collection not found" }, 404);
|
|
892
892
|
}
|
|
893
|
-
const filter =
|
|
893
|
+
const filter = chunkJDIM5AG7_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
|
|
894
894
|
const normalizedFilter = normalizePublicContentFilter(filter, c.get("user")?.role);
|
|
895
895
|
if (!normalizedFilter.where) {
|
|
896
896
|
normalizedFilter.where = { and: [] };
|
|
@@ -907,7 +907,7 @@ apiRoutes.get("/collections/:collection/content", chunkZWKCL46S_cjs.optionalAuth
|
|
|
907
907
|
normalizedFilter.limit = 50;
|
|
908
908
|
}
|
|
909
909
|
normalizedFilter.limit = Math.min(normalizedFilter.limit, 1e3);
|
|
910
|
-
const builder3 = new
|
|
910
|
+
const builder3 = new chunkJDIM5AG7_cjs.QueryFilterBuilder();
|
|
911
911
|
const queryResult = builder3.build("content", normalizedFilter);
|
|
912
912
|
if (queryResult.errors.length > 0) {
|
|
913
913
|
return c.json({
|
|
@@ -1028,7 +1028,7 @@ var fileValidationSchema = zod.z.object({
|
|
|
1028
1028
|
// 50MB max
|
|
1029
1029
|
});
|
|
1030
1030
|
var apiMediaRoutes = new hono.Hono();
|
|
1031
|
-
apiMediaRoutes.use("*",
|
|
1031
|
+
apiMediaRoutes.use("*", chunkK4Q4SFJJ_cjs.requireAuth());
|
|
1032
1032
|
apiMediaRoutes.post("/upload", async (c) => {
|
|
1033
1033
|
try {
|
|
1034
1034
|
const user = c.get("user");
|
|
@@ -1772,8 +1772,8 @@ apiSystemRoutes.get("/env", (c) => {
|
|
|
1772
1772
|
});
|
|
1773
1773
|
var api_system_default = apiSystemRoutes;
|
|
1774
1774
|
var adminApiRoutes = new hono.Hono();
|
|
1775
|
-
adminApiRoutes.use("*",
|
|
1776
|
-
adminApiRoutes.use("*",
|
|
1775
|
+
adminApiRoutes.use("*", chunkK4Q4SFJJ_cjs.requireAuth());
|
|
1776
|
+
adminApiRoutes.use("*", chunkK4Q4SFJJ_cjs.requireRole(["admin", "editor"]));
|
|
1777
1777
|
adminApiRoutes.get("/stats", async (c) => {
|
|
1778
1778
|
try {
|
|
1779
1779
|
const db = c.env.DB;
|
|
@@ -2283,7 +2283,7 @@ adminApiRoutes.delete("/collections/:id", async (c) => {
|
|
|
2283
2283
|
});
|
|
2284
2284
|
adminApiRoutes.get("/migrations/status", async (c) => {
|
|
2285
2285
|
try {
|
|
2286
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
2286
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-7X4RPH7O.cjs');
|
|
2287
2287
|
const db = c.env.DB;
|
|
2288
2288
|
const migrationService = new MigrationService2(db);
|
|
2289
2289
|
const status = await migrationService.getMigrationStatus();
|
|
@@ -2308,7 +2308,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
|
|
|
2308
2308
|
error: "Unauthorized. Admin access required."
|
|
2309
2309
|
}, 403);
|
|
2310
2310
|
}
|
|
2311
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
2311
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-7X4RPH7O.cjs');
|
|
2312
2312
|
const db = c.env.DB;
|
|
2313
2313
|
const migrationService = new MigrationService2(db);
|
|
2314
2314
|
const result = await migrationService.runPendingMigrations();
|
|
@@ -2327,7 +2327,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
|
|
|
2327
2327
|
});
|
|
2328
2328
|
adminApiRoutes.get("/migrations/validate", async (c) => {
|
|
2329
2329
|
try {
|
|
2330
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
2330
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-7X4RPH7O.cjs');
|
|
2331
2331
|
const db = c.env.DB;
|
|
2332
2332
|
const migrationService = new MigrationService2(db);
|
|
2333
2333
|
const validation = await migrationService.validateSchema();
|
|
@@ -2738,7 +2738,7 @@ var JWT_SECRET_FALLBACK = "your-super-secret-jwt-key-change-in-production";
|
|
|
2738
2738
|
async function setCsrfCookie(c) {
|
|
2739
2739
|
const secret = c.env?.JWT_SECRET || JWT_SECRET_FALLBACK;
|
|
2740
2740
|
const isDev = c.env?.ENVIRONMENT === "development" || !c.env?.ENVIRONMENT;
|
|
2741
|
-
const csrfToken = await
|
|
2741
|
+
const csrfToken = await chunkK4Q4SFJJ_cjs.generateCsrfToken(secret);
|
|
2742
2742
|
cookie.setCookie(c, "csrf_token", csrfToken, {
|
|
2743
2743
|
httpOnly: false,
|
|
2744
2744
|
secure: !isDev,
|
|
@@ -2795,7 +2795,7 @@ var loginSchema = zod.z.object({
|
|
|
2795
2795
|
});
|
|
2796
2796
|
authRoutes.post(
|
|
2797
2797
|
"/register",
|
|
2798
|
-
|
|
2798
|
+
chunkK4Q4SFJJ_cjs.rateLimit({ max: 3, windowMs: 60 * 1e3, keyPrefix: "register" }),
|
|
2799
2799
|
async (c) => {
|
|
2800
2800
|
try {
|
|
2801
2801
|
const db = c.env.DB;
|
|
@@ -2832,7 +2832,7 @@ authRoutes.post(
|
|
|
2832
2832
|
if (existingUser) {
|
|
2833
2833
|
return c.json({ error: "User with this email or username already exists" }, 400);
|
|
2834
2834
|
}
|
|
2835
|
-
const passwordHash = await
|
|
2835
|
+
const passwordHash = await chunkK4Q4SFJJ_cjs.AuthManager.hashPassword(password);
|
|
2836
2836
|
const userId = crypto.randomUUID();
|
|
2837
2837
|
const now = /* @__PURE__ */ new Date();
|
|
2838
2838
|
await db.prepare(`
|
|
@@ -2852,7 +2852,7 @@ authRoutes.post(
|
|
|
2852
2852
|
now.getTime(),
|
|
2853
2853
|
now.getTime()
|
|
2854
2854
|
).run();
|
|
2855
|
-
const token = await
|
|
2855
|
+
const token = await chunkK4Q4SFJJ_cjs.AuthManager.generateToken(userId, normalizedEmail, "viewer", c.env.JWT_SECRET);
|
|
2856
2856
|
cookie.setCookie(c, "auth_token", token, {
|
|
2857
2857
|
httpOnly: true,
|
|
2858
2858
|
secure: true,
|
|
@@ -2886,7 +2886,7 @@ authRoutes.post(
|
|
|
2886
2886
|
);
|
|
2887
2887
|
authRoutes.post(
|
|
2888
2888
|
"/login",
|
|
2889
|
-
|
|
2889
|
+
chunkK4Q4SFJJ_cjs.rateLimit({ max: 5, windowMs: 60 * 1e3, keyPrefix: "login" }),
|
|
2890
2890
|
async (c) => {
|
|
2891
2891
|
try {
|
|
2892
2892
|
const body = await c.req.json();
|
|
@@ -2909,19 +2909,19 @@ authRoutes.post(
|
|
|
2909
2909
|
if (!user) {
|
|
2910
2910
|
return c.json({ error: "Invalid email or password" }, 401);
|
|
2911
2911
|
}
|
|
2912
|
-
const isValidPassword = await
|
|
2912
|
+
const isValidPassword = await chunkK4Q4SFJJ_cjs.AuthManager.verifyPassword(password, user.password_hash);
|
|
2913
2913
|
if (!isValidPassword) {
|
|
2914
2914
|
return c.json({ error: "Invalid email or password" }, 401);
|
|
2915
2915
|
}
|
|
2916
|
-
if (
|
|
2916
|
+
if (chunkK4Q4SFJJ_cjs.AuthManager.isLegacyHash(user.password_hash)) {
|
|
2917
2917
|
try {
|
|
2918
|
-
const newHash = await
|
|
2918
|
+
const newHash = await chunkK4Q4SFJJ_cjs.AuthManager.hashPassword(password);
|
|
2919
2919
|
await db.prepare("UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?").bind(newHash, Date.now(), user.id).run();
|
|
2920
2920
|
} catch (rehashError) {
|
|
2921
2921
|
console.error("Password rehash failed (non-fatal):", rehashError);
|
|
2922
2922
|
}
|
|
2923
2923
|
}
|
|
2924
|
-
const token = await
|
|
2924
|
+
const token = await chunkK4Q4SFJJ_cjs.AuthManager.generateToken(user.id, user.email, user.role, c.env.JWT_SECRET);
|
|
2925
2925
|
cookie.setCookie(c, "auth_token", token, {
|
|
2926
2926
|
httpOnly: true,
|
|
2927
2927
|
secure: true,
|
|
@@ -2974,7 +2974,7 @@ authRoutes.get("/logout", (c) => {
|
|
|
2974
2974
|
clearCsrfCookie(c);
|
|
2975
2975
|
return c.redirect("/auth/login?message=You have been logged out successfully");
|
|
2976
2976
|
});
|
|
2977
|
-
authRoutes.get("/me",
|
|
2977
|
+
authRoutes.get("/me", chunkK4Q4SFJJ_cjs.requireAuth(), async (c) => {
|
|
2978
2978
|
try {
|
|
2979
2979
|
const user = c.get("user");
|
|
2980
2980
|
if (!user) {
|
|
@@ -2991,13 +2991,13 @@ authRoutes.get("/me", chunkZWKCL46S_cjs.requireAuth(), async (c) => {
|
|
|
2991
2991
|
return c.json({ error: "Failed to get user" }, 500);
|
|
2992
2992
|
}
|
|
2993
2993
|
});
|
|
2994
|
-
authRoutes.post("/refresh",
|
|
2994
|
+
authRoutes.post("/refresh", chunkK4Q4SFJJ_cjs.requireAuth(), async (c) => {
|
|
2995
2995
|
try {
|
|
2996
2996
|
const user = c.get("user");
|
|
2997
2997
|
if (!user) {
|
|
2998
2998
|
return c.json({ error: "Not authenticated" }, 401);
|
|
2999
2999
|
}
|
|
3000
|
-
const token = await
|
|
3000
|
+
const token = await chunkK4Q4SFJJ_cjs.AuthManager.generateToken(user.userId, user.email, user.role, c.env.JWT_SECRET);
|
|
3001
3001
|
cookie.setCookie(c, "auth_token", token, {
|
|
3002
3002
|
httpOnly: true,
|
|
3003
3003
|
secure: true,
|
|
@@ -3014,7 +3014,7 @@ authRoutes.post("/refresh", chunkZWKCL46S_cjs.requireAuth(), async (c) => {
|
|
|
3014
3014
|
});
|
|
3015
3015
|
authRoutes.post(
|
|
3016
3016
|
"/register/form",
|
|
3017
|
-
|
|
3017
|
+
chunkK4Q4SFJJ_cjs.rateLimit({ max: 3, windowMs: 60 * 1e3, keyPrefix: "register" }),
|
|
3018
3018
|
async (c) => {
|
|
3019
3019
|
try {
|
|
3020
3020
|
const db = c.env.DB;
|
|
@@ -3061,7 +3061,7 @@ authRoutes.post(
|
|
|
3061
3061
|
</div>
|
|
3062
3062
|
`);
|
|
3063
3063
|
}
|
|
3064
|
-
const passwordHash = await
|
|
3064
|
+
const passwordHash = await chunkK4Q4SFJJ_cjs.AuthManager.hashPassword(password);
|
|
3065
3065
|
const role = isFirstUser ? "admin" : "viewer";
|
|
3066
3066
|
const userId = crypto.randomUUID();
|
|
3067
3067
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -3081,7 +3081,7 @@ authRoutes.post(
|
|
|
3081
3081
|
now.getTime(),
|
|
3082
3082
|
now.getTime()
|
|
3083
3083
|
).run();
|
|
3084
|
-
const token = await
|
|
3084
|
+
const token = await chunkK4Q4SFJJ_cjs.AuthManager.generateToken(userId, normalizedEmail, role, c.env.JWT_SECRET);
|
|
3085
3085
|
cookie.setCookie(c, "auth_token", token, {
|
|
3086
3086
|
httpOnly: true,
|
|
3087
3087
|
secure: false,
|
|
@@ -3114,7 +3114,7 @@ authRoutes.post(
|
|
|
3114
3114
|
);
|
|
3115
3115
|
authRoutes.post(
|
|
3116
3116
|
"/login/form",
|
|
3117
|
-
|
|
3117
|
+
chunkK4Q4SFJJ_cjs.rateLimit({ max: 5, windowMs: 60 * 1e3, keyPrefix: "login" }),
|
|
3118
3118
|
async (c) => {
|
|
3119
3119
|
try {
|
|
3120
3120
|
const formData = await c.req.formData();
|
|
@@ -3138,7 +3138,7 @@ authRoutes.post(
|
|
|
3138
3138
|
</div>
|
|
3139
3139
|
`);
|
|
3140
3140
|
}
|
|
3141
|
-
const isValidPassword = await
|
|
3141
|
+
const isValidPassword = await chunkK4Q4SFJJ_cjs.AuthManager.verifyPassword(password, user.password_hash);
|
|
3142
3142
|
if (!isValidPassword) {
|
|
3143
3143
|
return c.html(html.html`
|
|
3144
3144
|
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded">
|
|
@@ -3146,15 +3146,15 @@ authRoutes.post(
|
|
|
3146
3146
|
</div>
|
|
3147
3147
|
`);
|
|
3148
3148
|
}
|
|
3149
|
-
if (
|
|
3149
|
+
if (chunkK4Q4SFJJ_cjs.AuthManager.isLegacyHash(user.password_hash)) {
|
|
3150
3150
|
try {
|
|
3151
|
-
const newHash = await
|
|
3151
|
+
const newHash = await chunkK4Q4SFJJ_cjs.AuthManager.hashPassword(password);
|
|
3152
3152
|
await db.prepare("UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?").bind(newHash, Date.now(), user.id).run();
|
|
3153
3153
|
} catch (rehashError) {
|
|
3154
3154
|
console.error("Password rehash failed (non-fatal):", rehashError);
|
|
3155
3155
|
}
|
|
3156
3156
|
}
|
|
3157
|
-
const token = await
|
|
3157
|
+
const token = await chunkK4Q4SFJJ_cjs.AuthManager.generateToken(user.id, user.email, user.role, c.env.JWT_SECRET);
|
|
3158
3158
|
cookie.setCookie(c, "auth_token", token, {
|
|
3159
3159
|
httpOnly: true,
|
|
3160
3160
|
secure: false,
|
|
@@ -3196,7 +3196,7 @@ authRoutes.post(
|
|
|
3196
3196
|
);
|
|
3197
3197
|
authRoutes.post(
|
|
3198
3198
|
"/seed-admin",
|
|
3199
|
-
|
|
3199
|
+
chunkK4Q4SFJJ_cjs.rateLimit({ max: 2, windowMs: 60 * 1e3, keyPrefix: "seed-admin" }),
|
|
3200
3200
|
async (c) => {
|
|
3201
3201
|
try {
|
|
3202
3202
|
const db = c.env.DB;
|
|
@@ -3218,7 +3218,7 @@ authRoutes.post(
|
|
|
3218
3218
|
`).run();
|
|
3219
3219
|
const existingAdmin = await db.prepare("SELECT id FROM users WHERE email = ? OR username = ?").bind("admin@sonicjs.com", "admin").first();
|
|
3220
3220
|
if (existingAdmin) {
|
|
3221
|
-
const passwordHash2 = await
|
|
3221
|
+
const passwordHash2 = await chunkK4Q4SFJJ_cjs.AuthManager.hashPassword("sonicjs!");
|
|
3222
3222
|
await db.prepare("UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?").bind(passwordHash2, Date.now(), existingAdmin.id).run();
|
|
3223
3223
|
return c.json({
|
|
3224
3224
|
message: "Admin user already exists (password updated)",
|
|
@@ -3230,7 +3230,7 @@ authRoutes.post(
|
|
|
3230
3230
|
}
|
|
3231
3231
|
});
|
|
3232
3232
|
}
|
|
3233
|
-
const passwordHash = await
|
|
3233
|
+
const passwordHash = await chunkK4Q4SFJJ_cjs.AuthManager.hashPassword("sonicjs!");
|
|
3234
3234
|
const userId = "admin-user-id";
|
|
3235
3235
|
const now = Date.now();
|
|
3236
3236
|
const adminEmail = "admin@sonicjs.com".toLowerCase();
|
|
@@ -3451,7 +3451,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
3451
3451
|
if (existingUsername) {
|
|
3452
3452
|
return c.json({ error: "Username is already taken" }, 400);
|
|
3453
3453
|
}
|
|
3454
|
-
const passwordHash = await
|
|
3454
|
+
const passwordHash = await chunkK4Q4SFJJ_cjs.AuthManager.hashPassword(password);
|
|
3455
3455
|
const updateStmt = db.prepare(`
|
|
3456
3456
|
UPDATE users SET
|
|
3457
3457
|
username = ?,
|
|
@@ -3470,7 +3470,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
3470
3470
|
Date.now(),
|
|
3471
3471
|
invitedUser.id
|
|
3472
3472
|
).run();
|
|
3473
|
-
const authToken = await
|
|
3473
|
+
const authToken = await chunkK4Q4SFJJ_cjs.AuthManager.generateToken(invitedUser.id, invitedUser.email, invitedUser.role, c.env.JWT_SECRET);
|
|
3474
3474
|
cookie.setCookie(c, "auth_token", authToken, {
|
|
3475
3475
|
httpOnly: true,
|
|
3476
3476
|
secure: true,
|
|
@@ -3487,7 +3487,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
3487
3487
|
});
|
|
3488
3488
|
authRoutes.post(
|
|
3489
3489
|
"/request-password-reset",
|
|
3490
|
-
|
|
3490
|
+
chunkK4Q4SFJJ_cjs.rateLimit({ max: 3, windowMs: 15 * 60 * 1e3, keyPrefix: "password-reset" }),
|
|
3491
3491
|
async (c) => {
|
|
3492
3492
|
try {
|
|
3493
3493
|
const formData = await c.req.formData();
|
|
@@ -3705,7 +3705,7 @@ authRoutes.post("/reset-password", async (c) => {
|
|
|
3705
3705
|
if (Date.now() > user.password_reset_expires) {
|
|
3706
3706
|
return c.json({ error: "Reset token has expired" }, 400);
|
|
3707
3707
|
}
|
|
3708
|
-
const newPasswordHash = await
|
|
3708
|
+
const newPasswordHash = await chunkK4Q4SFJJ_cjs.AuthManager.hashPassword(password);
|
|
3709
3709
|
try {
|
|
3710
3710
|
const historyStmt = db.prepare(`
|
|
3711
3711
|
INSERT INTO password_history (id, user_id, password_hash, created_at)
|
|
@@ -4782,6 +4782,7 @@ function getReadFieldValueScript() {
|
|
|
4782
4782
|
const textarea = fieldWrapper.querySelector('textarea');
|
|
4783
4783
|
const inputs = Array.from(fieldWrapper.querySelectorAll('input'));
|
|
4784
4784
|
const checkbox = inputs.find((input) => input.type === 'checkbox');
|
|
4785
|
+
const checkedRadio = inputs.find((input) => input.type === 'radio' && input.checked);
|
|
4785
4786
|
const nonHiddenInput = inputs.find((input) => input.type !== 'hidden' && input.type !== 'checkbox');
|
|
4786
4787
|
const hiddenInput = inputs.find((input) => input.type === 'hidden');
|
|
4787
4788
|
|
|
@@ -4804,6 +4805,10 @@ function getReadFieldValueScript() {
|
|
|
4804
4805
|
return checkbox.checked;
|
|
4805
4806
|
}
|
|
4806
4807
|
|
|
4808
|
+
if (fieldType === 'radio') {
|
|
4809
|
+
return checkedRadio ? checkedRadio.value : '';
|
|
4810
|
+
}
|
|
4811
|
+
|
|
4807
4812
|
if (select) {
|
|
4808
4813
|
if (select.multiple) {
|
|
4809
4814
|
return Array.from(select.selectedOptions).map((option) => option.value);
|
|
@@ -4843,9 +4848,9 @@ function renderDynamicField(field, options = {}) {
|
|
|
4843
4848
|
if (field.field_type === "quill" && !pluginStatuses.quillEnabled) {
|
|
4844
4849
|
fallbackToTextarea = true;
|
|
4845
4850
|
fallbackWarning = "\u26A0\uFE0F Quill Editor plugin is inactive. Using textarea fallback.";
|
|
4846
|
-
} else if (field.field_type === "mdxeditor" && !pluginStatuses.mdxeditorEnabled) {
|
|
4851
|
+
} else if ((field.field_type === "mdxeditor" || field.field_type === "easymde" || field.field_type === "markdown") && !pluginStatuses.mdxeditorEnabled) {
|
|
4847
4852
|
fallbackToTextarea = true;
|
|
4848
|
-
fallbackWarning = "\u26A0\uFE0F
|
|
4853
|
+
fallbackWarning = "\u26A0\uFE0F EasyMDE plugin is inactive. Using textarea fallback.";
|
|
4849
4854
|
} else if (field.field_type === "tinymce" && !pluginStatuses.tinymceEnabled) {
|
|
4850
4855
|
fallbackToTextarea = true;
|
|
4851
4856
|
fallbackWarning = "\u26A0\uFE0F TinyMCE plugin is inactive. Using textarea fallback.";
|
|
@@ -5004,6 +5009,9 @@ function renderDynamicField(field, options = {}) {
|
|
|
5004
5009
|
`;
|
|
5005
5010
|
break;
|
|
5006
5011
|
case "mdxeditor":
|
|
5012
|
+
case "tinymce":
|
|
5013
|
+
case "easymde":
|
|
5014
|
+
case "markdown":
|
|
5007
5015
|
fieldHTML = `
|
|
5008
5016
|
<div class="richtext-container" data-height="${opts.height || 300}" data-toolbar="${opts.toolbar || "full"}">
|
|
5009
5017
|
<textarea
|
|
@@ -5285,6 +5293,39 @@ function renderDynamicField(field, options = {}) {
|
|
|
5285
5293
|
` : ""}
|
|
5286
5294
|
`;
|
|
5287
5295
|
break;
|
|
5296
|
+
case "radio":
|
|
5297
|
+
const radioOptions = opts.options || (Array.isArray(opts.enum) ? opts.enum.map((optionValue, index) => ({
|
|
5298
|
+
value: optionValue,
|
|
5299
|
+
label: opts.enumLabels?.[index] || optionValue
|
|
5300
|
+
})) : []);
|
|
5301
|
+
const selectedRadioValue = value !== void 0 && value !== null ? String(value) : opts.default ? String(opts.default) : "";
|
|
5302
|
+
const isInline = opts.inline === true;
|
|
5303
|
+
fieldHTML = `
|
|
5304
|
+
<div class="${isInline ? "flex flex-wrap gap-4" : "space-y-3"}">
|
|
5305
|
+
${radioOptions.map((option, index) => {
|
|
5306
|
+
const optionValue = typeof option === "string" ? option : option.value;
|
|
5307
|
+
const optionLabel = typeof option === "string" ? option : option.label;
|
|
5308
|
+
const inputId = `${fieldId}-option-${index}`;
|
|
5309
|
+
const checked2 = selectedRadioValue === String(optionValue) ? "checked" : "";
|
|
5310
|
+
return `
|
|
5311
|
+
<label for="${inputId}" class="flex items-center gap-3 text-sm text-zinc-700 dark:text-zinc-300">
|
|
5312
|
+
<input
|
|
5313
|
+
type="radio"
|
|
5314
|
+
id="${inputId}"
|
|
5315
|
+
name="${fieldName}"
|
|
5316
|
+
value="${escapeHtml3(optionValue)}"
|
|
5317
|
+
class="h-4 w-4 text-zinc-900 focus:ring-zinc-400 dark:text-white dark:focus:ring-white"
|
|
5318
|
+
${checked2}
|
|
5319
|
+
${required}
|
|
5320
|
+
${disabled ? "disabled" : ""}
|
|
5321
|
+
>
|
|
5322
|
+
<span>${escapeHtml3(optionLabel)}</span>
|
|
5323
|
+
</label>
|
|
5324
|
+
`;
|
|
5325
|
+
}).join("")}
|
|
5326
|
+
</div>
|
|
5327
|
+
`;
|
|
5328
|
+
break;
|
|
5288
5329
|
case "reference":
|
|
5289
5330
|
let referenceCollections = [];
|
|
5290
5331
|
if (Array.isArray(opts.collection)) {
|
|
@@ -5555,8 +5596,19 @@ function renderStructuredArrayField(field, options, baseClasses, errorClasses) {
|
|
|
5555
5596
|
const fieldId = `field-${field.field_name}`;
|
|
5556
5597
|
const fieldName = field.field_name;
|
|
5557
5598
|
const arrayValue = normalizeStructuredArrayValue(value);
|
|
5599
|
+
const arrayTitle = opts.itemLabel || field.field_label || "Items";
|
|
5600
|
+
const hasItemTitle = typeof opts.itemTitle === "string" && opts.itemTitle.trim() !== "";
|
|
5601
|
+
const arrayItemTitle = hasItemTitle ? opts.itemTitle.trim() : "Item";
|
|
5602
|
+
const addItemLabel = hasItemTitle ? `Add ${arrayItemTitle}` : "Add item";
|
|
5558
5603
|
const items = arrayValue.map(
|
|
5559
|
-
(itemValue, index) => renderStructuredArrayItem(
|
|
5604
|
+
(itemValue, index) => renderStructuredArrayItem(
|
|
5605
|
+
field,
|
|
5606
|
+
itemsConfig,
|
|
5607
|
+
String(index),
|
|
5608
|
+
itemValue,
|
|
5609
|
+
pluginStatuses,
|
|
5610
|
+
arrayItemTitle
|
|
5611
|
+
)
|
|
5560
5612
|
).join("");
|
|
5561
5613
|
const emptyState = arrayValue.length === 0 ? `
|
|
5562
5614
|
<div class="rounded-lg border border-dashed border-zinc-200 dark:border-white/10 px-4 py-6 text-center text-sm text-zinc-500 dark:text-zinc-400" data-structured-empty>
|
|
@@ -5569,14 +5621,14 @@ function renderStructuredArrayField(field, options, baseClasses, errorClasses) {
|
|
|
5569
5621
|
|
|
5570
5622
|
<div class="flex items-center justify-between gap-3">
|
|
5571
5623
|
<div class="text-sm text-zinc-500 dark:text-zinc-400">
|
|
5572
|
-
${escapeHtml3(
|
|
5624
|
+
${escapeHtml3(arrayTitle)}
|
|
5573
5625
|
</div>
|
|
5574
5626
|
<button
|
|
5575
5627
|
type="button"
|
|
5576
5628
|
data-action="add-item"
|
|
5577
5629
|
class="inline-flex items-center justify-center rounded-lg bg-zinc-900 px-3 py-2 text-sm font-semibold text-white hover:bg-zinc-800 dark:bg-white/10 dark:hover:bg-white/20"
|
|
5578
5630
|
>
|
|
5579
|
-
|
|
5631
|
+
${escapeHtml3(addItemLabel)}
|
|
5580
5632
|
</button>
|
|
5581
5633
|
</div>
|
|
5582
5634
|
|
|
@@ -5585,14 +5637,21 @@ function renderStructuredArrayField(field, options, baseClasses, errorClasses) {
|
|
|
5585
5637
|
</div>
|
|
5586
5638
|
|
|
5587
5639
|
<template data-structured-array-template>
|
|
5588
|
-
${renderStructuredArrayItem(
|
|
5640
|
+
${renderStructuredArrayItem(
|
|
5641
|
+
field,
|
|
5642
|
+
itemsConfig,
|
|
5643
|
+
"__INDEX__",
|
|
5644
|
+
{},
|
|
5645
|
+
pluginStatuses,
|
|
5646
|
+
arrayItemTitle
|
|
5647
|
+
)}
|
|
5589
5648
|
</template>
|
|
5590
5649
|
</div>
|
|
5591
5650
|
${getDragSortableScript()}
|
|
5592
5651
|
${getStructuredFieldScript()}
|
|
5593
5652
|
`;
|
|
5594
5653
|
}
|
|
5595
|
-
function renderStructuredArrayItem(field, itemConfig, index, itemValue, pluginStatuses) {
|
|
5654
|
+
function renderStructuredArrayItem(field, itemConfig, index, itemValue, pluginStatuses, arrayItemTitle) {
|
|
5596
5655
|
const itemFields = renderStructuredItemFields(field, itemConfig, index, itemValue, pluginStatuses);
|
|
5597
5656
|
return `
|
|
5598
5657
|
<div class="structured-array-item rounded-lg border border-zinc-200 dark:border-white/10 bg-white/60 dark:bg-white/5 p-4 shadow-sm" data-array-index="${escapeHtml3(index)}" draggable="true">
|
|
@@ -5603,8 +5662,8 @@ function renderStructuredArrayItem(field, itemConfig, index, itemValue, pluginSt
|
|
|
5603
5662
|
<path stroke-linecap="round" stroke-linejoin="round" d="M4 8h16M4 16h16"/>
|
|
5604
5663
|
</svg>
|
|
5605
5664
|
</div>
|
|
5606
|
-
<div class="text-sm font-semibold text-zinc-900 dark:text-white">
|
|
5607
|
-
|
|
5665
|
+
<div class="text-sm font-semibold text-zinc-900 dark:text-white cursor-pointer" data-action="toggle-item">
|
|
5666
|
+
${escapeHtml3(arrayItemTitle)} <span class="ml-2 text-xs font-normal text-zinc-500 dark:text-zinc-400" data-array-order-label></span>
|
|
5608
5667
|
</div>
|
|
5609
5668
|
</div>
|
|
5610
5669
|
<div class="flex flex-wrap gap-2 text-xs">
|
|
@@ -5960,8 +6019,15 @@ function getStructuredFieldScript() {
|
|
|
5960
6019
|
if (!item || !list) return;
|
|
5961
6020
|
|
|
5962
6021
|
if (action === 'remove-item') {
|
|
5963
|
-
|
|
5964
|
-
|
|
6022
|
+
if (typeof requestRepeaterDelete === 'function') {
|
|
6023
|
+
requestRepeaterDelete(() => {
|
|
6024
|
+
item.remove();
|
|
6025
|
+
updateHiddenInput();
|
|
6026
|
+
});
|
|
6027
|
+
} else {
|
|
6028
|
+
item.remove();
|
|
6029
|
+
updateHiddenInput();
|
|
6030
|
+
}
|
|
5965
6031
|
return;
|
|
5966
6032
|
}
|
|
5967
6033
|
|
|
@@ -6152,8 +6218,15 @@ function getBlocksFieldScript() {
|
|
|
6152
6218
|
if (!item || !list) return;
|
|
6153
6219
|
|
|
6154
6220
|
if (action === 'remove-block') {
|
|
6155
|
-
|
|
6156
|
-
|
|
6221
|
+
if (typeof requestRepeaterDelete === 'function') {
|
|
6222
|
+
requestRepeaterDelete(() => {
|
|
6223
|
+
item.remove();
|
|
6224
|
+
updateHiddenInput();
|
|
6225
|
+
}, 'block');
|
|
6226
|
+
} else {
|
|
6227
|
+
item.remove();
|
|
6228
|
+
updateHiddenInput();
|
|
6229
|
+
}
|
|
6157
6230
|
return;
|
|
6158
6231
|
}
|
|
6159
6232
|
|
|
@@ -6562,6 +6635,28 @@ function renderContentFormPage(data) {
|
|
|
6562
6635
|
onConfirm: `performDeleteContent('${data.id}')`
|
|
6563
6636
|
})}
|
|
6564
6637
|
|
|
6638
|
+
${chunkLTKV7AE5_cjs.renderConfirmationDialog({
|
|
6639
|
+
id: "delete-repeater-item-confirm",
|
|
6640
|
+
title: "Delete Item",
|
|
6641
|
+
message: "Are you sure you want to delete this item? This action cannot be undone.",
|
|
6642
|
+
confirmText: "Delete",
|
|
6643
|
+
cancelText: "Cancel",
|
|
6644
|
+
iconColor: "red",
|
|
6645
|
+
confirmClass: "bg-red-500 hover:bg-red-400",
|
|
6646
|
+
onConfirm: "performRepeaterDelete()"
|
|
6647
|
+
})}
|
|
6648
|
+
|
|
6649
|
+
${chunkLTKV7AE5_cjs.renderConfirmationDialog({
|
|
6650
|
+
id: "delete-block-confirm",
|
|
6651
|
+
title: "Delete Block",
|
|
6652
|
+
message: "Are you sure you want to delete this block? This action cannot be undone.",
|
|
6653
|
+
confirmText: "Delete",
|
|
6654
|
+
cancelText: "Cancel",
|
|
6655
|
+
iconColor: "red",
|
|
6656
|
+
confirmClass: "bg-red-500 hover:bg-red-400",
|
|
6657
|
+
onConfirm: "performRepeaterDelete()"
|
|
6658
|
+
})}
|
|
6659
|
+
|
|
6565
6660
|
${chunkLTKV7AE5_cjs.getConfirmationDialogScript()}
|
|
6566
6661
|
|
|
6567
6662
|
${data.tinymceEnabled ? getTinyMCEScript(data.tinymceSettings?.apiKey) : "<!-- TinyMCE plugin not active -->"}
|
|
@@ -7118,6 +7213,29 @@ function renderContentFormPage(data) {
|
|
|
7118
7213
|
});
|
|
7119
7214
|
}
|
|
7120
7215
|
|
|
7216
|
+
// Repeater/blocks delete confirmation
|
|
7217
|
+
let pendingRepeaterDelete = null;
|
|
7218
|
+
function requestRepeaterDelete(callback, type = 'item') {
|
|
7219
|
+
pendingRepeaterDelete = callback;
|
|
7220
|
+
if (typeof showConfirmDialog === 'function') {
|
|
7221
|
+
showConfirmDialog(type === 'block' ? 'delete-block-confirm' : 'delete-repeater-item-confirm');
|
|
7222
|
+
return;
|
|
7223
|
+
}
|
|
7224
|
+
if (confirm('Remove this item? This action cannot be undone.')) {
|
|
7225
|
+
if (typeof pendingRepeaterDelete === 'function') {
|
|
7226
|
+
pendingRepeaterDelete();
|
|
7227
|
+
}
|
|
7228
|
+
}
|
|
7229
|
+
pendingRepeaterDelete = null;
|
|
7230
|
+
}
|
|
7231
|
+
|
|
7232
|
+
function performRepeaterDelete() {
|
|
7233
|
+
if (typeof pendingRepeaterDelete === 'function') {
|
|
7234
|
+
pendingRepeaterDelete();
|
|
7235
|
+
}
|
|
7236
|
+
pendingRepeaterDelete = null;
|
|
7237
|
+
}
|
|
7238
|
+
|
|
7121
7239
|
function showVersionHistory(contentId) {
|
|
7122
7240
|
// Create and show version history modal
|
|
7123
7241
|
const modal = document.createElement('div');
|
|
@@ -8130,9 +8248,9 @@ function parseFieldValue(field, formData, options = {}) {
|
|
|
8130
8248
|
const { skipValidation = false } = options;
|
|
8131
8249
|
const value = formData.get(field.field_name);
|
|
8132
8250
|
const errors = [];
|
|
8133
|
-
const blocksConfig =
|
|
8251
|
+
const blocksConfig = chunkJDIM5AG7_cjs.getBlocksFieldConfig(field.field_options);
|
|
8134
8252
|
if (blocksConfig) {
|
|
8135
|
-
const parsed =
|
|
8253
|
+
const parsed = chunkJDIM5AG7_cjs.parseBlocksValue(value, blocksConfig);
|
|
8136
8254
|
if (!skipValidation && field.is_required && parsed.value.length === 0) {
|
|
8137
8255
|
parsed.errors.push(`${field.field_label} is required`);
|
|
8138
8256
|
}
|
|
@@ -8242,7 +8360,7 @@ function extractFieldData(fields, formData, options = {}) {
|
|
|
8242
8360
|
}
|
|
8243
8361
|
return { data, errors };
|
|
8244
8362
|
}
|
|
8245
|
-
adminContentRoutes.use("*",
|
|
8363
|
+
adminContentRoutes.use("*", chunkK4Q4SFJJ_cjs.requireAuth());
|
|
8246
8364
|
async function getCollectionFields(db, collectionId) {
|
|
8247
8365
|
const cache = chunkVNLR35GO_cjs.getCacheService(chunkVNLR35GO_cjs.CACHE_CONFIGS.collection);
|
|
8248
8366
|
return cache.getOrSet(
|
|
@@ -8938,7 +9056,7 @@ adminContentRoutes.put("/:id", async (c) => {
|
|
|
8938
9056
|
`);
|
|
8939
9057
|
}
|
|
8940
9058
|
});
|
|
8941
|
-
adminContentRoutes.post("/preview",
|
|
9059
|
+
adminContentRoutes.post("/preview", chunkK4Q4SFJJ_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
8942
9060
|
try {
|
|
8943
9061
|
const formData = await c.req.formData();
|
|
8944
9062
|
const collectionId = formData.get("collection_id");
|
|
@@ -9316,7 +9434,7 @@ adminContentRoutes.post("/:id/restore/:version", async (c) => {
|
|
|
9316
9434
|
return c.json({ success: false, error: "Failed to restore version" });
|
|
9317
9435
|
}
|
|
9318
9436
|
});
|
|
9319
|
-
adminContentRoutes.get("/:id/version/:version/preview",
|
|
9437
|
+
adminContentRoutes.get("/:id/version/:version/preview", chunkK4Q4SFJJ_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
9320
9438
|
try {
|
|
9321
9439
|
const id = c.req.param("id");
|
|
9322
9440
|
const version = parseInt(c.req.param("version") || "0");
|
|
@@ -11283,7 +11401,7 @@ function renderUsersListPage(data) {
|
|
|
11283
11401
|
|
|
11284
11402
|
// src/routes/admin-users.ts
|
|
11285
11403
|
var userRoutes = new hono.Hono();
|
|
11286
|
-
userRoutes.use("*",
|
|
11404
|
+
userRoutes.use("*", chunkK4Q4SFJJ_cjs.requireAuth());
|
|
11287
11405
|
userRoutes.get("/", (c) => {
|
|
11288
11406
|
return c.redirect("/admin/dashboard");
|
|
11289
11407
|
});
|
|
@@ -11438,7 +11556,7 @@ userRoutes.put("/profile", async (c) => {
|
|
|
11438
11556
|
Date.now(),
|
|
11439
11557
|
user.userId
|
|
11440
11558
|
).run();
|
|
11441
|
-
await
|
|
11559
|
+
await chunkK4Q4SFJJ_cjs.logActivity(
|
|
11442
11560
|
db,
|
|
11443
11561
|
user.userId,
|
|
11444
11562
|
"profile.update",
|
|
@@ -11501,7 +11619,7 @@ userRoutes.post("/profile/avatar", async (c) => {
|
|
|
11501
11619
|
SELECT first_name, last_name FROM users WHERE id = ?
|
|
11502
11620
|
`);
|
|
11503
11621
|
const userData = await userStmt.bind(user.userId).first();
|
|
11504
|
-
await
|
|
11622
|
+
await chunkK4Q4SFJJ_cjs.logActivity(
|
|
11505
11623
|
db,
|
|
11506
11624
|
user.userId,
|
|
11507
11625
|
"profile.avatar_update",
|
|
@@ -11572,7 +11690,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
11572
11690
|
dismissible: true
|
|
11573
11691
|
}));
|
|
11574
11692
|
}
|
|
11575
|
-
const validPassword = await
|
|
11693
|
+
const validPassword = await chunkK4Q4SFJJ_cjs.AuthManager.verifyPassword(currentPassword, userData.password_hash);
|
|
11576
11694
|
if (!validPassword) {
|
|
11577
11695
|
return c.html(renderAlert2({
|
|
11578
11696
|
type: "error",
|
|
@@ -11580,7 +11698,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
11580
11698
|
dismissible: true
|
|
11581
11699
|
}));
|
|
11582
11700
|
}
|
|
11583
|
-
const newPasswordHash = await
|
|
11701
|
+
const newPasswordHash = await chunkK4Q4SFJJ_cjs.AuthManager.hashPassword(newPassword);
|
|
11584
11702
|
const historyStmt = db.prepare(`
|
|
11585
11703
|
INSERT INTO password_history (id, user_id, password_hash, created_at)
|
|
11586
11704
|
VALUES (?, ?, ?, ?)
|
|
@@ -11596,7 +11714,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
11596
11714
|
WHERE id = ?
|
|
11597
11715
|
`);
|
|
11598
11716
|
await updateStmt.bind(newPasswordHash, Date.now(), user.userId).run();
|
|
11599
|
-
await
|
|
11717
|
+
await chunkK4Q4SFJJ_cjs.logActivity(
|
|
11600
11718
|
db,
|
|
11601
11719
|
user.userId,
|
|
11602
11720
|
"profile.password_change",
|
|
@@ -11663,7 +11781,7 @@ userRoutes.get("/users", async (c) => {
|
|
|
11663
11781
|
`);
|
|
11664
11782
|
const countResult = await countStmt.bind(...params).first();
|
|
11665
11783
|
const totalUsers = countResult?.total || 0;
|
|
11666
|
-
await
|
|
11784
|
+
await chunkK4Q4SFJJ_cjs.logActivity(
|
|
11667
11785
|
db,
|
|
11668
11786
|
user.userId,
|
|
11669
11787
|
"users.list_view",
|
|
@@ -11817,7 +11935,7 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
11817
11935
|
dismissible: true
|
|
11818
11936
|
}));
|
|
11819
11937
|
}
|
|
11820
|
-
const passwordHash = await
|
|
11938
|
+
const passwordHash = await chunkK4Q4SFJJ_cjs.AuthManager.hashPassword(password);
|
|
11821
11939
|
const userId = crypto.randomUUID();
|
|
11822
11940
|
const createStmt = db.prepare(`
|
|
11823
11941
|
INSERT INTO users (
|
|
@@ -11840,7 +11958,7 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
11840
11958
|
Date.now(),
|
|
11841
11959
|
Date.now()
|
|
11842
11960
|
).run();
|
|
11843
|
-
await
|
|
11961
|
+
await chunkK4Q4SFJJ_cjs.logActivity(
|
|
11844
11962
|
db,
|
|
11845
11963
|
user.userId,
|
|
11846
11964
|
"user!.create",
|
|
@@ -11878,7 +11996,7 @@ userRoutes.get("/users/:id", async (c) => {
|
|
|
11878
11996
|
if (!userRecord) {
|
|
11879
11997
|
return c.json({ error: "User not found" }, 404);
|
|
11880
11998
|
}
|
|
11881
|
-
await
|
|
11999
|
+
await chunkK4Q4SFJJ_cjs.logActivity(
|
|
11882
12000
|
db,
|
|
11883
12001
|
user.userId,
|
|
11884
12002
|
"user!.view",
|
|
@@ -12103,7 +12221,7 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
12103
12221
|
).run();
|
|
12104
12222
|
}
|
|
12105
12223
|
}
|
|
12106
|
-
await
|
|
12224
|
+
await chunkK4Q4SFJJ_cjs.logActivity(
|
|
12107
12225
|
db,
|
|
12108
12226
|
user.userId,
|
|
12109
12227
|
"user.update",
|
|
@@ -12148,7 +12266,7 @@ userRoutes.post("/users/:id/toggle", async (c) => {
|
|
|
12148
12266
|
UPDATE users SET is_active = ?, updated_at = ? WHERE id = ?
|
|
12149
12267
|
`);
|
|
12150
12268
|
await toggleStmt.bind(active ? 1 : 0, Date.now(), userId).run();
|
|
12151
|
-
await
|
|
12269
|
+
await chunkK4Q4SFJJ_cjs.logActivity(
|
|
12152
12270
|
db,
|
|
12153
12271
|
user.userId,
|
|
12154
12272
|
active ? "user.activate" : "user.deactivate",
|
|
@@ -12189,7 +12307,7 @@ userRoutes.delete("/users/:id", async (c) => {
|
|
|
12189
12307
|
DELETE FROM users WHERE id = ?
|
|
12190
12308
|
`);
|
|
12191
12309
|
await deleteStmt.bind(userId).run();
|
|
12192
|
-
await
|
|
12310
|
+
await chunkK4Q4SFJJ_cjs.logActivity(
|
|
12193
12311
|
db,
|
|
12194
12312
|
user.userId,
|
|
12195
12313
|
"user!.hard_delete",
|
|
@@ -12208,7 +12326,7 @@ userRoutes.delete("/users/:id", async (c) => {
|
|
|
12208
12326
|
UPDATE users SET is_active = 0, updated_at = ? WHERE id = ?
|
|
12209
12327
|
`);
|
|
12210
12328
|
await deleteStmt.bind(Date.now(), userId).run();
|
|
12211
|
-
await
|
|
12329
|
+
await chunkK4Q4SFJJ_cjs.logActivity(
|
|
12212
12330
|
db,
|
|
12213
12331
|
user.userId,
|
|
12214
12332
|
"user!.soft_delete",
|
|
@@ -12274,7 +12392,7 @@ userRoutes.post("/invite-user", async (c) => {
|
|
|
12274
12392
|
Date.now(),
|
|
12275
12393
|
Date.now()
|
|
12276
12394
|
).run();
|
|
12277
|
-
await
|
|
12395
|
+
await chunkK4Q4SFJJ_cjs.logActivity(
|
|
12278
12396
|
db,
|
|
12279
12397
|
user.userId,
|
|
12280
12398
|
"user!.invite_sent",
|
|
@@ -12331,7 +12449,7 @@ userRoutes.post("/resend-invitation/:id", async (c) => {
|
|
|
12331
12449
|
Date.now(),
|
|
12332
12450
|
userId
|
|
12333
12451
|
).run();
|
|
12334
|
-
await
|
|
12452
|
+
await chunkK4Q4SFJJ_cjs.logActivity(
|
|
12335
12453
|
db,
|
|
12336
12454
|
user.userId,
|
|
12337
12455
|
"user!.invitation_resent",
|
|
@@ -12367,7 +12485,7 @@ userRoutes.delete("/cancel-invitation/:id", async (c) => {
|
|
|
12367
12485
|
}
|
|
12368
12486
|
const deleteStmt = db.prepare(`DELETE FROM users WHERE id = ?`);
|
|
12369
12487
|
await deleteStmt.bind(userId).run();
|
|
12370
|
-
await
|
|
12488
|
+
await chunkK4Q4SFJJ_cjs.logActivity(
|
|
12371
12489
|
db,
|
|
12372
12490
|
user.userId,
|
|
12373
12491
|
"user!.invitation_cancelled",
|
|
@@ -12450,7 +12568,7 @@ userRoutes.get("/activity-logs", async (c) => {
|
|
|
12450
12568
|
...log,
|
|
12451
12569
|
details: log.details ? JSON.parse(log.details) : null
|
|
12452
12570
|
}));
|
|
12453
|
-
await
|
|
12571
|
+
await chunkK4Q4SFJJ_cjs.logActivity(
|
|
12454
12572
|
db,
|
|
12455
12573
|
user.userId,
|
|
12456
12574
|
"activity.logs_viewed",
|
|
@@ -12557,7 +12675,7 @@ userRoutes.get("/activity-logs/export", async (c) => {
|
|
|
12557
12675
|
csvRows.push(row.join(","));
|
|
12558
12676
|
}
|
|
12559
12677
|
const csvContent = csvRows.join("\n");
|
|
12560
|
-
await
|
|
12678
|
+
await chunkK4Q4SFJJ_cjs.logActivity(
|
|
12561
12679
|
db,
|
|
12562
12680
|
user.userId,
|
|
12563
12681
|
"activity.logs_exported",
|
|
@@ -13896,7 +14014,7 @@ var fileValidationSchema2 = zod.z.object({
|
|
|
13896
14014
|
// 50MB max
|
|
13897
14015
|
});
|
|
13898
14016
|
var adminMediaRoutes = new hono.Hono();
|
|
13899
|
-
adminMediaRoutes.use("*",
|
|
14017
|
+
adminMediaRoutes.use("*", chunkK4Q4SFJJ_cjs.requireAuth());
|
|
13900
14018
|
adminMediaRoutes.get("/", async (c) => {
|
|
13901
14019
|
try {
|
|
13902
14020
|
const user = c.get("user");
|
|
@@ -14482,7 +14600,7 @@ adminMediaRoutes.put("/:id", async (c) => {
|
|
|
14482
14600
|
`);
|
|
14483
14601
|
}
|
|
14484
14602
|
});
|
|
14485
|
-
adminMediaRoutes.delete("/cleanup",
|
|
14603
|
+
adminMediaRoutes.delete("/cleanup", chunkK4Q4SFJJ_cjs.requireRole("admin"), async (c) => {
|
|
14486
14604
|
try {
|
|
14487
14605
|
const db = c.env.DB;
|
|
14488
14606
|
const allMediaStmt = db.prepare("SELECT id, r2_key, filename FROM media WHERE deleted_at IS NULL");
|
|
@@ -16705,7 +16823,7 @@ function renderEmailSettingsContent(plugin, settings) {
|
|
|
16705
16823
|
|
|
16706
16824
|
// src/routes/admin-plugins.ts
|
|
16707
16825
|
var adminPluginRoutes = new hono.Hono();
|
|
16708
|
-
adminPluginRoutes.use("*",
|
|
16826
|
+
adminPluginRoutes.use("*", chunkK4Q4SFJJ_cjs.requireAuth());
|
|
16709
16827
|
var AVAILABLE_PLUGINS = [
|
|
16710
16828
|
{
|
|
16711
16829
|
id: "third-party-faq",
|
|
@@ -18110,7 +18228,7 @@ function renderLogConfigPage(data) {
|
|
|
18110
18228
|
|
|
18111
18229
|
// src/routes/admin-logs.ts
|
|
18112
18230
|
var adminLogsRoutes = new hono.Hono();
|
|
18113
|
-
adminLogsRoutes.use("*",
|
|
18231
|
+
adminLogsRoutes.use("*", chunkK4Q4SFJJ_cjs.requireAuth());
|
|
18114
18232
|
adminLogsRoutes.get("/", async (c) => {
|
|
18115
18233
|
try {
|
|
18116
18234
|
const user = c.get("user");
|
|
@@ -20438,9 +20556,9 @@ function renderStorageUsage(databaseSizeBytes, mediaSizeBytes) {
|
|
|
20438
20556
|
}
|
|
20439
20557
|
|
|
20440
20558
|
// src/routes/admin-dashboard.ts
|
|
20441
|
-
var VERSION =
|
|
20559
|
+
var VERSION = chunkJDIM5AG7_cjs.getCoreVersion();
|
|
20442
20560
|
var router = new hono.Hono();
|
|
20443
|
-
router.use("*",
|
|
20561
|
+
router.use("*", chunkK4Q4SFJJ_cjs.requireAuth());
|
|
20444
20562
|
router.get("/", async (c) => {
|
|
20445
20563
|
const user = c.get("user");
|
|
20446
20564
|
try {
|
|
@@ -21648,6 +21766,7 @@ function renderCollectionFormPage(data) {
|
|
|
21648
21766
|
<option value="number">Number</option>
|
|
21649
21767
|
<option value="boolean">Boolean</option>
|
|
21650
21768
|
<option value="date">Date</option>
|
|
21769
|
+
<option value="radio">Radio</option>
|
|
21651
21770
|
<option value="select">Select</option>
|
|
21652
21771
|
<option value="media">Media</option>
|
|
21653
21772
|
<option value="reference">Reference</option>
|
|
@@ -21975,7 +22094,7 @@ function renderCollectionFormPage(data) {
|
|
|
21975
22094
|
|
|
21976
22095
|
console.log('[Edit Field] Showing options for field type:', fieldType, '(original:', field.field_type, ')');
|
|
21977
22096
|
|
|
21978
|
-
if (['select', 'media', 'richtext', 'reference'].includes(fieldType)) {
|
|
22097
|
+
if (['select', 'radio', 'media', 'richtext', 'reference'].includes(fieldType)) {
|
|
21979
22098
|
optionsContainer.classList.remove('hidden');
|
|
21980
22099
|
|
|
21981
22100
|
// Set help text based on type
|
|
@@ -21983,6 +22102,9 @@ function renderCollectionFormPage(data) {
|
|
|
21983
22102
|
case 'select':
|
|
21984
22103
|
helpText.textContent = 'Create a dropdown select field with custom options';
|
|
21985
22104
|
break;
|
|
22105
|
+
case 'radio':
|
|
22106
|
+
helpText.textContent = 'Single selection from a list of radio options';
|
|
22107
|
+
break;
|
|
21986
22108
|
case 'media':
|
|
21987
22109
|
helpText.textContent = 'Upload and manage media files (images, videos, documents)';
|
|
21988
22110
|
break;
|
|
@@ -22129,7 +22251,7 @@ function renderCollectionFormPage(data) {
|
|
|
22129
22251
|
const fieldNameInput = document.getElementById('modal-field-name');
|
|
22130
22252
|
|
|
22131
22253
|
// Show/hide options based on field type
|
|
22132
|
-
if (['select', 'media', 'richtext', 'guid', 'reference'].includes(this.value)) {
|
|
22254
|
+
if (['select', 'radio', 'media', 'richtext', 'guid', 'reference'].includes(this.value)) {
|
|
22133
22255
|
optionsContainer.classList.remove('hidden');
|
|
22134
22256
|
|
|
22135
22257
|
// Set default options and help text based on type
|
|
@@ -22138,6 +22260,10 @@ function renderCollectionFormPage(data) {
|
|
|
22138
22260
|
fieldOptions.value = '{"options": ["Option 1", "Option 2"], "multiple": false}';
|
|
22139
22261
|
helpText.textContent = 'Create a dropdown select field with custom options';
|
|
22140
22262
|
break;
|
|
22263
|
+
case 'radio':
|
|
22264
|
+
fieldOptions.value = '{"enum": ["Option 1", "Option 2"], "enumLabels": ["Option 1", "Option 2"], "default": "Option 1", "inline": false}';
|
|
22265
|
+
helpText.textContent = 'Single selection from a list of radio options';
|
|
22266
|
+
break;
|
|
22141
22267
|
case 'media':
|
|
22142
22268
|
fieldOptions.value = '{"accept": "image/*", "maxSize": "10MB"}';
|
|
22143
22269
|
helpText.textContent = 'Upload and manage media files (images, videos, documents)';
|
|
@@ -22220,7 +22346,7 @@ function renderCollectionFormPage(data) {
|
|
|
22220
22346
|
|
|
22221
22347
|
// src/routes/admin-collections.ts
|
|
22222
22348
|
var adminCollectionsRoutes = new hono.Hono();
|
|
22223
|
-
adminCollectionsRoutes.use("*",
|
|
22349
|
+
adminCollectionsRoutes.use("*", chunkK4Q4SFJJ_cjs.requireAuth());
|
|
22224
22350
|
adminCollectionsRoutes.get("/", async (c) => {
|
|
22225
22351
|
try {
|
|
22226
22352
|
const user = c.get("user");
|
|
@@ -22712,6 +22838,11 @@ adminCollectionsRoutes.post("/:id/fields", async (c) => {
|
|
|
22712
22838
|
fieldConfig.format = "date-time";
|
|
22713
22839
|
} else if (fieldType === "select") {
|
|
22714
22840
|
fieldConfig.enum = parsedOptions.options || [];
|
|
22841
|
+
} else if (fieldType === "radio") {
|
|
22842
|
+
fieldConfig.type = "radio";
|
|
22843
|
+
if (!parsedOptions.enum && parsedOptions.options) {
|
|
22844
|
+
fieldConfig.enum = parsedOptions.options;
|
|
22845
|
+
}
|
|
22715
22846
|
} else if (fieldType === "media") {
|
|
22716
22847
|
fieldConfig.format = "media";
|
|
22717
22848
|
} else if (fieldType === "slug") {
|
|
@@ -22721,6 +22852,12 @@ adminCollectionsRoutes.post("/:id/fields", async (c) => {
|
|
|
22721
22852
|
fieldConfig.type = "quill";
|
|
22722
22853
|
} else if (fieldType === "mdxeditor") {
|
|
22723
22854
|
fieldConfig.type = "mdxeditor";
|
|
22855
|
+
} else if (fieldType === "tinymce") {
|
|
22856
|
+
fieldConfig.type = "tinymce";
|
|
22857
|
+
} else if (fieldType === "easymde") {
|
|
22858
|
+
fieldConfig.type = "easymde";
|
|
22859
|
+
} else if (fieldType === "markdown") {
|
|
22860
|
+
fieldConfig.type = "markdown";
|
|
22724
22861
|
} else if (fieldType === "reference") {
|
|
22725
22862
|
fieldConfig.type = "reference";
|
|
22726
22863
|
}
|
|
@@ -24409,7 +24546,7 @@ function renderDatabaseToolsSettings(settings) {
|
|
|
24409
24546
|
|
|
24410
24547
|
// src/routes/admin-settings.ts
|
|
24411
24548
|
var adminSettingsRoutes = new hono.Hono();
|
|
24412
|
-
adminSettingsRoutes.use("*",
|
|
24549
|
+
adminSettingsRoutes.use("*", chunkK4Q4SFJJ_cjs.requireAuth());
|
|
24413
24550
|
function getMockSettings(user) {
|
|
24414
24551
|
return {
|
|
24415
24552
|
general: {
|
|
@@ -24577,7 +24714,7 @@ adminSettingsRoutes.get("/database-tools", (c) => {
|
|
|
24577
24714
|
adminSettingsRoutes.get("/api/migrations/status", async (c) => {
|
|
24578
24715
|
try {
|
|
24579
24716
|
const db = c.env.DB;
|
|
24580
|
-
const migrationService = new
|
|
24717
|
+
const migrationService = new chunkHXHVU5GM_cjs.MigrationService(db);
|
|
24581
24718
|
const status = await migrationService.getMigrationStatus();
|
|
24582
24719
|
return c.json({
|
|
24583
24720
|
success: true,
|
|
@@ -24601,7 +24738,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
|
|
|
24601
24738
|
}, 403);
|
|
24602
24739
|
}
|
|
24603
24740
|
const db = c.env.DB;
|
|
24604
|
-
const migrationService = new
|
|
24741
|
+
const migrationService = new chunkHXHVU5GM_cjs.MigrationService(db);
|
|
24605
24742
|
const result = await migrationService.runPendingMigrations();
|
|
24606
24743
|
return c.json({
|
|
24607
24744
|
success: result.success,
|
|
@@ -24619,7 +24756,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
|
|
|
24619
24756
|
adminSettingsRoutes.get("/api/migrations/validate", async (c) => {
|
|
24620
24757
|
try {
|
|
24621
24758
|
const db = c.env.DB;
|
|
24622
|
-
const migrationService = new
|
|
24759
|
+
const migrationService = new chunkHXHVU5GM_cjs.MigrationService(db);
|
|
24623
24760
|
const validation = await migrationService.validateSchema();
|
|
24624
24761
|
return c.json({
|
|
24625
24762
|
success: true,
|
|
@@ -26509,7 +26646,7 @@ function renderFormCreatePage(data) {
|
|
|
26509
26646
|
|
|
26510
26647
|
// src/routes/admin-forms.ts
|
|
26511
26648
|
var adminFormsRoutes = new hono.Hono();
|
|
26512
|
-
adminFormsRoutes.use("*",
|
|
26649
|
+
adminFormsRoutes.use("*", chunkK4Q4SFJJ_cjs.requireAuth());
|
|
26513
26650
|
adminFormsRoutes.get("/", async (c) => {
|
|
26514
26651
|
try {
|
|
26515
26652
|
const user = c.get("user");
|
|
@@ -27656,9 +27793,9 @@ function renderAPIReferencePage(data) {
|
|
|
27656
27793
|
}
|
|
27657
27794
|
|
|
27658
27795
|
// src/routes/admin-api-reference.ts
|
|
27659
|
-
var VERSION2 =
|
|
27796
|
+
var VERSION2 = chunkJDIM5AG7_cjs.getCoreVersion();
|
|
27660
27797
|
var router2 = new hono.Hono();
|
|
27661
|
-
router2.use("*",
|
|
27798
|
+
router2.use("*", chunkK4Q4SFJJ_cjs.requireAuth());
|
|
27662
27799
|
var apiEndpoints = [
|
|
27663
27800
|
// Auth endpoints
|
|
27664
27801
|
{
|
|
@@ -27939,5 +28076,5 @@ exports.router = router;
|
|
|
27939
28076
|
exports.router2 = router2;
|
|
27940
28077
|
exports.test_cleanup_default = test_cleanup_default;
|
|
27941
28078
|
exports.userRoutes = userRoutes;
|
|
27942
|
-
//# sourceMappingURL=chunk-
|
|
27943
|
-
//# sourceMappingURL=chunk-
|
|
28079
|
+
//# sourceMappingURL=chunk-R4WR3VTN.cjs.map
|
|
28080
|
+
//# sourceMappingURL=chunk-R4WR3VTN.cjs.map
|