Skip to content

Commit aebde14

Browse files
committed
openapi + keygen
1 parent 26caf40 commit aebde14

5 files changed

Lines changed: 1078 additions & 225 deletions

File tree

README.docker.md

Lines changed: 0 additions & 112 deletions
This file was deleted.

TODO.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# TODO
22

3-
- test the docker compose
4-
- docs: installation, email providers, templates, contacts, lists, workspaces, broadcast campaigns, transactional api, notification center
3+
- docs: email providers, templates, contacts, lists, workspaces, broadcast campaigns, transactional api, notification center
54

65
## Eventual features
76

keygen_function/function.go

Lines changed: 141 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package keygenfunction
22

33
import (
44
"encoding/base64"
5+
"encoding/hex"
56
"encoding/json"
67
"fmt"
78
"html/template"
89
"net/http"
910
"os"
11+
"time"
1012

1113
"aidanwoods.dev/go-paseto"
1214
"github.com/GoogleCloudPlatform/functions-framework-go/functions"
@@ -17,8 +19,17 @@ func init() {
1719
}
1820

1921
type KeyPair struct {
20-
PrivateKey string `json:"privateKey"`
21-
PublicKey string `json:"publicKey"`
22+
PrivateKey KeyData `json:"privateKey"`
23+
PublicKey KeyData `json:"publicKey"`
24+
GeneratedAt time.Time `json:"generatedAt"`
25+
KeyType string `json:"keyType"`
26+
Algorithm string `json:"algorithm"`
27+
}
28+
29+
type KeyData struct {
30+
Base64 string `json:"base64"`
31+
Hex string `json:"hex"`
32+
ByteLength int `json:"byteLength"`
2233
}
2334

2435
// KeygenHandler serves both the HTML page and handles key generation
@@ -105,14 +116,25 @@ func generateKeys(w http.ResponseWriter, r *http.Request) {
105116
secretKey := paseto.NewV4AsymmetricSecretKey()
106117
publicKey := secretKey.Public()
107118

108-
// Convert keys to base64 for storage
109-
privateKeyBase64 := base64.StdEncoding.EncodeToString(secretKey.ExportBytes())
110-
publicKeyBase64 := base64.StdEncoding.EncodeToString(publicKey.ExportBytes())
119+
// Export raw bytes
120+
privateKeyBytes := secretKey.ExportBytes()
121+
publicKeyBytes := publicKey.ExportBytes()
111122

112-
// Create response
123+
// Create response with multiple encoding formats
113124
keyPair := KeyPair{
114-
PrivateKey: privateKeyBase64,
115-
PublicKey: publicKeyBase64,
125+
PrivateKey: KeyData{
126+
Base64: base64.StdEncoding.EncodeToString(privateKeyBytes),
127+
Hex: hex.EncodeToString(privateKeyBytes),
128+
ByteLength: len(privateKeyBytes),
129+
},
130+
PublicKey: KeyData{
131+
Base64: base64.StdEncoding.EncodeToString(publicKeyBytes),
132+
Hex: hex.EncodeToString(publicKeyBytes),
133+
ByteLength: len(publicKeyBytes),
134+
},
135+
GeneratedAt: time.Now().UTC(),
136+
KeyType: "asymmetric",
137+
Algorithm: "PASETO v4",
116138
}
117139

118140
// Set response headers
@@ -346,6 +368,50 @@ const htmlTemplate = `
346368
margin-top: 20px;
347369
color: #721c24;
348370
}
371+
372+
.key-metadata {
373+
background: #e3f2fd;
374+
border-radius: 8px;
375+
padding: 15px;
376+
margin-bottom: 20px;
377+
border-left: 4px solid #2196f3;
378+
}
379+
380+
.key-metadata p {
381+
margin: 5px 0;
382+
color: #1565c0;
383+
}
384+
385+
.format-tabs {
386+
display: flex;
387+
margin-bottom: 10px;
388+
border-bottom: 1px solid #dee2e6;
389+
}
390+
391+
.format-tab {
392+
background: transparent;
393+
border: none;
394+
padding: 8px 16px;
395+
cursor: pointer;
396+
border-bottom: 2px solid transparent;
397+
color: #666;
398+
font-weight: 500;
399+
transition: all 0.2s;
400+
}
401+
402+
.format-tab:hover {
403+
color: #667eea;
404+
}
405+
406+
.format-tab.active {
407+
color: #667eea;
408+
border-bottom-color: #667eea;
409+
}
410+
411+
.key-info {
412+
margin-top: 8px;
413+
color: #666;
414+
}
349415
</style>
350416
</head>
351417
<body>
@@ -374,19 +440,47 @@ const htmlTemplate = `
374440
</div>
375441
376442
<div class="results" id="results">
443+
<div class="key-metadata" id="key-metadata">
444+
<p><strong>Generated:</strong> <span id="generated-at"></span></p>
445+
<p><strong>Algorithm:</strong> <span id="algorithm"></span></p>
446+
<p><strong>Type:</strong> <span id="key-type"></span></p>
447+
</div>
448+
377449
<div class="key-section private">
378450
<h3>Private Key</h3>
379-
<div class="key-display" id="private-key">
380-
<button class="copy-btn" onclick="copyToClipboard('private-key-text', this)">Copy</button>
381-
<span id="private-key-text"></span>
451+
<div class="format-tabs">
452+
<button class="format-tab active" onclick="switchFormat('private', 'base64')">Base64</button>
453+
<button class="format-tab" onclick="switchFormat('private', 'hex')">Hex</button>
454+
</div>
455+
<div class="key-display" id="private-key-base64">
456+
<button class="copy-btn" onclick="copyToClipboard('private-key-base64-text', this)">Copy</button>
457+
<span id="private-key-base64-text"></span>
458+
</div>
459+
<div class="key-display" id="private-key-hex" style="display: none;">
460+
<button class="copy-btn" onclick="copyToClipboard('private-key-hex-text', this)">Copy</button>
461+
<span id="private-key-hex-text"></span>
462+
</div>
463+
<div class="key-info">
464+
<small>Length: <span id="private-key-length"></span> bytes</small>
382465
</div>
383466
</div>
384467
385468
<div class="key-section public">
386469
<h3>Public Key</h3>
387-
<div class="key-display" id="public-key">
388-
<button class="copy-btn" onclick="copyToClipboard('public-key-text', this)">Copy</button>
389-
<span id="public-key-text"></span>
470+
<div class="format-tabs">
471+
<button class="format-tab active" onclick="switchFormat('public', 'base64')">Base64</button>
472+
<button class="format-tab" onclick="switchFormat('public', 'hex')">Hex</button>
473+
</div>
474+
<div class="key-display" id="public-key-base64">
475+
<button class="copy-btn" onclick="copyToClipboard('public-key-base64-text', this)">Copy</button>
476+
<span id="public-key-base64-text"></span>
477+
</div>
478+
<div class="key-display" id="public-key-hex" style="display: none;">
479+
<button class="copy-btn" onclick="copyToClipboard('public-key-hex-text', this)">Copy</button>
480+
<span id="public-key-hex-text"></span>
481+
</div>
482+
<div class="key-info">
483+
<small>Length: <span id="public-key-length"></span> bytes</small>
390484
</div>
391485
</div>
392486
@@ -424,9 +518,20 @@ const htmlTemplate = `
424518
425519
const data = await response.json();
426520
427-
// Display the keys
428-
document.getElementById('private-key-text').textContent = data.privateKey;
429-
document.getElementById('public-key-text').textContent = data.publicKey;
521+
// Display metadata
522+
document.getElementById('generated-at').textContent = new Date(data.generatedAt).toLocaleString();
523+
document.getElementById('algorithm').textContent = data.algorithm;
524+
document.getElementById('key-type').textContent = data.keyType;
525+
526+
// Display private key data
527+
document.getElementById('private-key-base64-text').textContent = data.privateKey.base64;
528+
document.getElementById('private-key-hex-text').textContent = data.privateKey.hex;
529+
document.getElementById('private-key-length').textContent = data.privateKey.byteLength;
530+
531+
// Display public key data
532+
document.getElementById('public-key-base64-text').textContent = data.publicKey.base64;
533+
document.getElementById('public-key-hex-text').textContent = data.publicKey.hex;
534+
document.getElementById('public-key-length').textContent = data.publicKey.byteLength;
430535
431536
// Show results
432537
loading.style.display = 'none';
@@ -485,6 +590,25 @@ const htmlTemplate = `
485590
}
486591
}
487592
593+
function switchFormat(keyType, format) {
594+
// Update tab states
595+
const tabs = document.querySelectorAll(` + "`" + `.key-section.${keyType} .format-tab` + "`" + `);
596+
tabs.forEach(tab => tab.classList.remove('active'));
597+
event.target.classList.add('active');
598+
599+
// Show/hide content
600+
const base64Display = document.getElementById(` + "`" + `${keyType}-key-base64` + "`" + `);
601+
const hexDisplay = document.getElementById(` + "`" + `${keyType}-key-hex` + "`" + `);
602+
603+
if (format === 'base64') {
604+
base64Display.style.display = 'block';
605+
hexDisplay.style.display = 'none';
606+
} else {
607+
base64Display.style.display = 'none';
608+
hexDisplay.style.display = 'block';
609+
}
610+
}
611+
488612
// Generate keys on page load for demo
489613
window.addEventListener('load', () => {
490614
// Uncomment the line below if you want to auto-generate keys on page load

0 commit comments

Comments
 (0)