-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2221169
commit f3d8331
Showing
15 changed files
with
457 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { JWTDecoded } from "@kinde/jwt-decoder"; | ||
import { getDecodedToken } from "./getDecodedToken"; | ||
|
||
/** | ||
* | ||
* @param keyName key to get from the token | ||
* @returns { Promise<string | number | string[] | null> } | ||
*/ | ||
export const getClaim = async <T = JWTDecoded, V = string | number | string[]>( | ||
keyName: keyof T, | ||
): Promise<{ | ||
name: keyof T; | ||
value: V; | ||
} | null> => { | ||
const claims = await getDecodedToken<T>("accessToken"); | ||
if (!claims) { | ||
return null; | ||
} | ||
return { | ||
name: keyName, | ||
value: claims[keyName] as V, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { JWTDecoded } from "@kinde/jwt-decoder"; | ||
import { getDecodedToken } from "./getDecodedToken"; | ||
|
||
/** | ||
* get all claims from the token | ||
* @returns { Promise<T | null> } | ||
*/ | ||
export const getClaims = async <T = JWTDecoded>(): Promise<T | null> => { | ||
return getDecodedToken<T>("accessToken"); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { getClaim } from "./getClaim"; | ||
|
||
/** | ||
* | ||
* @param keyName key to get from the token | ||
* @returns { Promise<string | number | string[] | null> } | ||
**/ | ||
export const getCurrentOrganization = async (): Promise<string | null> => { | ||
return ( | ||
(await getClaim<{ org_code: string }, string>("org_code"))?.value || null | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { describe, expect, it, beforeEach } from "vitest"; | ||
import { MemoryStorage, StorageKeys } from "../../sessionManager"; | ||
import { setActiveStorage, getFlag } from "."; | ||
import { createMockAccessToken } from "./testUtils"; | ||
|
||
const storage = new MemoryStorage(); | ||
|
||
describe("getFlag", () => { | ||
beforeEach(() => { | ||
setActiveStorage(storage); | ||
}); | ||
it("when no token", async () => { | ||
await storage.setSessionItem(StorageKeys.idToken, null); | ||
const idToken = await getFlag("test"); | ||
|
||
expect(idToken).toStrictEqual(null); | ||
}); | ||
|
||
it("boolean", async () => { | ||
await storage.setSessionItem(StorageKeys.accessToken, createMockAccessToken({ feature_flags: { | ||
test: { | ||
v: true, | ||
t: "b" | ||
}}}),); | ||
const idToken = await getFlag<boolean>("test"); | ||
|
||
expect(idToken).toStrictEqual(true); | ||
}); | ||
|
||
it("string", async () => { | ||
await storage.setSessionItem(StorageKeys.accessToken, createMockAccessToken({ feature_flags: { | ||
test: { | ||
v: "hello", | ||
t: "s" | ||
}}}),); | ||
const idToken = await getFlag<string>("test"); | ||
|
||
expect(idToken).toStrictEqual("hello"); | ||
}); | ||
|
||
it("integer", async () => { | ||
await storage.setSessionItem(StorageKeys.accessToken, createMockAccessToken({ feature_flags: { | ||
test: { | ||
v: 5, | ||
t: "i" | ||
}}}),); | ||
const idToken = await getFlag<number>("test"); | ||
|
||
expect(idToken).toStrictEqual(5); | ||
}); | ||
|
||
it("no existing flag", async () => { | ||
await storage.setSessionItem(StorageKeys.accessToken, createMockAccessToken({ feature_flags: { | ||
test: { | ||
v: 5, | ||
t: "i" | ||
}}}),); | ||
const idToken = await getFlag<number>("noexist"); | ||
|
||
expect(idToken).toStrictEqual(null); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { getClaim } from "./getClaim"; | ||
|
||
/** | ||
* | ||
* @param keyName key to get from the token | ||
* @returns { Promise<string | number | string[] | null> } | ||
*/ | ||
export const getFlag = async <T = string | boolean | number>( | ||
name: string, | ||
): Promise<T | null> => { | ||
const flags = ( | ||
await getClaim< | ||
{ feature_flags: string }, | ||
Record<string, { t: "b" | "i" | "s"; v: T }> | ||
>("feature_flags") | ||
)?.value; | ||
|
||
if (name && flags) { | ||
const value = flags[name]; | ||
return value?.v || null; | ||
} | ||
return null; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { describe, expect, it, beforeEach } from "vitest"; | ||
import { MemoryStorage, StorageKeys } from "../../sessionManager"; | ||
import { setActiveStorage, getPermission } from "."; | ||
import { createMockAccessToken } from "./testUtils"; | ||
|
||
const storage = new MemoryStorage(); | ||
|
||
enum PermissionEnum { | ||
canEdit = "canEdit", | ||
} | ||
|
||
describe("getPermission", () => { | ||
beforeEach(() => { | ||
setActiveStorage(storage); | ||
}); | ||
it("when no token", async () => { | ||
await storage.setSessionItem(StorageKeys.idToken, null); | ||
const idToken = await getPermission("test"); | ||
|
||
expect(idToken).toStrictEqual({ | ||
isGranted: false, | ||
orgCode: null, | ||
permissionKey: "test", | ||
}); | ||
}); | ||
|
||
it("when no token with enum", async () => { | ||
await storage.setSessionItem(StorageKeys.idToken, null); | ||
const idToken = await getPermission<PermissionEnum>(PermissionEnum.canEdit); | ||
|
||
expect(idToken).toStrictEqual({ | ||
isGranted: false, | ||
orgCode: null, | ||
permissionKey: "canEdit", | ||
}); | ||
}); | ||
|
||
it("with access", async () => { | ||
await storage.setSessionItem( | ||
StorageKeys.accessToken, | ||
createMockAccessToken({ permissions: ["canEdit"] }), | ||
); | ||
const idToken = await getPermission<PermissionEnum>(PermissionEnum.canEdit); | ||
|
||
expect(idToken).toStrictEqual({ | ||
isGranted: true, | ||
orgCode: "org_123456789", | ||
permissionKey: "canEdit", | ||
}); | ||
}); | ||
|
||
it("with access different org", async () => { | ||
await storage.setSessionItem( | ||
StorageKeys.accessToken, | ||
createMockAccessToken({ | ||
permissions: ["canEdit"], | ||
org_code: "org_123456799", | ||
}), | ||
); | ||
const idToken = await getPermission<PermissionEnum>(PermissionEnum.canEdit); | ||
|
||
expect(idToken).toStrictEqual({ | ||
isGranted: true, | ||
orgCode: "org_123456799", | ||
permissionKey: "canEdit", | ||
}); | ||
}); | ||
|
||
it("no access, empty permission array", async () => { | ||
await storage.setSessionItem( | ||
StorageKeys.accessToken, | ||
createMockAccessToken({ permissions: null }), | ||
); | ||
const idToken = await getPermission<PermissionEnum>(PermissionEnum.canEdit); | ||
|
||
expect(idToken).toStrictEqual({ | ||
isGranted: false, | ||
orgCode: "org_123456789", | ||
permissionKey: "canEdit", | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { getDecodedToken } from "."; | ||
|
||
export type PermissionAccess = { | ||
permissionKey: string; | ||
orgCode: string | null; | ||
isGranted: boolean; | ||
}; | ||
|
||
/** | ||
* | ||
* @param permissionKey gets the value of a permission | ||
* @returns { PermissionAccess } | ||
*/ | ||
export const getPermission = async <T = string>( | ||
permissionKey: T, | ||
): Promise<PermissionAccess> => { | ||
const token = await getDecodedToken(); | ||
|
||
if (!token) { | ||
return { | ||
permissionKey: permissionKey as string, | ||
orgCode: null, | ||
isGranted: false, | ||
}; | ||
} | ||
|
||
const permissions = token.permissions || []; | ||
return { | ||
permissionKey: permissionKey as string, | ||
orgCode: token.org_code, | ||
isGranted: !!permissions.includes(permissionKey as string), | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { describe, expect, it, beforeEach } from "vitest"; | ||
import { MemoryStorage, StorageKeys } from "../../sessionManager"; | ||
import { setActiveStorage } from "."; | ||
import { createMockAccessToken } from "./testUtils"; | ||
import { getPermissions } from "."; | ||
|
||
const storage = new MemoryStorage(); | ||
|
||
enum PermissionEnum { | ||
canEdit = "canEdit", | ||
} | ||
|
||
describe("getPermissions", () => { | ||
beforeEach(() => { | ||
setActiveStorage(storage); | ||
}); | ||
|
||
it("when no token", async () => { | ||
await storage.setSessionItem(StorageKeys.idToken, null); | ||
const idToken = await getPermissions(); | ||
|
||
expect(idToken).toStrictEqual({ | ||
orgCode: null, | ||
permissions: [], | ||
}); | ||
}); | ||
|
||
it("with value", async () => { | ||
await storage.setSessionItem( | ||
StorageKeys.accessToken, | ||
createMockAccessToken({ permissions: ["canEdit"] }), | ||
); | ||
const idToken = await getPermissions(); | ||
|
||
expect(idToken).toStrictEqual({ | ||
orgCode: "org_123456789", | ||
permissions: ["canEdit"], | ||
}); | ||
}); | ||
|
||
it("with value and typed permissions", async () => { | ||
await storage.setSessionItem( | ||
StorageKeys.accessToken, | ||
createMockAccessToken({ permissions: ["canEdit"] }), | ||
); | ||
const idToken = await getPermissions<PermissionEnum>(); | ||
|
||
expect(idToken).toStrictEqual({ | ||
orgCode: "org_123456789", | ||
permissions: [PermissionEnum.canEdit], | ||
}); | ||
}); | ||
|
||
it("no permissions array", async () => { | ||
await storage.setSessionItem( | ||
StorageKeys.accessToken, | ||
createMockAccessToken({ permissions: null }), | ||
); | ||
const idToken = await getPermissions<PermissionEnum>(); | ||
|
||
expect(idToken).toStrictEqual({ | ||
orgCode: "org_123456789", | ||
permissions: [], | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { getDecodedToken } from "."; | ||
|
||
export type Permissions<T> = { orgCode: string | null; permissions: T[] }; | ||
/** | ||
* Get all permissions | ||
* @returns { Promise<Permissions> } | ||
*/ | ||
export const getPermissions = async <T = string>(): Promise<Permissions<T>> => { | ||
const token = await getDecodedToken(); | ||
|
||
if (!token) { | ||
return { | ||
orgCode: null, | ||
permissions: [], | ||
}; | ||
} | ||
|
||
const permissions = token.permissions || []; | ||
return { | ||
orgCode: token.org_code, | ||
permissions: permissions as T[], | ||
}; | ||
}; |
Oops, something went wrong.