@sonicjs-cms/core 2.18.0 → 2.19.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-GH3HYA7D.js → chunk-4NPCDK6B.js} +33 -6
- package/dist/chunk-4NPCDK6B.js.map +1 -0
- package/dist/{chunk-3XP76LM7.cjs → chunk-7A4CB7T3.cjs} +36 -9
- package/dist/chunk-7A4CB7T3.cjs.map +1 -0
- package/dist/{chunk-NDS4S4AG.js → chunk-BU7SFHGP.js} +4 -4
- package/dist/{chunk-NDS4S4AG.js.map → chunk-BU7SFHGP.js.map} +1 -1
- package/dist/{chunk-56PLLVDG.cjs → chunk-E4YFJBM2.cjs} +2 -2
- package/dist/{chunk-56PLLVDG.cjs.map → chunk-E4YFJBM2.cjs.map} +1 -1
- package/dist/{chunk-YK5IEGQZ.js → chunk-JZV22DEV.js} +2 -2
- package/dist/{chunk-YK5IEGQZ.js.map → chunk-JZV22DEV.js.map} +1 -1
- package/dist/{chunk-74BFRAQS.cjs → chunk-JZVHLLSI.cjs} +4 -4
- package/dist/{chunk-74BFRAQS.cjs.map → chunk-JZVHLLSI.cjs.map} +1 -1
- package/dist/{chunk-RYRNZYND.js → chunk-OCL3HMEG.js} +207 -17
- package/dist/chunk-OCL3HMEG.js.map +1 -0
- package/dist/{chunk-LTJ7P7RT.cjs → chunk-R4FOLLFB.cjs} +321 -130
- package/dist/chunk-R4FOLLFB.cjs.map +1 -0
- package/dist/{chunk-DAESIIWY.cjs → chunk-RLMUFFUD.cjs} +2 -2
- package/dist/{chunk-DAESIIWY.cjs.map → chunk-RLMUFFUD.cjs.map} +1 -1
- package/dist/{chunk-OWJPOVFW.js → chunk-ZYAYUIZE.js} +2 -2
- package/dist/{chunk-OWJPOVFW.js.map → chunk-ZYAYUIZE.js.map} +1 -1
- package/dist/index.cjs +155 -145
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +24 -14
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +32 -32
- package/dist/middleware.d.cts +19 -0
- package/dist/middleware.d.ts +19 -0
- package/dist/middleware.js +3 -3
- package/dist/migrations-566IIPS2.cjs +13 -0
- package/dist/{migrations-CW2IT5YP.cjs.map → migrations-566IIPS2.cjs.map} +1 -1
- package/dist/migrations-H5IXZNCO.js +4 -0
- package/dist/{migrations-S42BOXI4.js.map → migrations-H5IXZNCO.js.map} +1 -1
- package/dist/routes.cjs +28 -28
- package/dist/routes.js +5 -5
- package/dist/services.cjs +23 -23
- package/dist/services.js +2 -2
- package/dist/utils.cjs +11 -11
- package/dist/utils.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-3XP76LM7.cjs.map +0 -1
- package/dist/chunk-GH3HYA7D.js.map +0 -1
- package/dist/chunk-LTJ7P7RT.cjs.map +0 -1
- package/dist/chunk-RYRNZYND.js.map +0 -1
- package/dist/migrations-CW2IT5YP.cjs +0 -13
- package/dist/migrations-S42BOXI4.js +0 -4
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunkWAEQXGCX_cjs = require('./chunk-WAEQXGCX.cjs');
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
4
|
+
var chunk7A4CB7T3_cjs = require('./chunk-7A4CB7T3.cjs');
|
|
5
|
+
var chunkE4YFJBM2_cjs = require('./chunk-E4YFJBM2.cjs');
|
|
6
|
+
var chunkRLMUFFUD_cjs = require('./chunk-RLMUFFUD.cjs');
|
|
7
7
|
var chunkOHYBNCVL_cjs = require('./chunk-OHYBNCVL.cjs');
|
|
8
8
|
var chunkUYJ6TJHX_cjs = require('./chunk-UYJ6TJHX.cjs');
|
|
9
9
|
var chunk635JAMSE_cjs = require('./chunk-635JAMSE.cjs');
|
|
10
|
-
var
|
|
10
|
+
var chunkJZVHLLSI_cjs = require('./chunk-JZVHLLSI.cjs');
|
|
11
11
|
var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
|
|
12
12
|
var chunkMNWKYY5E_cjs = require('./chunk-MNWKYY5E.cjs');
|
|
13
13
|
var hono = require('hono');
|
|
@@ -189,7 +189,7 @@ apiContentCrudRoutes.get("/:id", async (c) => {
|
|
|
189
189
|
}, 500);
|
|
190
190
|
}
|
|
191
191
|
});
|
|
192
|
-
apiContentCrudRoutes.post("/",
|
|
192
|
+
apiContentCrudRoutes.post("/", chunk7A4CB7T3_cjs.requireAuth(), chunk7A4CB7T3_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
193
193
|
try {
|
|
194
194
|
const db = c.env.DB;
|
|
195
195
|
const user = c.get("user");
|
|
@@ -255,7 +255,7 @@ apiContentCrudRoutes.post("/", chunk3XP76LM7_cjs.requireAuth(), chunk3XP76LM7_cj
|
|
|
255
255
|
}, 500);
|
|
256
256
|
}
|
|
257
257
|
});
|
|
258
|
-
apiContentCrudRoutes.put("/:id",
|
|
258
|
+
apiContentCrudRoutes.put("/:id", chunk7A4CB7T3_cjs.requireAuth(), chunk7A4CB7T3_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
259
259
|
try {
|
|
260
260
|
const id = c.req.param("id");
|
|
261
261
|
const db = c.env.DB;
|
|
@@ -319,7 +319,7 @@ apiContentCrudRoutes.put("/:id", chunk3XP76LM7_cjs.requireAuth(), chunk3XP76LM7_
|
|
|
319
319
|
}, 500);
|
|
320
320
|
}
|
|
321
321
|
});
|
|
322
|
-
apiContentCrudRoutes.delete("/:id",
|
|
322
|
+
apiContentCrudRoutes.delete("/:id", chunk7A4CB7T3_cjs.requireAuth(), chunk7A4CB7T3_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
323
323
|
try {
|
|
324
324
|
const id = c.req.param("id");
|
|
325
325
|
const db = c.env.DB;
|
|
@@ -355,7 +355,7 @@ apiRoutes.use("*", async (c, next) => {
|
|
|
355
355
|
c.header("X-Response-Time", `${totalTime}ms`);
|
|
356
356
|
});
|
|
357
357
|
apiRoutes.use("*", async (c, next) => {
|
|
358
|
-
const cacheEnabled = await
|
|
358
|
+
const cacheEnabled = await chunk7A4CB7T3_cjs.isPluginActive(c.env.DB, "core-cache");
|
|
359
359
|
c.set("cacheEnabled", cacheEnabled);
|
|
360
360
|
await next();
|
|
361
361
|
});
|
|
@@ -846,7 +846,7 @@ apiRoutes.get("/collections", async (c) => {
|
|
|
846
846
|
return c.json({ error: "Failed to fetch collections" }, 500);
|
|
847
847
|
}
|
|
848
848
|
});
|
|
849
|
-
apiRoutes.get("/content",
|
|
849
|
+
apiRoutes.get("/content", chunk7A4CB7T3_cjs.optionalAuth(), async (c) => {
|
|
850
850
|
const executionStart = Date.now();
|
|
851
851
|
try {
|
|
852
852
|
const db = c.env.DB;
|
|
@@ -869,13 +869,13 @@ apiRoutes.get("/content", chunk3XP76LM7_cjs.optionalAuth(), async (c) => {
|
|
|
869
869
|
});
|
|
870
870
|
}
|
|
871
871
|
}
|
|
872
|
-
const filter =
|
|
872
|
+
const filter = chunkJZVHLLSI_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
|
|
873
873
|
const normalizedFilter = normalizePublicContentFilter(filter, c.get("user")?.role);
|
|
874
874
|
if (!normalizedFilter.limit) {
|
|
875
875
|
normalizedFilter.limit = 50;
|
|
876
876
|
}
|
|
877
877
|
normalizedFilter.limit = Math.min(normalizedFilter.limit, 1e3);
|
|
878
|
-
const builder3 = new
|
|
878
|
+
const builder3 = new chunkJZVHLLSI_cjs.QueryFilterBuilder();
|
|
879
879
|
const queryResult = builder3.build("content", normalizedFilter);
|
|
880
880
|
if (queryResult.errors.length > 0) {
|
|
881
881
|
return c.json({
|
|
@@ -947,7 +947,7 @@ apiRoutes.get("/content", chunk3XP76LM7_cjs.optionalAuth(), async (c) => {
|
|
|
947
947
|
}, 500);
|
|
948
948
|
}
|
|
949
949
|
});
|
|
950
|
-
apiRoutes.get("/collections/:collection/content",
|
|
950
|
+
apiRoutes.get("/collections/:collection/content", chunk7A4CB7T3_cjs.optionalAuth(), async (c) => {
|
|
951
951
|
const executionStart = Date.now();
|
|
952
952
|
try {
|
|
953
953
|
const collection = c.req.param("collection");
|
|
@@ -958,7 +958,7 @@ apiRoutes.get("/collections/:collection/content", chunk3XP76LM7_cjs.optionalAuth
|
|
|
958
958
|
if (!collectionResult) {
|
|
959
959
|
return c.json({ error: "Collection not found" }, 404);
|
|
960
960
|
}
|
|
961
|
-
const filter =
|
|
961
|
+
const filter = chunkJZVHLLSI_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
|
|
962
962
|
const normalizedFilter = normalizePublicContentFilter(filter, c.get("user")?.role);
|
|
963
963
|
if (!normalizedFilter.where) {
|
|
964
964
|
normalizedFilter.where = { and: [] };
|
|
@@ -975,7 +975,7 @@ apiRoutes.get("/collections/:collection/content", chunk3XP76LM7_cjs.optionalAuth
|
|
|
975
975
|
normalizedFilter.limit = 50;
|
|
976
976
|
}
|
|
977
977
|
normalizedFilter.limit = Math.min(normalizedFilter.limit, 1e3);
|
|
978
|
-
const builder3 = new
|
|
978
|
+
const builder3 = new chunkJZVHLLSI_cjs.QueryFilterBuilder();
|
|
979
979
|
const queryResult = builder3.build("content", normalizedFilter);
|
|
980
980
|
if (queryResult.errors.length > 0) {
|
|
981
981
|
return c.json({
|
|
@@ -1096,7 +1096,7 @@ var fileValidationSchema = zod.z.object({
|
|
|
1096
1096
|
// 50MB max
|
|
1097
1097
|
});
|
|
1098
1098
|
var apiMediaRoutes = new hono.Hono();
|
|
1099
|
-
apiMediaRoutes.use("*",
|
|
1099
|
+
apiMediaRoutes.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
1100
1100
|
apiMediaRoutes.post("/upload", async (c) => {
|
|
1101
1101
|
try {
|
|
1102
1102
|
const user = c.get("user");
|
|
@@ -1840,8 +1840,8 @@ apiSystemRoutes.get("/env", (c) => {
|
|
|
1840
1840
|
});
|
|
1841
1841
|
var api_system_default = apiSystemRoutes;
|
|
1842
1842
|
var adminApiRoutes = new hono.Hono();
|
|
1843
|
-
adminApiRoutes.use("*",
|
|
1844
|
-
adminApiRoutes.use("*",
|
|
1843
|
+
adminApiRoutes.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
1844
|
+
adminApiRoutes.use("*", chunk7A4CB7T3_cjs.requireRole(["admin", "editor"]));
|
|
1845
1845
|
adminApiRoutes.get("/stats", async (c) => {
|
|
1846
1846
|
try {
|
|
1847
1847
|
const db = c.env.DB;
|
|
@@ -2353,7 +2353,7 @@ adminApiRoutes.delete("/collections/:id", async (c) => {
|
|
|
2353
2353
|
});
|
|
2354
2354
|
adminApiRoutes.get("/migrations/status", async (c) => {
|
|
2355
2355
|
try {
|
|
2356
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
2356
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-566IIPS2.cjs');
|
|
2357
2357
|
const db = c.env.DB;
|
|
2358
2358
|
const migrationService = new MigrationService2(db);
|
|
2359
2359
|
const status = await migrationService.getMigrationStatus();
|
|
@@ -2378,7 +2378,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
|
|
|
2378
2378
|
error: "Unauthorized. Admin access required."
|
|
2379
2379
|
}, 403);
|
|
2380
2380
|
}
|
|
2381
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
2381
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-566IIPS2.cjs');
|
|
2382
2382
|
const db = c.env.DB;
|
|
2383
2383
|
const migrationService = new MigrationService2(db);
|
|
2384
2384
|
const result = await migrationService.runPendingMigrations();
|
|
@@ -2400,7 +2400,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
|
|
|
2400
2400
|
});
|
|
2401
2401
|
adminApiRoutes.get("/migrations/validate", async (c) => {
|
|
2402
2402
|
try {
|
|
2403
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
2403
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-566IIPS2.cjs');
|
|
2404
2404
|
const db = c.env.DB;
|
|
2405
2405
|
const migrationService = new MigrationService2(db);
|
|
2406
2406
|
const validation = await migrationService.validateSchema();
|
|
@@ -3745,13 +3745,15 @@ function renderDynamicField(field, options = {}) {
|
|
|
3745
3745
|
break;
|
|
3746
3746
|
case "media":
|
|
3747
3747
|
const isMultiple = opts.multiple === true;
|
|
3748
|
-
const mediaValues = isMultiple && value ? Array.isArray(value) ? value : String(value).split(",").filter(Boolean) : [];
|
|
3749
|
-
const singleValue = !isMultiple ? value : "";
|
|
3748
|
+
const mediaValues = isMultiple && value ? Array.isArray(value) ? value.filter((url) => typeof url === "string" && url !== "") : String(value).split(",").filter(Boolean) : [];
|
|
3749
|
+
const singleValue = !isMultiple && typeof value === "string" ? value : "";
|
|
3750
3750
|
const isVideoUrl = (url) => {
|
|
3751
|
+
if (typeof url !== "string") return false;
|
|
3751
3752
|
const videoExtensions = [".mp4", ".webm", ".ogg", ".mov", ".avi"];
|
|
3752
3753
|
return videoExtensions.some((ext) => url.toLowerCase().endsWith(ext));
|
|
3753
3754
|
};
|
|
3754
3755
|
const renderMediaPreview = (url, alt, classes) => {
|
|
3756
|
+
if (typeof url !== "string" || url === "") return "";
|
|
3755
3757
|
if (isVideoUrl(url)) {
|
|
3756
3758
|
return `<video src="${url}" class="${classes}" muted></video>`;
|
|
3757
3759
|
}
|
|
@@ -4123,7 +4125,8 @@ function renderStructuredItemFields(field, itemConfig, index, itemValue, pluginS
|
|
|
4123
4125
|
).join("");
|
|
4124
4126
|
}
|
|
4125
4127
|
const normalizedField = normalizeBlockField(itemConfig, "Item");
|
|
4126
|
-
const
|
|
4128
|
+
const isEmptyPlainObject = itemValue !== null && typeof itemValue === "object" && !Array.isArray(itemValue) && Object.keys(itemValue).length === 0;
|
|
4129
|
+
const fieldValue = isEmptyPlainObject ? normalizedField.defaultValue ?? "" : itemValue ?? normalizedField.defaultValue ?? "";
|
|
4127
4130
|
const fieldDefinition = {
|
|
4128
4131
|
id: `array-${field.field_name}-${index}-value`,
|
|
4129
4132
|
field_name: `array-${field.field_name}-${index}-value`,
|
|
@@ -5153,8 +5156,8 @@ var JWT_SECRET_FALLBACK = "your-super-secret-jwt-key-change-in-production";
|
|
|
5153
5156
|
async function setCsrfCookie(c, maxAge) {
|
|
5154
5157
|
const secret = c.env?.JWT_SECRET || JWT_SECRET_FALLBACK;
|
|
5155
5158
|
const isDev = c.env?.ENVIRONMENT === "development" || !c.env?.ENVIRONMENT;
|
|
5156
|
-
const csrfToken = await
|
|
5157
|
-
const cookieMaxAge = await
|
|
5159
|
+
const csrfToken = await chunk7A4CB7T3_cjs.generateCsrfToken(secret);
|
|
5160
|
+
const cookieMaxAge = await chunk7A4CB7T3_cjs.getJwtExpirySecondsFromDb(c.env?.DB, c.env);
|
|
5158
5161
|
cookie.setCookie(c, "csrf_token", csrfToken, {
|
|
5159
5162
|
httpOnly: false,
|
|
5160
5163
|
secure: !isDev,
|
|
@@ -5211,7 +5214,7 @@ var loginSchema = zod.z.object({
|
|
|
5211
5214
|
});
|
|
5212
5215
|
authRoutes.post(
|
|
5213
5216
|
"/register",
|
|
5214
|
-
|
|
5217
|
+
chunk7A4CB7T3_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
|
|
5215
5218
|
async (c) => {
|
|
5216
5219
|
try {
|
|
5217
5220
|
const db = c.env.DB;
|
|
@@ -5248,7 +5251,7 @@ authRoutes.post(
|
|
|
5248
5251
|
if (existingUser) {
|
|
5249
5252
|
return c.json({ error: "User with this email or username already exists" }, 400);
|
|
5250
5253
|
}
|
|
5251
|
-
const passwordHash = await
|
|
5254
|
+
const passwordHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword(password);
|
|
5252
5255
|
const userId = crypto.randomUUID();
|
|
5253
5256
|
const now = /* @__PURE__ */ new Date();
|
|
5254
5257
|
await db.prepare(`
|
|
@@ -5282,8 +5285,8 @@ authRoutes.post(
|
|
|
5282
5285
|
await saveCustomData(db, userId, sanitized);
|
|
5283
5286
|
}
|
|
5284
5287
|
}
|
|
5285
|
-
const tokenTtl = await
|
|
5286
|
-
const token = await
|
|
5288
|
+
const tokenTtl = await chunk7A4CB7T3_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
5289
|
+
const token = await chunk7A4CB7T3_cjs.AuthManager.generateToken(userId, normalizedEmail, "viewer", c.env.JWT_SECRET, tokenTtl);
|
|
5287
5290
|
cookie.setCookie(c, "auth_token", token, {
|
|
5288
5291
|
httpOnly: true,
|
|
5289
5292
|
secure: true,
|
|
@@ -5316,7 +5319,7 @@ authRoutes.post(
|
|
|
5316
5319
|
);
|
|
5317
5320
|
authRoutes.post(
|
|
5318
5321
|
"/login",
|
|
5319
|
-
|
|
5322
|
+
chunk7A4CB7T3_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
|
|
5320
5323
|
async (c) => {
|
|
5321
5324
|
try {
|
|
5322
5325
|
const body = await c.req.json();
|
|
@@ -5339,20 +5342,20 @@ authRoutes.post(
|
|
|
5339
5342
|
if (!user) {
|
|
5340
5343
|
return c.json({ error: "Invalid email or password" }, 401);
|
|
5341
5344
|
}
|
|
5342
|
-
const isValidPassword = await
|
|
5345
|
+
const isValidPassword = await chunk7A4CB7T3_cjs.AuthManager.verifyPassword(password, user.password_hash);
|
|
5343
5346
|
if (!isValidPassword) {
|
|
5344
5347
|
return c.json({ error: "Invalid email or password" }, 401);
|
|
5345
5348
|
}
|
|
5346
|
-
if (
|
|
5349
|
+
if (chunk7A4CB7T3_cjs.AuthManager.isLegacyHash(user.password_hash)) {
|
|
5347
5350
|
try {
|
|
5348
|
-
const newHash = await
|
|
5351
|
+
const newHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword(password);
|
|
5349
5352
|
await db.prepare("UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?").bind(newHash, Date.now(), user.id).run();
|
|
5350
5353
|
} catch (rehashError) {
|
|
5351
5354
|
console.error("Password rehash failed (non-fatal):", rehashError);
|
|
5352
5355
|
}
|
|
5353
5356
|
}
|
|
5354
|
-
const tokenTtl = await
|
|
5355
|
-
const token = await
|
|
5357
|
+
const tokenTtl = await chunk7A4CB7T3_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
5358
|
+
const token = await chunk7A4CB7T3_cjs.AuthManager.generateToken(user.id, user.email, user.role, c.env.JWT_SECRET, tokenTtl);
|
|
5356
5359
|
cookie.setCookie(c, "auth_token", token, {
|
|
5357
5360
|
httpOnly: true,
|
|
5358
5361
|
secure: true,
|
|
@@ -5404,7 +5407,7 @@ authRoutes.get("/logout", (c) => {
|
|
|
5404
5407
|
clearCsrfCookie(c);
|
|
5405
5408
|
return c.redirect("/auth/login?message=You have been logged out successfully");
|
|
5406
5409
|
});
|
|
5407
|
-
authRoutes.get("/me",
|
|
5410
|
+
authRoutes.get("/me", chunk7A4CB7T3_cjs.requireAuth(), async (c) => {
|
|
5408
5411
|
try {
|
|
5409
5412
|
const user = c.get("user");
|
|
5410
5413
|
if (!user) {
|
|
@@ -5415,7 +5418,8 @@ authRoutes.get("/me", chunk3XP76LM7_cjs.requireAuth(), async (c) => {
|
|
|
5415
5418
|
if (!userData) {
|
|
5416
5419
|
return c.json({ error: "User not found" }, 404);
|
|
5417
5420
|
}
|
|
5418
|
-
|
|
5421
|
+
const customData = await getCustomData(db, user.userId);
|
|
5422
|
+
return c.json({ user: { ...userData, ...customData } });
|
|
5419
5423
|
} catch (error) {
|
|
5420
5424
|
console.error("Get user error:", error);
|
|
5421
5425
|
return c.json({ error: "Failed to get user" }, 500);
|
|
@@ -5423,7 +5427,7 @@ authRoutes.get("/me", chunk3XP76LM7_cjs.requireAuth(), async (c) => {
|
|
|
5423
5427
|
});
|
|
5424
5428
|
authRoutes.post(
|
|
5425
5429
|
"/refresh",
|
|
5426
|
-
|
|
5430
|
+
chunk7A4CB7T3_cjs.rateLimit({ max: 60, windowMs: 60 * 1e3, keyPrefix: "refresh" }),
|
|
5427
5431
|
async (c) => {
|
|
5428
5432
|
try {
|
|
5429
5433
|
let token = c.req.header("Authorization")?.replace("Bearer ", "");
|
|
@@ -5432,8 +5436,8 @@ authRoutes.post(
|
|
|
5432
5436
|
return c.json({ error: "Authentication required" }, 401);
|
|
5433
5437
|
}
|
|
5434
5438
|
const db = c.env.DB;
|
|
5435
|
-
const grace = await
|
|
5436
|
-
const payload = await
|
|
5439
|
+
const grace = await chunk7A4CB7T3_cjs.getJwtRefreshGraceSecondsFromDb(db, c.env);
|
|
5440
|
+
const payload = await chunk7A4CB7T3_cjs.AuthManager.verifyToken(token, c.env.JWT_SECRET, grace);
|
|
5437
5441
|
if (!payload) {
|
|
5438
5442
|
return c.json({ error: "Invalid or expired token" }, 401);
|
|
5439
5443
|
}
|
|
@@ -5441,8 +5445,8 @@ authRoutes.post(
|
|
|
5441
5445
|
if (!row || !row.is_active) {
|
|
5442
5446
|
return c.json({ error: "User is not active" }, 401);
|
|
5443
5447
|
}
|
|
5444
|
-
const tokenTtl = await
|
|
5445
|
-
const newToken = await
|
|
5448
|
+
const tokenTtl = await chunk7A4CB7T3_cjs.getJwtExpirySecondsFromDb(db, c.env);
|
|
5449
|
+
const newToken = await chunk7A4CB7T3_cjs.AuthManager.generateToken(row.id, row.email, row.role, c.env.JWT_SECRET, tokenTtl);
|
|
5446
5450
|
cookie.setCookie(c, "auth_token", newToken, {
|
|
5447
5451
|
httpOnly: true,
|
|
5448
5452
|
secure: true,
|
|
@@ -5462,7 +5466,7 @@ authRoutes.post(
|
|
|
5462
5466
|
);
|
|
5463
5467
|
authRoutes.post(
|
|
5464
5468
|
"/register/form",
|
|
5465
|
-
|
|
5469
|
+
chunk7A4CB7T3_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
|
|
5466
5470
|
async (c) => {
|
|
5467
5471
|
try {
|
|
5468
5472
|
const db = c.env.DB;
|
|
@@ -5509,7 +5513,7 @@ authRoutes.post(
|
|
|
5509
5513
|
</div>
|
|
5510
5514
|
`);
|
|
5511
5515
|
}
|
|
5512
|
-
const passwordHash = await
|
|
5516
|
+
const passwordHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword(password);
|
|
5513
5517
|
const role = isFirstUser ? "admin" : "viewer";
|
|
5514
5518
|
const userId = crypto.randomUUID();
|
|
5515
5519
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -5544,8 +5548,8 @@ authRoutes.post(
|
|
|
5544
5548
|
await saveCustomData(db, userId, sanitized);
|
|
5545
5549
|
}
|
|
5546
5550
|
}
|
|
5547
|
-
const tokenTtl = await
|
|
5548
|
-
const token = await
|
|
5551
|
+
const tokenTtl = await chunk7A4CB7T3_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
5552
|
+
const token = await chunk7A4CB7T3_cjs.AuthManager.generateToken(userId, normalizedEmail, role, c.env.JWT_SECRET, tokenTtl);
|
|
5549
5553
|
cookie.setCookie(c, "auth_token", token, {
|
|
5550
5554
|
httpOnly: true,
|
|
5551
5555
|
secure: false,
|
|
@@ -5577,7 +5581,7 @@ authRoutes.post(
|
|
|
5577
5581
|
);
|
|
5578
5582
|
authRoutes.post(
|
|
5579
5583
|
"/login/form",
|
|
5580
|
-
|
|
5584
|
+
chunk7A4CB7T3_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
|
|
5581
5585
|
async (c) => {
|
|
5582
5586
|
try {
|
|
5583
5587
|
const formData = await c.req.formData();
|
|
@@ -5601,7 +5605,7 @@ authRoutes.post(
|
|
|
5601
5605
|
</div>
|
|
5602
5606
|
`);
|
|
5603
5607
|
}
|
|
5604
|
-
const isValidPassword = await
|
|
5608
|
+
const isValidPassword = await chunk7A4CB7T3_cjs.AuthManager.verifyPassword(password, user.password_hash);
|
|
5605
5609
|
if (!isValidPassword) {
|
|
5606
5610
|
return c.html(html.html`
|
|
5607
5611
|
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded">
|
|
@@ -5609,16 +5613,16 @@ authRoutes.post(
|
|
|
5609
5613
|
</div>
|
|
5610
5614
|
`);
|
|
5611
5615
|
}
|
|
5612
|
-
if (
|
|
5616
|
+
if (chunk7A4CB7T3_cjs.AuthManager.isLegacyHash(user.password_hash)) {
|
|
5613
5617
|
try {
|
|
5614
|
-
const newHash = await
|
|
5618
|
+
const newHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword(password);
|
|
5615
5619
|
await db.prepare("UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?").bind(newHash, Date.now(), user.id).run();
|
|
5616
5620
|
} catch (rehashError) {
|
|
5617
5621
|
console.error("Password rehash failed (non-fatal):", rehashError);
|
|
5618
5622
|
}
|
|
5619
5623
|
}
|
|
5620
|
-
const tokenTtl = await
|
|
5621
|
-
const token = await
|
|
5624
|
+
const tokenTtl = await chunk7A4CB7T3_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
5625
|
+
const token = await chunk7A4CB7T3_cjs.AuthManager.generateToken(user.id, user.email, user.role, c.env.JWT_SECRET, tokenTtl);
|
|
5622
5626
|
cookie.setCookie(c, "auth_token", token, {
|
|
5623
5627
|
httpOnly: true,
|
|
5624
5628
|
secure: false,
|
|
@@ -5659,7 +5663,7 @@ authRoutes.post(
|
|
|
5659
5663
|
);
|
|
5660
5664
|
authRoutes.post(
|
|
5661
5665
|
"/seed-admin",
|
|
5662
|
-
|
|
5666
|
+
chunk7A4CB7T3_cjs.rateLimit({ max: 10, windowMs: 60 * 1e3, keyPrefix: "seed-admin" }),
|
|
5663
5667
|
async (c) => {
|
|
5664
5668
|
try {
|
|
5665
5669
|
const db = c.env.DB;
|
|
@@ -5681,7 +5685,7 @@ authRoutes.post(
|
|
|
5681
5685
|
`).run();
|
|
5682
5686
|
const existingAdmin = await db.prepare("SELECT id FROM users WHERE email = ? OR username = ?").bind("admin@sonicjs.com", "admin").first();
|
|
5683
5687
|
if (existingAdmin) {
|
|
5684
|
-
const passwordHash2 = await
|
|
5688
|
+
const passwordHash2 = await chunk7A4CB7T3_cjs.AuthManager.hashPassword("sonicjs!");
|
|
5685
5689
|
await db.prepare("UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?").bind(passwordHash2, Date.now(), existingAdmin.id).run();
|
|
5686
5690
|
return c.json({
|
|
5687
5691
|
message: "Admin user already exists (password updated)",
|
|
@@ -5693,7 +5697,7 @@ authRoutes.post(
|
|
|
5693
5697
|
}
|
|
5694
5698
|
});
|
|
5695
5699
|
}
|
|
5696
|
-
const passwordHash = await
|
|
5700
|
+
const passwordHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword("sonicjs!");
|
|
5697
5701
|
const userId = "admin-user-id";
|
|
5698
5702
|
const now = Date.now();
|
|
5699
5703
|
const adminEmail = "admin@sonicjs.com".toLowerCase();
|
|
@@ -5914,7 +5918,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
5914
5918
|
if (existingUsername) {
|
|
5915
5919
|
return c.json({ error: "Username is already taken" }, 400);
|
|
5916
5920
|
}
|
|
5917
|
-
const passwordHash = await
|
|
5921
|
+
const passwordHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword(password);
|
|
5918
5922
|
const updateStmt = db.prepare(`
|
|
5919
5923
|
UPDATE users SET
|
|
5920
5924
|
username = ?,
|
|
@@ -5933,8 +5937,8 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
5933
5937
|
Date.now(),
|
|
5934
5938
|
invitedUser.id
|
|
5935
5939
|
).run();
|
|
5936
|
-
const tokenTtl = await
|
|
5937
|
-
const authToken = await
|
|
5940
|
+
const tokenTtl = await chunk7A4CB7T3_cjs.getJwtExpirySecondsFromDb(c.env.DB, c.env);
|
|
5941
|
+
const authToken = await chunk7A4CB7T3_cjs.AuthManager.generateToken(invitedUser.id, invitedUser.email, invitedUser.role, c.env.JWT_SECRET, tokenTtl);
|
|
5938
5942
|
cookie.setCookie(c, "auth_token", authToken, {
|
|
5939
5943
|
httpOnly: true,
|
|
5940
5944
|
secure: true,
|
|
@@ -5950,7 +5954,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
5950
5954
|
});
|
|
5951
5955
|
authRoutes.post(
|
|
5952
5956
|
"/request-password-reset",
|
|
5953
|
-
|
|
5957
|
+
chunk7A4CB7T3_cjs.rateLimit({ max: 3, windowMs: 15 * 60 * 1e3, keyPrefix: "password-reset" }),
|
|
5954
5958
|
async (c) => {
|
|
5955
5959
|
try {
|
|
5956
5960
|
const formData = await c.req.formData();
|
|
@@ -6168,7 +6172,7 @@ authRoutes.post("/reset-password", async (c) => {
|
|
|
6168
6172
|
if (Date.now() > user.password_reset_expires) {
|
|
6169
6173
|
return c.json({ error: "Reset token has expired" }, 400);
|
|
6170
6174
|
}
|
|
6171
|
-
const newPasswordHash = await
|
|
6175
|
+
const newPasswordHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword(password);
|
|
6172
6176
|
try {
|
|
6173
6177
|
const historyStmt = db.prepare(`
|
|
6174
6178
|
INSERT INTO password_history (id, user_id, password_hash, created_at)
|
|
@@ -9544,9 +9548,9 @@ function parseFieldValue(field, formData, options = {}) {
|
|
|
9544
9548
|
const { skipValidation = false } = options;
|
|
9545
9549
|
const value = formData.get(field.field_name);
|
|
9546
9550
|
const errors = [];
|
|
9547
|
-
const blocksConfig =
|
|
9551
|
+
const blocksConfig = chunkJZVHLLSI_cjs.getBlocksFieldConfig(field.field_options);
|
|
9548
9552
|
if (blocksConfig) {
|
|
9549
|
-
const parsed =
|
|
9553
|
+
const parsed = chunkJZVHLLSI_cjs.parseBlocksValue(value, blocksConfig);
|
|
9550
9554
|
if (!skipValidation && field.is_required && parsed.value.length === 0) {
|
|
9551
9555
|
parsed.errors.push(`${field.field_label} is required`);
|
|
9552
9556
|
}
|
|
@@ -9656,7 +9660,7 @@ function extractFieldData(fields, formData, options = {}) {
|
|
|
9656
9660
|
}
|
|
9657
9661
|
return { data, errors };
|
|
9658
9662
|
}
|
|
9659
|
-
adminContentRoutes.use("*",
|
|
9663
|
+
adminContentRoutes.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
9660
9664
|
async function getCollectionFields(db, collectionId) {
|
|
9661
9665
|
const cache = chunkWAEQXGCX_cjs.getCacheService(chunkWAEQXGCX_cjs.CACHE_CONFIGS.collection);
|
|
9662
9666
|
return cache.getOrSet(
|
|
@@ -9933,21 +9937,21 @@ adminContentRoutes.get("/new", async (c) => {
|
|
|
9933
9937
|
const tinymceEnabled = await isPluginActive2(db, "tinymce-plugin");
|
|
9934
9938
|
let tinymceSettings;
|
|
9935
9939
|
if (tinymceEnabled) {
|
|
9936
|
-
const pluginService = new
|
|
9940
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
9937
9941
|
const tinymcePlugin2 = await pluginService.getPlugin("tinymce-plugin");
|
|
9938
9942
|
tinymceSettings = tinymcePlugin2?.settings;
|
|
9939
9943
|
}
|
|
9940
9944
|
const quillEnabled = await isPluginActive2(db, "quill-editor");
|
|
9941
9945
|
let quillSettings;
|
|
9942
9946
|
if (quillEnabled) {
|
|
9943
|
-
const pluginService = new
|
|
9947
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
9944
9948
|
const quillPlugin = await pluginService.getPlugin("quill-editor");
|
|
9945
9949
|
quillSettings = quillPlugin?.settings;
|
|
9946
9950
|
}
|
|
9947
9951
|
const mdxeditorEnabled = await isPluginActive2(db, "easy-mdx");
|
|
9948
9952
|
let mdxeditorSettings;
|
|
9949
9953
|
if (mdxeditorEnabled) {
|
|
9950
|
-
const pluginService = new
|
|
9954
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
9951
9955
|
const mdxeditorPlugin = await pluginService.getPlugin("easy-mdx");
|
|
9952
9956
|
mdxeditorSettings = mdxeditorPlugin?.settings;
|
|
9953
9957
|
}
|
|
@@ -10038,21 +10042,21 @@ adminContentRoutes.get("/:id/edit", async (c) => {
|
|
|
10038
10042
|
const tinymceEnabled = await isPluginActive2(db, "tinymce-plugin");
|
|
10039
10043
|
let tinymceSettings;
|
|
10040
10044
|
if (tinymceEnabled) {
|
|
10041
|
-
const pluginService = new
|
|
10045
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
10042
10046
|
const tinymcePlugin2 = await pluginService.getPlugin("tinymce-plugin");
|
|
10043
10047
|
tinymceSettings = tinymcePlugin2?.settings;
|
|
10044
10048
|
}
|
|
10045
10049
|
const quillEnabled = await isPluginActive2(db, "quill-editor");
|
|
10046
10050
|
let quillSettings;
|
|
10047
10051
|
if (quillEnabled) {
|
|
10048
|
-
const pluginService = new
|
|
10052
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
10049
10053
|
const quillPlugin = await pluginService.getPlugin("quill-editor");
|
|
10050
10054
|
quillSettings = quillPlugin?.settings;
|
|
10051
10055
|
}
|
|
10052
10056
|
const mdxeditorEnabled = await isPluginActive2(db, "easy-mdx");
|
|
10053
10057
|
let mdxeditorSettings;
|
|
10054
10058
|
if (mdxeditorEnabled) {
|
|
10055
|
-
const pluginService = new
|
|
10059
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
10056
10060
|
const mdxeditorPlugin = await pluginService.getPlugin("easy-mdx");
|
|
10057
10061
|
mdxeditorSettings = mdxeditorPlugin?.settings;
|
|
10058
10062
|
}
|
|
@@ -10347,7 +10351,7 @@ adminContentRoutes.put("/:id", async (c) => {
|
|
|
10347
10351
|
`);
|
|
10348
10352
|
}
|
|
10349
10353
|
});
|
|
10350
|
-
adminContentRoutes.post("/preview",
|
|
10354
|
+
adminContentRoutes.post("/preview", chunk7A4CB7T3_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
10351
10355
|
try {
|
|
10352
10356
|
const formData = await c.req.formData();
|
|
10353
10357
|
const collectionId = formData.get("collection_id");
|
|
@@ -10725,7 +10729,7 @@ adminContentRoutes.post("/:id/restore/:version", async (c) => {
|
|
|
10725
10729
|
return c.json({ success: false, error: "Failed to restore version" });
|
|
10726
10730
|
}
|
|
10727
10731
|
});
|
|
10728
|
-
adminContentRoutes.get("/:id/version/:version/preview",
|
|
10732
|
+
adminContentRoutes.get("/:id/version/:version/preview", chunk7A4CB7T3_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
10729
10733
|
try {
|
|
10730
10734
|
const id = c.req.param("id");
|
|
10731
10735
|
const version = parseInt(c.req.param("version") || "0");
|
|
@@ -12724,14 +12728,14 @@ function renderUsersListPage(data) {
|
|
|
12724
12728
|
|
|
12725
12729
|
// src/routes/admin-users.ts
|
|
12726
12730
|
var userRoutes = new hono.Hono();
|
|
12727
|
-
userRoutes.use("*",
|
|
12728
|
-
userRoutes.use("/users/*",
|
|
12729
|
-
userRoutes.use("/users",
|
|
12730
|
-
userRoutes.use("/invite-user",
|
|
12731
|
-
userRoutes.use("/resend-invitation/*",
|
|
12732
|
-
userRoutes.use("/cancel-invitation/*",
|
|
12733
|
-
userRoutes.use("/activity-logs",
|
|
12734
|
-
userRoutes.use("/activity-logs/*",
|
|
12731
|
+
userRoutes.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
12732
|
+
userRoutes.use("/users/*", chunk7A4CB7T3_cjs.requireRole(["admin"]));
|
|
12733
|
+
userRoutes.use("/users", chunk7A4CB7T3_cjs.requireRole(["admin"]));
|
|
12734
|
+
userRoutes.use("/invite-user", chunk7A4CB7T3_cjs.requireRole(["admin"]));
|
|
12735
|
+
userRoutes.use("/resend-invitation/*", chunk7A4CB7T3_cjs.requireRole(["admin"]));
|
|
12736
|
+
userRoutes.use("/cancel-invitation/*", chunk7A4CB7T3_cjs.requireRole(["admin"]));
|
|
12737
|
+
userRoutes.use("/activity-logs", chunk7A4CB7T3_cjs.requireRole(["admin"]));
|
|
12738
|
+
userRoutes.use("/activity-logs/*", chunk7A4CB7T3_cjs.requireRole(["admin"]));
|
|
12735
12739
|
userRoutes.get("/", (c) => {
|
|
12736
12740
|
return c.redirect("/admin/dashboard");
|
|
12737
12741
|
});
|
|
@@ -12901,7 +12905,7 @@ userRoutes.put("/profile", async (c) => {
|
|
|
12901
12905
|
}
|
|
12902
12906
|
await saveCustomData(db, user.userId, sanitized);
|
|
12903
12907
|
}
|
|
12904
|
-
await
|
|
12908
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
12905
12909
|
db,
|
|
12906
12910
|
user.userId,
|
|
12907
12911
|
"profile.update",
|
|
@@ -12964,7 +12968,7 @@ userRoutes.post("/profile/avatar", async (c) => {
|
|
|
12964
12968
|
SELECT first_name, last_name FROM users WHERE id = ?
|
|
12965
12969
|
`);
|
|
12966
12970
|
const userData = await userStmt.bind(user.userId).first();
|
|
12967
|
-
await
|
|
12971
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
12968
12972
|
db,
|
|
12969
12973
|
user.userId,
|
|
12970
12974
|
"profile.avatar_update",
|
|
@@ -13035,7 +13039,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
13035
13039
|
dismissible: true
|
|
13036
13040
|
}));
|
|
13037
13041
|
}
|
|
13038
|
-
const validPassword = await
|
|
13042
|
+
const validPassword = await chunk7A4CB7T3_cjs.AuthManager.verifyPassword(currentPassword, userData.password_hash);
|
|
13039
13043
|
if (!validPassword) {
|
|
13040
13044
|
return c.html(renderAlert2({
|
|
13041
13045
|
type: "error",
|
|
@@ -13043,7 +13047,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
13043
13047
|
dismissible: true
|
|
13044
13048
|
}));
|
|
13045
13049
|
}
|
|
13046
|
-
const newPasswordHash = await
|
|
13050
|
+
const newPasswordHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword(newPassword);
|
|
13047
13051
|
const historyStmt = db.prepare(`
|
|
13048
13052
|
INSERT INTO password_history (id, user_id, password_hash, created_at)
|
|
13049
13053
|
VALUES (?, ?, ?, ?)
|
|
@@ -13059,7 +13063,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
13059
13063
|
WHERE id = ?
|
|
13060
13064
|
`);
|
|
13061
13065
|
await updateStmt.bind(newPasswordHash, Date.now(), user.userId).run();
|
|
13062
|
-
await
|
|
13066
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13063
13067
|
db,
|
|
13064
13068
|
user.userId,
|
|
13065
13069
|
"profile.password_change",
|
|
@@ -13126,7 +13130,7 @@ userRoutes.get("/users", async (c) => {
|
|
|
13126
13130
|
`);
|
|
13127
13131
|
const countResult = await countStmt.bind(...params).first();
|
|
13128
13132
|
const totalUsers = countResult?.total || 0;
|
|
13129
|
-
await
|
|
13133
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13130
13134
|
db,
|
|
13131
13135
|
user.userId,
|
|
13132
13136
|
"users.list_view",
|
|
@@ -13284,7 +13288,7 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
13284
13288
|
dismissible: true
|
|
13285
13289
|
}));
|
|
13286
13290
|
}
|
|
13287
|
-
const passwordHash = await
|
|
13291
|
+
const passwordHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword(password);
|
|
13288
13292
|
const userId = crypto.randomUUID();
|
|
13289
13293
|
const createStmt = db.prepare(`
|
|
13290
13294
|
INSERT INTO users (
|
|
@@ -13307,7 +13311,7 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
13307
13311
|
Date.now(),
|
|
13308
13312
|
Date.now()
|
|
13309
13313
|
).run();
|
|
13310
|
-
await
|
|
13314
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13311
13315
|
db,
|
|
13312
13316
|
user.userId,
|
|
13313
13317
|
"user!.create",
|
|
@@ -13346,7 +13350,7 @@ userRoutes.get("/users/:id", async (c) => {
|
|
|
13346
13350
|
if (!userRecord) {
|
|
13347
13351
|
return c.json({ error: "User not found" }, 404);
|
|
13348
13352
|
}
|
|
13349
|
-
await
|
|
13353
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13350
13354
|
db,
|
|
13351
13355
|
user.userId,
|
|
13352
13356
|
"user!.view",
|
|
@@ -13572,7 +13576,7 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
13572
13576
|
userId
|
|
13573
13577
|
).run();
|
|
13574
13578
|
if (newPassword) {
|
|
13575
|
-
const passwordHash = await
|
|
13579
|
+
const passwordHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword(newPassword);
|
|
13576
13580
|
const updatePasswordStmt = db.prepare(`
|
|
13577
13581
|
UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?
|
|
13578
13582
|
`);
|
|
@@ -13626,7 +13630,7 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
13626
13630
|
).run();
|
|
13627
13631
|
}
|
|
13628
13632
|
}
|
|
13629
|
-
await
|
|
13633
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13630
13634
|
db,
|
|
13631
13635
|
user.userId,
|
|
13632
13636
|
"user.update",
|
|
@@ -13671,7 +13675,7 @@ userRoutes.post("/users/:id/toggle", async (c) => {
|
|
|
13671
13675
|
UPDATE users SET is_active = ?, updated_at = ? WHERE id = ?
|
|
13672
13676
|
`);
|
|
13673
13677
|
await toggleStmt.bind(active ? 1 : 0, Date.now(), userId).run();
|
|
13674
|
-
await
|
|
13678
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13675
13679
|
db,
|
|
13676
13680
|
user.userId,
|
|
13677
13681
|
active ? "user.activate" : "user.deactivate",
|
|
@@ -13712,7 +13716,7 @@ userRoutes.delete("/users/:id", async (c) => {
|
|
|
13712
13716
|
DELETE FROM users WHERE id = ?
|
|
13713
13717
|
`);
|
|
13714
13718
|
await deleteStmt.bind(userId).run();
|
|
13715
|
-
await
|
|
13719
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13716
13720
|
db,
|
|
13717
13721
|
user.userId,
|
|
13718
13722
|
"user!.hard_delete",
|
|
@@ -13731,7 +13735,7 @@ userRoutes.delete("/users/:id", async (c) => {
|
|
|
13731
13735
|
UPDATE users SET is_active = 0, updated_at = ? WHERE id = ?
|
|
13732
13736
|
`);
|
|
13733
13737
|
await deleteStmt.bind(Date.now(), userId).run();
|
|
13734
|
-
await
|
|
13738
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13735
13739
|
db,
|
|
13736
13740
|
user.userId,
|
|
13737
13741
|
"user!.soft_delete",
|
|
@@ -13797,7 +13801,7 @@ userRoutes.post("/invite-user", async (c) => {
|
|
|
13797
13801
|
Date.now(),
|
|
13798
13802
|
Date.now()
|
|
13799
13803
|
).run();
|
|
13800
|
-
await
|
|
13804
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13801
13805
|
db,
|
|
13802
13806
|
user.userId,
|
|
13803
13807
|
"user!.invite_sent",
|
|
@@ -13854,7 +13858,7 @@ userRoutes.post("/resend-invitation/:id", async (c) => {
|
|
|
13854
13858
|
Date.now(),
|
|
13855
13859
|
userId
|
|
13856
13860
|
).run();
|
|
13857
|
-
await
|
|
13861
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13858
13862
|
db,
|
|
13859
13863
|
user.userId,
|
|
13860
13864
|
"user!.invitation_resent",
|
|
@@ -13890,7 +13894,7 @@ userRoutes.delete("/cancel-invitation/:id", async (c) => {
|
|
|
13890
13894
|
}
|
|
13891
13895
|
const deleteStmt = db.prepare(`DELETE FROM users WHERE id = ?`);
|
|
13892
13896
|
await deleteStmt.bind(userId).run();
|
|
13893
|
-
await
|
|
13897
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13894
13898
|
db,
|
|
13895
13899
|
user.userId,
|
|
13896
13900
|
"user!.invitation_cancelled",
|
|
@@ -13973,7 +13977,7 @@ userRoutes.get("/activity-logs", async (c) => {
|
|
|
13973
13977
|
...log,
|
|
13974
13978
|
details: log.details ? JSON.parse(log.details) : null
|
|
13975
13979
|
}));
|
|
13976
|
-
await
|
|
13980
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13977
13981
|
db,
|
|
13978
13982
|
user.userId,
|
|
13979
13983
|
"activity.logs_viewed",
|
|
@@ -14080,7 +14084,7 @@ userRoutes.get("/activity-logs/export", async (c) => {
|
|
|
14080
14084
|
csvRows.push(row.join(","));
|
|
14081
14085
|
}
|
|
14082
14086
|
const csvContent = csvRows.join("\n");
|
|
14083
|
-
await
|
|
14087
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
14084
14088
|
db,
|
|
14085
14089
|
user.userId,
|
|
14086
14090
|
"activity.logs_exported",
|
|
@@ -15419,7 +15423,7 @@ var fileValidationSchema2 = zod.z.object({
|
|
|
15419
15423
|
// 50MB max
|
|
15420
15424
|
});
|
|
15421
15425
|
var adminMediaRoutes = new hono.Hono();
|
|
15422
|
-
adminMediaRoutes.use("*",
|
|
15426
|
+
adminMediaRoutes.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
15423
15427
|
adminMediaRoutes.get("/", async (c) => {
|
|
15424
15428
|
try {
|
|
15425
15429
|
const user = c.get("user");
|
|
@@ -15811,8 +15815,8 @@ adminMediaRoutes.post("/upload", async (c) => {
|
|
|
15811
15815
|
});
|
|
15812
15816
|
continue;
|
|
15813
15817
|
}
|
|
15814
|
-
let width;
|
|
15815
|
-
let height;
|
|
15818
|
+
let width = null;
|
|
15819
|
+
let height = null;
|
|
15816
15820
|
if (file.type.startsWith("image/") && !file.type.includes("svg")) {
|
|
15817
15821
|
try {
|
|
15818
15822
|
const dimensions = await getImageDimensions2(arrayBuffer);
|
|
@@ -15823,7 +15827,7 @@ adminMediaRoutes.post("/upload", async (c) => {
|
|
|
15823
15827
|
}
|
|
15824
15828
|
}
|
|
15825
15829
|
const publicUrl = `/files/${r2Key}`;
|
|
15826
|
-
const thumbnailUrl = file.type.startsWith("image/") ? publicUrl :
|
|
15830
|
+
const thumbnailUrl = file.type.startsWith("image/") ? publicUrl : null;
|
|
15827
15831
|
const stmt = c.env.DB.prepare(`
|
|
15828
15832
|
INSERT INTO media (
|
|
15829
15833
|
id, filename, original_name, mime_type, size, width, height,
|
|
@@ -16005,7 +16009,7 @@ adminMediaRoutes.put("/:id", async (c) => {
|
|
|
16005
16009
|
`);
|
|
16006
16010
|
}
|
|
16007
16011
|
});
|
|
16008
|
-
adminMediaRoutes.delete("/cleanup",
|
|
16012
|
+
adminMediaRoutes.delete("/cleanup", chunk7A4CB7T3_cjs.requireRole("admin"), async (c) => {
|
|
16009
16013
|
try {
|
|
16010
16014
|
const db = c.env.DB;
|
|
16011
16015
|
const allMediaStmt = db.prepare("SELECT id, r2_key, filename FROM media WHERE deleted_at IS NULL");
|
|
@@ -18348,8 +18352,8 @@ function renderEmailSettingsContent(plugin, settings) {
|
|
|
18348
18352
|
|
|
18349
18353
|
// src/routes/admin-plugins.ts
|
|
18350
18354
|
var adminPluginRoutes = new hono.Hono();
|
|
18351
|
-
adminPluginRoutes.use("*",
|
|
18352
|
-
var AVAILABLE_PLUGINS = Object.values(
|
|
18355
|
+
adminPluginRoutes.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
18356
|
+
var AVAILABLE_PLUGINS = Object.values(chunkE4YFJBM2_cjs.PLUGIN_REGISTRY).map((p) => ({
|
|
18353
18357
|
id: p.id,
|
|
18354
18358
|
name: p.codeName,
|
|
18355
18359
|
display_name: p.displayName,
|
|
@@ -18369,7 +18373,7 @@ adminPluginRoutes.get("/", async (c) => {
|
|
|
18369
18373
|
if (user?.role !== "admin") {
|
|
18370
18374
|
return c.text("Access denied", 403);
|
|
18371
18375
|
}
|
|
18372
|
-
const pluginService = new
|
|
18376
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
18373
18377
|
let installedPlugins = [];
|
|
18374
18378
|
let stats = { total: 0, active: 0, inactive: 0, errors: 0, uninstalled: 0 };
|
|
18375
18379
|
try {
|
|
@@ -18441,7 +18445,7 @@ adminPluginRoutes.get("/:id", async (c) => {
|
|
|
18441
18445
|
if (user?.role !== "admin") {
|
|
18442
18446
|
return c.redirect("/admin/plugins");
|
|
18443
18447
|
}
|
|
18444
|
-
const pluginService = new
|
|
18448
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
18445
18449
|
const plugin = await pluginService.getPlugin(pluginId);
|
|
18446
18450
|
if (!plugin) {
|
|
18447
18451
|
return c.text("Plugin not found", 404);
|
|
@@ -18517,7 +18521,7 @@ adminPluginRoutes.post("/:id/activate", async (c) => {
|
|
|
18517
18521
|
if (user?.role !== "admin") {
|
|
18518
18522
|
return c.json({ error: "Access denied" }, 403);
|
|
18519
18523
|
}
|
|
18520
|
-
const pluginService = new
|
|
18524
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
18521
18525
|
await pluginService.activatePlugin(pluginId);
|
|
18522
18526
|
return c.json({ success: true });
|
|
18523
18527
|
} catch (error) {
|
|
@@ -18534,7 +18538,7 @@ adminPluginRoutes.post("/:id/deactivate", async (c) => {
|
|
|
18534
18538
|
if (user?.role !== "admin") {
|
|
18535
18539
|
return c.json({ error: "Access denied" }, 403);
|
|
18536
18540
|
}
|
|
18537
|
-
const pluginService = new
|
|
18541
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
18538
18542
|
await pluginService.deactivatePlugin(pluginId);
|
|
18539
18543
|
return c.json({ success: true });
|
|
18540
18544
|
} catch (error) {
|
|
@@ -18551,8 +18555,8 @@ adminPluginRoutes.post("/install", async (c) => {
|
|
|
18551
18555
|
return c.json({ error: "Access denied" }, 403);
|
|
18552
18556
|
}
|
|
18553
18557
|
const body = await c.req.json();
|
|
18554
|
-
const pluginService = new
|
|
18555
|
-
const registryEntry =
|
|
18558
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
18559
|
+
const registryEntry = chunkE4YFJBM2_cjs.findPluginByCodeName(body.name) || chunkE4YFJBM2_cjs.PLUGIN_REGISTRY[body.name] || chunkE4YFJBM2_cjs.PLUGIN_REGISTRY[body.id];
|
|
18556
18560
|
if (!registryEntry) {
|
|
18557
18561
|
return c.json({ error: "Plugin not found in registry" }, 404);
|
|
18558
18562
|
}
|
|
@@ -18585,7 +18589,7 @@ adminPluginRoutes.post("/:id/uninstall", async (c) => {
|
|
|
18585
18589
|
if (user?.role !== "admin") {
|
|
18586
18590
|
return c.json({ error: "Access denied" }, 403);
|
|
18587
18591
|
}
|
|
18588
|
-
const pluginService = new
|
|
18592
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
18589
18593
|
await pluginService.uninstallPlugin(pluginId);
|
|
18590
18594
|
return c.json({ success: true });
|
|
18591
18595
|
} catch (error) {
|
|
@@ -18603,7 +18607,7 @@ adminPluginRoutes.post("/:id/settings", async (c) => {
|
|
|
18603
18607
|
return c.json({ error: "Access denied" }, 403);
|
|
18604
18608
|
}
|
|
18605
18609
|
const settings = await c.req.json();
|
|
18606
|
-
const pluginService = new
|
|
18610
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
18607
18611
|
await pluginService.updatePluginSettings(pluginId, settings);
|
|
18608
18612
|
if (pluginId === "core-auth") {
|
|
18609
18613
|
try {
|
|
@@ -19411,7 +19415,7 @@ function renderLogConfigPage(data) {
|
|
|
19411
19415
|
|
|
19412
19416
|
// src/routes/admin-logs.ts
|
|
19413
19417
|
var adminLogsRoutes = new hono.Hono();
|
|
19414
|
-
adminLogsRoutes.use("*",
|
|
19418
|
+
adminLogsRoutes.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
19415
19419
|
adminLogsRoutes.get("/", async (c) => {
|
|
19416
19420
|
try {
|
|
19417
19421
|
const user = c.get("user");
|
|
@@ -21739,9 +21743,9 @@ function renderStorageUsage(databaseSizeBytes, mediaSizeBytes) {
|
|
|
21739
21743
|
}
|
|
21740
21744
|
|
|
21741
21745
|
// src/routes/admin-dashboard.ts
|
|
21742
|
-
var VERSION =
|
|
21746
|
+
var VERSION = chunkJZVHLLSI_cjs.getCoreVersion();
|
|
21743
21747
|
var router = new hono.Hono();
|
|
21744
|
-
router.use("*",
|
|
21748
|
+
router.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
21745
21749
|
router.get("/", async (c) => {
|
|
21746
21750
|
const user = c.get("user");
|
|
21747
21751
|
try {
|
|
@@ -22609,6 +22613,22 @@ function renderCollectionFormPage(data) {
|
|
|
22609
22613
|
<h2 class="text-base/7 font-semibold text-zinc-950 dark:text-white">Collection Details</h2>
|
|
22610
22614
|
<p class="text-sm/6 text-zinc-500 dark:text-zinc-400">Configure your collection settings below</p>
|
|
22611
22615
|
</div>
|
|
22616
|
+
|
|
22617
|
+
${isEdit && data.name ? `
|
|
22618
|
+
<!-- Export Button: only on edit (need a collection name to fetch) -->
|
|
22619
|
+
<div class="ml-auto">
|
|
22620
|
+
<button
|
|
22621
|
+
type="button"
|
|
22622
|
+
id="export-collection-btn"
|
|
22623
|
+
title="Export as code"
|
|
22624
|
+
class="inline-flex items-center gap-x-1.5 px-3.5 py-2.5 bg-zinc-950 dark:bg-white text-white dark:text-zinc-950 font-semibold text-sm rounded-lg hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm"
|
|
22625
|
+
>
|
|
22626
|
+
<svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
22627
|
+
<path d="M7 8L3 11.6923L7 16M17 8L21 11.6923L17 16M14 4L10 20" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
22628
|
+
</svg>
|
|
22629
|
+
</button>
|
|
22630
|
+
</div>
|
|
22631
|
+
` : ""}
|
|
22612
22632
|
</div>
|
|
22613
22633
|
</div>
|
|
22614
22634
|
|
|
@@ -23068,6 +23088,176 @@ function renderCollectionFormPage(data) {
|
|
|
23068
23088
|
</div>
|
|
23069
23089
|
</div>
|
|
23070
23090
|
|
|
23091
|
+
${isEdit && data.name ? `
|
|
23092
|
+
<!-- Code Export Modal -->
|
|
23093
|
+
<div id="code-export-modal" class="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50 hidden">
|
|
23094
|
+
<div class="rounded-xl bg-white dark:bg-zinc-900 shadow-xl ring-1 ring-zinc-950/5 dark:ring-white/10 w-full max-w-2xl mx-4">
|
|
23095
|
+
<div class="px-6 py-4 border-b border-zinc-950/5 dark:border-white/10">
|
|
23096
|
+
<div class="flex items-center justify-between">
|
|
23097
|
+
<h3 id="code-export-modal-title" class="text-lg font-semibold text-zinc-950 dark:text-white">
|
|
23098
|
+
Code-Based version of ${chunkMNWKYY5E_cjs.escapeHtml(data.display_name || "this collection")}
|
|
23099
|
+
</h3>
|
|
23100
|
+
<button onclick="toggleCodeExportModal()" class="text-zinc-500 dark:text-zinc-400 hover:text-zinc-950 dark:hover:text-white transition-colors">
|
|
23101
|
+
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
23102
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
|
23103
|
+
</svg>
|
|
23104
|
+
</button>
|
|
23105
|
+
</div>
|
|
23106
|
+
</div>
|
|
23107
|
+
|
|
23108
|
+
<div id="code-export-form" class="p-6 space-y-4">
|
|
23109
|
+
<div id="code-export-options-container">
|
|
23110
|
+
<div class="relative">
|
|
23111
|
+
<textarea
|
|
23112
|
+
id="code-export-options"
|
|
23113
|
+
name="code_export_options"
|
|
23114
|
+
rows="8"
|
|
23115
|
+
class="w-full rounded-lg bg-white dark:bg-zinc-800 px-4 py-3 text-sm text-zinc-950 dark:text-white placeholder-zinc-500 dark:placeholder-zinc-400 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 focus:ring-2 focus:ring-blue-600 dark:focus:ring-blue-500 focus:outline-none transition-colors font-mono"
|
|
23116
|
+
readonly
|
|
23117
|
+
></textarea>
|
|
23118
|
+
<button
|
|
23119
|
+
id="copy-options-btn"
|
|
23120
|
+
type="button"
|
|
23121
|
+
class="absolute top-2 right-4 p-1 rounded bg-white/10 dark:bg-zinc-800/10 text-zinc-500 dark:text-zinc-400 hover:text-zinc-950 dark:hover:text-white hover:bg-zinc-100 dark:hover:bg-zinc-700 transition-colors cursor-copy"
|
|
23122
|
+
title="Copy to clipboard"
|
|
23123
|
+
>
|
|
23124
|
+
<svg class="w-5 h-5" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" fill="none">
|
|
23125
|
+
<path fill="currentColor" fill-rule="evenodd" d="M4 2a2 2 0 00-2 2v9a2 2 0 002 2h2v2a2 2 0 002 2h9a2 2 0 002-2V8a2 2 0 00-2-2h-2V4a2 2 0 00-2-2H4zm9 4V4H4v9h2V8a2 2 0 012-2h5zM8 8h9v9H8V8z"/>
|
|
23126
|
+
</svg>
|
|
23127
|
+
</button>
|
|
23128
|
+
</div>
|
|
23129
|
+
<div class="flex items-center justify-between mt-1 gap-x-4">
|
|
23130
|
+
<p class="text-xs text-zinc-500 dark:text-zinc-400">
|
|
23131
|
+
This is a code-based representation of ${data.display_name ? `the ${chunkMNWKYY5E_cjs.escapeHtml(data.display_name)}` : "this"} collection.
|
|
23132
|
+
Learn more about
|
|
23133
|
+
<a href="https://sonicjs.com/collections" target="_blank" class="text-blue-600 dark:text-blue-400 hover:underline">
|
|
23134
|
+
collections here.
|
|
23135
|
+
</a>
|
|
23136
|
+
</p>
|
|
23137
|
+
<span id="copy-options-feedback" class="invisible text-xs text-green-600 dark:text-green-400">Copied!</span>
|
|
23138
|
+
</div>
|
|
23139
|
+
</div>
|
|
23140
|
+
|
|
23141
|
+
<div class="flex justify-end space-x-3 pt-4 border-t border-zinc-950/5 dark:border-white/10">
|
|
23142
|
+
<button
|
|
23143
|
+
type="button"
|
|
23144
|
+
onclick="toggleCodeExportModal()"
|
|
23145
|
+
class="rounded-lg bg-white dark:bg-zinc-800 px-4 py-2 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors"
|
|
23146
|
+
>
|
|
23147
|
+
Close
|
|
23148
|
+
</button>
|
|
23149
|
+
</div>
|
|
23150
|
+
</div>
|
|
23151
|
+
</div>
|
|
23152
|
+
</div>
|
|
23153
|
+
|
|
23154
|
+
<script>
|
|
23155
|
+
(function() {
|
|
23156
|
+
const collectionName = ${JSON.stringify(data.name || "")};
|
|
23157
|
+
|
|
23158
|
+
// Fields returned by the collections API that aren't part of CollectionConfig.
|
|
23159
|
+
const unwantedKeys = ['id', 'source_type', 'source_id', 'created_at', 'updated_at'];
|
|
23160
|
+
|
|
23161
|
+
function normalizeCollectionObject(obj) {
|
|
23162
|
+
if (Array.isArray(obj)) {
|
|
23163
|
+
return obj.map(normalizeCollectionObject);
|
|
23164
|
+
} else if (obj !== null && typeof obj === 'object') {
|
|
23165
|
+
return Object.keys(obj).reduce((acc, key) => {
|
|
23166
|
+
if (unwantedKeys.includes(key)) return acc;
|
|
23167
|
+
const camelCaseKey = key.replace(/_([a-z])/g, g => g[1].toUpperCase());
|
|
23168
|
+
acc[camelCaseKey] = normalizeCollectionObject(obj[key]);
|
|
23169
|
+
return acc;
|
|
23170
|
+
}, {});
|
|
23171
|
+
}
|
|
23172
|
+
return obj;
|
|
23173
|
+
}
|
|
23174
|
+
|
|
23175
|
+
function generateCollectionTemplate(data) {
|
|
23176
|
+
const normalizedData = normalizeCollectionObject(data);
|
|
23177
|
+
return "import type { CollectionConfig } from '@sonicjs-cms/core';\\n\\n" +
|
|
23178
|
+
\`export default \${JSON.stringify(normalizedData, null, 2)} satisfies CollectionConfig;\`;
|
|
23179
|
+
}
|
|
23180
|
+
|
|
23181
|
+
const modal = document.getElementById('code-export-modal');
|
|
23182
|
+
const triggerBtn = document.getElementById('export-collection-btn');
|
|
23183
|
+
if (!modal || !triggerBtn) return;
|
|
23184
|
+
|
|
23185
|
+
function isOpen() {
|
|
23186
|
+
return !modal.classList.contains('hidden');
|
|
23187
|
+
}
|
|
23188
|
+
|
|
23189
|
+
function toggleModal() {
|
|
23190
|
+
modal.classList.toggle('hidden');
|
|
23191
|
+
if (!isOpen()) {
|
|
23192
|
+
modal.querySelector('#code-export-options').value = '';
|
|
23193
|
+
}
|
|
23194
|
+
}
|
|
23195
|
+
// Exposed for inline onclick handlers in the modal markup.
|
|
23196
|
+
window.toggleCodeExportModal = toggleModal;
|
|
23197
|
+
|
|
23198
|
+
async function fetchCollectionByName(name) {
|
|
23199
|
+
try {
|
|
23200
|
+
const response = await fetch(\`/api/collections/\${encodeURIComponent(name)}/content\`, {
|
|
23201
|
+
headers: { 'Accept': 'application/json' }
|
|
23202
|
+
});
|
|
23203
|
+
if (!response.ok) throw new Error('Network response was not ok');
|
|
23204
|
+
const res = await response.json();
|
|
23205
|
+
return res.meta?.collection || {};
|
|
23206
|
+
} catch (error) {
|
|
23207
|
+
console.error('Error fetching collection data for export:', error);
|
|
23208
|
+
alert('Failed to load collection data for export. Please try again.');
|
|
23209
|
+
return null;
|
|
23210
|
+
}
|
|
23211
|
+
}
|
|
23212
|
+
|
|
23213
|
+
async function copyToClipboard(text) {
|
|
23214
|
+
if (navigator.clipboard?.writeText) {
|
|
23215
|
+
await navigator.clipboard.writeText(text);
|
|
23216
|
+
return;
|
|
23217
|
+
}
|
|
23218
|
+
// Fallback for non-secure contexts.
|
|
23219
|
+
const textarea = modal.querySelector('#code-export-options');
|
|
23220
|
+
textarea.select();
|
|
23221
|
+
textarea.setSelectionRange(0, 99999);
|
|
23222
|
+
if (!document.execCommand('copy')) throw new Error('Copy command was unsuccessful');
|
|
23223
|
+
}
|
|
23224
|
+
|
|
23225
|
+
triggerBtn.addEventListener('click', async function() {
|
|
23226
|
+
if (!collectionName) return;
|
|
23227
|
+
const res = await fetchCollectionByName(collectionName);
|
|
23228
|
+
if (!res) return;
|
|
23229
|
+
try {
|
|
23230
|
+
modal.querySelector('#code-export-options').value = generateCollectionTemplate(res);
|
|
23231
|
+
toggleModal();
|
|
23232
|
+
} catch (e) {
|
|
23233
|
+
console.error('Error preparing collection data for export:', e);
|
|
23234
|
+
alert('Failed to prepare collection data for export. Please try again.');
|
|
23235
|
+
}
|
|
23236
|
+
});
|
|
23237
|
+
|
|
23238
|
+
modal.querySelector('#copy-options-btn').addEventListener('click', async function() {
|
|
23239
|
+
const textarea = modal.querySelector('#code-export-options');
|
|
23240
|
+
try {
|
|
23241
|
+
await copyToClipboard(textarea.value);
|
|
23242
|
+
const feedback = modal.querySelector('#copy-options-feedback');
|
|
23243
|
+
feedback.classList.remove('invisible');
|
|
23244
|
+
setTimeout(() => feedback.classList.add('invisible'), 2000);
|
|
23245
|
+
} catch (err) {
|
|
23246
|
+
console.error('Error copying to clipboard:', err);
|
|
23247
|
+
alert('Failed to copy to clipboard. Please try copying manually.');
|
|
23248
|
+
}
|
|
23249
|
+
});
|
|
23250
|
+
|
|
23251
|
+
document.addEventListener('keydown', function(e) {
|
|
23252
|
+
if (e.key === 'Escape' && isOpen()) toggleModal();
|
|
23253
|
+
});
|
|
23254
|
+
|
|
23255
|
+
modal.addEventListener('click', function(e) {
|
|
23256
|
+
if (e.target === modal) toggleModal();
|
|
23257
|
+
});
|
|
23258
|
+
})();
|
|
23259
|
+
</script>
|
|
23260
|
+
` : ""}
|
|
23071
23261
|
<script>
|
|
23072
23262
|
const collectionId = '${data.id || ""}';
|
|
23073
23263
|
|
|
@@ -23560,10 +23750,10 @@ function renderCollectionFormPage(data) {
|
|
|
23560
23750
|
|
|
23561
23751
|
// src/routes/admin-collections.ts
|
|
23562
23752
|
var adminCollectionsRoutes = new hono.Hono();
|
|
23563
|
-
adminCollectionsRoutes.use("*",
|
|
23564
|
-
adminCollectionsRoutes.post("*",
|
|
23565
|
-
adminCollectionsRoutes.put("*",
|
|
23566
|
-
adminCollectionsRoutes.delete("*",
|
|
23753
|
+
adminCollectionsRoutes.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
23754
|
+
adminCollectionsRoutes.post("*", chunk7A4CB7T3_cjs.requireRole(["admin"]));
|
|
23755
|
+
adminCollectionsRoutes.put("*", chunk7A4CB7T3_cjs.requireRole(["admin"]));
|
|
23756
|
+
adminCollectionsRoutes.delete("*", chunk7A4CB7T3_cjs.requireRole(["admin"]));
|
|
23567
23757
|
adminCollectionsRoutes.get("/", async (c) => {
|
|
23568
23758
|
try {
|
|
23569
23759
|
const user = c.get("user");
|
|
@@ -25858,7 +26048,7 @@ function renderDatabaseToolsSettings(settings) {
|
|
|
25858
26048
|
|
|
25859
26049
|
// src/routes/admin-settings.ts
|
|
25860
26050
|
var adminSettingsRoutes = new hono.Hono();
|
|
25861
|
-
adminSettingsRoutes.use("*",
|
|
26051
|
+
adminSettingsRoutes.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
25862
26052
|
function getMockSettings(user) {
|
|
25863
26053
|
return {
|
|
25864
26054
|
general: {
|
|
@@ -26035,7 +26225,7 @@ adminSettingsRoutes.get("/database-tools", (c) => {
|
|
|
26035
26225
|
adminSettingsRoutes.get("/api/migrations/status", async (c) => {
|
|
26036
26226
|
try {
|
|
26037
26227
|
const db = c.env.DB;
|
|
26038
|
-
const migrationService = new
|
|
26228
|
+
const migrationService = new chunkRLMUFFUD_cjs.MigrationService(db);
|
|
26039
26229
|
const status = await migrationService.getMigrationStatus();
|
|
26040
26230
|
return c.json({
|
|
26041
26231
|
success: true,
|
|
@@ -26059,7 +26249,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
|
|
|
26059
26249
|
}, 403);
|
|
26060
26250
|
}
|
|
26061
26251
|
const db = c.env.DB;
|
|
26062
|
-
const migrationService = new
|
|
26252
|
+
const migrationService = new chunkRLMUFFUD_cjs.MigrationService(db);
|
|
26063
26253
|
const result = await migrationService.runPendingMigrations();
|
|
26064
26254
|
return c.json({
|
|
26065
26255
|
success: result.success,
|
|
@@ -26077,7 +26267,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
|
|
|
26077
26267
|
adminSettingsRoutes.get("/api/migrations/validate", async (c) => {
|
|
26078
26268
|
try {
|
|
26079
26269
|
const db = c.env.DB;
|
|
26080
|
-
const migrationService = new
|
|
26270
|
+
const migrationService = new chunkRLMUFFUD_cjs.MigrationService(db);
|
|
26081
26271
|
const validation = await migrationService.validateSchema();
|
|
26082
26272
|
return c.json({
|
|
26083
26273
|
success: true,
|
|
@@ -28016,7 +28206,7 @@ function renderFormCreatePage(data) {
|
|
|
28016
28206
|
|
|
28017
28207
|
// src/routes/admin-forms.ts
|
|
28018
28208
|
var adminFormsRoutes = new hono.Hono();
|
|
28019
|
-
adminFormsRoutes.use("*",
|
|
28209
|
+
adminFormsRoutes.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
28020
28210
|
adminFormsRoutes.get("/", async (c) => {
|
|
28021
28211
|
try {
|
|
28022
28212
|
const user = c.get("user");
|
|
@@ -28821,7 +29011,7 @@ publicFormsRoutes.post("/:identifier/submit", async (c) => {
|
|
|
28821
29011
|
`).bind(now, form.id).run();
|
|
28822
29012
|
let contentId = null;
|
|
28823
29013
|
try {
|
|
28824
|
-
contentId = await
|
|
29014
|
+
contentId = await chunkE4YFJBM2_cjs.createContentFromSubmission(
|
|
28825
29015
|
db,
|
|
28826
29016
|
sanitizedData,
|
|
28827
29017
|
{ id: form.id, name: form.name, display_name: form.display_name },
|
|
@@ -29189,9 +29379,9 @@ function renderAPIReferencePage(data) {
|
|
|
29189
29379
|
}
|
|
29190
29380
|
|
|
29191
29381
|
// src/routes/admin-api-reference.ts
|
|
29192
|
-
var VERSION2 =
|
|
29382
|
+
var VERSION2 = chunkJZVHLLSI_cjs.getCoreVersion();
|
|
29193
29383
|
var router2 = new hono.Hono();
|
|
29194
|
-
router2.use("*",
|
|
29384
|
+
router2.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
29195
29385
|
router2.get("/", async (c) => {
|
|
29196
29386
|
const user = c.get("user");
|
|
29197
29387
|
try {
|
|
@@ -29274,6 +29464,7 @@ exports.auth_default = auth_default;
|
|
|
29274
29464
|
exports.createUserProfilesPlugin = createUserProfilesPlugin;
|
|
29275
29465
|
exports.defineUserProfile = defineUserProfile;
|
|
29276
29466
|
exports.getConfirmationDialogScript = getConfirmationDialogScript2;
|
|
29467
|
+
exports.getCustomData = getCustomData;
|
|
29277
29468
|
exports.getUserProfileConfig = getUserProfileConfig;
|
|
29278
29469
|
exports.public_forms_default = public_forms_default;
|
|
29279
29470
|
exports.renderConfirmationDialog = renderConfirmationDialog2;
|
|
@@ -29282,5 +29473,5 @@ exports.router2 = router2;
|
|
|
29282
29473
|
exports.test_cleanup_default = test_cleanup_default;
|
|
29283
29474
|
exports.userProfilesPlugin = userProfilesPlugin;
|
|
29284
29475
|
exports.userRoutes = userRoutes;
|
|
29285
|
-
//# sourceMappingURL=chunk-
|
|
29286
|
-
//# sourceMappingURL=chunk-
|
|
29476
|
+
//# sourceMappingURL=chunk-R4FOLLFB.cjs.map
|
|
29477
|
+
//# sourceMappingURL=chunk-R4FOLLFB.cjs.map
|