🐐 Several security fixes
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
let profile: any = $state(null);
|
||||
let loading = $state(true);
|
||||
let notFound = $state(false);
|
||||
let needsAuth = $state(false);
|
||||
let favExpanded = $state(false);
|
||||
let wttExpanded = $state(false);
|
||||
|
||||
@@ -114,32 +115,36 @@
|
||||
const username = get(page).params.username;
|
||||
const token = localStorage.getItem('token');
|
||||
|
||||
const res = await fetch(`${API_URL}/users/${username}`);
|
||||
// Profiles now require auth. Show a prompt rather than bouncing to /auth, so
|
||||
// a shared profile link explains itself instead of silently vanishing.
|
||||
if (!token) { needsAuth = true; loading = false; return; }
|
||||
|
||||
// apiFetch (not raw fetch) so an expired access token gets refreshed
|
||||
const res = await apiFetch(`${API_URL}/users/${username}`);
|
||||
if (res.status === 401) { needsAuth = true; loading = false; return; }
|
||||
if (res.status === 404) { notFound = true; loading = false; return; }
|
||||
const data = await res.json();
|
||||
|
||||
// Redirect to own profile if logged-in user visits their own public page
|
||||
if (token) {
|
||||
try {
|
||||
const meRes = await fetch(`${API_URL}/profile`, {
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
});
|
||||
if (meRes.ok) {
|
||||
const me = await meRes.json();
|
||||
if (me.username === username) { goto('/profile'); return; }
|
||||
isLoggedIn = true;
|
||||
try {
|
||||
const meRes = await fetch(`${API_URL}/profile`, {
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
});
|
||||
if (meRes.ok) {
|
||||
const me = await meRes.json();
|
||||
if (me.username === username) { goto('/profile'); return; }
|
||||
isLoggedIn = true;
|
||||
|
||||
// Check existing friendship status
|
||||
const statusRes = await apiFetch(`${API_URL}/friendship-status/${username}`);
|
||||
if (statusRes.ok) {
|
||||
const s = await statusRes.json();
|
||||
if (s.status === 'friends') { friendStatus = 'friends'; friendshipId = s.friendship_id; }
|
||||
else if (s.status === 'pending_sent') { friendStatus = 'pending'; }
|
||||
else if (s.status === 'pending_received') { friendStatus = 'pending_received'; friendshipId = s.friendship_id; }
|
||||
}
|
||||
// Check existing friendship status
|
||||
const statusRes = await apiFetch(`${API_URL}/friendship-status/${username}`);
|
||||
if (statusRes.ok) {
|
||||
const s = await statusRes.json();
|
||||
if (s.status === 'friends') { friendStatus = 'friends'; friendshipId = s.friendship_id; }
|
||||
else if (s.status === 'pending_sent') { friendStatus = 'pending'; }
|
||||
else if (s.status === 'pending_received') { friendStatus = 'pending_received'; friendshipId = s.friendship_id; }
|
||||
}
|
||||
} catch { /* non-critical */ }
|
||||
}
|
||||
}
|
||||
} catch { /* non-critical */ }
|
||||
|
||||
profile = data;
|
||||
loading = false;
|
||||
@@ -151,6 +156,16 @@
|
||||
<p class="status-text">Loading...</p>
|
||||
</main>
|
||||
|
||||
{:else if needsAuth}
|
||||
<main class="page">
|
||||
<div class="not-found">
|
||||
<div class="not-found-sigil">✦</div>
|
||||
<h1 class="not-found-title">Adventurers Only</h1>
|
||||
<p class="not-found-sub">Sign in to view this collector's profile.</p>
|
||||
<a href="/auth" class="btn-primary">Sign In</a>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{:else if notFound}
|
||||
<main class="page">
|
||||
<div class="not-found">
|
||||
|
||||
Reference in New Issue
Block a user