Refactor error handling and logging in API responses
This commit is contained in:
@ -27,14 +27,17 @@ export function redirectToLogin() {
|
||||
/** @returns {boolean} true if the response means the session is no longer valid */
|
||||
function isSessionInvalidResponse(res, json) {
|
||||
if (res.status === 401) return true;
|
||||
const errMsg = json.error?.message || json.error || '';
|
||||
return res.status === 403 && (
|
||||
errMsg === 'Invalid or expired token'
|
||||
|| errMsg === 'Missing Bearer token'
|
||||
|| errMsg === 'Password change required before access'
|
||||
|| json.error?.code === 'UNAUTHORIZED'
|
||||
|| json.error?.code === 'PASSWORD_CHANGE_REQUIRED'
|
||||
);
|
||||
const errMsg = json.error?.message || (typeof json.error === 'string' ? json.error : '');
|
||||
const errCode = json.error?.code || '';
|
||||
return res.status === 401
|
||||
|| res.status === 403 && (
|
||||
errCode === 'UNAUTHORIZED'
|
||||
|| errCode === 'PASSWORD_CHANGE_REQUIRED'
|
||||
|| errCode === 'FORBIDDEN'
|
||||
|| errMsg === 'Invalid or expired token'
|
||||
|| errMsg === 'Missing Bearer token'
|
||||
|| errMsg === 'Password change required before access'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,7 +128,9 @@ function unwrap(json) {
|
||||
const d = json.data || {};
|
||||
return { success: true, ...(Array.isArray(d) ? { items: d } : d) };
|
||||
}
|
||||
return { success: false, error: json.error?.message || 'Unknown error' };
|
||||
const err = json.error;
|
||||
const msg = typeof err === 'string' ? err : (err?.message || 'Unknown error');
|
||||
return { success: false, error: msg, errorCode: typeof err === 'object' ? err?.code : null };
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ const ACTIVITY_LABELS = {
|
||||
app_change: 'App change',
|
||||
web_change: 'Website change',
|
||||
web_export: 'Website export',
|
||||
api_error: 'API error',
|
||||
};
|
||||
|
||||
export function devPage() {
|
||||
@ -75,6 +76,7 @@ export function devPage() {
|
||||
<option value="app_change">App change</option>
|
||||
<option value="web_change">Website change</option>
|
||||
<option value="web_export">Website export</option>
|
||||
<option value="errors">Errors only (4xx/5xx)</option>
|
||||
</select>
|
||||
<button type="button" class="btn btn-sm" id="activityLogRefresh">Refresh</button>
|
||||
</div>
|
||||
@ -324,7 +326,9 @@ async function loadActivityLog() {
|
||||
const label = ACTIVITY_LABELS[kind] || kind || '—';
|
||||
const badgeClass = kind ? `badge-activity-${kind}` : '';
|
||||
const time = formatActivityTime(e.ts);
|
||||
const status = e.status != null ? String(e.status) : '—';
|
||||
const statusNum = e.status != null ? Number(e.status) : null;
|
||||
const status = statusNum != null ? String(statusNum) : '—';
|
||||
const statusClass = statusNum != null && statusNum >= 400 ? 'error-text' : '';
|
||||
const dur = e.duration_ms != null ? `${e.duration_ms} ms` : '—';
|
||||
const subject = formatActivitySubject(e);
|
||||
const performedBy = formatActivityPerformer(e);
|
||||
@ -339,7 +343,7 @@ async function loadActivityLog() {
|
||||
<td><code>${escHtml(e.method || '')}</code></td>
|
||||
<td><code>${escHtml(e.route || '')}</code></td>
|
||||
<td class="activity-log-ip"><code>${escHtml(ip)}</code></td>
|
||||
<td>${escHtml(status)}</td>
|
||||
<td class="${statusClass}">${escHtml(status)}</td>
|
||||
<td>${escHtml(dur)}</td>
|
||||
<td class="activity-log-changes-cell">${renderActivityChanges(e.changes)}</td>
|
||||
<td class="activity-log-actor">${performedBy}${errPart}</td>
|
||||
|
||||
Reference in New Issue
Block a user