@canmingir/link 1.2.5 → 1.2.6
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/package.json +1 -1
- package/src/context/reducer.js +1 -4
- package/src/http/index.js +11 -8
- package/src/http/user.js +48 -16
- package/src/layouts/DashboardLayout/nav-mini.jsx +34 -14
- package/src/layouts/FullScreenLayout/nav-horizontal.jsx +6 -1
- package/src/layouts/common/ProjectBar/index.jsx +13 -13
- package/src/layouts/common/account-popover.jsx +2 -3
- package/src/lib/Flow/FlowNode.jsx +8 -12
- package/src/pages/Callback.jsx +9 -9
- package/src/pages/LoginPage.jsx +4 -1
- package/src/widgets/Login/Login.jsx +4 -1
- package/src/widgets/LoginForm/LoginForm.jsx +5 -5
package/package.json
CHANGED
package/src/context/reducer.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import config from "../config/config";
|
|
2
1
|
import { jwtDecode } from "jwt-decode";
|
|
3
2
|
import { storage } from "@nucleoidjs/webstorage";
|
|
4
3
|
|
|
5
|
-
const { name } = config();
|
|
6
|
-
|
|
7
4
|
let login = true;
|
|
8
5
|
const itemId = storage.get("itemId");
|
|
9
6
|
try {
|
|
10
|
-
const token = storage.get(
|
|
7
|
+
const token = storage.get("link", "accessToken");
|
|
11
8
|
const decodedToken = jwtDecode(token);
|
|
12
9
|
|
|
13
10
|
if (decodedToken.exp * 1000 < Date.now()) {
|
package/src/http/index.js
CHANGED
|
@@ -15,8 +15,8 @@ const instance = axios.create({
|
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
instance.interceptors.request.use((request) => {
|
|
18
|
-
const {
|
|
19
|
-
const accessToken = storage.get(
|
|
18
|
+
const { base } = config();
|
|
19
|
+
const accessToken = storage.get("link", "accessToken");
|
|
20
20
|
|
|
21
21
|
if (!accessToken) {
|
|
22
22
|
window.location.href = base === "/" ? "/login" : `${base}/login`;
|
|
@@ -85,14 +85,17 @@ export const fetcher = (url) => instance.get(url).then((res) => res.data);
|
|
|
85
85
|
|
|
86
86
|
const refreshAuthLogic = async (failedRequest) => {
|
|
87
87
|
try {
|
|
88
|
-
const {
|
|
88
|
+
const { appId } = config();
|
|
89
89
|
|
|
90
90
|
const projectId = storage.get("projectId");
|
|
91
91
|
|
|
92
|
+
const identityProvider = storage.get("link", "identityProvider");
|
|
93
|
+
|
|
92
94
|
const { data } = await oauth.post("/oauth", {
|
|
93
|
-
refreshToken: storage.get(
|
|
95
|
+
refreshToken: storage.get("link", "refreshToken"),
|
|
94
96
|
appId,
|
|
95
97
|
projectId,
|
|
98
|
+
identityProvider,
|
|
96
99
|
});
|
|
97
100
|
|
|
98
101
|
const accessToken = data.accessToken;
|
|
@@ -100,13 +103,13 @@ const refreshAuthLogic = async (failedRequest) => {
|
|
|
100
103
|
failedRequest.response.config.headers["Authorization"] =
|
|
101
104
|
"Bearer " + accessToken;
|
|
102
105
|
|
|
103
|
-
storage.set(
|
|
106
|
+
storage.set("link", "accessToken", accessToken);
|
|
104
107
|
return Promise.resolve();
|
|
105
108
|
} catch (error) {
|
|
106
109
|
const { name, base } = config();
|
|
107
110
|
|
|
108
|
-
storage.remove(
|
|
109
|
-
storage.remove(
|
|
111
|
+
storage.remove("link", "accessToken");
|
|
112
|
+
storage.remove("link", "refreshToken");
|
|
110
113
|
|
|
111
114
|
window.location.href = `${window.location.origin}${base}/login`;
|
|
112
115
|
return Promise.reject(error);
|
|
@@ -122,7 +125,7 @@ refreshInterceptor(instance, refreshAuthLogic, {
|
|
|
122
125
|
statusCodes: [401, 403],
|
|
123
126
|
shouldRefresh: () => {
|
|
124
127
|
const { name, base } = config();
|
|
125
|
-
const token = storage.get(
|
|
128
|
+
const token = storage.get("link", "accessToken");
|
|
126
129
|
|
|
127
130
|
if (!token) {
|
|
128
131
|
window.location.href = `${window.location.origin}${base}/login`;
|
package/src/http/user.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
2
|
import config from "../config/config.js";
|
|
3
3
|
import http from "./index";
|
|
4
|
+
import { jwtDecode } from "jwt-decode";
|
|
5
|
+
import oauth from "./oauth";
|
|
4
6
|
import { storage } from "@nucleoidjs/webstorage";
|
|
5
7
|
|
|
6
8
|
const instance = axios.create({
|
|
@@ -11,15 +13,8 @@ const instance = axios.create({
|
|
|
11
13
|
},
|
|
12
14
|
});
|
|
13
15
|
|
|
14
|
-
function getProjectName() {
|
|
15
|
-
const { name } = config();
|
|
16
|
-
if (name) {
|
|
17
|
-
return name;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
16
|
instance.interceptors.request.use(async (request) => {
|
|
22
|
-
const refreshToken = await storage.get(
|
|
17
|
+
const refreshToken = await storage.get("link", "refreshToken");
|
|
23
18
|
if (refreshToken) {
|
|
24
19
|
request.headers["Authorization"] = `Bearer ${refreshToken}`;
|
|
25
20
|
}
|
|
@@ -28,25 +23,62 @@ instance.interceptors.request.use(async (request) => {
|
|
|
28
23
|
|
|
29
24
|
instance.getUserDetails = async () => {
|
|
30
25
|
try {
|
|
31
|
-
const refreshToken = await storage.get(
|
|
26
|
+
const refreshToken = await storage.get("link", "refreshToken");
|
|
27
|
+
|
|
32
28
|
if (!refreshToken) {
|
|
33
29
|
console.log("No refresh token found");
|
|
34
30
|
return null;
|
|
35
31
|
}
|
|
36
32
|
|
|
33
|
+
let accessToken = await storage.get("link", "accessToken");
|
|
34
|
+
|
|
35
|
+
if (!accessToken) {
|
|
36
|
+
console.log("No access token found");
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const decodedToken = jwtDecode(accessToken);
|
|
42
|
+
const isExpired = decodedToken.exp * 1000 < Date.now();
|
|
43
|
+
|
|
44
|
+
if (isExpired) {
|
|
45
|
+
console.log(
|
|
46
|
+
"Access token expired, refreshing before fetching user details..."
|
|
47
|
+
);
|
|
48
|
+
const { appId } = config();
|
|
49
|
+
const projectId = storage.get("projectId");
|
|
50
|
+
const identityProvider = storage.get("link", "identityProvider");
|
|
51
|
+
|
|
52
|
+
const { data } = await oauth.post("/oauth", {
|
|
53
|
+
refreshToken,
|
|
54
|
+
appId,
|
|
55
|
+
projectId,
|
|
56
|
+
identityProvider,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
accessToken = data.accessToken;
|
|
60
|
+
storage.set("link", "accessToken", accessToken);
|
|
61
|
+
console.log(
|
|
62
|
+
"Access token refreshed successfully, now fetching user details"
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error("Error checking or refreshing token:", error);
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
37
70
|
const response = await http.get("/oauth/user", {
|
|
38
71
|
headers: {
|
|
39
|
-
|
|
40
|
-
}
|
|
72
|
+
"X-Refresh-Token": refreshToken,
|
|
73
|
+
},
|
|
41
74
|
});
|
|
42
|
-
|
|
75
|
+
|
|
43
76
|
if (response.data && response.data.user) {
|
|
44
77
|
return response.data.user;
|
|
45
78
|
}
|
|
46
|
-
|
|
79
|
+
|
|
47
80
|
console.log("No user data received from server");
|
|
48
81
|
return null;
|
|
49
|
-
|
|
50
82
|
} catch (error) {
|
|
51
83
|
console.error("Error fetching user details from server:", error);
|
|
52
84
|
return null;
|
|
@@ -55,7 +87,7 @@ instance.getUserDetails = async () => {
|
|
|
55
87
|
|
|
56
88
|
instance.getPermittedUsers = async () => {
|
|
57
89
|
const userIds = [];
|
|
58
|
-
const refreshToken = await storage.get(
|
|
90
|
+
const refreshToken = await storage.get("link", "refreshToken");
|
|
59
91
|
const response = await http.get("/permissions");
|
|
60
92
|
|
|
61
93
|
response.data.forEach((permission) => {
|
|
@@ -75,4 +107,4 @@ instance.getPermittedUsers = async () => {
|
|
|
75
107
|
return users;
|
|
76
108
|
};
|
|
77
109
|
|
|
78
|
-
export default instance;
|
|
110
|
+
export default instance;
|
|
@@ -9,15 +9,16 @@ import SettingsDialog from "../../widgets/SettingsDialog";
|
|
|
9
9
|
import Stack from "@mui/material/Stack";
|
|
10
10
|
import config from "../../config/config";
|
|
11
11
|
import { hideScroll } from "../../theme/css";
|
|
12
|
+
import { useResponsive } from "../../hooks/use-responsive";
|
|
12
13
|
import { useUser } from "../../hooks/use-user";
|
|
13
14
|
|
|
14
15
|
import React, { useState } from "react";
|
|
15
16
|
|
|
16
17
|
export default function NavMini({ only }) {
|
|
17
18
|
const { user } = useUser();
|
|
18
|
-
const { sideMenu } = config().menu;
|
|
19
|
+
const { sideMenu, actionButtons } = config().menu;
|
|
19
20
|
const [openSettings, setOpenSettings] = useState(false);
|
|
20
|
-
|
|
21
|
+
const lgUp = useResponsive("up", "lg");
|
|
21
22
|
const handleCloseSettings = () => {
|
|
22
23
|
setOpenSettings(false);
|
|
23
24
|
};
|
|
@@ -57,21 +58,40 @@ export default function NavMini({ only }) {
|
|
|
57
58
|
}}
|
|
58
59
|
/>
|
|
59
60
|
<Box sx={{ flexGrow: 1 }} />
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
<Stack
|
|
62
|
+
direction={"column"}
|
|
63
|
+
alignItems={"center"}
|
|
64
|
+
justifyItems={"center"}
|
|
65
|
+
sx={{
|
|
66
|
+
marginBottom: lgUp ? 3 : 0,
|
|
67
|
+
position: lgUp ? "static" : "fixed",
|
|
68
|
+
bottom: lgUp ? "auto" : 66,
|
|
69
|
+
width: "100%",
|
|
70
|
+
}}
|
|
71
|
+
gap={2}
|
|
64
72
|
>
|
|
65
|
-
|
|
66
|
-
|
|
73
|
+
{actionButtons &&
|
|
74
|
+
actionButtons.map((Action, index) => (
|
|
75
|
+
<Box key={index} component={Action}></Box>
|
|
76
|
+
))}
|
|
77
|
+
<Button
|
|
78
|
+
onClick={() => setOpenSettings(true)}
|
|
67
79
|
sx={{
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
mx: "auto",
|
|
80
|
+
position: lgUp ? "static" : "fixed",
|
|
81
|
+
bottom: lgUp ? "auto" : 16,
|
|
82
|
+
width: "100%",
|
|
72
83
|
}}
|
|
73
|
-
|
|
74
|
-
|
|
84
|
+
>
|
|
85
|
+
<Iconify
|
|
86
|
+
icon={"ic:baseline-settings"}
|
|
87
|
+
sx={{
|
|
88
|
+
width: 32,
|
|
89
|
+
height: 32,
|
|
90
|
+
color: "text.secondary",
|
|
91
|
+
}}
|
|
92
|
+
/>
|
|
93
|
+
</Button>
|
|
94
|
+
</Stack>
|
|
75
95
|
<SettingsDialog open={openSettings} handleClose={handleCloseSettings} />
|
|
76
96
|
</Stack>
|
|
77
97
|
</Box>
|
|
@@ -16,7 +16,7 @@ function NavHorizontal() {
|
|
|
16
16
|
|
|
17
17
|
const { user } = useUser();
|
|
18
18
|
|
|
19
|
-
const { sideMenu } = config().menu;
|
|
19
|
+
const { sideMenu, actionButtons } = config().menu;
|
|
20
20
|
return (
|
|
21
21
|
<AppBar component="div" data-cy="nav-horizontal">
|
|
22
22
|
<Toolbar
|
|
@@ -35,6 +35,11 @@ function NavHorizontal() {
|
|
|
35
35
|
...theme.mixins.toolbar,
|
|
36
36
|
}}
|
|
37
37
|
/>
|
|
38
|
+
|
|
39
|
+
{actionButtons &&
|
|
40
|
+
actionButtons.map((Action, index) => (
|
|
41
|
+
<Box key={index} component={Action}></Box>
|
|
42
|
+
))}
|
|
38
43
|
</Toolbar>
|
|
39
44
|
|
|
40
45
|
<HeaderShadow />
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
import { Button, DialogActions } from "@mui/material";
|
|
2
|
-
import Dialog, { dialogClasses } from "@mui/material/Dialog";
|
|
3
|
-
import React, { useCallback, useState } from "react";
|
|
4
|
-
import { publish, useEvent } from "@nucleoidai/react-event";
|
|
5
|
-
import { storage, useStorage } from "@nucleoidjs/webstorage";
|
|
6
|
-
import { useMediaQuery, useTheme } from "@mui/material";
|
|
7
|
-
|
|
8
1
|
import Box from "@mui/material/Box";
|
|
9
2
|
import IconButton from "@mui/material/IconButton";
|
|
10
3
|
import Iconify from "../../../components/Iconify";
|
|
@@ -29,9 +22,16 @@ import { useEventListener } from "../../../hooks/use-event-listener";
|
|
|
29
22
|
import { useNavigate } from "react-router-dom";
|
|
30
23
|
import useProjects from "../../../hooks/useProjects";
|
|
31
24
|
|
|
25
|
+
import { Button, DialogActions } from "@mui/material";
|
|
26
|
+
import Dialog, { dialogClasses } from "@mui/material/Dialog";
|
|
27
|
+
import React, { useCallback, useState } from "react";
|
|
28
|
+
import { publish, useEvent } from "@nucleoidai/react-event";
|
|
29
|
+
import { storage, useStorage } from "@nucleoidjs/webstorage";
|
|
30
|
+
import { useMediaQuery, useTheme } from "@mui/material";
|
|
31
|
+
|
|
32
32
|
function ProjectBar() {
|
|
33
33
|
const label = config().template?.projectBar?.label;
|
|
34
|
-
const { appId
|
|
34
|
+
const { appId } = config();
|
|
35
35
|
const theme = useTheme();
|
|
36
36
|
const isSmallScreen = useMediaQuery(theme.breakpoints.down(435));
|
|
37
37
|
const { loading, projects, getProjects } = useProjects();
|
|
@@ -91,15 +91,15 @@ function ProjectBar() {
|
|
|
91
91
|
const handleSelect = (project) => {
|
|
92
92
|
const { id: projectId } = project;
|
|
93
93
|
|
|
94
|
-
const refreshToken = storage.get(
|
|
95
|
-
const
|
|
94
|
+
const refreshToken = storage.get("link", "refreshToken");
|
|
95
|
+
const identityProvider = storage.get("link", "identityProvider");
|
|
96
96
|
|
|
97
97
|
oauth
|
|
98
|
-
.post("/oauth", { appId, refreshToken, projectId,
|
|
98
|
+
.post("/oauth", { appId, refreshToken, projectId, identityProvider })
|
|
99
99
|
.then(({ data }) => {
|
|
100
100
|
const { refreshToken, accessToken } = data;
|
|
101
|
-
storage.set(
|
|
102
|
-
storage.set(
|
|
101
|
+
storage.set("link", "accessToken", accessToken);
|
|
102
|
+
storage.set("link", "refreshToken", refreshToken);
|
|
103
103
|
storage.set("projectId", projectId);
|
|
104
104
|
})
|
|
105
105
|
.finally(() => {
|
|
@@ -19,7 +19,6 @@ import CustomPopover, { usePopover } from "../../components/custom-popover";
|
|
|
19
19
|
// ----------------------------------------------------------------------
|
|
20
20
|
|
|
21
21
|
export default function AccountPopover() {
|
|
22
|
-
const { name } = config();
|
|
23
22
|
const { options } = config().menu;
|
|
24
23
|
const router = useRouter();
|
|
25
24
|
const { user } = useUser();
|
|
@@ -28,8 +27,8 @@ export default function AccountPopover() {
|
|
|
28
27
|
|
|
29
28
|
const handleLogout = async () => {
|
|
30
29
|
try {
|
|
31
|
-
storage.remove(
|
|
32
|
-
storage.remove(
|
|
30
|
+
storage.remove("link", "accessToken");
|
|
31
|
+
storage.remove("link", "refreshToken");
|
|
33
32
|
popover.onClose();
|
|
34
33
|
router.replace("/login");
|
|
35
34
|
} catch (error) {
|
|
@@ -25,23 +25,19 @@ const FlowNode = ({ node, type, variant, style, plugin }) => {
|
|
|
25
25
|
styleTokens = style;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
let
|
|
28
|
+
let _plugin = null;
|
|
29
29
|
if (plugin) {
|
|
30
30
|
if (typeof plugin === "function") {
|
|
31
|
-
|
|
32
|
-
} else if (
|
|
33
|
-
|
|
34
|
-
(typeof plugin.renderNode === "function" ||
|
|
35
|
-
typeof plugin.resolveStyle === "function")
|
|
36
|
-
) {
|
|
37
|
-
plugins = plugin;
|
|
31
|
+
_plugin = plugin(type, node) || null;
|
|
32
|
+
} else if (typeof plugin === "object") {
|
|
33
|
+
_plugin = plugin;
|
|
38
34
|
}
|
|
39
35
|
}
|
|
40
36
|
|
|
41
37
|
let pluginTokens = {};
|
|
42
|
-
if (
|
|
38
|
+
if (_plugin && typeof _plugin.style === "function") {
|
|
43
39
|
pluginTokens =
|
|
44
|
-
|
|
40
|
+
_plugin.style({
|
|
45
41
|
node,
|
|
46
42
|
style: styleTokens,
|
|
47
43
|
}) || {};
|
|
@@ -194,8 +190,8 @@ const FlowNode = ({ node, type, variant, style, plugin }) => {
|
|
|
194
190
|
};
|
|
195
191
|
|
|
196
192
|
const renderContent = () => {
|
|
197
|
-
if (
|
|
198
|
-
return
|
|
193
|
+
if (_plugin && typeof _plugin.node === "function") {
|
|
194
|
+
return _plugin.node({
|
|
199
195
|
node,
|
|
200
196
|
title,
|
|
201
197
|
subtitle,
|
package/src/pages/Callback.jsx
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { useEffect, useRef } from "react";
|
|
2
|
-
|
|
3
1
|
import Page from "../layouts/Page";
|
|
4
2
|
import React from "react";
|
|
5
3
|
import config from "../config/config";
|
|
@@ -10,6 +8,8 @@ import { useContext } from "../ContextProvider/ContextProvider";
|
|
|
10
8
|
import { useLocation } from "react-router-dom";
|
|
11
9
|
import { useNavigate } from "react-router-dom";
|
|
12
10
|
|
|
11
|
+
import { useEffect, useRef } from "react";
|
|
12
|
+
|
|
13
13
|
function Callback() {
|
|
14
14
|
const { project: appConfig, name, appId } = config();
|
|
15
15
|
const projectBar = config().template?.projectBar;
|
|
@@ -28,12 +28,12 @@ function Callback() {
|
|
|
28
28
|
const parsedQuery = qs.parse(location.search, { ignoreQueryPrefix: true });
|
|
29
29
|
const { code, error, error_description, state } = parsedQuery;
|
|
30
30
|
|
|
31
|
-
let
|
|
31
|
+
let identityProvider;
|
|
32
32
|
let stateData = {};
|
|
33
33
|
|
|
34
34
|
if (state) {
|
|
35
35
|
stateData = JSON.parse(decodeURIComponent(state));
|
|
36
|
-
|
|
36
|
+
identityProvider = stateData.identityProvider;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
if (error) {
|
|
@@ -59,7 +59,7 @@ function Callback() {
|
|
|
59
59
|
google,
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
-
const providerConfig = providerConfigs[
|
|
62
|
+
const providerConfig = providerConfigs[identityProvider];
|
|
63
63
|
|
|
64
64
|
if (!providerConfig) {
|
|
65
65
|
console.error("Could not determine OAuth provider or redirect URI");
|
|
@@ -85,7 +85,7 @@ function Callback() {
|
|
|
85
85
|
appId,
|
|
86
86
|
code,
|
|
87
87
|
redirectUri,
|
|
88
|
-
|
|
88
|
+
identityProvider: identityProvider,
|
|
89
89
|
grant_type: "authorization_code",
|
|
90
90
|
})
|
|
91
91
|
.then(({ data }) => {
|
|
@@ -93,10 +93,10 @@ function Callback() {
|
|
|
93
93
|
const refreshToken = data.refreshToken;
|
|
94
94
|
const userInfo = data.user;
|
|
95
95
|
|
|
96
|
-
storage.set(
|
|
97
|
-
storage.set(
|
|
96
|
+
storage.set("link", "accessToken", accessToken);
|
|
97
|
+
storage.set("link", "refreshToken", refreshToken);
|
|
98
98
|
// TODO - update provider info
|
|
99
|
-
storage.set(
|
|
99
|
+
storage.set("link", "identityProvider", identityProvider);
|
|
100
100
|
|
|
101
101
|
dispatch({ type: "LOGIN", payload: { user: userInfo } });
|
|
102
102
|
|
package/src/pages/LoginPage.jsx
CHANGED
|
@@ -11,7 +11,10 @@ function LoginPage() {
|
|
|
11
11
|
const navigate = useNavigate();
|
|
12
12
|
|
|
13
13
|
function token() {
|
|
14
|
-
if (
|
|
14
|
+
if (
|
|
15
|
+
storage.get("link", "refreshToken") &&
|
|
16
|
+
storage.get("link", "accessToken")
|
|
17
|
+
) {
|
|
15
18
|
return true;
|
|
16
19
|
} else {
|
|
17
20
|
return false;
|
|
@@ -19,7 +19,10 @@ export default function Auth0LoginView() {
|
|
|
19
19
|
const navigate = useNavigate();
|
|
20
20
|
|
|
21
21
|
function token() {
|
|
22
|
-
if (
|
|
22
|
+
if (
|
|
23
|
+
storage.get("link", "refreshToken") &&
|
|
24
|
+
storage.get("link", "accessToken")
|
|
25
|
+
) {
|
|
23
26
|
return true;
|
|
24
27
|
} else {
|
|
25
28
|
return false;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { Box, Divider, Link as MuiLink, Typography } from "@mui/material";
|
|
2
|
-
import React, { useState } from "react";
|
|
3
|
-
|
|
4
1
|
import NucleoidLoginForm from "../../components/NucleoidLoginForm";
|
|
5
2
|
import SocialLoginButtons from "../../components/SocialLoginButtons";
|
|
6
3
|
import Stack from "@mui/material/Stack";
|
|
7
4
|
import config from "../../config/config";
|
|
8
5
|
|
|
6
|
+
import { Box, Divider, Link as MuiLink, Typography } from "@mui/material";
|
|
7
|
+
import React, { useState } from "react";
|
|
8
|
+
|
|
9
9
|
const handleOAuthLogin = (
|
|
10
10
|
{ redirectUri, authUrl, clientId, scope },
|
|
11
|
-
|
|
11
|
+
identityProvider
|
|
12
12
|
) => {
|
|
13
13
|
const state = JSON.stringify({
|
|
14
|
-
|
|
14
|
+
identityProvider: identityProvider,
|
|
15
15
|
});
|
|
16
16
|
const encodedState = encodeURIComponent(state);
|
|
17
17
|
window.location.href = `${authUrl}?client_id=${clientId}&scope=${scope}&response_type=code&redirect_uri=${redirectUri}&state=${encodedState}`;
|