@xk2800/nextjs-template 0.7.1-beta.3 → 0.7.1-beta.5
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/README.md +1 -1
- package/components/auth/deviceCheck.tsx +47 -6
- package/components/auth/oneTap.tsx +5 -5
- package/components/dashboard/admin/adminUserConsentCard.tsx +79 -0
- package/components/dashboard/admin/adminUserDevicesCard.tsx +80 -0
- package/components/dashboard/admin/systemSettingsForm.tsx +33 -0
- package/components/dashboard/admin/systemSettingsSection.tsx +8 -2
- package/components/site/cookie-banner.tsx +109 -7
- package/dist/activity/logger.js +30 -0
- package/dist/activity/logger.js.map +1 -1
- package/dist/activity/logger.mjs +3 -3
- package/dist/activity/queries.d.mts +1 -1
- package/dist/activity/queries.d.ts +1 -1
- package/dist/activity/queries.js +30 -0
- package/dist/activity/queries.js.map +1 -1
- package/dist/activity/queries.mjs +2 -2
- package/dist/admin/queries.d.mts +19 -1
- package/dist/admin/queries.d.ts +19 -1
- package/dist/admin/queries.js +58 -0
- package/dist/admin/queries.js.map +1 -1
- package/dist/admin/queries.mjs +25 -4
- package/dist/admin/queries.mjs.map +1 -1
- package/dist/api/feedback.js +46 -2
- package/dist/api/feedback.js.map +1 -1
- package/dist/api/feedback.mjs +7 -7
- package/dist/auth/helpers.js +44 -0
- package/dist/auth/helpers.js.map +1 -1
- package/dist/auth/helpers.mjs +6 -6
- package/dist/auth/index.js +44 -0
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/index.mjs +6 -6
- package/dist/{chunk-XWVAJXAG.mjs → chunk-4GGLYS5R.mjs} +20 -8
- package/dist/chunk-4GGLYS5R.mjs.map +1 -0
- package/dist/{chunk-KAEA35OC.mjs → chunk-6KTSULA5.mjs} +4 -4
- package/dist/{chunk-KAEA35OC.mjs.map → chunk-6KTSULA5.mjs.map} +1 -1
- package/dist/{chunk-N6ECRCHY.mjs → chunk-6OAHCEDJ.mjs} +4 -3
- package/dist/chunk-6OAHCEDJ.mjs.map +1 -0
- package/dist/{chunk-3MGEAGHU.mjs → chunk-F776DQAM.mjs} +10 -5
- package/dist/chunk-F776DQAM.mjs.map +1 -0
- package/dist/{chunk-WZDAMCUX.mjs → chunk-F7CG5CA3.mjs} +3 -3
- package/dist/{chunk-WZDAMCUX.mjs.map → chunk-F7CG5CA3.mjs.map} +1 -1
- package/dist/{chunk-VQ5B4MA7.mjs → chunk-FVLMSLTX.mjs} +4 -4
- package/dist/{chunk-VQ5B4MA7.mjs.map → chunk-FVLMSLTX.mjs.map} +1 -1
- package/dist/{chunk-ZQCALTKB.mjs → chunk-TR5XFBTD.mjs} +34 -4
- package/dist/chunk-TR5XFBTD.mjs.map +1 -0
- package/dist/db/index.d.mts +1 -1
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.js +30 -0
- package/dist/db/index.js.map +1 -1
- package/dist/db/index.mjs +2 -2
- package/dist/db/schema.d.mts +1 -1
- package/dist/db/schema.d.ts +1 -1
- package/dist/db/schema.js +30 -0
- package/dist/db/schema.js.map +1 -1
- package/dist/db/schema.mjs +1 -1
- package/dist/errors.js +30 -0
- package/dist/errors.js.map +1 -1
- package/dist/errors.mjs +3 -3
- package/dist/{schema-UuqxoOzS.d.mts → schema-CN_Y6EXv.d.mts} +148 -2
- package/dist/{schema-UuqxoOzS.d.ts → schema-CN_Y6EXv.d.ts} +148 -2
- package/dist/sessions/queries.js +30 -0
- package/dist/sessions/queries.js.map +1 -1
- package/dist/sessions/queries.mjs +2 -2
- package/dist/settings/queries.d.mts +4 -3
- package/dist/settings/queries.d.ts +4 -3
- package/dist/settings/queries.js +36 -0
- package/dist/settings/queries.js.map +1 -1
- package/dist/settings/queries.mjs +3 -3
- package/dist/users/queries.js +30 -0
- package/dist/users/queries.js.map +1 -1
- package/dist/users/queries.mjs +2 -2
- package/lib/cookie-consent.ts +72 -20
- package/lib/cookie-names.ts +47 -0
- package/lib/device-fingerprint.ts +66 -10
- package/package.json +7 -2
- package/dist/chunk-3MGEAGHU.mjs.map +0 -1
- package/dist/chunk-N6ECRCHY.mjs.map +0 -1
- package/dist/chunk-XWVAJXAG.mjs.map +0 -1
- package/dist/chunk-ZQCALTKB.mjs.map +0 -1
package/dist/auth/index.js
CHANGED
|
@@ -207,6 +207,7 @@ __export(schema_exports, {
|
|
|
207
207
|
accounts: () => accounts,
|
|
208
208
|
activityLogs: () => activityLogs,
|
|
209
209
|
authThrottle: () => authThrottle,
|
|
210
|
+
consentLog: () => consentLog,
|
|
210
211
|
deviceFingerprints: () => deviceFingerprints,
|
|
211
212
|
errorRefs: () => errorRefs,
|
|
212
213
|
passkeys: () => passkeys,
|
|
@@ -361,10 +362,32 @@ var deviceFingerprints = pgCore.pgTable("device_fingerprint", {
|
|
|
361
362
|
userAgent: pgCore.text("userAgent"),
|
|
362
363
|
country: pgCore.text("country"),
|
|
363
364
|
city: pgCore.text("city"),
|
|
365
|
+
// Latest FingerprintJS signals for this device (lib/device-fingerprint.ts
|
|
366
|
+
// getDeviceSignals(): accessibility signals dropped, large values hashed),
|
|
367
|
+
// shown on the admin user page. Null for rows from before this column.
|
|
368
|
+
components: pgCore.jsonb("components").$type(),
|
|
364
369
|
createdAt: pgCore.timestamp("createdAt").notNull().defaultNow()
|
|
365
370
|
}, (table) => [
|
|
366
371
|
pgCore.unique("device_fingerprint_user_visitor").on(table.userId, table.visitorId)
|
|
367
372
|
]);
|
|
373
|
+
var consentLog = pgCore.pgTable("consent_log", {
|
|
374
|
+
id: pgCore.text("id").notNull().primaryKey().$defaultFn(() => cuid2.createId()),
|
|
375
|
+
userId: pgCore.text("userId").notNull().references(() => users.id, { onDelete: "cascade" }),
|
|
376
|
+
// The cookie_consent value: "all", "necessary" or a comma list of purposes.
|
|
377
|
+
choice: pgCore.text("choice").notNull(),
|
|
378
|
+
// CONSENT_VERSION (lib/cookie-names.ts) at the time — which banner/policy
|
|
379
|
+
// wording the user agreed to.
|
|
380
|
+
version: pgCore.integer("version").notNull(),
|
|
381
|
+
// id of the user's record this one follows ("" for their first). Unique per
|
|
382
|
+
// user, so concurrent posts from several tabs that all saw the same latest
|
|
383
|
+
// record can't each insert a duplicate — one wins, the rest conflict. Works
|
|
384
|
+
// without transactions (neon-http has none). Null on rows from before it.
|
|
385
|
+
previousId: pgCore.text("previousId"),
|
|
386
|
+
createdAt: pgCore.timestamp("createdAt").notNull().defaultNow()
|
|
387
|
+
}, (table) => [
|
|
388
|
+
pgCore.index("consent_log_user_idx").on(table.userId, table.createdAt),
|
|
389
|
+
pgCore.unique("consent_log_chain").on(table.userId, table.previousId)
|
|
390
|
+
]);
|
|
368
391
|
var authThrottle = pgCore.pgTable("auth_throttle", {
|
|
369
392
|
fingerprint: pgCore.text("fingerprint").notNull().primaryKey(),
|
|
370
393
|
count: pgCore.integer("count").notNull().default(0),
|
|
@@ -394,6 +417,13 @@ var systemSettings = pgCore.pgTable("system_settings", {
|
|
|
394
417
|
// Attach the error a user hit to feedback they send from it (see
|
|
395
418
|
// lib/feedback-route.ts). Off = only what the user typed is sent.
|
|
396
419
|
feedbackAttachErrors: pgCore.boolean("feedbackAttachErrors").notNull().default(true),
|
|
420
|
+
// GDPR/ePrivacy consent mode. On: cookie banner, FingerprintJS and One Tap
|
|
421
|
+
// only after "Accept all", device record erased on withdrawal. Off (no EU/UK
|
|
422
|
+
// users): no banner, treated as consented. Null = follow
|
|
423
|
+
// NEXT_PUBLIC_COOKIE_BANNER (nullable so migrating never flips a deployed
|
|
424
|
+
// banner on or off). proxy.ts mirrors the effective value into the
|
|
425
|
+
// consent_required cookie for the client (lib/cookie-consent.ts).
|
|
426
|
+
consentRequired: pgCore.boolean("consentRequired"),
|
|
397
427
|
updatedAt: pgCore.timestamp("updatedAt").notNull().defaultNow(),
|
|
398
428
|
// Who last changed a setting. This row doesn't "belong" to that admin the
|
|
399
429
|
// way sessions/activityLogs belong to their user, so deleting that admin's
|
|
@@ -554,6 +584,7 @@ var DEVICE_FINGERPRINT_HEADER = "x-device-fingerprint";
|
|
|
554
584
|
var WINDOW_MS = 15 * 60 * 1e3;
|
|
555
585
|
var MAX = 10;
|
|
556
586
|
var MAX_IP = MAX * 3;
|
|
587
|
+
var RETENTION_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
557
588
|
function isOverLimit(row, now, max = MAX) {
|
|
558
589
|
if (!row) return false;
|
|
559
590
|
if (now - row.windowStart.getTime() >= WINDOW_MS) return false;
|
|
@@ -591,6 +622,18 @@ async function recordDeviceAttempt(fingerprint, meta) {
|
|
|
591
622
|
} catch (error) {
|
|
592
623
|
console.error("auth-throttle write failed", error);
|
|
593
624
|
}
|
|
625
|
+
await pruneStaleRows(now);
|
|
626
|
+
}
|
|
627
|
+
var PRUNE_EVERY_MS = 60 * 60 * 1e3;
|
|
628
|
+
var lastPrune = 0;
|
|
629
|
+
async function pruneStaleRows(now = /* @__PURE__ */ new Date()) {
|
|
630
|
+
if (now.getTime() - lastPrune < PRUNE_EVERY_MS) return;
|
|
631
|
+
lastPrune = now.getTime();
|
|
632
|
+
try {
|
|
633
|
+
await db.delete(authThrottle).where(drizzleOrm.lt(authThrottle.lastAttemptAt, new Date(now.getTime() - RETENTION_MS)));
|
|
634
|
+
} catch (error) {
|
|
635
|
+
console.error("auth-throttle prune failed", error);
|
|
636
|
+
}
|
|
594
637
|
}
|
|
595
638
|
async function clearDeviceThrottle(fingerprint) {
|
|
596
639
|
try {
|
|
@@ -613,6 +656,7 @@ function fallbackSettings() {
|
|
|
613
656
|
authEnableOneTap: config.AUTH_ENABLE_ONE_TAP,
|
|
614
657
|
enableSessionRevocation: config.ENABLE_SESSION_REVOCATION,
|
|
615
658
|
feedbackAttachErrors: true,
|
|
659
|
+
consentRequired: null,
|
|
616
660
|
updatedAt: /* @__PURE__ */ new Date(0),
|
|
617
661
|
updatedBy: null
|
|
618
662
|
};
|