Skip to content
This repository has been archived by the owner on Sep 17, 2024. It is now read-only.

Commit

Permalink
feat(tokens): Add script to extend token life
Browse files Browse the repository at this point in the history
  • Loading branch information
Blckbrry-Pi committed Mar 28, 2024
1 parent b5c0823 commit 01a9205
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 3 deletions.
3 changes: 3 additions & 0 deletions modules/tokens/module.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ scripts:
validate:
name: Validate Token
description: Validate a token. Throws an error if the token is invalid.
extend:
name: Extend Token
description: Extend or remove the expiration date of a token. (Only works on valid tokens.)
errors:
token_not_found:
name: Token Not Found
Expand Down
37 changes: 37 additions & 0 deletions modules/tokens/scripts/extend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { ScriptContext } from "../_gen/scripts/extend.ts";
import { TokenWithSecret } from "../types/common.ts";
import { tokenFromRow } from "../types/common.ts";

export interface Request {
token: string;
newExpiration: string | null;
}

export interface Response {
token: TokenWithSecret;
}

export async function run(
ctx: ScriptContext,
req: Request,
): Promise<Response> {
// Ensure the token hasn't expired or been revoked yet
const { token } = await ctx.modules.tokens.validate({
token: req.token,
});

// Update the token's expiration date
const newToken = await ctx.db.token.update({
where: {
id: token.id,
},
data: {
expireAt: req.newExpiration,
},
});

// Return the updated token
return {
token: tokenFromRow(newToken),
};
}
51 changes: 48 additions & 3 deletions modules/tokens/tests/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { RuntimeError, test, TestContext } from "../_gen/test.ts";
import {
assertEquals,
assertRejects,
assertGreater,
} from "https://deno.land/[email protected]/assert/mod.ts";

test(
Expand All @@ -10,7 +11,7 @@ test(
const error = await assertRejects(async () => {
await ctx.modules.tokens.validate({ token: "invalid token" });
}, RuntimeError);
assertEquals(error.code, "TOKEN_NOT_FOUND");
assertEquals(error.code, "token_not_found");
},
);

Expand All @@ -27,7 +28,7 @@ test(
const error = await assertRejects(async () => {
await ctx.modules.tokens.validate({ token: token.token });
}, RuntimeError);
assertEquals(error.code, "TOKEN_REVOKED");
assertEquals(error.code, "token_revoked");
},
);

Expand All @@ -52,6 +53,50 @@ test(
const error = await assertRejects(async () => {
await ctx.modules.tokens.validate({ token: token.token });
}, RuntimeError);
assertEquals(error.code, "TOKEN_EXPIRED");
assertEquals(error.code, "token_expired");
},
);

test(
"validate token extended not expired",
async (ctx: TestContext) => {
const { token } = await ctx.modules.tokens.create({
type: "test",
meta: { foo: "bar" },
// Set initial expiration to 200ms in the future
expireAt: new Date(Date.now() + 200).toISOString(),
});

// Token should be valid
const validateRes = await ctx.modules.tokens.validate({
token: token.token,
});
assertEquals(token.id, validateRes.token.id);

// Extend token expiration by 10 seconds
await ctx.modules.tokens.extend({
token: token.token,
newExpiration: new Date(Date.now() + 10000).toISOString(),
});

// Wait for 0.5 seconds to ensure token WOULD HAVE expired without
// extension.
await new Promise((resolve) => setTimeout(resolve, 500));

// Token should STILL be valid, and have a different `expireAt` time
const validateResAfterWait = await ctx.modules.tokens.validate({
token: token.token,
});

// Assert that everything except `expireAt` is the same and `expireAt`
// is greater.
assertGreater(validateResAfterWait.token.expireAt, token.expireAt);
assertEquals({
...validateResAfterWait.token,
expireAt: null,
}, {
...token,
expireAt: null,
})
},
);

0 comments on commit 01a9205

Please sign in to comment.