mirror of
https://github.com/withastro/astro.git
synced 2025-01-27 22:19:04 -05:00
Create new token when current has expired (#10435)
* Create new token when current has expired * Add changeset * Rename renew timer function: * Handle creating a new token on renewal
This commit is contained in:
parent
156c094c3e
commit
37a485b4d1
2 changed files with 48 additions and 14 deletions
5
.changeset/long-buckets-end.md
Normal file
5
.changeset/long-buckets-end.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@astrojs/db": patch
|
||||
---
|
||||
|
||||
Fetch new app token when previous has expired
|
|
@ -31,9 +31,20 @@ class ManagedRemoteAppToken implements ManagedAppToken {
|
|||
session: string;
|
||||
projectId: string;
|
||||
ttl: number;
|
||||
expires: Date;
|
||||
renewTimer: NodeJS.Timeout | undefined;
|
||||
|
||||
static async create(sessionToken: string, projectId: string) {
|
||||
const { token: shortLivedAppToken, ttl } = await this.createToken(sessionToken, projectId);
|
||||
return new ManagedRemoteAppToken({
|
||||
token: shortLivedAppToken,
|
||||
session: sessionToken,
|
||||
projectId,
|
||||
ttl,
|
||||
});
|
||||
}
|
||||
|
||||
static async createToken(sessionToken: string, projectId: string): Promise<{ token: string; ttl: number; }> {
|
||||
const spinner = ora('Connecting to remote database...').start();
|
||||
const response = await safeFetch(
|
||||
new URL(`${getAstroStudioUrl()}/auth/cli/token-create`),
|
||||
|
@ -54,13 +65,8 @@ class ManagedRemoteAppToken implements ManagedAppToken {
|
|||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
spinner.succeed(green('Connected to remote database.'));
|
||||
|
||||
const { token: shortLivedAppToken, ttl } = await response.json();
|
||||
return new ManagedRemoteAppToken({
|
||||
token: shortLivedAppToken,
|
||||
session: sessionToken,
|
||||
projectId,
|
||||
ttl,
|
||||
});
|
||||
const { token, ttl } = await response.json();
|
||||
return { token, ttl };
|
||||
}
|
||||
|
||||
constructor(options: { token: string; session: string; projectId: string; ttl: number }) {
|
||||
|
@ -69,6 +75,7 @@ class ManagedRemoteAppToken implements ManagedAppToken {
|
|||
this.projectId = options.projectId;
|
||||
this.ttl = options.ttl;
|
||||
this.renewTimer = setTimeout(() => this.renew(), (1000 * 60 * 5) / 2);
|
||||
this.expires = getExpiresFromTtl(this.ttl);
|
||||
}
|
||||
|
||||
private async fetch(url: string, body: Record<string, unknown>) {
|
||||
|
@ -88,24 +95,41 @@ class ManagedRemoteAppToken implements ManagedAppToken {
|
|||
);
|
||||
}
|
||||
|
||||
tokenIsValid() {
|
||||
return new Date() > this.expires;
|
||||
}
|
||||
|
||||
createRenewTimer() {
|
||||
return setTimeout(() => this.renew(), (1000 * 60 * this.ttl) / 2);
|
||||
}
|
||||
|
||||
async renew() {
|
||||
clearTimeout(this.renewTimer);
|
||||
delete this.renewTimer;
|
||||
try {
|
||||
|
||||
if(this.tokenIsValid()) {
|
||||
const response = await this.fetch('/auth/cli/token-renew', {
|
||||
token: this.token,
|
||||
projectId: this.projectId,
|
||||
});
|
||||
if (response.status === 200) {
|
||||
this.renewTimer = setTimeout(() => this.renew(), (1000 * 60 * this.ttl) / 2);
|
||||
this.expires = getExpiresFromTtl(this.ttl);
|
||||
this.renewTimer = this.createRenewTimer();
|
||||
} else {
|
||||
throw new Error(`Unexpected response: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const { token, ttl } = await ManagedRemoteAppToken.createToken(this.session, this.projectId);
|
||||
this.token = token;
|
||||
this.ttl = ttl;
|
||||
this.expires = getExpiresFromTtl(ttl);
|
||||
this.renewTimer = this.createRenewTimer();
|
||||
} catch {
|
||||
// If we get here we couldn't create a new token. Since the existing token
|
||||
// is expired we really can't do anything and should exit.
|
||||
throw new Error(`Token has expired and attempts to renew it have failed, please try again.`);
|
||||
}
|
||||
} catch (error: any) {
|
||||
const retryIn = (60 * this.ttl) / 10;
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`Failed to renew token. Retrying in ${retryIn} seconds.`, error?.message);
|
||||
this.renewTimer = setTimeout(() => this.renew(), retryIn * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,3 +187,8 @@ export async function getManagedAppTokenOrExit(token?: string): Promise<ManagedA
|
|||
}
|
||||
return ManagedRemoteAppToken.create(sessionToken, projectId);
|
||||
}
|
||||
|
||||
function getExpiresFromTtl(ttl: number): Date {
|
||||
// ttl is in minutes
|
||||
return new Date(Date.now() + ttl * 60 * 1000);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue