-
Notifications
You must be signed in to change notification settings - Fork 79
/
primitiveClaim.ts
100 lines (90 loc) · 3.62 KB
/
primitiveClaim.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import RecipeUserId from "../../../recipeUserId";
import { JSONObject, JSONPrimitive, UserContext } from "../../../types";
import { SessionClaim, SessionClaimValidator } from "../types";
export class PrimitiveClaim<T extends JSONPrimitive> extends SessionClaim<T> {
public readonly fetchValue: (
userId: string,
recipeUserId: RecipeUserId,
tenantId: string,
currentPayload: JSONObject | undefined,
userContext: UserContext
) => Promise<T | undefined> | T | undefined;
public readonly defaultMaxAgeInSeconds: number | undefined;
constructor(config: { key: string; fetchValue: SessionClaim<T>["fetchValue"]; defaultMaxAgeInSeconds?: number }) {
super(config.key);
this.fetchValue = config.fetchValue;
this.defaultMaxAgeInSeconds = config.defaultMaxAgeInSeconds;
}
addToPayload_internal(payload: any, value: T, _userContext: UserContext): any {
return {
...payload,
[this.key]: {
v: value,
t: Date.now(),
},
};
}
removeFromPayloadByMerge_internal(payload: any, _userContext: UserContext): any {
const res = {
...payload,
[this.key]: null,
};
return res;
}
removeFromPayload(payload: any, _userContext: UserContext): any {
const res = {
...payload,
};
delete res[this.key];
return res;
}
getValueFromPayload(payload: any, _userContext: UserContext): T | undefined {
return payload[this.key]?.v;
}
getLastRefetchTime(payload: any, _userContext: UserContext): number | undefined {
return payload[this.key]?.t;
}
validators = {
hasValue: (
val: T,
maxAgeInSeconds: number | undefined = this.defaultMaxAgeInSeconds,
id?: string
): SessionClaimValidator => {
return {
claim: this,
id: id ?? this.key,
shouldRefetch: (payload, ctx) =>
this.getValueFromPayload(payload, ctx) === undefined ||
(maxAgeInSeconds !== undefined && // We know payload[this.id] is defined since the value is not undefined in this branch
payload[this.key].t < Date.now() - maxAgeInSeconds * 1000),
validate: async (payload, ctx) => {
const claimVal = this.getValueFromPayload(payload, ctx);
if (claimVal === undefined) {
return {
isValid: false,
reason: { message: "value does not exist", expectedValue: val, actualValue: claimVal },
};
}
const ageInSeconds = (Date.now() - this.getLastRefetchTime(payload, ctx)!) / 1000;
if (maxAgeInSeconds !== undefined && ageInSeconds > maxAgeInSeconds) {
return {
isValid: false,
reason: {
message: "expired",
ageInSeconds,
maxAgeInSeconds,
},
};
}
if (claimVal !== val) {
return {
isValid: false,
reason: { message: "wrong value", expectedValue: val, actualValue: claimVal },
};
}
return { isValid: true };
},
};
},
};
}