@bool-ts/guard-sdk 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +2 -0
- package/dist/constants/enums.d.ts +3 -0
- package/dist/constants/index.d.ts +2 -0
- package/dist/constants/keys.d.ts +4 -0
- package/dist/decorators/actionGuard.decorator.d.ts +1 -0
- package/dist/decorators/authState.decorator.d.ts +1 -0
- package/dist/decorators/controllerGuard.decorator.d.ts +1 -0
- package/dist/decorators/index.d.ts +3 -0
- package/dist/entities/index.d.ts +2 -0
- package/dist/entities/interceptor.d.ts +5 -0
- package/dist/entities/loader.d.ts +4 -0
- package/dist/entities/middleware.d.ts +19 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +57 -0
- package/dist/instances/client.d.ts +47 -0
- package/dist/instances/index.d.ts +1 -0
- package/dist/interfaces/account.interface.d.ts +6 -0
- package/dist/interfaces/accountCredential.interface.d.ts +7 -0
- package/dist/interfaces/base.d.ts +3 -0
- package/dist/interfaces/client.interface.d.ts +48 -0
- package/dist/interfaces/index.d.ts +4 -0
- package/package.json +50 -0
- package/src/constants/enums.ts +3 -0
- package/src/constants/index.ts +2 -0
- package/src/constants/keys.ts +4 -0
- package/src/decorators/actionGuard.decorator.ts +5 -0
- package/src/decorators/authState.decorator.ts +4 -0
- package/src/decorators/controllerGuard.decorator.ts +5 -0
- package/src/decorators/index.ts +3 -0
- package/src/entities/index.ts +2 -0
- package/src/entities/interceptor.ts +47 -0
- package/src/entities/loader.ts +20 -0
- package/src/entities/middleware.ts +73 -0
- package/src/index.ts +6 -0
- package/src/instances/client.ts +314 -0
- package/src/instances/index.ts +1 -0
- package/src/interfaces/account.interface.ts +7 -0
- package/src/interfaces/accountCredential.interface.ts +7 -0
- package/src/interfaces/base.ts +3 -0
- package/src/interfaces/client.interface.ts +52 -0
- package/src/interfaces/index.ts +4 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { IClient, TClientConfigs, TClientOptions } from "../interfaces/client.interface";
|
|
2
|
+
export declare class Client implements IClient {
|
|
3
|
+
#private;
|
|
4
|
+
private readonly configs;
|
|
5
|
+
private readonly options?;
|
|
6
|
+
private token;
|
|
7
|
+
/**
|
|
8
|
+
* Initialize BoolGuard client instance
|
|
9
|
+
* @param configs
|
|
10
|
+
* @param options
|
|
11
|
+
*/
|
|
12
|
+
constructor(configs: TClientConfigs, options?: TClientOptions | undefined);
|
|
13
|
+
/**
|
|
14
|
+
* Sign JWT token with Ed25519 algorithm
|
|
15
|
+
* @returns
|
|
16
|
+
*/
|
|
17
|
+
signToken(): Promise<string>;
|
|
18
|
+
/**
|
|
19
|
+
* Ping to BoolGuard service to check if the service is reachable
|
|
20
|
+
* This action should be done before any other actions.
|
|
21
|
+
* @returns
|
|
22
|
+
*/
|
|
23
|
+
ping(): Promise<boolean>;
|
|
24
|
+
/**
|
|
25
|
+
* Create a new plain account with custom account name
|
|
26
|
+
* @param args
|
|
27
|
+
* @returns
|
|
28
|
+
*/
|
|
29
|
+
createPlainAccount({ identity, password, metadata }: Parameters<IClient["createPlainAccount"]>[number]): ReturnType<IClient["createPlainAccount"]>;
|
|
30
|
+
/**
|
|
31
|
+
* Create a new email account, this action will create email record and link to account
|
|
32
|
+
* with random account alias generated by system.
|
|
33
|
+
* @param args
|
|
34
|
+
*/
|
|
35
|
+
createEmailAccount({ identity, password, metadata }: Parameters<IClient["createEmailAccount"]>[number]): ReturnType<IClient["createEmailAccount"]>;
|
|
36
|
+
/**
|
|
37
|
+
* Authenticate an account with account name and password
|
|
38
|
+
* This action will return account info and JWT token if successful
|
|
39
|
+
* @param param0
|
|
40
|
+
*/
|
|
41
|
+
authenticate({ identity, password }: Parameters<IClient["authenticate"]>[number]): ReturnType<IClient["authenticate"]>;
|
|
42
|
+
/**
|
|
43
|
+
* Authenticate a token and return account info if token is valid
|
|
44
|
+
* @param param0
|
|
45
|
+
*/
|
|
46
|
+
verifyToken({ token }: Parameters<IClient["verifyToken"]>[number]): ReturnType<IClient["verifyToken"]>;
|
|
47
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Client } from "./client";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { IAccount, TDefaultAccountMetadata } from "./account.interface";
|
|
2
|
+
import type { IAccountCredential } from "./accountCredential.interface";
|
|
3
|
+
export type TClientConfigs = {
|
|
4
|
+
tenantId: string;
|
|
5
|
+
appId: string;
|
|
6
|
+
modeId: string;
|
|
7
|
+
secretKey: string;
|
|
8
|
+
};
|
|
9
|
+
export type TClientOptions = {
|
|
10
|
+
version?: 1;
|
|
11
|
+
logs?: boolean;
|
|
12
|
+
};
|
|
13
|
+
export interface IClient<TAccountMetadata extends TDefaultAccountMetadata = TDefaultAccountMetadata> {
|
|
14
|
+
createPlainAccount(args: {
|
|
15
|
+
identity: string;
|
|
16
|
+
password: string;
|
|
17
|
+
metadata?: TAccountMetadata | null;
|
|
18
|
+
}): Promise<Readonly<{
|
|
19
|
+
account: IAccount<TAccountMetadata>;
|
|
20
|
+
credential: IAccountCredential;
|
|
21
|
+
}>>;
|
|
22
|
+
createEmailAccount(args: {
|
|
23
|
+
identity: string;
|
|
24
|
+
password: string | null;
|
|
25
|
+
metadata?: TAccountMetadata | null;
|
|
26
|
+
}): Promise<Readonly<{
|
|
27
|
+
account: IAccount<TAccountMetadata>;
|
|
28
|
+
credential: IAccountCredential;
|
|
29
|
+
}>>;
|
|
30
|
+
authenticate(args: {
|
|
31
|
+
identity: string;
|
|
32
|
+
password?: string | null;
|
|
33
|
+
}): Promise<{
|
|
34
|
+
token: string;
|
|
35
|
+
account: IAccount<TAccountMetadata>;
|
|
36
|
+
credential: IAccountCredential;
|
|
37
|
+
}>;
|
|
38
|
+
verifyToken(args: {
|
|
39
|
+
token: string;
|
|
40
|
+
}): Promise<{
|
|
41
|
+
account: IAccount<TAccountMetadata>;
|
|
42
|
+
credential: IAccountCredential;
|
|
43
|
+
}>;
|
|
44
|
+
}
|
|
45
|
+
export type TAuthState = {
|
|
46
|
+
account: IAccount;
|
|
47
|
+
credential: IAccountCredential;
|
|
48
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"author": "Trần Đức Tâm (Neo)",
|
|
3
|
+
"bugs": {
|
|
4
|
+
"url": "https://github.com/BoolTS/guard-sdk/issues"
|
|
5
|
+
},
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"jose": "^6.1.0",
|
|
8
|
+
"reflect-metadata": "^0.2.2",
|
|
9
|
+
"zod": "^4.1.9"
|
|
10
|
+
},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"@types/bun": "latest",
|
|
13
|
+
"typescript": "^5.9.2"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"./dist",
|
|
17
|
+
"./src"
|
|
18
|
+
],
|
|
19
|
+
"homepage": "https://github.com/BoolTS/guard-sdk#readme",
|
|
20
|
+
"keywords": [
|
|
21
|
+
"bool",
|
|
22
|
+
"typescript",
|
|
23
|
+
"ts",
|
|
24
|
+
"bun",
|
|
25
|
+
"framework",
|
|
26
|
+
"guards",
|
|
27
|
+
"security",
|
|
28
|
+
"SDK"
|
|
29
|
+
],
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"main": "./dist/index.js",
|
|
32
|
+
"name": "@bool-ts/guard-sdk",
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@bool-ts/core": "^2.0.3"
|
|
35
|
+
},
|
|
36
|
+
"private": false,
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "git+https://github.com/BoolTS/guard-sdk.git"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsc --emitDeclarationOnly && bun run app.build.ts",
|
|
46
|
+
"test": "bun --hot run __test/index.ts"
|
|
47
|
+
},
|
|
48
|
+
"types": "./dist/index.d.ts",
|
|
49
|
+
"version": "1.0.0-beta.1"
|
|
50
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { IInterceptor, THttpRouteModel } from "@bool-ts/core";
|
|
2
|
+
import type { TAuthState } from "../interfaces/client.interface";
|
|
3
|
+
|
|
4
|
+
import { Interceptor as BoolInterceptor, HttpClientError, RouteModel } from "@bool-ts/core";
|
|
5
|
+
import { Keys } from "../constants";
|
|
6
|
+
import { AuthState } from "../decorators/authState.decorator";
|
|
7
|
+
|
|
8
|
+
@BoolInterceptor()
|
|
9
|
+
export class Interceptor implements IInterceptor {
|
|
10
|
+
open(
|
|
11
|
+
@RouteModel()
|
|
12
|
+
routeModel: THttpRouteModel,
|
|
13
|
+
@AuthState()
|
|
14
|
+
authState: TAuthState
|
|
15
|
+
) {
|
|
16
|
+
const actionMetadataKeys = Reflect.getOwnMetadataKeys(
|
|
17
|
+
routeModel.class.prototype,
|
|
18
|
+
routeModel.funcName
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
if (actionMetadataKeys.includes(Keys.authState)) {
|
|
22
|
+
if (!authState) {
|
|
23
|
+
throw new HttpClientError({
|
|
24
|
+
httpCode: 401,
|
|
25
|
+
message: "Unauthorized",
|
|
26
|
+
data: undefined
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const controllerMetadataKeys = Reflect.getOwnMetadataKeys(routeModel.class);
|
|
34
|
+
|
|
35
|
+
if (controllerMetadataKeys.includes(Keys.authState)) {
|
|
36
|
+
if (!authState) {
|
|
37
|
+
throw new HttpClientError({
|
|
38
|
+
httpCode: 401,
|
|
39
|
+
message: "Unauthorized",
|
|
40
|
+
data: undefined
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { TClientConfigs, TClientOptions } from "../interfaces/client.interface";
|
|
2
|
+
|
|
3
|
+
import { Keys } from "../constants";
|
|
4
|
+
import { Client } from "../instances/client";
|
|
5
|
+
|
|
6
|
+
export const loader = async (clientConfigs: TClientConfigs, clientOptions?: TClientOptions) => {
|
|
7
|
+
const boolGuardClient = new Client(clientConfigs, clientOptions);
|
|
8
|
+
|
|
9
|
+
await boolGuardClient.signToken();
|
|
10
|
+
|
|
11
|
+
const pingResult = await boolGuardClient.ping();
|
|
12
|
+
|
|
13
|
+
if (!pingResult) {
|
|
14
|
+
throw new Error("Ping to Bool Guard service failed!");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return [Keys.guardClient, boolGuardClient];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default loader;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { IContext, IMiddleware } from "@bool-ts/core";
|
|
2
|
+
import type { IClient, TAuthState } from "../interfaces/client.interface";
|
|
3
|
+
|
|
4
|
+
import { Context, Inject, RequestHeaders } from "@bool-ts/core";
|
|
5
|
+
import { object, string } from "zod/v4";
|
|
6
|
+
import { Keys } from "../constants";
|
|
7
|
+
import { Client } from "../instances";
|
|
8
|
+
|
|
9
|
+
const headersSchema = object({
|
|
10
|
+
authorization: string()
|
|
11
|
+
.startsWith("Bearer ")
|
|
12
|
+
.min(24)
|
|
13
|
+
.transform((value) => {
|
|
14
|
+
const [schema, token] = value.split(" ");
|
|
15
|
+
|
|
16
|
+
return Object.freeze({
|
|
17
|
+
schema,
|
|
18
|
+
token
|
|
19
|
+
});
|
|
20
|
+
})
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Bool guard middleware for Bool Typescript framework
|
|
25
|
+
*/
|
|
26
|
+
export class Middleware implements IMiddleware {
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @param tenantAppModesService
|
|
30
|
+
*/
|
|
31
|
+
constructor(
|
|
32
|
+
@Inject(Client)
|
|
33
|
+
private readonly clientInstance: IClient
|
|
34
|
+
) {}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* @param context
|
|
39
|
+
* @param requestHeaders
|
|
40
|
+
*/
|
|
41
|
+
async start(
|
|
42
|
+
@Context()
|
|
43
|
+
context: IContext,
|
|
44
|
+
@RequestHeaders()
|
|
45
|
+
requestHeaders: Headers
|
|
46
|
+
) {
|
|
47
|
+
const headersValidation = await headersSchema.safeParseAsync(requestHeaders.toJSON());
|
|
48
|
+
|
|
49
|
+
if (!headersValidation.success) {
|
|
50
|
+
return context.set(Keys.authState, undefined);
|
|
51
|
+
} else {
|
|
52
|
+
const {
|
|
53
|
+
authorization: { token }
|
|
54
|
+
} = headersValidation.data;
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
const { account, credential } = await this.clientInstance.verifyToken({
|
|
58
|
+
token: token
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const authState: TAuthState = Object.freeze({
|
|
62
|
+
account: account,
|
|
63
|
+
credential: credential
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return context.set(Keys.authState, authState);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error(error);
|
|
69
|
+
return context.set(Keys.authState, undefined);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import type { TApiResponse } from "../interfaces/base";
|
|
2
|
+
import type { IClient, TClientConfigs, TClientOptions } from "../interfaces/client.interface";
|
|
3
|
+
|
|
4
|
+
import { SignJWT } from "jose";
|
|
5
|
+
import { email } from "zod/v4";
|
|
6
|
+
import { Enums } from "../constants";
|
|
7
|
+
|
|
8
|
+
export class Client implements IClient {
|
|
9
|
+
readonly #baseUri = Enums.ETokenAudiences.SYSTEM;
|
|
10
|
+
|
|
11
|
+
private token: string | undefined;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Initialize BoolGuard client instance
|
|
15
|
+
* @param configs
|
|
16
|
+
* @param options
|
|
17
|
+
*/
|
|
18
|
+
constructor(
|
|
19
|
+
private readonly configs: TClientConfigs,
|
|
20
|
+
private readonly options?: TClientOptions
|
|
21
|
+
) {}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Sign JWT token with Ed25519 algorithm
|
|
25
|
+
* @returns
|
|
26
|
+
*/
|
|
27
|
+
async signToken() {
|
|
28
|
+
try {
|
|
29
|
+
const rawKey = new Uint8Array(Buffer.from(this.configs.secretKey, "base64"));
|
|
30
|
+
const privateKey = await crypto.subtle.importKey(
|
|
31
|
+
"raw",
|
|
32
|
+
rawKey,
|
|
33
|
+
{ name: "HMAC", hash: "SHA-512" },
|
|
34
|
+
false,
|
|
35
|
+
["sign", "verify"]
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const jwt = await new SignJWT({
|
|
39
|
+
tenantId: this.configs.tenantId,
|
|
40
|
+
appId: this.configs.appId,
|
|
41
|
+
modeId: this.configs.modeId,
|
|
42
|
+
iss: this.configs.tenantId,
|
|
43
|
+
aud: Enums.ETokenAudiences.SYSTEM
|
|
44
|
+
})
|
|
45
|
+
.setProtectedHeader({ alg: "HS512" })
|
|
46
|
+
.sign(privateKey);
|
|
47
|
+
|
|
48
|
+
this.token = jwt;
|
|
49
|
+
|
|
50
|
+
return jwt;
|
|
51
|
+
} catch (error) {
|
|
52
|
+
if (this.options?.logs) {
|
|
53
|
+
console.error("[BoolGuard] Sign token error:", error);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Ping to BoolGuard service to check if the service is reachable
|
|
62
|
+
* This action should be done before any other actions.
|
|
63
|
+
* @returns
|
|
64
|
+
*/
|
|
65
|
+
async ping() {
|
|
66
|
+
try {
|
|
67
|
+
const authToken = this.token || (await this.signToken());
|
|
68
|
+
|
|
69
|
+
const requestHeaders = new Headers();
|
|
70
|
+
requestHeaders.append("X-Tenant-ID", this.configs.tenantId);
|
|
71
|
+
requestHeaders.append("X-App-ID", this.configs.appId);
|
|
72
|
+
requestHeaders.append("X-Mode-ID", this.configs.modeId);
|
|
73
|
+
requestHeaders.append("Authorization", `Bearer ${authToken}`);
|
|
74
|
+
|
|
75
|
+
const response = await fetch(
|
|
76
|
+
`${this.#baseUri}/v${this.options?.version}/tenant-app-modes/ping`,
|
|
77
|
+
{
|
|
78
|
+
method: "GET",
|
|
79
|
+
headers: requestHeaders
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
throw await response.json();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return response.ok;
|
|
88
|
+
} catch (error) {
|
|
89
|
+
if (this.options?.logs) {
|
|
90
|
+
console.error("[BoolGuard] Ping error:", error);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Create a new plain account with custom account name
|
|
99
|
+
* @param args
|
|
100
|
+
* @returns
|
|
101
|
+
*/
|
|
102
|
+
async createPlainAccount({
|
|
103
|
+
identity,
|
|
104
|
+
password,
|
|
105
|
+
metadata
|
|
106
|
+
}: Parameters<IClient["createPlainAccount"]>[number]): ReturnType<
|
|
107
|
+
IClient["createPlainAccount"]
|
|
108
|
+
> {
|
|
109
|
+
try {
|
|
110
|
+
const authToken = this.token || (await this.signToken());
|
|
111
|
+
|
|
112
|
+
const requestHeaders = new Headers();
|
|
113
|
+
requestHeaders.append("X-Tenant-ID", this.configs.tenantId);
|
|
114
|
+
requestHeaders.append("X-App-ID", this.configs.appId);
|
|
115
|
+
requestHeaders.append("X-Mode-ID", this.configs.modeId);
|
|
116
|
+
requestHeaders.append("Authorization", `Bearer ${authToken}`);
|
|
117
|
+
requestHeaders.append("Content-Type", "application/json");
|
|
118
|
+
|
|
119
|
+
const response = await fetch(
|
|
120
|
+
`${this.#baseUri}/v${this.options?.version}/tenant-app-mode-accounts`,
|
|
121
|
+
{
|
|
122
|
+
method: "POST",
|
|
123
|
+
headers: requestHeaders,
|
|
124
|
+
body: JSON.stringify({
|
|
125
|
+
data: {
|
|
126
|
+
type: "plain",
|
|
127
|
+
identity: identity,
|
|
128
|
+
password: password,
|
|
129
|
+
metadata: metadata
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
if (!response.ok) {
|
|
136
|
+
throw await response.json();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const { data } = (await response.json()) as TApiResponse<IClient["createPlainAccount"]>;
|
|
140
|
+
|
|
141
|
+
return Object.freeze({
|
|
142
|
+
account: data.account,
|
|
143
|
+
credential: data.credential
|
|
144
|
+
});
|
|
145
|
+
} catch (error) {
|
|
146
|
+
if (this.options?.logs) {
|
|
147
|
+
console.error("[BoolGuard] Create plain account error:", error);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Create a new email account, this action will create email record and link to account
|
|
156
|
+
* with random account alias generated by system.
|
|
157
|
+
* @param args
|
|
158
|
+
*/
|
|
159
|
+
async createEmailAccount({
|
|
160
|
+
identity,
|
|
161
|
+
password,
|
|
162
|
+
metadata
|
|
163
|
+
}: Parameters<IClient["createEmailAccount"]>[number]): ReturnType<
|
|
164
|
+
IClient["createEmailAccount"]
|
|
165
|
+
> {
|
|
166
|
+
try {
|
|
167
|
+
const authToken = this.token || (await this.signToken());
|
|
168
|
+
|
|
169
|
+
const requestHeaders = new Headers();
|
|
170
|
+
requestHeaders.append("X-Tenant-ID", this.configs.tenantId);
|
|
171
|
+
requestHeaders.append("X-App-ID", this.configs.appId);
|
|
172
|
+
requestHeaders.append("X-Mode-ID", this.configs.modeId);
|
|
173
|
+
requestHeaders.append("Authorization", `Bearer ${authToken}`);
|
|
174
|
+
requestHeaders.append("Content-Type", "application/json");
|
|
175
|
+
|
|
176
|
+
const response = await fetch(
|
|
177
|
+
`${this.#baseUri}/v${this.options?.version}/tenant-app-mode-accounts`,
|
|
178
|
+
{
|
|
179
|
+
method: "POST",
|
|
180
|
+
headers: requestHeaders,
|
|
181
|
+
body: JSON.stringify({
|
|
182
|
+
data: {
|
|
183
|
+
type: "email",
|
|
184
|
+
identity: identity,
|
|
185
|
+
password: password,
|
|
186
|
+
metadata: metadata
|
|
187
|
+
}
|
|
188
|
+
})
|
|
189
|
+
}
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
if (!response.ok) {
|
|
193
|
+
throw await response.json();
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const { data } = (await response.json()) as TApiResponse<IClient["createEmailAccount"]>;
|
|
197
|
+
|
|
198
|
+
return Object.freeze({
|
|
199
|
+
account: data.account,
|
|
200
|
+
credential: data.credential
|
|
201
|
+
});
|
|
202
|
+
} catch (error) {
|
|
203
|
+
if (this.options?.logs) {
|
|
204
|
+
console.error("[BoolGuard] Create email account error:", error);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
throw error;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Authenticate an account with account name and password
|
|
213
|
+
* This action will return account info and JWT token if successful
|
|
214
|
+
* @param param0
|
|
215
|
+
*/
|
|
216
|
+
async authenticate({
|
|
217
|
+
identity,
|
|
218
|
+
password
|
|
219
|
+
}: Parameters<IClient["authenticate"]>[number]): ReturnType<IClient["authenticate"]> {
|
|
220
|
+
try {
|
|
221
|
+
const authToken = this.token || (await this.signToken());
|
|
222
|
+
const emailValidation = await email().safeParseAsync(identity);
|
|
223
|
+
|
|
224
|
+
const requestHeaders = new Headers();
|
|
225
|
+
requestHeaders.append("X-Tenant-ID", this.configs.tenantId);
|
|
226
|
+
requestHeaders.append("X-App-ID", this.configs.appId);
|
|
227
|
+
requestHeaders.append("X-Mode-ID", this.configs.modeId);
|
|
228
|
+
requestHeaders.append("Authorization", `Bearer ${authToken}`);
|
|
229
|
+
requestHeaders.append("Content-Type", "application/json");
|
|
230
|
+
|
|
231
|
+
const response = await fetch(
|
|
232
|
+
`${this.#baseUri}/v${this.options?.version}/tenant-app-mode-accounts/authenticate`,
|
|
233
|
+
{
|
|
234
|
+
method: "POST",
|
|
235
|
+
headers: requestHeaders,
|
|
236
|
+
body: JSON.stringify({
|
|
237
|
+
data: {
|
|
238
|
+
type: !emailValidation.success ? "plain" : "email",
|
|
239
|
+
identity: identity,
|
|
240
|
+
password: password
|
|
241
|
+
}
|
|
242
|
+
})
|
|
243
|
+
}
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
if (!response.ok) {
|
|
247
|
+
throw await response.json();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const { data } = (await response.json()) as TApiResponse<IClient["authenticate"]>;
|
|
251
|
+
|
|
252
|
+
return Object.freeze({
|
|
253
|
+
account: data.account,
|
|
254
|
+
credential: data.credential,
|
|
255
|
+
token: data.token
|
|
256
|
+
});
|
|
257
|
+
} catch (error) {
|
|
258
|
+
if (this.options?.logs) {
|
|
259
|
+
console.error("[BoolGuard] Authenticate error:", error);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
throw error;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Authenticate a token and return account info if token is valid
|
|
268
|
+
* @param param0
|
|
269
|
+
*/
|
|
270
|
+
async verifyToken({
|
|
271
|
+
token
|
|
272
|
+
}: Parameters<IClient["verifyToken"]>[number]): ReturnType<IClient["verifyToken"]> {
|
|
273
|
+
try {
|
|
274
|
+
const authToken = this.token || (await this.signToken());
|
|
275
|
+
|
|
276
|
+
const requestHeaders = new Headers();
|
|
277
|
+
requestHeaders.append("X-Tenant-ID", this.configs.tenantId);
|
|
278
|
+
requestHeaders.append("X-App-ID", this.configs.appId);
|
|
279
|
+
requestHeaders.append("X-Mode-ID", this.configs.modeId);
|
|
280
|
+
requestHeaders.append("Authorization", `Bearer ${authToken}`);
|
|
281
|
+
requestHeaders.append("Content-Type", "application/json");
|
|
282
|
+
|
|
283
|
+
const response = await fetch(
|
|
284
|
+
`${this.#baseUri}/v${this.options?.version}/tenant-app-mode-accounts/verify`,
|
|
285
|
+
{
|
|
286
|
+
method: "POST",
|
|
287
|
+
headers: requestHeaders,
|
|
288
|
+
body: JSON.stringify({
|
|
289
|
+
data: {
|
|
290
|
+
token: token
|
|
291
|
+
}
|
|
292
|
+
})
|
|
293
|
+
}
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
if (!response.ok) {
|
|
297
|
+
throw await response.json();
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const { data } = (await response.json()) as TApiResponse<IClient["verifyToken"]>;
|
|
301
|
+
|
|
302
|
+
return Object.freeze({
|
|
303
|
+
account: data.account,
|
|
304
|
+
credential: data.credential
|
|
305
|
+
});
|
|
306
|
+
} catch (error) {
|
|
307
|
+
if (this.options?.logs) {
|
|
308
|
+
console.error("[BoolGuard] Verify token error:", error);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
throw error;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|