dauth-context-react 4.0.4 → 5.0.0
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/index.d.mts +3 -6
- package/dist/index.d.ts +3 -6
- package/dist/index.js +198 -370
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +199 -372
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/api/dauth.api.ts +73 -93
- package/src/api/interfaces/dauth.api.responses.ts +11 -13
- package/src/api/utils/config.ts +3 -11
- package/src/api/utils/routes.ts +0 -1
- package/src/constants.ts +0 -2
- package/src/index.tsx +42 -126
- package/src/initialDauthState.ts +0 -1
- package/src/interfaces.ts +8 -12
- package/src/reducer/dauth.actions.ts +114 -189
package/src/index.tsx
CHANGED
|
@@ -5,21 +5,18 @@ import React, {
|
|
|
5
5
|
useCallback,
|
|
6
6
|
createContext,
|
|
7
7
|
useContext,
|
|
8
|
-
useRef,
|
|
9
8
|
} from 'react';
|
|
10
9
|
import initialDauthState from './initialDauthState';
|
|
11
10
|
import userReducer from './reducer/dauth.reducer';
|
|
12
11
|
import * as action from './reducer/dauth.actions';
|
|
13
12
|
import { getClientBasePath, setDauthUrl } from './api/utils/config';
|
|
14
|
-
import {
|
|
13
|
+
import { AUTH_CODE_PARAM } from './constants';
|
|
15
14
|
import { routes } from './api/utils/routes';
|
|
16
15
|
import type {
|
|
17
16
|
IDauthProviderProps,
|
|
18
|
-
IDauthStorageKeys,
|
|
19
|
-
IDauthUser,
|
|
20
17
|
IDauthAuthMethods,
|
|
18
|
+
IDauthUser,
|
|
21
19
|
} from './interfaces';
|
|
22
|
-
import { SET_IS_LOADING } from './reducer/dauth.types';
|
|
23
20
|
|
|
24
21
|
export type { IDauthProviderProps, IDauthAuthMethods };
|
|
25
22
|
|
|
@@ -28,127 +25,60 @@ const defaultOnError = (error: Error) => console.error(error);
|
|
|
28
25
|
export const DauthProvider: React.FC<IDauthProviderProps> = (
|
|
29
26
|
props: IDauthProviderProps
|
|
30
27
|
) => {
|
|
31
|
-
const {
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
const {
|
|
29
|
+
domainName,
|
|
30
|
+
children,
|
|
31
|
+
authProxyPath = '/api/auth',
|
|
32
|
+
onError,
|
|
33
|
+
env,
|
|
34
|
+
dauthUrl,
|
|
35
|
+
} = props;
|
|
36
|
+
const [dauthState, dispatch] = useReducer(
|
|
37
|
+
userReducer,
|
|
38
|
+
initialDauthState
|
|
39
|
+
);
|
|
34
40
|
|
|
35
41
|
// Configure custom dauth URL before any API calls
|
|
36
42
|
useEffect(() => {
|
|
37
43
|
setDauthUrl(dauthUrl);
|
|
38
44
|
}, [dauthUrl]);
|
|
39
45
|
|
|
40
|
-
const storageKeys: IDauthStorageKeys = useMemo(
|
|
41
|
-
() => ({
|
|
42
|
-
accessToken: storageKey?.accessToken ?? TOKEN_LS,
|
|
43
|
-
refreshToken: storageKey?.refreshToken ?? REFRESH_TOKEN_LS,
|
|
44
|
-
}),
|
|
45
|
-
[storageKey?.accessToken, storageKey?.refreshToken]
|
|
46
|
-
);
|
|
47
|
-
|
|
48
46
|
const handleError = useCallback(
|
|
49
47
|
(error: Error) => (onError ?? defaultOnError)(error),
|
|
50
48
|
[onError]
|
|
51
49
|
);
|
|
52
50
|
|
|
53
|
-
// Build action context
|
|
54
51
|
const ctx = useMemo(
|
|
55
|
-
() => ({ dispatch,
|
|
56
|
-
[
|
|
52
|
+
() => ({ dispatch, authProxyPath, onError: handleError }),
|
|
53
|
+
[authProxyPath, handleError]
|
|
57
54
|
);
|
|
58
55
|
|
|
59
|
-
//
|
|
60
|
-
const scheduleRefresh = useCallback(() => {
|
|
61
|
-
if (refreshTimerRef.current) clearTimeout(refreshTimerRef.current);
|
|
62
|
-
const token = localStorage.getItem(storageKeys.accessToken);
|
|
63
|
-
if (!token) return;
|
|
64
|
-
try {
|
|
65
|
-
const payloadB64 = token.split('.')[1];
|
|
66
|
-
if (!payloadB64) return;
|
|
67
|
-
const payload = JSON.parse(atob(payloadB64));
|
|
68
|
-
const expiresIn = (payload.exp || 0) * 1000 - Date.now();
|
|
69
|
-
// Refresh 5 minutes before expiry, minimum 10 seconds
|
|
70
|
-
const refreshIn = Math.max(expiresIn - 5 * 60 * 1000, 10_000);
|
|
71
|
-
refreshTimerRef.current = setTimeout(async () => {
|
|
72
|
-
await action.refreshSessionAction(ctx);
|
|
73
|
-
scheduleRefresh();
|
|
74
|
-
}, refreshIn);
|
|
75
|
-
} catch (_) {
|
|
76
|
-
// If decode fails, retry in 5 minutes
|
|
77
|
-
refreshTimerRef.current = setTimeout(
|
|
78
|
-
async () => {
|
|
79
|
-
await action.refreshSessionAction(ctx);
|
|
80
|
-
scheduleRefresh();
|
|
81
|
-
},
|
|
82
|
-
5 * 60 * 1000
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
}, [ctx, storageKeys.accessToken]);
|
|
86
|
-
|
|
87
|
-
// Catch login redirect — exchange authorization code for tokens
|
|
56
|
+
// On mount: exchange code or auto-login via session cookie
|
|
88
57
|
useEffect(() => {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return action.exchangeCodeAction({ ...ctx, code });
|
|
96
|
-
}
|
|
97
|
-
})();
|
|
98
|
-
}, []);
|
|
99
|
-
|
|
100
|
-
// Auto Login
|
|
101
|
-
useEffect(() => {
|
|
102
|
-
(async () => {
|
|
103
|
-
// Skip if code exchange is in progress — that effect handles isLoading
|
|
104
|
-
const urlParams = new URLSearchParams(window.location.search);
|
|
105
|
-
if (urlParams.get(AUTH_CODE_PARAM)) return;
|
|
106
|
-
|
|
107
|
-
const refreshToken = localStorage.getItem(storageKeys.refreshToken);
|
|
108
|
-
if (refreshToken && !dauthState.isAuthenticated) {
|
|
109
|
-
return action.setAutoLoginAction(ctx);
|
|
110
|
-
} else {
|
|
111
|
-
return dispatch({
|
|
112
|
-
type: SET_IS_LOADING,
|
|
113
|
-
payload: { isLoading: false },
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
})();
|
|
117
|
-
}, []);
|
|
118
|
-
|
|
119
|
-
// Schedule proactive refresh when authenticated
|
|
120
|
-
useEffect(() => {
|
|
121
|
-
if (dauthState.isAuthenticated) {
|
|
122
|
-
scheduleRefresh();
|
|
58
|
+
const params = new URLSearchParams(window.location.search);
|
|
59
|
+
const code = params.get(AUTH_CODE_PARAM);
|
|
60
|
+
if (code) {
|
|
61
|
+
action.exchangeCodeAction(ctx, code);
|
|
62
|
+
} else {
|
|
63
|
+
action.autoLoginAction(ctx);
|
|
123
64
|
}
|
|
124
|
-
|
|
125
|
-
if (refreshTimerRef.current) clearTimeout(refreshTimerRef.current);
|
|
126
|
-
};
|
|
127
|
-
}, [dauthState.isAuthenticated, scheduleRefresh]);
|
|
65
|
+
}, []);
|
|
128
66
|
|
|
129
67
|
const loginWithRedirect = useCallback(() => {
|
|
130
68
|
const base = `${getClientBasePath()}/${domainName}/${routes.signin}`;
|
|
131
|
-
const url = env
|
|
69
|
+
const url = env
|
|
70
|
+
? `${base}?env=${encodeURIComponent(env)}`
|
|
71
|
+
: base;
|
|
132
72
|
return window.location.replace(url);
|
|
133
73
|
}, [domainName, env]);
|
|
134
74
|
|
|
135
|
-
const logout = useCallback(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
domainName,
|
|
140
|
-
storageKeys,
|
|
141
|
-
});
|
|
142
|
-
}, [domainName, storageKeys]);
|
|
143
|
-
|
|
144
|
-
const getAccessToken = useCallback(async () => {
|
|
145
|
-
const token = await action.getAccessTokenAction(ctx);
|
|
146
|
-
return token as string;
|
|
147
|
-
}, [ctx]);
|
|
75
|
+
const logout = useCallback(
|
|
76
|
+
() => action.logoutAction(ctx),
|
|
77
|
+
[ctx]
|
|
78
|
+
);
|
|
148
79
|
|
|
149
80
|
const updateUser = useCallback(
|
|
150
81
|
async (fields: Partial<IDauthUser>) => {
|
|
151
|
-
const token_ls = localStorage.getItem(storageKeys.accessToken);
|
|
152
82
|
const {
|
|
153
83
|
name,
|
|
154
84
|
lastname,
|
|
@@ -173,39 +103,26 @@ export const DauthProvider: React.FC<IDauthProviderProps> = (
|
|
|
173
103
|
country,
|
|
174
104
|
metadata,
|
|
175
105
|
} as Partial<IDauthUser>;
|
|
176
|
-
return
|
|
177
|
-
...ctx,
|
|
178
|
-
user,
|
|
179
|
-
token: token_ls,
|
|
180
|
-
})) as boolean;
|
|
106
|
+
return action.updateUserAction(ctx, user);
|
|
181
107
|
},
|
|
182
|
-
[ctx
|
|
108
|
+
[ctx]
|
|
183
109
|
);
|
|
184
110
|
|
|
185
|
-
const updateUserWithRedirect = useCallback(
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
const token_ls = localStorage.getItem(storageKeys.accessToken);
|
|
195
|
-
if (!token_ls) return false;
|
|
196
|
-
if (refreshTimerRef.current) clearTimeout(refreshTimerRef.current);
|
|
197
|
-
return (await action.deleteAccountAction({
|
|
198
|
-
...ctx,
|
|
199
|
-
token: token_ls,
|
|
200
|
-
})) as boolean;
|
|
201
|
-
}, [ctx, storageKeys.accessToken]);
|
|
111
|
+
const updateUserWithRedirect = useCallback(
|
|
112
|
+
() => action.updateUserWithRedirectAction(ctx),
|
|
113
|
+
[ctx]
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
const deleteAccount = useCallback(
|
|
117
|
+
() => action.deleteAccountAction(ctx),
|
|
118
|
+
[ctx]
|
|
119
|
+
);
|
|
202
120
|
|
|
203
121
|
const memoProvider = useMemo(
|
|
204
122
|
() => ({
|
|
205
123
|
...dauthState,
|
|
206
124
|
loginWithRedirect,
|
|
207
125
|
logout,
|
|
208
|
-
getAccessToken,
|
|
209
126
|
updateUser,
|
|
210
127
|
updateUserWithRedirect,
|
|
211
128
|
deleteAccount,
|
|
@@ -214,7 +131,6 @@ export const DauthProvider: React.FC<IDauthProviderProps> = (
|
|
|
214
131
|
dauthState,
|
|
215
132
|
loginWithRedirect,
|
|
216
133
|
logout,
|
|
217
|
-
getAccessToken,
|
|
218
134
|
updateUser,
|
|
219
135
|
updateUserWithRedirect,
|
|
220
136
|
deleteAccount,
|
package/src/initialDauthState.ts
CHANGED
|
@@ -12,7 +12,6 @@ const initialDauthState: IDauthState = {
|
|
|
12
12
|
isAuthenticated: false,
|
|
13
13
|
loginWithRedirect: () => {},
|
|
14
14
|
logout: () => {},
|
|
15
|
-
getAccessToken: () => Promise.resolve(''),
|
|
16
15
|
updateUser: () => Promise.resolve(false),
|
|
17
16
|
updateUserWithRedirect: () => {},
|
|
18
17
|
deleteAccount: () => Promise.resolve(false),
|
package/src/interfaces.ts
CHANGED
|
@@ -46,7 +46,6 @@ export interface IDauthState {
|
|
|
46
46
|
isAuthenticated: boolean;
|
|
47
47
|
loginWithRedirect: () => void;
|
|
48
48
|
logout: () => void;
|
|
49
|
-
getAccessToken: () => Promise<string>;
|
|
50
49
|
updateUser: (fields: Partial<IDauthUser>) => Promise<boolean>;
|
|
51
50
|
updateUserWithRedirect: () => void;
|
|
52
51
|
deleteAccount: () => Promise<boolean>;
|
|
@@ -56,22 +55,19 @@ export interface IActionStatus {
|
|
|
56
55
|
type: TStatusTypes;
|
|
57
56
|
message: string;
|
|
58
57
|
}
|
|
59
|
-
export type TStatusTypes =
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
58
|
+
export type TStatusTypes =
|
|
59
|
+
| 'success'
|
|
60
|
+
| 'error'
|
|
61
|
+
| 'info'
|
|
62
|
+
| 'warning';
|
|
65
63
|
|
|
66
64
|
export interface IDauthProviderProps {
|
|
67
65
|
domainName: string;
|
|
68
66
|
children: React.ReactNode;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
refreshToken?: string;
|
|
72
|
-
};
|
|
67
|
+
/** Base path of the auth proxy on the consumer backend. Default: '/api/auth'. */
|
|
68
|
+
authProxyPath?: string;
|
|
73
69
|
onError?: (error: Error) => void;
|
|
74
70
|
env?: string;
|
|
75
|
-
/** Override the dauth
|
|
71
|
+
/** Override the dauth frontend URL for loginWithRedirect (e.g. 'https://dev.dauth.ovh' for staging) */
|
|
76
72
|
dauthUrl?: string;
|
|
77
73
|
}
|
|
@@ -1,63 +1,54 @@
|
|
|
1
1
|
import {
|
|
2
|
-
deleteAccountAPI,
|
|
3
2
|
exchangeCodeAPI,
|
|
4
|
-
|
|
3
|
+
getSessionAPI,
|
|
5
4
|
logoutAPI,
|
|
6
|
-
refreshTokenAPI,
|
|
7
5
|
updateUserAPI,
|
|
6
|
+
deleteAccountAPI,
|
|
7
|
+
profileRedirectAPI,
|
|
8
8
|
} from '../api/dauth.api';
|
|
9
|
-
import {
|
|
10
|
-
IDauthDomainState,
|
|
11
|
-
IDauthStorageKeys,
|
|
12
|
-
IDauthUser,
|
|
13
|
-
} from '../interfaces';
|
|
9
|
+
import { IDauthDomainState, IDauthUser } from '../interfaces';
|
|
14
10
|
import * as DauthTypes from './dauth.types';
|
|
15
11
|
|
|
16
12
|
export interface ActionContext {
|
|
17
13
|
dispatch: React.Dispatch<any>;
|
|
18
|
-
|
|
19
|
-
storageKeys: IDauthStorageKeys;
|
|
14
|
+
authProxyPath: string;
|
|
20
15
|
onError: (error: Error) => void;
|
|
21
16
|
}
|
|
22
17
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
storageKeys,
|
|
29
|
-
onError,
|
|
30
|
-
}: TExchangeCodeAction) {
|
|
18
|
+
export async function exchangeCodeAction(
|
|
19
|
+
ctx: ActionContext,
|
|
20
|
+
code: string
|
|
21
|
+
) {
|
|
22
|
+
const { dispatch, authProxyPath, onError } = ctx;
|
|
31
23
|
dispatch({
|
|
32
24
|
type: DauthTypes.SET_IS_LOADING,
|
|
33
25
|
payload: { isLoading: true },
|
|
34
26
|
});
|
|
35
27
|
try {
|
|
36
28
|
// Clean URL immediately (before any fetch)
|
|
37
|
-
window.history.replaceState(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
localStorage.setItem(storageKeys.refreshToken, refreshToken);
|
|
45
|
-
const getUserFetch = await getUserAPI(domainName, accessToken);
|
|
46
|
-
if (getUserFetch.response.status === 200) {
|
|
29
|
+
window.history.replaceState(
|
|
30
|
+
{},
|
|
31
|
+
document.title,
|
|
32
|
+
window.location.pathname
|
|
33
|
+
);
|
|
34
|
+
const result = await exchangeCodeAPI(authProxyPath, code);
|
|
35
|
+
if (result.response.status === 200) {
|
|
47
36
|
dispatch({
|
|
48
37
|
type: DauthTypes.LOGIN,
|
|
49
38
|
payload: {
|
|
50
|
-
user:
|
|
51
|
-
domain:
|
|
39
|
+
user: result.data.user,
|
|
40
|
+
domain: result.data.domain,
|
|
52
41
|
isAuthenticated: true,
|
|
53
42
|
},
|
|
54
43
|
});
|
|
55
44
|
return;
|
|
56
45
|
}
|
|
57
|
-
|
|
46
|
+
resetUser(dispatch);
|
|
58
47
|
} catch (error) {
|
|
59
|
-
onError(
|
|
60
|
-
|
|
48
|
+
onError(
|
|
49
|
+
error instanceof Error ? error : new Error(String(error))
|
|
50
|
+
);
|
|
51
|
+
resetUser(dispatch);
|
|
61
52
|
} finally {
|
|
62
53
|
dispatch({
|
|
63
54
|
type: DauthTypes.SET_IS_LOADING,
|
|
@@ -66,46 +57,32 @@ export async function exchangeCodeAction({
|
|
|
66
57
|
}
|
|
67
58
|
}
|
|
68
59
|
|
|
69
|
-
export async function
|
|
70
|
-
dispatch,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
dispatch({ type: DauthTypes.SET_IS_LOADING, payload: { isLoading: true } });
|
|
76
|
-
const storedRefreshToken = localStorage.getItem(storageKeys.refreshToken);
|
|
77
|
-
if (!storedRefreshToken) {
|
|
78
|
-
dispatch({
|
|
79
|
-
type: DauthTypes.SET_IS_LOADING,
|
|
80
|
-
payload: { isLoading: false },
|
|
81
|
-
});
|
|
82
|
-
return resetUser(dispatch, storageKeys);
|
|
83
|
-
}
|
|
60
|
+
export async function autoLoginAction(ctx: ActionContext) {
|
|
61
|
+
const { dispatch, authProxyPath, onError } = ctx;
|
|
62
|
+
dispatch({
|
|
63
|
+
type: DauthTypes.SET_IS_LOADING,
|
|
64
|
+
payload: { isLoading: true },
|
|
65
|
+
});
|
|
84
66
|
try {
|
|
85
|
-
const
|
|
86
|
-
if (
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
user: getUserFetch.data.user,
|
|
97
|
-
domain: getUserFetch.data.domain,
|
|
98
|
-
isAuthenticated: true,
|
|
99
|
-
},
|
|
100
|
-
});
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
67
|
+
const result = await getSessionAPI(authProxyPath);
|
|
68
|
+
if (result.response.status === 200) {
|
|
69
|
+
dispatch({
|
|
70
|
+
type: DauthTypes.LOGIN,
|
|
71
|
+
payload: {
|
|
72
|
+
user: result.data.user,
|
|
73
|
+
domain: result.data.domain,
|
|
74
|
+
isAuthenticated: true,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
return;
|
|
103
78
|
}
|
|
104
|
-
//
|
|
105
|
-
resetUser(dispatch
|
|
79
|
+
// No session — not authenticated (not an error)
|
|
80
|
+
resetUser(dispatch);
|
|
106
81
|
} catch (error) {
|
|
107
|
-
onError(
|
|
108
|
-
|
|
82
|
+
onError(
|
|
83
|
+
error instanceof Error ? error : new Error(String(error))
|
|
84
|
+
);
|
|
85
|
+
resetUser(dispatch);
|
|
109
86
|
} finally {
|
|
110
87
|
dispatch({
|
|
111
88
|
type: DauthTypes.SET_IS_LOADING,
|
|
@@ -114,168 +91,116 @@ export async function setAutoLoginAction({
|
|
|
114
91
|
}
|
|
115
92
|
}
|
|
116
93
|
|
|
117
|
-
export async function
|
|
118
|
-
dispatch,
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (storedRefreshToken && domainName) {
|
|
124
|
-
try {
|
|
125
|
-
await logoutAPI(domainName, storedRefreshToken);
|
|
126
|
-
} catch (_) {
|
|
127
|
-
// Best-effort server-side logout
|
|
128
|
-
}
|
|
94
|
+
export async function logoutAction(ctx: ActionContext) {
|
|
95
|
+
const { dispatch, authProxyPath } = ctx;
|
|
96
|
+
try {
|
|
97
|
+
await logoutAPI(authProxyPath);
|
|
98
|
+
} catch {
|
|
99
|
+
// Best-effort server-side logout
|
|
129
100
|
}
|
|
130
|
-
dispatch({
|
|
101
|
+
dispatch({
|
|
102
|
+
type: DauthTypes.SET_IS_LOADING,
|
|
103
|
+
payload: { isLoading: true },
|
|
104
|
+
});
|
|
131
105
|
dispatch({
|
|
132
106
|
type: DauthTypes.LOGIN,
|
|
133
107
|
payload: {
|
|
134
108
|
user: {
|
|
135
|
-
language:
|
|
109
|
+
language:
|
|
110
|
+
window.document.documentElement.getAttribute('lang') ||
|
|
111
|
+
'es',
|
|
136
112
|
},
|
|
137
113
|
domain: {},
|
|
138
114
|
isAuthenticated: false,
|
|
139
115
|
},
|
|
140
116
|
});
|
|
141
|
-
|
|
142
|
-
localStorage.removeItem(storageKeys.refreshToken);
|
|
143
|
-
return dispatch({
|
|
117
|
+
dispatch({
|
|
144
118
|
type: DauthTypes.SET_IS_LOADING,
|
|
145
119
|
payload: { isLoading: false },
|
|
146
120
|
});
|
|
147
121
|
}
|
|
148
122
|
|
|
149
|
-
export async function
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
onError
|
|
154
|
-
}: ActionContext) {
|
|
155
|
-
const storedRefreshToken = localStorage.getItem(storageKeys.refreshToken);
|
|
156
|
-
if (!storedRefreshToken) {
|
|
157
|
-
return resetUser(dispatch, storageKeys);
|
|
158
|
-
}
|
|
159
|
-
try {
|
|
160
|
-
const refreshResult = await refreshTokenAPI(domainName, storedRefreshToken);
|
|
161
|
-
if (refreshResult.response.status === 200) {
|
|
162
|
-
localStorage.setItem(
|
|
163
|
-
storageKeys.accessToken,
|
|
164
|
-
refreshResult.data.accessToken
|
|
165
|
-
);
|
|
166
|
-
localStorage.setItem(
|
|
167
|
-
storageKeys.refreshToken,
|
|
168
|
-
refreshResult.data.refreshToken
|
|
169
|
-
);
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
// Refresh failed — revoked or expired
|
|
173
|
-
resetUser(dispatch, storageKeys);
|
|
174
|
-
} catch (error) {
|
|
175
|
-
onError(error instanceof Error ? error : new Error(String(error)));
|
|
176
|
-
resetUser(dispatch, storageKeys);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
type TSetUpdateAction = ActionContext & {
|
|
181
|
-
user: Partial<IDauthUser>;
|
|
182
|
-
token: string | null;
|
|
183
|
-
};
|
|
184
|
-
export async function setUpdateUserAction({
|
|
185
|
-
dispatch,
|
|
186
|
-
domainName,
|
|
187
|
-
user,
|
|
188
|
-
token,
|
|
189
|
-
onError,
|
|
190
|
-
}: TSetUpdateAction) {
|
|
123
|
+
export async function updateUserAction(
|
|
124
|
+
ctx: ActionContext,
|
|
125
|
+
user: Partial<IDauthUser>
|
|
126
|
+
): Promise<boolean> {
|
|
127
|
+
const { dispatch, authProxyPath, onError } = ctx;
|
|
191
128
|
if (user.language) {
|
|
192
|
-
window.document.documentElement.setAttribute(
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
type: DauthTypes.UPDATE_USER,
|
|
197
|
-
payload: user,
|
|
198
|
-
});
|
|
199
|
-
return false;
|
|
129
|
+
window.document.documentElement.setAttribute(
|
|
130
|
+
'lang',
|
|
131
|
+
user.language
|
|
132
|
+
);
|
|
200
133
|
}
|
|
201
134
|
try {
|
|
202
|
-
const
|
|
203
|
-
if (
|
|
135
|
+
const result = await updateUserAPI(authProxyPath, user);
|
|
136
|
+
if (result.response.status === 200) {
|
|
204
137
|
dispatch({
|
|
205
138
|
type: DauthTypes.UPDATE_USER,
|
|
206
|
-
payload:
|
|
139
|
+
payload: result.data.user,
|
|
207
140
|
});
|
|
208
141
|
return true;
|
|
209
|
-
} else {
|
|
210
|
-
onError(new Error('Update user error: ' + getUserFetch.data.message));
|
|
211
|
-
return false;
|
|
212
142
|
}
|
|
143
|
+
onError(
|
|
144
|
+
new Error('Update user error: ' + result.data.message)
|
|
145
|
+
);
|
|
146
|
+
return false;
|
|
213
147
|
} catch (error) {
|
|
214
|
-
onError(
|
|
148
|
+
onError(
|
|
149
|
+
error instanceof Error
|
|
150
|
+
? error
|
|
151
|
+
: new Error('Update user error')
|
|
152
|
+
);
|
|
215
153
|
return false;
|
|
216
154
|
}
|
|
217
155
|
}
|
|
218
156
|
|
|
219
|
-
export async function
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
onError,
|
|
224
|
-
}: ActionContext) {
|
|
225
|
-
const token_ls = localStorage.getItem(storageKeys.accessToken);
|
|
226
|
-
if (!token_ls) return 'token-not-found';
|
|
227
|
-
// Decode JWT to check expiry (without verification — that's the server's job)
|
|
157
|
+
export async function updateUserWithRedirectAction(
|
|
158
|
+
ctx: ActionContext
|
|
159
|
+
) {
|
|
160
|
+
const { authProxyPath, onError } = ctx;
|
|
228
161
|
try {
|
|
229
|
-
const
|
|
230
|
-
if (
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
dispatch,
|
|
237
|
-
domainName,
|
|
238
|
-
storageKeys,
|
|
239
|
-
onError,
|
|
240
|
-
});
|
|
241
|
-
const refreshedToken = localStorage.getItem(storageKeys.accessToken);
|
|
242
|
-
return refreshedToken || 'token-not-found';
|
|
243
|
-
}
|
|
162
|
+
const result = await profileRedirectAPI(authProxyPath);
|
|
163
|
+
if (
|
|
164
|
+
result.response.status === 200 &&
|
|
165
|
+
result.data.redirectUrl
|
|
166
|
+
) {
|
|
167
|
+
window.location.replace(result.data.redirectUrl);
|
|
168
|
+
return;
|
|
244
169
|
}
|
|
245
|
-
|
|
246
|
-
|
|
170
|
+
onError(
|
|
171
|
+
new Error('Could not generate profile redirect')
|
|
172
|
+
);
|
|
173
|
+
} catch (error) {
|
|
174
|
+
onError(
|
|
175
|
+
error instanceof Error
|
|
176
|
+
? error
|
|
177
|
+
: new Error('Profile redirect error')
|
|
178
|
+
);
|
|
247
179
|
}
|
|
248
|
-
return token_ls;
|
|
249
180
|
}
|
|
250
181
|
|
|
251
|
-
export async function deleteAccountAction(
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
onError,
|
|
256
|
-
token,
|
|
257
|
-
}: ActionContext & { token: string }) {
|
|
182
|
+
export async function deleteAccountAction(
|
|
183
|
+
ctx: ActionContext
|
|
184
|
+
): Promise<boolean> {
|
|
185
|
+
const { dispatch, authProxyPath, onError } = ctx;
|
|
258
186
|
try {
|
|
259
|
-
const result = await deleteAccountAPI(
|
|
187
|
+
const result = await deleteAccountAPI(authProxyPath);
|
|
260
188
|
if (result.response.status === 200) {
|
|
261
|
-
resetUser(dispatch
|
|
189
|
+
resetUser(dispatch);
|
|
262
190
|
return true;
|
|
263
191
|
}
|
|
264
192
|
return false;
|
|
265
193
|
} catch (error) {
|
|
266
|
-
onError(
|
|
194
|
+
onError(
|
|
195
|
+
error instanceof Error
|
|
196
|
+
? error
|
|
197
|
+
: new Error('Delete account error')
|
|
198
|
+
);
|
|
267
199
|
return false;
|
|
268
200
|
}
|
|
269
201
|
}
|
|
270
202
|
|
|
271
|
-
|
|
272
|
-
//////////////////////////////////////////
|
|
273
|
-
export const resetUser = (
|
|
274
|
-
dispatch: React.Dispatch<any>,
|
|
275
|
-
storageKeys: IDauthStorageKeys
|
|
276
|
-
) => {
|
|
277
|
-
localStorage.removeItem(storageKeys.accessToken);
|
|
278
|
-
localStorage.removeItem(storageKeys.refreshToken);
|
|
203
|
+
export const resetUser = (dispatch: React.Dispatch<any>) => {
|
|
279
204
|
return dispatch({
|
|
280
205
|
type: DauthTypes.LOGIN,
|
|
281
206
|
payload: {
|