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

Commit ad1b37d

Browse files
authored
feat(tokens): Add script to extend token life (#73)
Resolves OGB-38
1 parent b5c0823 commit ad1b37d

File tree

3 files changed

+88
-3
lines changed

3 files changed

+88
-3
lines changed

modules/tokens/module.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ scripts:
2323
validate:
2424
name: Validate Token
2525
description: Validate a token. Throws an error if the token is invalid.
26+
extend:
27+
name: Extend Token
28+
description: Extend or remove the expiration date of a token. (Only works on valid tokens.)
2629
errors:
2730
token_not_found:
2831
name: Token Not Found

modules/tokens/scripts/extend.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { ScriptContext } from "../_gen/scripts/extend.ts";
2+
import { TokenWithSecret } from "../types/common.ts";
3+
import { tokenFromRow } from "../types/common.ts";
4+
5+
export interface Request {
6+
token: string;
7+
newExpiration: string | null;
8+
}
9+
10+
export interface Response {
11+
token: TokenWithSecret;
12+
}
13+
14+
export async function run(
15+
ctx: ScriptContext,
16+
req: Request,
17+
): Promise<Response> {
18+
// Ensure the token hasn't expired or been revoked yet
19+
const { token } = await ctx.modules.tokens.validate({
20+
token: req.token,
21+
});
22+
23+
// Update the token's expiration date
24+
const newToken = await ctx.db.token.update({
25+
where: {
26+
id: token.id,
27+
},
28+
data: {
29+
expireAt: req.newExpiration,
30+
},
31+
});
32+
33+
// Return the updated token
34+
return {
35+
token: tokenFromRow(newToken),
36+
};
37+
}

modules/tokens/tests/validate.ts

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { RuntimeError, test, TestContext } from "../_gen/test.ts";
22
import {
33
assertEquals,
44
assertRejects,
5+
assertGreater,
56
} from "https://deno.land/std@0.217.0/assert/mod.ts";
67

78
test(
@@ -10,7 +11,7 @@ test(
1011
const error = await assertRejects(async () => {
1112
await ctx.modules.tokens.validate({ token: "invalid token" });
1213
}, RuntimeError);
13-
assertEquals(error.code, "TOKEN_NOT_FOUND");
14+
assertEquals(error.code, "token_not_found");
1415
},
1516
);
1617

@@ -27,7 +28,7 @@ test(
2728
const error = await assertRejects(async () => {
2829
await ctx.modules.tokens.validate({ token: token.token });
2930
}, RuntimeError);
30-
assertEquals(error.code, "TOKEN_REVOKED");
31+
assertEquals(error.code, "token_revoked");
3132
},
3233
);
3334

@@ -52,6 +53,50 @@ test(
5253
const error = await assertRejects(async () => {
5354
await ctx.modules.tokens.validate({ token: token.token });
5455
}, RuntimeError);
55-
assertEquals(error.code, "TOKEN_EXPIRED");
56+
assertEquals(error.code, "token_expired");
57+
},
58+
);
59+
60+
test(
61+
"validate token extended not expired",
62+
async (ctx: TestContext) => {
63+
const { token } = await ctx.modules.tokens.create({
64+
type: "test",
65+
meta: { foo: "bar" },
66+
// Set initial expiration to 200ms in the future
67+
expireAt: new Date(Date.now() + 200).toISOString(),
68+
});
69+
70+
// Token should be valid
71+
const validateRes = await ctx.modules.tokens.validate({
72+
token: token.token,
73+
});
74+
assertEquals(token.id, validateRes.token.id);
75+
76+
// Extend token expiration by 10 seconds
77+
await ctx.modules.tokens.extend({
78+
token: token.token,
79+
newExpiration: new Date(Date.now() + 10000).toISOString(),
80+
});
81+
82+
// Wait for 0.5 seconds to ensure token WOULD HAVE expired without
83+
// extension.
84+
await new Promise((resolve) => setTimeout(resolve, 500));
85+
86+
// Token should STILL be valid, and have a different `expireAt` time
87+
const validateResAfterWait = await ctx.modules.tokens.validate({
88+
token: token.token,
89+
});
90+
91+
// Assert that everything except `expireAt` is the same and `expireAt`
92+
// is greater.
93+
assertGreater(validateResAfterWait.token.expireAt, token.expireAt);
94+
assertEquals({
95+
...validateResAfterWait.token,
96+
expireAt: null,
97+
}, {
98+
...token,
99+
expireAt: null,
100+
})
56101
},
57102
);

0 commit comments

Comments
 (0)