@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/index.cjs CHANGED
@@ -1,16 +1,16 @@
1
1
  'use strict';
2
2
 
3
- var chunk64MMUYMK_cjs = require('./chunk-64MMUYMK.cjs');
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
- // src/auth/auth.ts
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
- const hasGForms = Boolean(env.GFORMS_SERVICE_ACCOUNT_JSON);
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: 600
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("*", chunk64MMUYMK_cjs.createTurnstileMiddleware());
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(chunk64MMUYMK_cjs.TURNSTILE_VERIFY_PATH, chunk64MMUYMK_cjs.handleTurnstileVerify);
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)};<\/script>`;
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)};<\/script>`;
2722
+ const configScript = `<script>window.__CONFIG__=${JSON.stringify(config)};</script>`;
2658
2723
  return html.replace("</head>", `${configScript}</head>`);
2659
2724
  }
2660
2725