@access-dlsu/leapify 0.260524.3 → 0.260601.1
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/auth/auth.d.ts +2 -2
- package/dist/{chunk-AKCERDGP.js → chunk-2JEY6TSO.js} +2 -2
- package/dist/chunk-2JEY6TSO.js.map +1 -0
- package/dist/{chunk-64MMUYMK.cjs → chunk-X4OB4DZ3.cjs} +2 -2
- package/dist/chunk-X4OB4DZ3.cjs.map +1 -0
- package/dist/client/auth.d.ts +57 -41
- package/dist/client/auth.d.ts.map +1 -1
- package/dist/client/index.cjs +2 -0
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.js +2 -0
- package/dist/client/index.js.map +1 -1
- package/dist/index.cjs +129 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +125 -60
- package/dist/index.js.map +1 -1
- package/dist/lib/middleware/cors.d.ts.map +1 -1
- package/dist/lib/middleware/referer-guard.d.ts +1 -1
- package/dist/lib/middleware/referer-guard.d.ts.map +1 -1
- package/dist/lib/middleware/turnstile-challenge.cjs +6 -6
- package/dist/lib/middleware/turnstile-challenge.js +1 -1
- package/dist/routes/site-config.d.ts +2 -2
- package/dist/routes/site-config.d.ts.map +1 -1
- package/dist/worker.js +278 -213
- package/dist/worker.js.map +1 -1
- package/package.json +155 -155
- package/dist/chunk-64MMUYMK.cjs.map +0 -1
- package/dist/chunk-AKCERDGP.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkX4OB4DZ3_cjs = require('./chunk-X4OB4DZ3.cjs');
|
|
4
4
|
var chunkQ7SFCCGT_cjs = require('./chunk-Q7SFCCGT.cjs');
|
|
5
5
|
var hono = require('hono');
|
|
6
6
|
var cors = require('hono/cors');
|
|
7
|
+
var d1 = require('drizzle-orm/d1');
|
|
8
|
+
var sqliteCore = require('drizzle-orm/sqlite-core');
|
|
9
|
+
var drizzleOrm = require('drizzle-orm');
|
|
7
10
|
var factory = require('hono/factory');
|
|
8
11
|
var betterAuth = require('better-auth');
|
|
9
12
|
var drizzle = require('better-auth/adapters/drizzle');
|
|
10
13
|
var plugins = require('better-auth/plugins');
|
|
11
|
-
var drizzleOrm = require('drizzle-orm');
|
|
12
|
-
var d1 = require('drizzle-orm/d1');
|
|
13
|
-
var sqliteCore = require('drizzle-orm/sqlite-core');
|
|
14
14
|
var zodValidator = require('@hono/zod-validator');
|
|
15
15
|
var zod = require('zod');
|
|
16
16
|
|
|
@@ -22,6 +22,8 @@ var LeapifyError = class extends Error {
|
|
|
22
22
|
this.code = code;
|
|
23
23
|
this.name = "LeapifyError";
|
|
24
24
|
}
|
|
25
|
+
statusCode;
|
|
26
|
+
code;
|
|
25
27
|
};
|
|
26
28
|
var unauthorized = (message = "Unauthorized") => new LeapifyError(401, "UNAUTHORIZED", message);
|
|
27
29
|
var domainRestricted = () => new LeapifyError(
|
|
@@ -50,58 +52,6 @@ var errorHandler = (err, c) => {
|
|
|
50
52
|
500
|
|
51
53
|
);
|
|
52
54
|
};
|
|
53
|
-
function createCorsMiddleware(allowedOrigins) {
|
|
54
|
-
return async (c, next) => {
|
|
55
|
-
const origin = c.req.header("origin");
|
|
56
|
-
const dynamicOriginsJson = await c.env.KV.get("config:allowed_origins", "json");
|
|
57
|
-
const currentAllowedOrigins = dynamicOriginsJson ?? allowedOrigins;
|
|
58
|
-
if (c.req.path.startsWith("/api/uploads/images")) {
|
|
59
|
-
c.header("Access-Control-Allow-Origin", "*");
|
|
60
|
-
c.header("Access-Control-Allow-Methods", "GET, OPTIONS");
|
|
61
|
-
if (c.req.method === "OPTIONS") {
|
|
62
|
-
return c.body(null, 204);
|
|
63
|
-
}
|
|
64
|
-
return next();
|
|
65
|
-
}
|
|
66
|
-
if (!c.req.path.startsWith("/health") && !c.req.path.startsWith("/api/auth") && !c.req.path.startsWith("/internal") && origin && !currentAllowedOrigins.includes("*") && !currentAllowedOrigins.includes(origin)) {
|
|
67
|
-
return c.json(
|
|
68
|
-
{
|
|
69
|
-
error: {
|
|
70
|
-
code: "DOMAIN_RESTRICTED",
|
|
71
|
-
message: `Origin ${origin} is not allowed`
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
403
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
const honoCors = cors.cors({
|
|
78
|
-
origin: currentAllowedOrigins,
|
|
79
|
-
allowMethods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"],
|
|
80
|
-
allowHeaders: ["Content-Type", "Authorization"],
|
|
81
|
-
exposeHeaders: ["ETag", "Last-Modified", "Cache-Control"],
|
|
82
|
-
maxAge: 86400,
|
|
83
|
-
credentials: true
|
|
84
|
-
});
|
|
85
|
-
return honoCors(c, next);
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
function createRefererGuard(allowedOrigins) {
|
|
89
|
-
const MUTATION_METHODS = /* @__PURE__ */ new Set(["POST", "PATCH", "PUT", "DELETE"]);
|
|
90
|
-
const SKIP_PREFIXES = ["/health", "/internal", "/api/auth", "/.well-known"];
|
|
91
|
-
return factory.createMiddleware(async (c, next) => {
|
|
92
|
-
if (!MUTATION_METHODS.has(c.req.method)) return next();
|
|
93
|
-
if (SKIP_PREFIXES.some((p) => c.req.path.startsWith(p))) return next();
|
|
94
|
-
const dynamicOriginsJson = await c.env.KV.get("config:allowed_origins", "json");
|
|
95
|
-
const currentAllowedOrigins = dynamicOriginsJson ?? allowedOrigins;
|
|
96
|
-
if (currentAllowedOrigins.includes("*")) return next();
|
|
97
|
-
const referer = c.req.header("referer") ?? "";
|
|
98
|
-
const isAllowed = currentAllowedOrigins.some((origin) => referer.startsWith(origin));
|
|
99
|
-
if (!isAllowed) {
|
|
100
|
-
throw forbidden("Request origin not permitted");
|
|
101
|
-
}
|
|
102
|
-
return next();
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
55
|
|
|
106
56
|
// src/db/schema/index.ts
|
|
107
57
|
var schema_exports = {};
|
|
@@ -334,8 +284,112 @@ var authVerification = sqliteCore.sqliteTable(
|
|
|
334
284
|
function createDb(d1$1) {
|
|
335
285
|
return d1.drizzle(d1$1, { schema: schema_exports });
|
|
336
286
|
}
|
|
337
|
-
|
|
338
|
-
|
|
287
|
+
async function getOriginsFromDb(env) {
|
|
288
|
+
try {
|
|
289
|
+
const db = createDb(env.DB);
|
|
290
|
+
const row = await db.query.siteConfig.findFirst({
|
|
291
|
+
where: drizzleOrm.eq(siteConfig.key, "allowed_origins")
|
|
292
|
+
});
|
|
293
|
+
if (row) return JSON.parse(row.value);
|
|
294
|
+
} catch {
|
|
295
|
+
}
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
function createCorsMiddleware(allowedOrigins) {
|
|
299
|
+
return async (c, next) => {
|
|
300
|
+
const origin = c.req.header("origin");
|
|
301
|
+
const dynamicOriginsJson = await c.env.KV.get(
|
|
302
|
+
"config:allowed_origins",
|
|
303
|
+
"json"
|
|
304
|
+
);
|
|
305
|
+
let currentAllowedOrigins = dynamicOriginsJson ?? allowedOrigins;
|
|
306
|
+
if (!dynamicOriginsJson) {
|
|
307
|
+
const dbOrigins = await getOriginsFromDb(c.env);
|
|
308
|
+
if (dbOrigins) {
|
|
309
|
+
currentAllowedOrigins = dbOrigins;
|
|
310
|
+
await c.env.KV.put(
|
|
311
|
+
"config:allowed_origins",
|
|
312
|
+
JSON.stringify(dbOrigins),
|
|
313
|
+
{ expirationTtl: 86400 }
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
if (c.req.path.startsWith("/api/uploads/images")) {
|
|
318
|
+
c.header("Access-Control-Allow-Origin", "*");
|
|
319
|
+
c.header("Access-Control-Allow-Methods", "GET, OPTIONS");
|
|
320
|
+
if (c.req.method === "OPTIONS") {
|
|
321
|
+
return c.body(null, 204);
|
|
322
|
+
}
|
|
323
|
+
return next();
|
|
324
|
+
}
|
|
325
|
+
if (!c.req.path.startsWith("/health") && !c.req.path.startsWith("/api/auth") && !c.req.path.startsWith("/internal") && origin && !currentAllowedOrigins.includes("*") && !currentAllowedOrigins.includes(origin) && origin !== new URL(c.req.url).origin) {
|
|
326
|
+
return c.json(
|
|
327
|
+
{
|
|
328
|
+
error: {
|
|
329
|
+
code: "DOMAIN_RESTRICTED",
|
|
330
|
+
message: `Origin ${origin} is not allowed`
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
403
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
const honoCors = cors.cors({
|
|
337
|
+
origin: currentAllowedOrigins,
|
|
338
|
+
allowMethods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"],
|
|
339
|
+
allowHeaders: ["Content-Type", "Authorization"],
|
|
340
|
+
exposeHeaders: ["ETag", "Last-Modified", "Cache-Control"],
|
|
341
|
+
maxAge: 86400,
|
|
342
|
+
credentials: true
|
|
343
|
+
});
|
|
344
|
+
return honoCors(c, next);
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
async function getOriginsFromDb2(env) {
|
|
348
|
+
try {
|
|
349
|
+
const db = createDb(env.DB);
|
|
350
|
+
const row = await db.query.siteConfig.findFirst({
|
|
351
|
+
where: drizzleOrm.eq(siteConfig.key, "allowed_origins")
|
|
352
|
+
});
|
|
353
|
+
if (row) return JSON.parse(row.value);
|
|
354
|
+
} catch {
|
|
355
|
+
}
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
function createRefererGuard(allowedOrigins) {
|
|
359
|
+
const MUTATION_METHODS = /* @__PURE__ */ new Set(["POST", "PATCH", "PUT", "DELETE"]);
|
|
360
|
+
const SKIP_PREFIXES = ["/health", "/internal", "/api/auth", "/.well-known"];
|
|
361
|
+
return factory.createMiddleware(async (c, next) => {
|
|
362
|
+
if (!MUTATION_METHODS.has(c.req.method)) return next();
|
|
363
|
+
if (SKIP_PREFIXES.some((p) => c.req.path.startsWith(p))) return next();
|
|
364
|
+
const dynamicOriginsJson = await c.env.KV.get(
|
|
365
|
+
"config:allowed_origins",
|
|
366
|
+
"json"
|
|
367
|
+
);
|
|
368
|
+
let currentAllowedOrigins = dynamicOriginsJson ?? allowedOrigins;
|
|
369
|
+
if (!dynamicOriginsJson) {
|
|
370
|
+
const dbOrigins = await getOriginsFromDb2(c.env);
|
|
371
|
+
if (dbOrigins) {
|
|
372
|
+
currentAllowedOrigins = dbOrigins;
|
|
373
|
+
await c.env.KV.put(
|
|
374
|
+
"config:allowed_origins",
|
|
375
|
+
JSON.stringify(dbOrigins),
|
|
376
|
+
{ expirationTtl: 86400 }
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
if (currentAllowedOrigins.includes("*")) return next();
|
|
381
|
+
const referer = c.req.header("referer") ?? "";
|
|
382
|
+
const requestOrigin = new URL(c.req.url).origin;
|
|
383
|
+
if (referer.startsWith(requestOrigin)) return next();
|
|
384
|
+
const isAllowed = currentAllowedOrigins.some(
|
|
385
|
+
(origin) => referer.startsWith(origin)
|
|
386
|
+
);
|
|
387
|
+
if (!isAllowed) {
|
|
388
|
+
throw forbidden("Request origin not permitted");
|
|
389
|
+
}
|
|
390
|
+
return next();
|
|
391
|
+
});
|
|
392
|
+
}
|
|
339
393
|
var DLSU_DOMAIN = "@dlsu.edu.ph";
|
|
340
394
|
function createAuth(env) {
|
|
341
395
|
const db = createDb(env.DB);
|
|
@@ -631,7 +685,14 @@ healthRoute.get("/", async (c) => {
|
|
|
631
685
|
const env = c.env;
|
|
632
686
|
const hasSes = Boolean(env.SES_REGION) && Boolean(env.SES_ACCESS_KEY_ID) && Boolean(env.SES_SECRET_ACCESS_KEY);
|
|
633
687
|
const hasResend = Boolean(env.RESEND_API_KEY);
|
|
634
|
-
|
|
688
|
+
let hasGForms = false;
|
|
689
|
+
if (env.GFORMS_SERVICE_ACCOUNT_JSON) {
|
|
690
|
+
try {
|
|
691
|
+
const parsed = JSON.parse(env.GFORMS_SERVICE_ACCOUNT_JSON);
|
|
692
|
+
hasGForms = Boolean(parsed.client_email && parsed.private_key);
|
|
693
|
+
} catch {
|
|
694
|
+
}
|
|
695
|
+
}
|
|
635
696
|
const probes = [];
|
|
636
697
|
if (hasSes) {
|
|
637
698
|
probes.push(
|
|
@@ -689,6 +750,7 @@ var CacheService = class {
|
|
|
689
750
|
constructor(kv) {
|
|
690
751
|
this.kv = kv;
|
|
691
752
|
}
|
|
753
|
+
kv;
|
|
692
754
|
async get(key) {
|
|
693
755
|
return this.kv.get(key, "json");
|
|
694
756
|
}
|
|
@@ -734,6 +796,8 @@ var SlotsService = class {
|
|
|
734
796
|
this.db = db;
|
|
735
797
|
this.cache = cache;
|
|
736
798
|
}
|
|
799
|
+
db;
|
|
800
|
+
cache;
|
|
737
801
|
kvKey(slug) {
|
|
738
802
|
return `${SLOT_KV_PREFIX}${slug}`;
|
|
739
803
|
}
|
|
@@ -1348,7 +1412,7 @@ siteConfigRoute.patch("/:key", authMiddleware, adminMiddleware, async (c) => {
|
|
|
1348
1412
|
set: { value: JSON.stringify(value), updatedAt: now }
|
|
1349
1413
|
});
|
|
1350
1414
|
await c.env.KV.put(`config:${key}`, JSON.stringify(value), {
|
|
1351
|
-
expirationTtl:
|
|
1415
|
+
expirationTtl: 86400
|
|
1352
1416
|
});
|
|
1353
1417
|
return c.json({ data: { key, value } });
|
|
1354
1418
|
});
|
|
@@ -1694,7 +1758,7 @@ function createApp(options = {}) {
|
|
|
1694
1758
|
});
|
|
1695
1759
|
}
|
|
1696
1760
|
app.use("*", createCorsMiddleware(options.allowedOrigins ?? ["*"]));
|
|
1697
|
-
app.use("*",
|
|
1761
|
+
app.use("*", chunkX4OB4DZ3_cjs.createTurnstileMiddleware());
|
|
1698
1762
|
app.use("*", createRefererGuard(options.allowedOrigins ?? ["*"]));
|
|
1699
1763
|
app.on(["POST", "GET"], "/api/auth/*", (c) => {
|
|
1700
1764
|
const auth = createAuth(c.env);
|
|
@@ -1725,7 +1789,7 @@ function createApp(options = {}) {
|
|
|
1725
1789
|
}
|
|
1726
1790
|
return next();
|
|
1727
1791
|
});
|
|
1728
|
-
app.post(
|
|
1792
|
+
app.post(chunkX4OB4DZ3_cjs.TURNSTILE_VERIFY_PATH, chunkX4OB4DZ3_cjs.handleTurnstileVerify);
|
|
1729
1793
|
app.route("/health", healthRoute);
|
|
1730
1794
|
app.route("/api/config", siteConfigRoute);
|
|
1731
1795
|
app.route("/api/classes", classesRoute);
|
|
@@ -1840,6 +1904,7 @@ var SesError = class extends Error {
|
|
|
1840
1904
|
this.status = status;
|
|
1841
1905
|
this.name = "SesError";
|
|
1842
1906
|
}
|
|
1907
|
+
status;
|
|
1843
1908
|
/**
|
|
1844
1909
|
* True for errors that are permanent (not worth retrying via SES again).
|
|
1845
1910
|
* 400 BadRequest, 403 Forbidden, 404 NotFound → non-retryable.
|
|
@@ -2532,7 +2597,7 @@ function defaultGetRuntimeConfig(env) {
|
|
|
2532
2597
|
};
|
|
2533
2598
|
}
|
|
2534
2599
|
function injectConfig(html, config) {
|
|
2535
|
-
const configScript = `<script>window.__CONFIG__=${JSON.stringify(config)}
|
|
2600
|
+
const configScript = `<script>window.__CONFIG__=${JSON.stringify(config)};</script>`;
|
|
2536
2601
|
return html.replace("</head>", `${configScript}</head>`);
|
|
2537
2602
|
}
|
|
2538
2603
|
function createWorkerHandler(options) {
|
|
@@ -2654,7 +2719,7 @@ function getRuntimeConfig(env) {
|
|
|
2654
2719
|
};
|
|
2655
2720
|
}
|
|
2656
2721
|
function injectConfig2(html, config) {
|
|
2657
|
-
const configScript = `<script>window.__CONFIG__=${JSON.stringify(config)}
|
|
2722
|
+
const configScript = `<script>window.__CONFIG__=${JSON.stringify(config)};</script>`;
|
|
2658
2723
|
return html.replace("</head>", `${configScript}</head>`);
|
|
2659
2724
|
}
|
|
2660
2725
|
|