-
Notifications
You must be signed in to change notification settings - Fork 0
Enhance link management with folders, audits, and admin UI #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
21a5cdd
feat: v2.1 link management, domains, folders, audit
339956a
fix: align delete/hosts and add admin UIs
3a8efde
fix: migrate host keys when port added
2e85f99
fix: robust link lookup across key formats
cafbd45
fix: derive redirect host from URL
42178ee
chore: add debug link lookup endpoint
862870c
chore: add redirect debug headers
a620b95
fix(dev): disable custom route for localhost
b4b8fa2
feat(admin): folder sidebar + modal
06da3ed
Make Templates for WranglerTOML
4c5fa03
Merge pull request #2 from SillyLittleTech/v2/s6
kiyarose 25a9ef5
Update Docs, and fix some RCs
b6b1f87
Fixed implicet auth for debug endpoint
ea2abea
Potential fix for pull request finding
kiyarose d43451e
Harden debug/admin endpoints and improve admin flows
075170f
Fix LocalAuth Regression
9a3a06b
Make easy switch toml script
6dfec5e
Switch TOML to prod
d76d32b
Add heartbeat unit
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import { readFileSync, writeFileSync } from 'node:fs'; | ||
| import { fileURLToPath } from 'node:url'; | ||
| import { dirname, resolve } from 'node:path'; | ||
|
|
||
| const scriptDir = dirname(fileURLToPath(import.meta.url)); | ||
| const root = dirname(scriptDir); | ||
| const activePath = resolve(root, 'wrangler.toml'); | ||
| const devPath = resolve(root, 'wrangler.toml.local.bac'); | ||
| const prodPath = resolve(root, 'wrangler.toml.cloud.bac'); | ||
|
|
||
| const mode = (process.argv[2] || 'toggle').toLowerCase(); | ||
|
|
||
| const active = readFileSync(activePath, 'utf8'); | ||
| const dev = readFileSync(devPath, 'utf8'); | ||
| const prod = readFileSync(prodPath, 'utf8'); | ||
|
|
||
| let next; | ||
|
|
||
| if (mode === 'dev') { | ||
| next = dev; | ||
| } else if (mode === 'prod') { | ||
| next = prod; | ||
| } else if (active === dev) { | ||
| next = prod; | ||
| } else if (active === prod) { | ||
| next = dev; | ||
| } else { | ||
| console.error('wrangler.toml does not match either backup. Use `npm run toml:dev` or `npm run toml:prod`.'); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| writeFileSync(activePath, next); | ||
|
|
||
| const label = next === dev ? 'dev' : 'prod'; | ||
| console.log(`Updated wrangler.toml -> ${label}`); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| import { normalizeHost } from './kv.js'; | ||
|
|
||
| function padTs(ts) { | ||
| // 13-digit ms timestamp, lexicographically sortable | ||
| return String(ts).padStart(13, '0'); | ||
| } | ||
|
|
||
| function auditKey(ts, id) { | ||
| return `audit:${padTs(ts)}:${id}`; | ||
| } | ||
|
|
||
| function randomId() { | ||
| // short, URL-safe (avoid Math.random predictability/collisions) | ||
| try { | ||
| return crypto.randomUUID().replace(/-/g, '').slice(0, 12); | ||
| } catch { | ||
| const bytes = new Uint8Array(8); | ||
| crypto.getRandomValues(bytes); | ||
| return Array.from(bytes).map((b) => b.toString(16).padStart(2, '0')).join(''); | ||
| } | ||
| } | ||
|
|
||
| export function getActor(request) { | ||
| const ip = | ||
| request.headers.get('cf-connecting-ip') || | ||
| (request.headers.get('x-forwarded-for') || '').split(',')[0].trim() || | ||
| null; | ||
| const ua = request.headers.get('user-agent') || null; | ||
| const ray = request.headers.get('cf-ray') || null; | ||
| return { ip, ua, ray }; | ||
| } | ||
|
|
||
| export async function writeAudit(env, event) { | ||
| const ts = event.timestamp ?? Date.now(); | ||
| const id = event.id ?? randomId(); | ||
| const key = auditKey(ts, id); | ||
| const payload = { ...event, timestamp: ts, id }; | ||
| if (payload.host) payload.host = normalizeHost(payload.host); | ||
| await env.LINKIVERSE.put(key, JSON.stringify(payload)); | ||
| return { key, id, timestamp: ts }; | ||
| } | ||
|
|
||
| export async function listAudit(env, { limit = 100 } = {}) { | ||
| const keysWindow = []; | ||
| const windowSize = Math.max(200, Math.min(1000, limit * 5)); | ||
| let cursor; | ||
| do { | ||
| const page = await env.LINKIVERSE.list({ prefix: 'audit:', limit: 100, cursor }); | ||
| for (const key of page.keys) { | ||
| keysWindow.push(key.name); | ||
| if (keysWindow.length > windowSize) keysWindow.shift(); | ||
| } | ||
| cursor = page.list_complete ? undefined : page.cursor; | ||
| } while (cursor); | ||
|
|
||
| const items = []; | ||
| for (const name of keysWindow) { | ||
| const raw = await env.LINKIVERSE.get(name); | ||
| if (!raw) continue; | ||
| try { | ||
| items.push(JSON.parse(raw)); | ||
| } catch { | ||
| // ignore | ||
| } | ||
| } | ||
|
|
||
| items.sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0)); | ||
| return items.slice(0, limit); | ||
| } | ||
|
kiyarose marked this conversation as resolved.
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| // Shared constants for the Plummer worker. | ||
|
|
||
| export const RESERVED = new Set([ | ||
| 'admin', | ||
| 'api', | ||
| 'favicon.ico', | ||
| 'robots.txt', | ||
| 'sitemap.xml', | ||
| ]); | ||
|
|
||
| export const ADMIN_REALM = 'Plummer Admin'; | ||
|
|
||
| // Visible build version displayed in the UI footer. | ||
| export const APP_VERSION = 'v2.1'; | ||
|
|
||
| export const SECURITY_HEADERS = { | ||
| 'X-Content-Type-Options': 'nosniff', | ||
| 'X-Frame-Options': 'DENY', | ||
| 'Referrer-Policy': 'strict-origin-when-cross-origin', | ||
| }; | ||
|
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.