Add API key authentication to all endpoints

This commit is contained in:
Your Name 2026-05-19 20:19:02 -04:00
parent 56d8fb4d56
commit 176439c1df
4 changed files with 207 additions and 28 deletions

View file

@ -12,6 +12,8 @@ function RecordingDetail({ recording: r, data, onBack, allHighlights, setAllHigh
const [showAddHighlight, setShowAddHighlight] = useStateRD(false);
const [newHighlightTag, setNewHighlightTag] = useStateRD('important');
const [newHighlightNote, setNewHighlightNote] = useStateRD('');
const [audioBlobUrl, setAudioBlobUrl] = useStateRD(null);
const [audioLoading, setAudioLoading] = useStateRD(true);
const audioRef = useRefRD(null);
const transcriptRef = useRefRD(null);
@ -20,8 +22,35 @@ function RecordingDetail({ recording: r, data, onBack, allHighlights, setAllHigh
const totalSeconds = audioDuration || metadataDuration || 1; // avoid division by zero
const recHighlights = allHighlights.filter(h => h.recordingId === r.id);
// Audio URL from API
const audioUrl = `${API_BASE}/api/v1/recordings/${r.id}/audio`;
// Fetch audio with auth and create blob URL
useEffectRD(() => {
let cancelled = false;
let blobUrl = null;
async function fetchAudio() {
setAudioLoading(true);
try {
const res = await window.authFetch(`${API_BASE}/api/v1/recordings/${r.id}/audio`);
if (cancelled) return;
if (!res.ok) throw new Error('Failed to fetch audio');
const blob = await res.blob();
if (cancelled) return;
blobUrl = URL.createObjectURL(blob);
setAudioBlobUrl(blobUrl);
} catch (err) {
console.error('Failed to load audio:', err);
} finally {
if (!cancelled) setAudioLoading(false);
}
}
fetchAudio();
return () => {
cancelled = true;
if (blobUrl) URL.revokeObjectURL(blobUrl);
};
}, [r.id]);
// Track recording ID to detect when recording changes
const lastRecordingId = useRefRD(null);
@ -33,6 +62,7 @@ function RecordingDetail({ recording: r, data, onBack, allHighlights, setAllHigh
hasAutoPlayed.current = false;
lastRecordingId.current = r.id;
setAudioDuration(null); // Reset to use metadata until audio loads
setAudioBlobUrl(null); // Clear old blob URL
}
}, [r.id]);
@ -190,7 +220,7 @@ function RecordingDetail({ recording: r, data, onBack, allHighlights, setAllHigh
const endSecs = highlightEndTime; // null for point highlight
try {
const res = await fetch(`${API_BASE}/api/v1/highlights`, {
const res = await window.authFetch(`${API_BASE}/api/v1/highlights`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
@ -230,7 +260,7 @@ function RecordingDetail({ recording: r, data, onBack, allHighlights, setAllHigh
const numericId = hid.startsWith('h-') ? hid.slice(2) : hid;
try {
const res = await fetch(`${API_BASE}/api/v1/highlights/${numericId}`, {
const res = await window.authFetch(`${API_BASE}/api/v1/highlights/${numericId}`, {
method: 'DELETE',
});
if (!res.ok && res.status !== 404) {
@ -444,7 +474,8 @@ function RecordingDetail({ recording: r, data, onBack, allHighlights, setAllHigh
</div>
{/* Hidden audio element */}
<audio ref={audioRef} src={audioUrl} preload="metadata" />
{audioBlobUrl && <audio ref={audioRef} src={audioBlobUrl} preload="metadata" />}
{audioLoading && <div style={{ color: 'var(--text3)', fontSize: 11, fontFamily: 'var(--font-mono)' }}>Loading audio...</div>}
{/* Controls */}
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>