@nexys/user-management-sdk 0.0.7 → 0.0.10
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/dist/client.d.ts +13 -2
- package/dist/client.js +22 -4
- package/dist/context.d.ts +4 -2
- package/dist/context.js +10 -4
- package/dist/sso-response.d.ts +1 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +3 -0
- package/dist/utils.test.js +13 -17
- package/package.json +12 -5
- package/dist/login-utils.d.ts +0 -4
- package/dist/login-utils.js +0 -9
package/dist/client.d.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import { Locale, Profile, SSOService, UserAdmin
|
|
1
|
+
import { Locale, Permission, Profile, SSOService, UserAdmin } from "./type";
|
|
2
|
+
export declare const redirectUrl: (ssoService: SSOService) => string;
|
|
2
3
|
declare class AuthClient {
|
|
3
4
|
apiBasename: string;
|
|
4
5
|
constructor(apiBasename: string);
|
|
5
|
-
authSSOUrl: (service: SSOService
|
|
6
|
+
authSSOUrl: (service: SSOService, params?: Partial<{
|
|
7
|
+
isSignup: boolean;
|
|
8
|
+
redirectUrl: string;
|
|
9
|
+
instance: string;
|
|
10
|
+
}>) => Promise<{
|
|
6
11
|
url: string;
|
|
7
12
|
}>;
|
|
8
13
|
authGoogleRedirect: (ssoService: SSOService, code: string, state: string) => Promise<{
|
|
@@ -21,6 +26,12 @@ declare class AuthClient {
|
|
|
21
26
|
locale: Locale;
|
|
22
27
|
}>;
|
|
23
28
|
authLogout: () => Promise<any>;
|
|
29
|
+
tenantExists: (data: {
|
|
30
|
+
name: string;
|
|
31
|
+
}) => Promise<{
|
|
32
|
+
uuid: string;
|
|
33
|
+
name: string;
|
|
34
|
+
}>;
|
|
24
35
|
adminUserList: () => Promise<UserAdmin[]>;
|
|
25
36
|
authRefresh: () => Promise<{
|
|
26
37
|
message: string;
|
package/dist/client.js
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
|
+
import { paramsToString } from "./utils";
|
|
1
2
|
// auth stuff
|
|
2
|
-
const
|
|
3
|
+
const headers = { "content-type": "application/json" };
|
|
4
|
+
export const redirectUrl = (ssoService) => [window.location.origin, "auth", "sso", ssoService, "redirect"].join("/");
|
|
3
5
|
class AuthClient {
|
|
4
6
|
apiBasename;
|
|
5
7
|
constructor(apiBasename) {
|
|
6
8
|
this.apiBasename = apiBasename;
|
|
7
9
|
}
|
|
8
|
-
authSSOUrl = async (service) => {
|
|
9
|
-
const
|
|
10
|
-
|
|
10
|
+
authSSOUrl = async (service, params = {}) => {
|
|
11
|
+
const url = `${this.apiBasename}/auth/${service}/url?${paramsToString(params)}`;
|
|
12
|
+
const response = await fetch(url);
|
|
13
|
+
if (response.ok) {
|
|
14
|
+
return response.json();
|
|
15
|
+
}
|
|
16
|
+
return Promise.reject(response.json());
|
|
11
17
|
};
|
|
12
18
|
authGoogleRedirect = async (ssoService, code, state) => {
|
|
13
19
|
const response = await fetch(this.apiBasename +
|
|
@@ -35,9 +41,21 @@ class AuthClient {
|
|
|
35
41
|
const response = await fetch(this.apiBasename + "/auth/logout");
|
|
36
42
|
return response.json();
|
|
37
43
|
};
|
|
44
|
+
tenantExists = async (data) => {
|
|
45
|
+
const response = await fetch("/napi/instance/exists", {
|
|
46
|
+
method: "POST",
|
|
47
|
+
headers,
|
|
48
|
+
body: JSON.stringify(data),
|
|
49
|
+
});
|
|
50
|
+
if (response.ok) {
|
|
51
|
+
return response.json();
|
|
52
|
+
}
|
|
53
|
+
return Promise.reject(response.json());
|
|
54
|
+
};
|
|
38
55
|
adminUserList = async () => {
|
|
39
56
|
const response = await fetch(this.apiBasename + "/admin/user/list", {
|
|
40
57
|
method: "POST",
|
|
58
|
+
headers,
|
|
41
59
|
});
|
|
42
60
|
return response.json();
|
|
43
61
|
};
|
package/dist/context.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import React, { ReactNode } from "react";
|
|
1
|
+
import React, { JSX, ReactNode } from "react";
|
|
2
2
|
import AuthClient from "./client.js";
|
|
3
|
-
import { Profile } from "./type.js";
|
|
3
|
+
import { Locale, Permission, Profile } from "./type.js";
|
|
4
4
|
export type AuthContextType = {
|
|
5
5
|
profile: Profile;
|
|
6
|
+
permissions: Permission[];
|
|
7
|
+
locale: Locale;
|
|
6
8
|
logout: () => void;
|
|
7
9
|
};
|
|
8
10
|
export declare const AdminContext: React.Context<AuthContextType | undefined>;
|
package/dist/context.js
CHANGED
|
@@ -6,6 +6,8 @@ const REFRESH_INTERVAL = 5 * 60 * 1000; // 5 minutes in milliseconds
|
|
|
6
6
|
export const AuthProvider = ({ authClient, Spinner, loginPath, }) => ({ children }) => {
|
|
7
7
|
const navigate = useNavigate();
|
|
8
8
|
const [profile, setProfile] = useState(null);
|
|
9
|
+
const [permissions, setPermissions] = useState([]);
|
|
10
|
+
const [locale, setLocale] = useState({ country: "US", lang: "en" });
|
|
9
11
|
const refreshToken = useCallback(async () => {
|
|
10
12
|
try {
|
|
11
13
|
await authClient.authRefresh();
|
|
@@ -25,8 +27,10 @@ export const AuthProvider = ({ authClient, Spinner, loginPath, }) => ({ children
|
|
|
25
27
|
.catch(async () => {
|
|
26
28
|
try {
|
|
27
29
|
await authClient.authRefresh();
|
|
28
|
-
const { profile } = await authClient.getProfile();
|
|
30
|
+
const { profile, permissions, locale } = await authClient.getProfile();
|
|
29
31
|
setProfile(profile);
|
|
32
|
+
setPermissions(permissions);
|
|
33
|
+
setLocale(locale);
|
|
30
34
|
}
|
|
31
35
|
catch (e) {
|
|
32
36
|
console.log("e1", e);
|
|
@@ -47,9 +51,6 @@ export const AuthProvider = ({ authClient, Spinner, loginPath, }) => ({ children
|
|
|
47
51
|
return navigate(loginPath, { state: navigationMessage });
|
|
48
52
|
}
|
|
49
53
|
}, []);
|
|
50
|
-
if (profile === null) {
|
|
51
|
-
return _jsx(Spinner, {});
|
|
52
|
-
}
|
|
53
54
|
// Set up refresh interval when profile exists
|
|
54
55
|
React.useEffect(() => {
|
|
55
56
|
if (!profile)
|
|
@@ -59,6 +60,9 @@ export const AuthProvider = ({ authClient, Spinner, loginPath, }) => ({ children
|
|
|
59
60
|
clearInterval(intervalId);
|
|
60
61
|
};
|
|
61
62
|
}, [profile, refreshToken]);
|
|
63
|
+
if (profile === null) {
|
|
64
|
+
return _jsx(Spinner, {});
|
|
65
|
+
}
|
|
62
66
|
const logout = () => {
|
|
63
67
|
setProfile(null);
|
|
64
68
|
authClient.authLogout();
|
|
@@ -73,6 +77,8 @@ export const AuthProvider = ({ authClient, Spinner, loginPath, }) => ({ children
|
|
|
73
77
|
};
|
|
74
78
|
const value = {
|
|
75
79
|
profile,
|
|
80
|
+
permissions,
|
|
81
|
+
locale,
|
|
76
82
|
logout,
|
|
77
83
|
};
|
|
78
84
|
return (_jsx(AdminContext.Provider, { value: value, children: children }));
|
package/dist/sso-response.d.ts
CHANGED
package/dist/utils.d.ts
CHANGED
|
@@ -4,3 +4,4 @@ export declare const getLoginInfoFromQuery: (lSearch: string) => {
|
|
|
4
4
|
} | null;
|
|
5
5
|
export declare const base64UrlToUint8Array: (base64Url: string) => Uint8Array;
|
|
6
6
|
export declare const arrayBufferToBase64: (buffer: ArrayBuffer) => string;
|
|
7
|
+
export declare const paramsToString: (params: Record<string, any>) => string;
|
package/dist/utils.js
CHANGED
|
@@ -32,3 +32,6 @@ export const arrayBufferToBase64 = (buffer) => {
|
|
|
32
32
|
// by replacing "+" with "-", "/" with "_", and stripping "=" padding
|
|
33
33
|
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
34
34
|
};
|
|
35
|
+
export const paramsToString = (params) => Object.entries(params)
|
|
36
|
+
.map(([k, v]) => [k, encodeURIComponent(v)].join("="))
|
|
37
|
+
.join("&");
|
package/dist/utils.test.js
CHANGED
|
@@ -1,25 +1,23 @@
|
|
|
1
|
-
//
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
// Mock browser's atob and btoa for Node.js
|
|
1
|
+
// utils.test.js
|
|
2
|
+
import { describe, expect, it } from "bun:test";
|
|
3
|
+
import { arrayBufferToBase64, base64UrlToUint8Array, getLoginInfoFromQuery, } from "./utils.js";
|
|
4
|
+
// Mock browser's atob and btoa for Node.js/Bun environment
|
|
6
5
|
global.atob = (base64) => Buffer.from(base64, "base64").toString("binary");
|
|
7
6
|
global.btoa = (binary) => Buffer.from(binary, "binary").toString("base64");
|
|
8
|
-
// Describe the test suite
|
|
9
7
|
describe("getLoginInfoFromQuery", () => {
|
|
10
8
|
it('should return null if the query does not contain the "q" parameter', () => {
|
|
11
9
|
const result = getLoginInfoFromQuery("?someOtherParam=abc");
|
|
12
|
-
|
|
10
|
+
expect(result).toBe(null);
|
|
13
11
|
});
|
|
14
12
|
it('should return null if the "q" parameter is missing', () => {
|
|
15
13
|
const result = getLoginInfoFromQuery("");
|
|
16
|
-
|
|
14
|
+
expect(result).toBe(null);
|
|
17
15
|
});
|
|
18
16
|
it('should decode the "q" parameter and return the correct userId and instanceId', () => {
|
|
19
17
|
const encodedParam = Buffer.from("user123:instance456").toString("base64");
|
|
20
18
|
const query = `?q=${encodedParam}`;
|
|
21
19
|
const result = getLoginInfoFromQuery(query);
|
|
22
|
-
|
|
20
|
+
expect(result).toEqual({
|
|
23
21
|
userId: "user123",
|
|
24
22
|
instanceId: "instance456",
|
|
25
23
|
});
|
|
@@ -28,13 +26,12 @@ describe("getLoginInfoFromQuery", () => {
|
|
|
28
26
|
const encodedParam = Buffer.from("user123").toString("base64");
|
|
29
27
|
const query = `?q=${encodedParam}`;
|
|
30
28
|
const result = getLoginInfoFromQuery(query);
|
|
31
|
-
|
|
29
|
+
expect(result).toEqual({
|
|
32
30
|
userId: "user123",
|
|
33
31
|
instanceId: undefined,
|
|
34
32
|
});
|
|
35
33
|
});
|
|
36
34
|
});
|
|
37
|
-
// Tests for base64UrlToUint8Array
|
|
38
35
|
describe("base64UrlToUint8Array", () => {
|
|
39
36
|
it("should correctly convert Base64URL string to Uint8Array", () => {
|
|
40
37
|
const base64Url = "SGVsbG8td29ybGQ_"; // Base64URL for "Hello-world?"
|
|
@@ -42,7 +39,7 @@ describe("base64UrlToUint8Array", () => {
|
|
|
42
39
|
72, 101, 108, 108, 111, 45, 119, 111, 114, 108, 100, 63,
|
|
43
40
|
]);
|
|
44
41
|
const result = base64UrlToUint8Array(base64Url);
|
|
45
|
-
|
|
42
|
+
expect(result).toEqual(expectedArray);
|
|
46
43
|
});
|
|
47
44
|
it("should handle padding correctly", () => {
|
|
48
45
|
const base64Url = "SGVsbG8gd29ybGQ"; // Base64URL for "Hello world" without padding
|
|
@@ -50,10 +47,9 @@ describe("base64UrlToUint8Array", () => {
|
|
|
50
47
|
72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100,
|
|
51
48
|
]);
|
|
52
49
|
const result = base64UrlToUint8Array(base64Url);
|
|
53
|
-
|
|
50
|
+
expect(result).toEqual(expectedArray);
|
|
54
51
|
});
|
|
55
52
|
});
|
|
56
|
-
// Tests for arrayBufferToBase64
|
|
57
53
|
describe("arrayBufferToBase64", () => {
|
|
58
54
|
it("should correctly convert ArrayBuffer to Base64URL string", () => {
|
|
59
55
|
const buffer = new Uint8Array([
|
|
@@ -61,18 +57,18 @@ describe("arrayBufferToBase64", () => {
|
|
|
61
57
|
]).buffer;
|
|
62
58
|
const expectedBase64Url = "SGVsbG8td29ybGQ_";
|
|
63
59
|
const result = arrayBufferToBase64(buffer);
|
|
64
|
-
|
|
60
|
+
expect(result).toBe(expectedBase64Url);
|
|
65
61
|
});
|
|
66
62
|
it("should handle empty ArrayBuffer", () => {
|
|
67
63
|
const buffer = new ArrayBuffer(0);
|
|
68
64
|
const expectedBase64Url = "";
|
|
69
65
|
const result = arrayBufferToBase64(buffer);
|
|
70
|
-
|
|
66
|
+
expect(result).toBe(expectedBase64Url);
|
|
71
67
|
});
|
|
72
68
|
it("should handle large ArrayBuffer", () => {
|
|
73
69
|
const buffer = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]).buffer;
|
|
74
70
|
const expectedBase64Url = "AAECAwQFBgcICQ";
|
|
75
71
|
const result = arrayBufferToBase64(buffer);
|
|
76
|
-
|
|
72
|
+
expect(result).toBe(expectedBase64Url);
|
|
77
73
|
});
|
|
78
74
|
});
|
package/package.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexys/user-management-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "react client/sdk that faciliates connecting to the user management",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"devDependencies": {
|
|
8
|
+
"@types/bun": "^1.1.14",
|
|
8
9
|
"@types/node": "^22.5.4",
|
|
9
|
-
"@types/react": "^
|
|
10
|
-
"react": "^
|
|
10
|
+
"@types/react": "^19.0.2",
|
|
11
|
+
"@types/react-dom": "^19.0.2",
|
|
12
|
+
"react": "^19.0.0",
|
|
11
13
|
"react-router-dom": "^6.26.2",
|
|
12
14
|
"typescript": "^5.6.2"
|
|
13
15
|
},
|
|
@@ -17,7 +19,7 @@
|
|
|
17
19
|
],
|
|
18
20
|
"scripts": {
|
|
19
21
|
"build": "tsc",
|
|
20
|
-
"test": "
|
|
22
|
+
"test": "bun test",
|
|
21
23
|
"buildPackage": "yarn build; rm dist/*.test.js; rm dist/*.test.d.ts"
|
|
22
24
|
},
|
|
23
25
|
"repository": {
|
|
@@ -29,5 +31,10 @@
|
|
|
29
31
|
"bugs": {
|
|
30
32
|
"url": "https://github.com/nexys-system/user-management-client/issues"
|
|
31
33
|
},
|
|
32
|
-
"homepage": "https://github.com/nexys-system/user-management-client#readme"
|
|
34
|
+
"homepage": "https://github.com/nexys-system/user-management-client#readme",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@nexys/user-management-aas": "^0.6.8",
|
|
37
|
+
"@nexys/validation": "^2.1.8",
|
|
38
|
+
"react-dom": "^19.0.0"
|
|
39
|
+
}
|
|
33
40
|
}
|
package/dist/login-utils.d.ts
DELETED
package/dist/login-utils.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export const getLoginInfoFromQuery = (lSearch) => {
|
|
2
|
-
const queryParams = new URLSearchParams(lSearch);
|
|
3
|
-
const paramValue = queryParams.get("q");
|
|
4
|
-
if (!paramValue) {
|
|
5
|
-
return null;
|
|
6
|
-
}
|
|
7
|
-
const [userId, instanceId] = atob(paramValue).split(":");
|
|
8
|
-
return { userId, instanceId };
|
|
9
|
-
};
|