@sonicjs-cms/core 2.18.1 → 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-I2H5NGJQ.js → chunk-4NPCDK6B.js} +33 -6
- package/dist/chunk-4NPCDK6B.js.map +1 -0
- package/dist/{chunk-DSUJ5YQH.cjs → chunk-7A4CB7T3.cjs} +36 -9
- package/dist/chunk-7A4CB7T3.cjs.map +1 -0
- package/dist/{chunk-MGFRZO24.js → chunk-BU7SFHGP.js} +4 -4
- package/dist/{chunk-MGFRZO24.js.map → chunk-BU7SFHGP.js.map} +1 -1
- package/dist/{chunk-T3Q5V33G.cjs → chunk-E4YFJBM2.cjs} +2 -2
- package/dist/{chunk-T3Q5V33G.cjs.map → chunk-E4YFJBM2.cjs.map} +1 -1
- package/dist/{chunk-EW5NOBVU.js → chunk-JZV22DEV.js} +2 -2
- package/dist/{chunk-EW5NOBVU.js.map → chunk-JZV22DEV.js.map} +1 -1
- package/dist/{chunk-SQ6FNXU2.cjs → chunk-JZVHLLSI.cjs} +4 -4
- package/dist/{chunk-SQ6FNXU2.cjs.map → chunk-JZVHLLSI.cjs.map} +1 -1
- package/dist/{chunk-XXDFQERJ.js → chunk-OCL3HMEG.js} +204 -15
- package/dist/chunk-OCL3HMEG.js.map +1 -0
- package/dist/{chunk-SXXTQETM.cjs → chunk-R4FOLLFB.cjs} +318 -129
- package/dist/chunk-R4FOLLFB.cjs.map +1 -0
- package/dist/{chunk-C54YUA23.cjs → chunk-RLMUFFUD.cjs} +2 -2
- package/dist/{chunk-C54YUA23.cjs.map → chunk-RLMUFFUD.cjs.map} +1 -1
- package/dist/{chunk-4R3NOOL3.js → chunk-ZYAYUIZE.js} +2 -2
- package/dist/{chunk-4R3NOOL3.js.map → chunk-ZYAYUIZE.js.map} +1 -1
- package/dist/index.cjs +142 -142
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +10 -10
- 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-IYNTWDC6.cjs.map → migrations-566IIPS2.cjs.map} +1 -1
- package/dist/migrations-H5IXZNCO.js +4 -0
- package/dist/{migrations-R337UD46.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-DSUJ5YQH.cjs.map +0 -1
- package/dist/chunk-I2H5NGJQ.js.map +0 -1
- package/dist/chunk-SXXTQETM.cjs.map +0 -1
- package/dist/chunk-XXDFQERJ.js.map +0 -1
- package/dist/migrations-IYNTWDC6.cjs +0 -13
- package/dist/migrations-R337UD46.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("/", chunkDSUJ5YQH_cjs.requireAuth(), chunkDSUJ5YQH_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", chunkDSUJ5YQH_cjs.requireAuth(), chunkDSUJ5YQH_
|
|
|
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", chunkDSUJ5YQH_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", chunkDSUJ5YQH_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", chunkDSUJ5YQH_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", chunkDSUJ5YQH_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) {
|
|
@@ -5424,7 +5427,7 @@ authRoutes.get("/me", chunkDSUJ5YQH_cjs.requireAuth(), async (c) => {
|
|
|
5424
5427
|
});
|
|
5425
5428
|
authRoutes.post(
|
|
5426
5429
|
"/refresh",
|
|
5427
|
-
|
|
5430
|
+
chunk7A4CB7T3_cjs.rateLimit({ max: 60, windowMs: 60 * 1e3, keyPrefix: "refresh" }),
|
|
5428
5431
|
async (c) => {
|
|
5429
5432
|
try {
|
|
5430
5433
|
let token = c.req.header("Authorization")?.replace("Bearer ", "");
|
|
@@ -5433,8 +5436,8 @@ authRoutes.post(
|
|
|
5433
5436
|
return c.json({ error: "Authentication required" }, 401);
|
|
5434
5437
|
}
|
|
5435
5438
|
const db = c.env.DB;
|
|
5436
|
-
const grace = await
|
|
5437
|
-
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);
|
|
5438
5441
|
if (!payload) {
|
|
5439
5442
|
return c.json({ error: "Invalid or expired token" }, 401);
|
|
5440
5443
|
}
|
|
@@ -5442,8 +5445,8 @@ authRoutes.post(
|
|
|
5442
5445
|
if (!row || !row.is_active) {
|
|
5443
5446
|
return c.json({ error: "User is not active" }, 401);
|
|
5444
5447
|
}
|
|
5445
|
-
const tokenTtl = await
|
|
5446
|
-
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);
|
|
5447
5450
|
cookie.setCookie(c, "auth_token", newToken, {
|
|
5448
5451
|
httpOnly: true,
|
|
5449
5452
|
secure: true,
|
|
@@ -5463,7 +5466,7 @@ authRoutes.post(
|
|
|
5463
5466
|
);
|
|
5464
5467
|
authRoutes.post(
|
|
5465
5468
|
"/register/form",
|
|
5466
|
-
|
|
5469
|
+
chunk7A4CB7T3_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "register" }),
|
|
5467
5470
|
async (c) => {
|
|
5468
5471
|
try {
|
|
5469
5472
|
const db = c.env.DB;
|
|
@@ -5510,7 +5513,7 @@ authRoutes.post(
|
|
|
5510
5513
|
</div>
|
|
5511
5514
|
`);
|
|
5512
5515
|
}
|
|
5513
|
-
const passwordHash = await
|
|
5516
|
+
const passwordHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword(password);
|
|
5514
5517
|
const role = isFirstUser ? "admin" : "viewer";
|
|
5515
5518
|
const userId = crypto.randomUUID();
|
|
5516
5519
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -5545,8 +5548,8 @@ authRoutes.post(
|
|
|
5545
5548
|
await saveCustomData(db, userId, sanitized);
|
|
5546
5549
|
}
|
|
5547
5550
|
}
|
|
5548
|
-
const tokenTtl = await
|
|
5549
|
-
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);
|
|
5550
5553
|
cookie.setCookie(c, "auth_token", token, {
|
|
5551
5554
|
httpOnly: true,
|
|
5552
5555
|
secure: false,
|
|
@@ -5578,7 +5581,7 @@ authRoutes.post(
|
|
|
5578
5581
|
);
|
|
5579
5582
|
authRoutes.post(
|
|
5580
5583
|
"/login/form",
|
|
5581
|
-
|
|
5584
|
+
chunk7A4CB7T3_cjs.rateLimit({ max: 30, windowMs: 60 * 1e3, keyPrefix: "login" }),
|
|
5582
5585
|
async (c) => {
|
|
5583
5586
|
try {
|
|
5584
5587
|
const formData = await c.req.formData();
|
|
@@ -5602,7 +5605,7 @@ authRoutes.post(
|
|
|
5602
5605
|
</div>
|
|
5603
5606
|
`);
|
|
5604
5607
|
}
|
|
5605
|
-
const isValidPassword = await
|
|
5608
|
+
const isValidPassword = await chunk7A4CB7T3_cjs.AuthManager.verifyPassword(password, user.password_hash);
|
|
5606
5609
|
if (!isValidPassword) {
|
|
5607
5610
|
return c.html(html.html`
|
|
5608
5611
|
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded">
|
|
@@ -5610,16 +5613,16 @@ authRoutes.post(
|
|
|
5610
5613
|
</div>
|
|
5611
5614
|
`);
|
|
5612
5615
|
}
|
|
5613
|
-
if (
|
|
5616
|
+
if (chunk7A4CB7T3_cjs.AuthManager.isLegacyHash(user.password_hash)) {
|
|
5614
5617
|
try {
|
|
5615
|
-
const newHash = await
|
|
5618
|
+
const newHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword(password);
|
|
5616
5619
|
await db.prepare("UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?").bind(newHash, Date.now(), user.id).run();
|
|
5617
5620
|
} catch (rehashError) {
|
|
5618
5621
|
console.error("Password rehash failed (non-fatal):", rehashError);
|
|
5619
5622
|
}
|
|
5620
5623
|
}
|
|
5621
|
-
const tokenTtl = await
|
|
5622
|
-
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);
|
|
5623
5626
|
cookie.setCookie(c, "auth_token", token, {
|
|
5624
5627
|
httpOnly: true,
|
|
5625
5628
|
secure: false,
|
|
@@ -5660,7 +5663,7 @@ authRoutes.post(
|
|
|
5660
5663
|
);
|
|
5661
5664
|
authRoutes.post(
|
|
5662
5665
|
"/seed-admin",
|
|
5663
|
-
|
|
5666
|
+
chunk7A4CB7T3_cjs.rateLimit({ max: 10, windowMs: 60 * 1e3, keyPrefix: "seed-admin" }),
|
|
5664
5667
|
async (c) => {
|
|
5665
5668
|
try {
|
|
5666
5669
|
const db = c.env.DB;
|
|
@@ -5682,7 +5685,7 @@ authRoutes.post(
|
|
|
5682
5685
|
`).run();
|
|
5683
5686
|
const existingAdmin = await db.prepare("SELECT id FROM users WHERE email = ? OR username = ?").bind("admin@sonicjs.com", "admin").first();
|
|
5684
5687
|
if (existingAdmin) {
|
|
5685
|
-
const passwordHash2 = await
|
|
5688
|
+
const passwordHash2 = await chunk7A4CB7T3_cjs.AuthManager.hashPassword("sonicjs!");
|
|
5686
5689
|
await db.prepare("UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?").bind(passwordHash2, Date.now(), existingAdmin.id).run();
|
|
5687
5690
|
return c.json({
|
|
5688
5691
|
message: "Admin user already exists (password updated)",
|
|
@@ -5694,7 +5697,7 @@ authRoutes.post(
|
|
|
5694
5697
|
}
|
|
5695
5698
|
});
|
|
5696
5699
|
}
|
|
5697
|
-
const passwordHash = await
|
|
5700
|
+
const passwordHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword("sonicjs!");
|
|
5698
5701
|
const userId = "admin-user-id";
|
|
5699
5702
|
const now = Date.now();
|
|
5700
5703
|
const adminEmail = "admin@sonicjs.com".toLowerCase();
|
|
@@ -5915,7 +5918,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
5915
5918
|
if (existingUsername) {
|
|
5916
5919
|
return c.json({ error: "Username is already taken" }, 400);
|
|
5917
5920
|
}
|
|
5918
|
-
const passwordHash = await
|
|
5921
|
+
const passwordHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword(password);
|
|
5919
5922
|
const updateStmt = db.prepare(`
|
|
5920
5923
|
UPDATE users SET
|
|
5921
5924
|
username = ?,
|
|
@@ -5934,8 +5937,8 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
5934
5937
|
Date.now(),
|
|
5935
5938
|
invitedUser.id
|
|
5936
5939
|
).run();
|
|
5937
|
-
const tokenTtl = await
|
|
5938
|
-
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);
|
|
5939
5942
|
cookie.setCookie(c, "auth_token", authToken, {
|
|
5940
5943
|
httpOnly: true,
|
|
5941
5944
|
secure: true,
|
|
@@ -5951,7 +5954,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
5951
5954
|
});
|
|
5952
5955
|
authRoutes.post(
|
|
5953
5956
|
"/request-password-reset",
|
|
5954
|
-
|
|
5957
|
+
chunk7A4CB7T3_cjs.rateLimit({ max: 3, windowMs: 15 * 60 * 1e3, keyPrefix: "password-reset" }),
|
|
5955
5958
|
async (c) => {
|
|
5956
5959
|
try {
|
|
5957
5960
|
const formData = await c.req.formData();
|
|
@@ -6169,7 +6172,7 @@ authRoutes.post("/reset-password", async (c) => {
|
|
|
6169
6172
|
if (Date.now() > user.password_reset_expires) {
|
|
6170
6173
|
return c.json({ error: "Reset token has expired" }, 400);
|
|
6171
6174
|
}
|
|
6172
|
-
const newPasswordHash = await
|
|
6175
|
+
const newPasswordHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword(password);
|
|
6173
6176
|
try {
|
|
6174
6177
|
const historyStmt = db.prepare(`
|
|
6175
6178
|
INSERT INTO password_history (id, user_id, password_hash, created_at)
|
|
@@ -9545,9 +9548,9 @@ function parseFieldValue(field, formData, options = {}) {
|
|
|
9545
9548
|
const { skipValidation = false } = options;
|
|
9546
9549
|
const value = formData.get(field.field_name);
|
|
9547
9550
|
const errors = [];
|
|
9548
|
-
const blocksConfig =
|
|
9551
|
+
const blocksConfig = chunkJZVHLLSI_cjs.getBlocksFieldConfig(field.field_options);
|
|
9549
9552
|
if (blocksConfig) {
|
|
9550
|
-
const parsed =
|
|
9553
|
+
const parsed = chunkJZVHLLSI_cjs.parseBlocksValue(value, blocksConfig);
|
|
9551
9554
|
if (!skipValidation && field.is_required && parsed.value.length === 0) {
|
|
9552
9555
|
parsed.errors.push(`${field.field_label} is required`);
|
|
9553
9556
|
}
|
|
@@ -9657,7 +9660,7 @@ function extractFieldData(fields, formData, options = {}) {
|
|
|
9657
9660
|
}
|
|
9658
9661
|
return { data, errors };
|
|
9659
9662
|
}
|
|
9660
|
-
adminContentRoutes.use("*",
|
|
9663
|
+
adminContentRoutes.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
9661
9664
|
async function getCollectionFields(db, collectionId) {
|
|
9662
9665
|
const cache = chunkWAEQXGCX_cjs.getCacheService(chunkWAEQXGCX_cjs.CACHE_CONFIGS.collection);
|
|
9663
9666
|
return cache.getOrSet(
|
|
@@ -9934,21 +9937,21 @@ adminContentRoutes.get("/new", async (c) => {
|
|
|
9934
9937
|
const tinymceEnabled = await isPluginActive2(db, "tinymce-plugin");
|
|
9935
9938
|
let tinymceSettings;
|
|
9936
9939
|
if (tinymceEnabled) {
|
|
9937
|
-
const pluginService = new
|
|
9940
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
9938
9941
|
const tinymcePlugin2 = await pluginService.getPlugin("tinymce-plugin");
|
|
9939
9942
|
tinymceSettings = tinymcePlugin2?.settings;
|
|
9940
9943
|
}
|
|
9941
9944
|
const quillEnabled = await isPluginActive2(db, "quill-editor");
|
|
9942
9945
|
let quillSettings;
|
|
9943
9946
|
if (quillEnabled) {
|
|
9944
|
-
const pluginService = new
|
|
9947
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
9945
9948
|
const quillPlugin = await pluginService.getPlugin("quill-editor");
|
|
9946
9949
|
quillSettings = quillPlugin?.settings;
|
|
9947
9950
|
}
|
|
9948
9951
|
const mdxeditorEnabled = await isPluginActive2(db, "easy-mdx");
|
|
9949
9952
|
let mdxeditorSettings;
|
|
9950
9953
|
if (mdxeditorEnabled) {
|
|
9951
|
-
const pluginService = new
|
|
9954
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
9952
9955
|
const mdxeditorPlugin = await pluginService.getPlugin("easy-mdx");
|
|
9953
9956
|
mdxeditorSettings = mdxeditorPlugin?.settings;
|
|
9954
9957
|
}
|
|
@@ -10039,21 +10042,21 @@ adminContentRoutes.get("/:id/edit", async (c) => {
|
|
|
10039
10042
|
const tinymceEnabled = await isPluginActive2(db, "tinymce-plugin");
|
|
10040
10043
|
let tinymceSettings;
|
|
10041
10044
|
if (tinymceEnabled) {
|
|
10042
|
-
const pluginService = new
|
|
10045
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
10043
10046
|
const tinymcePlugin2 = await pluginService.getPlugin("tinymce-plugin");
|
|
10044
10047
|
tinymceSettings = tinymcePlugin2?.settings;
|
|
10045
10048
|
}
|
|
10046
10049
|
const quillEnabled = await isPluginActive2(db, "quill-editor");
|
|
10047
10050
|
let quillSettings;
|
|
10048
10051
|
if (quillEnabled) {
|
|
10049
|
-
const pluginService = new
|
|
10052
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
10050
10053
|
const quillPlugin = await pluginService.getPlugin("quill-editor");
|
|
10051
10054
|
quillSettings = quillPlugin?.settings;
|
|
10052
10055
|
}
|
|
10053
10056
|
const mdxeditorEnabled = await isPluginActive2(db, "easy-mdx");
|
|
10054
10057
|
let mdxeditorSettings;
|
|
10055
10058
|
if (mdxeditorEnabled) {
|
|
10056
|
-
const pluginService = new
|
|
10059
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
10057
10060
|
const mdxeditorPlugin = await pluginService.getPlugin("easy-mdx");
|
|
10058
10061
|
mdxeditorSettings = mdxeditorPlugin?.settings;
|
|
10059
10062
|
}
|
|
@@ -10348,7 +10351,7 @@ adminContentRoutes.put("/:id", async (c) => {
|
|
|
10348
10351
|
`);
|
|
10349
10352
|
}
|
|
10350
10353
|
});
|
|
10351
|
-
adminContentRoutes.post("/preview",
|
|
10354
|
+
adminContentRoutes.post("/preview", chunk7A4CB7T3_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
10352
10355
|
try {
|
|
10353
10356
|
const formData = await c.req.formData();
|
|
10354
10357
|
const collectionId = formData.get("collection_id");
|
|
@@ -10726,7 +10729,7 @@ adminContentRoutes.post("/:id/restore/:version", async (c) => {
|
|
|
10726
10729
|
return c.json({ success: false, error: "Failed to restore version" });
|
|
10727
10730
|
}
|
|
10728
10731
|
});
|
|
10729
|
-
adminContentRoutes.get("/:id/version/:version/preview",
|
|
10732
|
+
adminContentRoutes.get("/:id/version/:version/preview", chunk7A4CB7T3_cjs.requireRole(["admin", "editor", "author"]), async (c) => {
|
|
10730
10733
|
try {
|
|
10731
10734
|
const id = c.req.param("id");
|
|
10732
10735
|
const version = parseInt(c.req.param("version") || "0");
|
|
@@ -12725,14 +12728,14 @@ function renderUsersListPage(data) {
|
|
|
12725
12728
|
|
|
12726
12729
|
// src/routes/admin-users.ts
|
|
12727
12730
|
var userRoutes = new hono.Hono();
|
|
12728
|
-
userRoutes.use("*",
|
|
12729
|
-
userRoutes.use("/users/*",
|
|
12730
|
-
userRoutes.use("/users",
|
|
12731
|
-
userRoutes.use("/invite-user",
|
|
12732
|
-
userRoutes.use("/resend-invitation/*",
|
|
12733
|
-
userRoutes.use("/cancel-invitation/*",
|
|
12734
|
-
userRoutes.use("/activity-logs",
|
|
12735
|
-
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"]));
|
|
12736
12739
|
userRoutes.get("/", (c) => {
|
|
12737
12740
|
return c.redirect("/admin/dashboard");
|
|
12738
12741
|
});
|
|
@@ -12902,7 +12905,7 @@ userRoutes.put("/profile", async (c) => {
|
|
|
12902
12905
|
}
|
|
12903
12906
|
await saveCustomData(db, user.userId, sanitized);
|
|
12904
12907
|
}
|
|
12905
|
-
await
|
|
12908
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
12906
12909
|
db,
|
|
12907
12910
|
user.userId,
|
|
12908
12911
|
"profile.update",
|
|
@@ -12965,7 +12968,7 @@ userRoutes.post("/profile/avatar", async (c) => {
|
|
|
12965
12968
|
SELECT first_name, last_name FROM users WHERE id = ?
|
|
12966
12969
|
`);
|
|
12967
12970
|
const userData = await userStmt.bind(user.userId).first();
|
|
12968
|
-
await
|
|
12971
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
12969
12972
|
db,
|
|
12970
12973
|
user.userId,
|
|
12971
12974
|
"profile.avatar_update",
|
|
@@ -13036,7 +13039,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
13036
13039
|
dismissible: true
|
|
13037
13040
|
}));
|
|
13038
13041
|
}
|
|
13039
|
-
const validPassword = await
|
|
13042
|
+
const validPassword = await chunk7A4CB7T3_cjs.AuthManager.verifyPassword(currentPassword, userData.password_hash);
|
|
13040
13043
|
if (!validPassword) {
|
|
13041
13044
|
return c.html(renderAlert2({
|
|
13042
13045
|
type: "error",
|
|
@@ -13044,7 +13047,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
13044
13047
|
dismissible: true
|
|
13045
13048
|
}));
|
|
13046
13049
|
}
|
|
13047
|
-
const newPasswordHash = await
|
|
13050
|
+
const newPasswordHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword(newPassword);
|
|
13048
13051
|
const historyStmt = db.prepare(`
|
|
13049
13052
|
INSERT INTO password_history (id, user_id, password_hash, created_at)
|
|
13050
13053
|
VALUES (?, ?, ?, ?)
|
|
@@ -13060,7 +13063,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
13060
13063
|
WHERE id = ?
|
|
13061
13064
|
`);
|
|
13062
13065
|
await updateStmt.bind(newPasswordHash, Date.now(), user.userId).run();
|
|
13063
|
-
await
|
|
13066
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13064
13067
|
db,
|
|
13065
13068
|
user.userId,
|
|
13066
13069
|
"profile.password_change",
|
|
@@ -13127,7 +13130,7 @@ userRoutes.get("/users", async (c) => {
|
|
|
13127
13130
|
`);
|
|
13128
13131
|
const countResult = await countStmt.bind(...params).first();
|
|
13129
13132
|
const totalUsers = countResult?.total || 0;
|
|
13130
|
-
await
|
|
13133
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13131
13134
|
db,
|
|
13132
13135
|
user.userId,
|
|
13133
13136
|
"users.list_view",
|
|
@@ -13285,7 +13288,7 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
13285
13288
|
dismissible: true
|
|
13286
13289
|
}));
|
|
13287
13290
|
}
|
|
13288
|
-
const passwordHash = await
|
|
13291
|
+
const passwordHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword(password);
|
|
13289
13292
|
const userId = crypto.randomUUID();
|
|
13290
13293
|
const createStmt = db.prepare(`
|
|
13291
13294
|
INSERT INTO users (
|
|
@@ -13308,7 +13311,7 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
13308
13311
|
Date.now(),
|
|
13309
13312
|
Date.now()
|
|
13310
13313
|
).run();
|
|
13311
|
-
await
|
|
13314
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13312
13315
|
db,
|
|
13313
13316
|
user.userId,
|
|
13314
13317
|
"user!.create",
|
|
@@ -13347,7 +13350,7 @@ userRoutes.get("/users/:id", async (c) => {
|
|
|
13347
13350
|
if (!userRecord) {
|
|
13348
13351
|
return c.json({ error: "User not found" }, 404);
|
|
13349
13352
|
}
|
|
13350
|
-
await
|
|
13353
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13351
13354
|
db,
|
|
13352
13355
|
user.userId,
|
|
13353
13356
|
"user!.view",
|
|
@@ -13573,7 +13576,7 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
13573
13576
|
userId
|
|
13574
13577
|
).run();
|
|
13575
13578
|
if (newPassword) {
|
|
13576
|
-
const passwordHash = await
|
|
13579
|
+
const passwordHash = await chunk7A4CB7T3_cjs.AuthManager.hashPassword(newPassword);
|
|
13577
13580
|
const updatePasswordStmt = db.prepare(`
|
|
13578
13581
|
UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?
|
|
13579
13582
|
`);
|
|
@@ -13627,7 +13630,7 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
13627
13630
|
).run();
|
|
13628
13631
|
}
|
|
13629
13632
|
}
|
|
13630
|
-
await
|
|
13633
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13631
13634
|
db,
|
|
13632
13635
|
user.userId,
|
|
13633
13636
|
"user.update",
|
|
@@ -13672,7 +13675,7 @@ userRoutes.post("/users/:id/toggle", async (c) => {
|
|
|
13672
13675
|
UPDATE users SET is_active = ?, updated_at = ? WHERE id = ?
|
|
13673
13676
|
`);
|
|
13674
13677
|
await toggleStmt.bind(active ? 1 : 0, Date.now(), userId).run();
|
|
13675
|
-
await
|
|
13678
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13676
13679
|
db,
|
|
13677
13680
|
user.userId,
|
|
13678
13681
|
active ? "user.activate" : "user.deactivate",
|
|
@@ -13713,7 +13716,7 @@ userRoutes.delete("/users/:id", async (c) => {
|
|
|
13713
13716
|
DELETE FROM users WHERE id = ?
|
|
13714
13717
|
`);
|
|
13715
13718
|
await deleteStmt.bind(userId).run();
|
|
13716
|
-
await
|
|
13719
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13717
13720
|
db,
|
|
13718
13721
|
user.userId,
|
|
13719
13722
|
"user!.hard_delete",
|
|
@@ -13732,7 +13735,7 @@ userRoutes.delete("/users/:id", async (c) => {
|
|
|
13732
13735
|
UPDATE users SET is_active = 0, updated_at = ? WHERE id = ?
|
|
13733
13736
|
`);
|
|
13734
13737
|
await deleteStmt.bind(Date.now(), userId).run();
|
|
13735
|
-
await
|
|
13738
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13736
13739
|
db,
|
|
13737
13740
|
user.userId,
|
|
13738
13741
|
"user!.soft_delete",
|
|
@@ -13798,7 +13801,7 @@ userRoutes.post("/invite-user", async (c) => {
|
|
|
13798
13801
|
Date.now(),
|
|
13799
13802
|
Date.now()
|
|
13800
13803
|
).run();
|
|
13801
|
-
await
|
|
13804
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13802
13805
|
db,
|
|
13803
13806
|
user.userId,
|
|
13804
13807
|
"user!.invite_sent",
|
|
@@ -13855,7 +13858,7 @@ userRoutes.post("/resend-invitation/:id", async (c) => {
|
|
|
13855
13858
|
Date.now(),
|
|
13856
13859
|
userId
|
|
13857
13860
|
).run();
|
|
13858
|
-
await
|
|
13861
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13859
13862
|
db,
|
|
13860
13863
|
user.userId,
|
|
13861
13864
|
"user!.invitation_resent",
|
|
@@ -13891,7 +13894,7 @@ userRoutes.delete("/cancel-invitation/:id", async (c) => {
|
|
|
13891
13894
|
}
|
|
13892
13895
|
const deleteStmt = db.prepare(`DELETE FROM users WHERE id = ?`);
|
|
13893
13896
|
await deleteStmt.bind(userId).run();
|
|
13894
|
-
await
|
|
13897
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13895
13898
|
db,
|
|
13896
13899
|
user.userId,
|
|
13897
13900
|
"user!.invitation_cancelled",
|
|
@@ -13974,7 +13977,7 @@ userRoutes.get("/activity-logs", async (c) => {
|
|
|
13974
13977
|
...log,
|
|
13975
13978
|
details: log.details ? JSON.parse(log.details) : null
|
|
13976
13979
|
}));
|
|
13977
|
-
await
|
|
13980
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
13978
13981
|
db,
|
|
13979
13982
|
user.userId,
|
|
13980
13983
|
"activity.logs_viewed",
|
|
@@ -14081,7 +14084,7 @@ userRoutes.get("/activity-logs/export", async (c) => {
|
|
|
14081
14084
|
csvRows.push(row.join(","));
|
|
14082
14085
|
}
|
|
14083
14086
|
const csvContent = csvRows.join("\n");
|
|
14084
|
-
await
|
|
14087
|
+
await chunk7A4CB7T3_cjs.logActivity(
|
|
14085
14088
|
db,
|
|
14086
14089
|
user.userId,
|
|
14087
14090
|
"activity.logs_exported",
|
|
@@ -15420,7 +15423,7 @@ var fileValidationSchema2 = zod.z.object({
|
|
|
15420
15423
|
// 50MB max
|
|
15421
15424
|
});
|
|
15422
15425
|
var adminMediaRoutes = new hono.Hono();
|
|
15423
|
-
adminMediaRoutes.use("*",
|
|
15426
|
+
adminMediaRoutes.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
15424
15427
|
adminMediaRoutes.get("/", async (c) => {
|
|
15425
15428
|
try {
|
|
15426
15429
|
const user = c.get("user");
|
|
@@ -15812,8 +15815,8 @@ adminMediaRoutes.post("/upload", async (c) => {
|
|
|
15812
15815
|
});
|
|
15813
15816
|
continue;
|
|
15814
15817
|
}
|
|
15815
|
-
let width;
|
|
15816
|
-
let height;
|
|
15818
|
+
let width = null;
|
|
15819
|
+
let height = null;
|
|
15817
15820
|
if (file.type.startsWith("image/") && !file.type.includes("svg")) {
|
|
15818
15821
|
try {
|
|
15819
15822
|
const dimensions = await getImageDimensions2(arrayBuffer);
|
|
@@ -15824,7 +15827,7 @@ adminMediaRoutes.post("/upload", async (c) => {
|
|
|
15824
15827
|
}
|
|
15825
15828
|
}
|
|
15826
15829
|
const publicUrl = `/files/${r2Key}`;
|
|
15827
|
-
const thumbnailUrl = file.type.startsWith("image/") ? publicUrl :
|
|
15830
|
+
const thumbnailUrl = file.type.startsWith("image/") ? publicUrl : null;
|
|
15828
15831
|
const stmt = c.env.DB.prepare(`
|
|
15829
15832
|
INSERT INTO media (
|
|
15830
15833
|
id, filename, original_name, mime_type, size, width, height,
|
|
@@ -16006,7 +16009,7 @@ adminMediaRoutes.put("/:id", async (c) => {
|
|
|
16006
16009
|
`);
|
|
16007
16010
|
}
|
|
16008
16011
|
});
|
|
16009
|
-
adminMediaRoutes.delete("/cleanup",
|
|
16012
|
+
adminMediaRoutes.delete("/cleanup", chunk7A4CB7T3_cjs.requireRole("admin"), async (c) => {
|
|
16010
16013
|
try {
|
|
16011
16014
|
const db = c.env.DB;
|
|
16012
16015
|
const allMediaStmt = db.prepare("SELECT id, r2_key, filename FROM media WHERE deleted_at IS NULL");
|
|
@@ -18349,8 +18352,8 @@ function renderEmailSettingsContent(plugin, settings) {
|
|
|
18349
18352
|
|
|
18350
18353
|
// src/routes/admin-plugins.ts
|
|
18351
18354
|
var adminPluginRoutes = new hono.Hono();
|
|
18352
|
-
adminPluginRoutes.use("*",
|
|
18353
|
-
var AVAILABLE_PLUGINS = Object.values(
|
|
18355
|
+
adminPluginRoutes.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
18356
|
+
var AVAILABLE_PLUGINS = Object.values(chunkE4YFJBM2_cjs.PLUGIN_REGISTRY).map((p) => ({
|
|
18354
18357
|
id: p.id,
|
|
18355
18358
|
name: p.codeName,
|
|
18356
18359
|
display_name: p.displayName,
|
|
@@ -18370,7 +18373,7 @@ adminPluginRoutes.get("/", async (c) => {
|
|
|
18370
18373
|
if (user?.role !== "admin") {
|
|
18371
18374
|
return c.text("Access denied", 403);
|
|
18372
18375
|
}
|
|
18373
|
-
const pluginService = new
|
|
18376
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
18374
18377
|
let installedPlugins = [];
|
|
18375
18378
|
let stats = { total: 0, active: 0, inactive: 0, errors: 0, uninstalled: 0 };
|
|
18376
18379
|
try {
|
|
@@ -18442,7 +18445,7 @@ adminPluginRoutes.get("/:id", async (c) => {
|
|
|
18442
18445
|
if (user?.role !== "admin") {
|
|
18443
18446
|
return c.redirect("/admin/plugins");
|
|
18444
18447
|
}
|
|
18445
|
-
const pluginService = new
|
|
18448
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
18446
18449
|
const plugin = await pluginService.getPlugin(pluginId);
|
|
18447
18450
|
if (!plugin) {
|
|
18448
18451
|
return c.text("Plugin not found", 404);
|
|
@@ -18518,7 +18521,7 @@ adminPluginRoutes.post("/:id/activate", async (c) => {
|
|
|
18518
18521
|
if (user?.role !== "admin") {
|
|
18519
18522
|
return c.json({ error: "Access denied" }, 403);
|
|
18520
18523
|
}
|
|
18521
|
-
const pluginService = new
|
|
18524
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
18522
18525
|
await pluginService.activatePlugin(pluginId);
|
|
18523
18526
|
return c.json({ success: true });
|
|
18524
18527
|
} catch (error) {
|
|
@@ -18535,7 +18538,7 @@ adminPluginRoutes.post("/:id/deactivate", async (c) => {
|
|
|
18535
18538
|
if (user?.role !== "admin") {
|
|
18536
18539
|
return c.json({ error: "Access denied" }, 403);
|
|
18537
18540
|
}
|
|
18538
|
-
const pluginService = new
|
|
18541
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
18539
18542
|
await pluginService.deactivatePlugin(pluginId);
|
|
18540
18543
|
return c.json({ success: true });
|
|
18541
18544
|
} catch (error) {
|
|
@@ -18552,8 +18555,8 @@ adminPluginRoutes.post("/install", async (c) => {
|
|
|
18552
18555
|
return c.json({ error: "Access denied" }, 403);
|
|
18553
18556
|
}
|
|
18554
18557
|
const body = await c.req.json();
|
|
18555
|
-
const pluginService = new
|
|
18556
|
-
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];
|
|
18557
18560
|
if (!registryEntry) {
|
|
18558
18561
|
return c.json({ error: "Plugin not found in registry" }, 404);
|
|
18559
18562
|
}
|
|
@@ -18586,7 +18589,7 @@ adminPluginRoutes.post("/:id/uninstall", async (c) => {
|
|
|
18586
18589
|
if (user?.role !== "admin") {
|
|
18587
18590
|
return c.json({ error: "Access denied" }, 403);
|
|
18588
18591
|
}
|
|
18589
|
-
const pluginService = new
|
|
18592
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
18590
18593
|
await pluginService.uninstallPlugin(pluginId);
|
|
18591
18594
|
return c.json({ success: true });
|
|
18592
18595
|
} catch (error) {
|
|
@@ -18604,7 +18607,7 @@ adminPluginRoutes.post("/:id/settings", async (c) => {
|
|
|
18604
18607
|
return c.json({ error: "Access denied" }, 403);
|
|
18605
18608
|
}
|
|
18606
18609
|
const settings = await c.req.json();
|
|
18607
|
-
const pluginService = new
|
|
18610
|
+
const pluginService = new chunkE4YFJBM2_cjs.PluginService(db);
|
|
18608
18611
|
await pluginService.updatePluginSettings(pluginId, settings);
|
|
18609
18612
|
if (pluginId === "core-auth") {
|
|
18610
18613
|
try {
|
|
@@ -19412,7 +19415,7 @@ function renderLogConfigPage(data) {
|
|
|
19412
19415
|
|
|
19413
19416
|
// src/routes/admin-logs.ts
|
|
19414
19417
|
var adminLogsRoutes = new hono.Hono();
|
|
19415
|
-
adminLogsRoutes.use("*",
|
|
19418
|
+
adminLogsRoutes.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
19416
19419
|
adminLogsRoutes.get("/", async (c) => {
|
|
19417
19420
|
try {
|
|
19418
19421
|
const user = c.get("user");
|
|
@@ -21740,9 +21743,9 @@ function renderStorageUsage(databaseSizeBytes, mediaSizeBytes) {
|
|
|
21740
21743
|
}
|
|
21741
21744
|
|
|
21742
21745
|
// src/routes/admin-dashboard.ts
|
|
21743
|
-
var VERSION =
|
|
21746
|
+
var VERSION = chunkJZVHLLSI_cjs.getCoreVersion();
|
|
21744
21747
|
var router = new hono.Hono();
|
|
21745
|
-
router.use("*",
|
|
21748
|
+
router.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
21746
21749
|
router.get("/", async (c) => {
|
|
21747
21750
|
const user = c.get("user");
|
|
21748
21751
|
try {
|
|
@@ -22610,6 +22613,22 @@ function renderCollectionFormPage(data) {
|
|
|
22610
22613
|
<h2 class="text-base/7 font-semibold text-zinc-950 dark:text-white">Collection Details</h2>
|
|
22611
22614
|
<p class="text-sm/6 text-zinc-500 dark:text-zinc-400">Configure your collection settings below</p>
|
|
22612
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
|
+
` : ""}
|
|
22613
22632
|
</div>
|
|
22614
22633
|
</div>
|
|
22615
22634
|
|
|
@@ -23069,6 +23088,176 @@ function renderCollectionFormPage(data) {
|
|
|
23069
23088
|
</div>
|
|
23070
23089
|
</div>
|
|
23071
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
|
+
` : ""}
|
|
23072
23261
|
<script>
|
|
23073
23262
|
const collectionId = '${data.id || ""}';
|
|
23074
23263
|
|
|
@@ -23561,10 +23750,10 @@ function renderCollectionFormPage(data) {
|
|
|
23561
23750
|
|
|
23562
23751
|
// src/routes/admin-collections.ts
|
|
23563
23752
|
var adminCollectionsRoutes = new hono.Hono();
|
|
23564
|
-
adminCollectionsRoutes.use("*",
|
|
23565
|
-
adminCollectionsRoutes.post("*",
|
|
23566
|
-
adminCollectionsRoutes.put("*",
|
|
23567
|
-
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"]));
|
|
23568
23757
|
adminCollectionsRoutes.get("/", async (c) => {
|
|
23569
23758
|
try {
|
|
23570
23759
|
const user = c.get("user");
|
|
@@ -25859,7 +26048,7 @@ function renderDatabaseToolsSettings(settings) {
|
|
|
25859
26048
|
|
|
25860
26049
|
// src/routes/admin-settings.ts
|
|
25861
26050
|
var adminSettingsRoutes = new hono.Hono();
|
|
25862
|
-
adminSettingsRoutes.use("*",
|
|
26051
|
+
adminSettingsRoutes.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
25863
26052
|
function getMockSettings(user) {
|
|
25864
26053
|
return {
|
|
25865
26054
|
general: {
|
|
@@ -26036,7 +26225,7 @@ adminSettingsRoutes.get("/database-tools", (c) => {
|
|
|
26036
26225
|
adminSettingsRoutes.get("/api/migrations/status", async (c) => {
|
|
26037
26226
|
try {
|
|
26038
26227
|
const db = c.env.DB;
|
|
26039
|
-
const migrationService = new
|
|
26228
|
+
const migrationService = new chunkRLMUFFUD_cjs.MigrationService(db);
|
|
26040
26229
|
const status = await migrationService.getMigrationStatus();
|
|
26041
26230
|
return c.json({
|
|
26042
26231
|
success: true,
|
|
@@ -26060,7 +26249,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
|
|
|
26060
26249
|
}, 403);
|
|
26061
26250
|
}
|
|
26062
26251
|
const db = c.env.DB;
|
|
26063
|
-
const migrationService = new
|
|
26252
|
+
const migrationService = new chunkRLMUFFUD_cjs.MigrationService(db);
|
|
26064
26253
|
const result = await migrationService.runPendingMigrations();
|
|
26065
26254
|
return c.json({
|
|
26066
26255
|
success: result.success,
|
|
@@ -26078,7 +26267,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
|
|
|
26078
26267
|
adminSettingsRoutes.get("/api/migrations/validate", async (c) => {
|
|
26079
26268
|
try {
|
|
26080
26269
|
const db = c.env.DB;
|
|
26081
|
-
const migrationService = new
|
|
26270
|
+
const migrationService = new chunkRLMUFFUD_cjs.MigrationService(db);
|
|
26082
26271
|
const validation = await migrationService.validateSchema();
|
|
26083
26272
|
return c.json({
|
|
26084
26273
|
success: true,
|
|
@@ -28017,7 +28206,7 @@ function renderFormCreatePage(data) {
|
|
|
28017
28206
|
|
|
28018
28207
|
// src/routes/admin-forms.ts
|
|
28019
28208
|
var adminFormsRoutes = new hono.Hono();
|
|
28020
|
-
adminFormsRoutes.use("*",
|
|
28209
|
+
adminFormsRoutes.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
28021
28210
|
adminFormsRoutes.get("/", async (c) => {
|
|
28022
28211
|
try {
|
|
28023
28212
|
const user = c.get("user");
|
|
@@ -28822,7 +29011,7 @@ publicFormsRoutes.post("/:identifier/submit", async (c) => {
|
|
|
28822
29011
|
`).bind(now, form.id).run();
|
|
28823
29012
|
let contentId = null;
|
|
28824
29013
|
try {
|
|
28825
|
-
contentId = await
|
|
29014
|
+
contentId = await chunkE4YFJBM2_cjs.createContentFromSubmission(
|
|
28826
29015
|
db,
|
|
28827
29016
|
sanitizedData,
|
|
28828
29017
|
{ id: form.id, name: form.name, display_name: form.display_name },
|
|
@@ -29190,9 +29379,9 @@ function renderAPIReferencePage(data) {
|
|
|
29190
29379
|
}
|
|
29191
29380
|
|
|
29192
29381
|
// src/routes/admin-api-reference.ts
|
|
29193
|
-
var VERSION2 =
|
|
29382
|
+
var VERSION2 = chunkJZVHLLSI_cjs.getCoreVersion();
|
|
29194
29383
|
var router2 = new hono.Hono();
|
|
29195
|
-
router2.use("*",
|
|
29384
|
+
router2.use("*", chunk7A4CB7T3_cjs.requireAuth());
|
|
29196
29385
|
router2.get("/", async (c) => {
|
|
29197
29386
|
const user = c.get("user");
|
|
29198
29387
|
try {
|
|
@@ -29284,5 +29473,5 @@ exports.router2 = router2;
|
|
|
29284
29473
|
exports.test_cleanup_default = test_cleanup_default;
|
|
29285
29474
|
exports.userProfilesPlugin = userProfilesPlugin;
|
|
29286
29475
|
exports.userRoutes = userRoutes;
|
|
29287
|
-
//# sourceMappingURL=chunk-
|
|
29288
|
-
//# sourceMappingURL=chunk-
|
|
29476
|
+
//# sourceMappingURL=chunk-R4FOLLFB.cjs.map
|
|
29477
|
+
//# sourceMappingURL=chunk-R4FOLLFB.cjs.map
|