mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
fix: use Date header from health/version instead of health.getTime()
health.getTime() requires health.read scope which regular console users don't have. Instead, parse the Date header from the existing health/version fetch that already happens on console load. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
e8938c3113
commit
2fbb953232
@@ -7,23 +7,15 @@ const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour
|
||||
let serverTimeCache: { serverSecs: number; fetchedAtMs: number } | null = null;
|
||||
|
||||
/**
|
||||
* Fetch and cache the server's clock so fingerprint timestamps always align
|
||||
* with the backend's clock, regardless of local clock drift.
|
||||
* Cache the server's clock so fingerprint timestamps always align with the
|
||||
* backend's clock, regardless of local clock drift.
|
||||
*
|
||||
* @param getServerTime - callback that returns the server's unix timestamp in seconds
|
||||
* (e.g. `health.getTime()` → `response.localTime`)
|
||||
* @param serverTimeSecs - the server's unix timestamp in seconds
|
||||
* (e.g. parsed from a response Date header)
|
||||
*/
|
||||
export async function syncServerTime(
|
||||
getServerTime: () => Promise<number>
|
||||
): Promise<void> {
|
||||
export function syncServerTime(serverTimeSecs: number): void {
|
||||
if (serverTimeCache) return;
|
||||
try {
|
||||
const fetchedAtMs = Date.now();
|
||||
const serverSecs = await getServerTime();
|
||||
serverTimeCache = { serverSecs, fetchedAtMs };
|
||||
} catch {
|
||||
console.warn('Failed to sync server time for fingerprint');
|
||||
}
|
||||
serverTimeCache = { serverSecs: serverTimeSecs, fetchedAtMs: Date.now() };
|
||||
}
|
||||
|
||||
function getServerTimestamp(): number {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { Platform, Query } from '@appwrite.io/console';
|
||||
import { makePlansMap } from '$lib/helpers/billing';
|
||||
import { plansInfo as plansInfoStore } from '$lib/stores/billing';
|
||||
import { normalizeConsoleVariables } from '$lib/helpers/domains';
|
||||
import { syncServerTime } from '$lib/helpers/fingerprint';
|
||||
|
||||
export const load: LayoutLoad = async ({ depends, parent }) => {
|
||||
const { organizations, plansInfo } = await parent();
|
||||
@@ -28,7 +29,13 @@ export const load: LayoutLoad = async ({ depends, parent }) => {
|
||||
plansArrayPromise,
|
||||
fetch(`${endpoint}/health/version`, {
|
||||
headers: { 'X-Appwrite-Project': project as string }
|
||||
}).then((response) => response.json() as { version?: string }),
|
||||
}).then((response) => {
|
||||
const dateHeader = response.headers.get('Date');
|
||||
if (dateHeader) {
|
||||
syncServerTime(Math.floor(new Date(dateHeader).getTime() / 1000));
|
||||
}
|
||||
return response.json() as { version?: string };
|
||||
}),
|
||||
sdk.forConsole.console.variables()
|
||||
]);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import { loadAvailableRegions } from '$routes/(console)/regions';
|
||||
import { type Models, Platform } from '@appwrite.io/console';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { resolve } from '$app/paths';
|
||||
import { generateFingerprintToken, syncServerTime } from '$lib/helpers/fingerprint';
|
||||
import { generateFingerprintToken } from '$lib/helpers/fingerprint';
|
||||
import { normalizeConsoleVariables } from '$lib/helpers/domains';
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
@@ -107,11 +107,7 @@ export const load: LayoutLoad = async ({ params, depends, parent }) => {
|
||||
// Track console access for cloud projects (fire-and-forget, backend has 6-day cooldown).
|
||||
// Skip if paused — user must explicitly resume via the paused project modal.
|
||||
if (isCloud && browser && project.status !== 'paused') {
|
||||
syncServerTime(async () => {
|
||||
const { localTime } = await sdk.forConsole.health.getTime();
|
||||
return localTime;
|
||||
})
|
||||
.then(() => generateFingerprintToken())
|
||||
generateFingerprintToken()
|
||||
.then((fingerprint) => {
|
||||
sdk.forConsole.client.headers['X-Appwrite-Console-Fingerprint'] = fingerprint;
|
||||
return sdk.forConsole.projects.updateConsoleAccess({
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { Submit, trackError } from '$lib/actions/analytics';
|
||||
import { generateFingerprintToken, syncServerTime } from '$lib/helpers/fingerprint';
|
||||
import { generateFingerprintToken } from '$lib/helpers/fingerprint';
|
||||
import { Alert, Layout, Modal, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { Status } from '@appwrite.io/console';
|
||||
|
||||
@@ -28,10 +28,6 @@
|
||||
error = null;
|
||||
|
||||
try {
|
||||
await syncServerTime(async () => {
|
||||
const { localTime } = await sdk.forConsole.health.getTime();
|
||||
return localTime;
|
||||
});
|
||||
const fingerprint = await generateFingerprintToken();
|
||||
sdk.forConsole.client.headers['X-Appwrite-Console-Fingerprint'] = fingerprint;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user