@lukoweb/apitogo 0.1.37 → 0.1.39
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/cli/cli.js +1 -1
- package/dist/declarations/lib/authentication/authentication.d.ts +1 -0
- package/dist/declarations/lib/authentication/providers/dev-portal.d.ts +1 -0
- package/package.json +1 -1
- package/src/lib/authentication/authentication.ts +3 -0
- package/src/lib/authentication/hook.ts +1 -0
- package/src/lib/authentication/providers/dev-portal.tsx +4 -0
- package/src/lib/core/RouteGuard.tsx +54 -11
- package/src/lib/plugins/openapi/playground/PlaygroundDialog.tsx +9 -3
package/dist/cli/cli.js
CHANGED
|
@@ -14,6 +14,7 @@ export interface AuthenticationPlugin {
|
|
|
14
14
|
signUp({ navigate }: AuthActionContext, options?: AuthActionOptions): Promise<void>;
|
|
15
15
|
signIn({ navigate }: AuthActionContext, options?: AuthActionOptions): Promise<void>;
|
|
16
16
|
signOut({ navigate }: AuthActionContext): Promise<void>;
|
|
17
|
+
hasDistinctSignUpFlow?(): boolean;
|
|
17
18
|
signRequest(request: Request): Promise<Request>;
|
|
18
19
|
requestEmailVerification?({ navigate }: AuthActionContext, options?: AuthActionOptions): Promise<void>;
|
|
19
20
|
getAccessToken?(): Promise<string>;
|
|
@@ -33,6 +33,7 @@ export declare class DevPortalAuthenticationProvider extends CoreAuthenticationP
|
|
|
33
33
|
signIn(_: AuthActionContext, { redirectTo }?: AuthActionOptions): Promise<void>;
|
|
34
34
|
signUp(_: AuthActionContext, { redirectTo }?: AuthActionOptions): Promise<void>;
|
|
35
35
|
signOut(_: AuthActionContext): Promise<void>;
|
|
36
|
+
hasDistinctSignUpFlow(): boolean;
|
|
36
37
|
signRequest(request: Request): Promise<Request>;
|
|
37
38
|
}
|
|
38
39
|
declare const devPortalAuth: AuthenticationProviderInitializer<DevPortalAuthenticationConfig>;
|
package/package.json
CHANGED
|
@@ -26,6 +26,9 @@ export interface AuthenticationPlugin {
|
|
|
26
26
|
|
|
27
27
|
signOut({ navigate }: AuthActionContext): Promise<void>;
|
|
28
28
|
|
|
29
|
+
/** When false, sign-in and sign-up use the same IdP redirect; UI should not offer separate choices. */
|
|
30
|
+
hasDistinctSignUpFlow?(): boolean;
|
|
31
|
+
|
|
29
32
|
signRequest(request: Request): Promise<Request>;
|
|
30
33
|
requestEmailVerification?(
|
|
31
34
|
{ navigate }: AuthActionContext,
|
|
@@ -79,6 +79,7 @@ export const useAuth = () => {
|
|
|
79
79
|
...authState,
|
|
80
80
|
isBackendAvailable: authState.isBackendAvailable,
|
|
81
81
|
authMode: authState.authMode,
|
|
82
|
+
hasDistinctSignUpFlow: authentication?.hasDistinctSignUpFlow?.() ?? true,
|
|
82
83
|
|
|
83
84
|
login: async (options?: AuthActionOptions) => {
|
|
84
85
|
if (!isAuthEnabled) {
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
DialogTitle,
|
|
9
9
|
} from "@lukoweb/apitogo/ui/Dialog.js";
|
|
10
10
|
import { Helmet } from "@zudoku/react-helmet-async";
|
|
11
|
-
import { use, useCallback, useEffect, useMemo } from "react";
|
|
11
|
+
import { use, useCallback, useEffect, useMemo, useRef } from "react";
|
|
12
12
|
import {
|
|
13
13
|
matchPath,
|
|
14
14
|
Outlet,
|
|
@@ -31,6 +31,7 @@ type LoginDialogProps = {
|
|
|
31
31
|
onCancel: () => void;
|
|
32
32
|
onLogin: () => void;
|
|
33
33
|
onRegister: () => void;
|
|
34
|
+
hasDistinctSignUpFlow: boolean;
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
const LoginDialog = ({
|
|
@@ -38,22 +39,33 @@ const LoginDialog = ({
|
|
|
38
39
|
onCancel,
|
|
39
40
|
onLogin,
|
|
40
41
|
onRegister,
|
|
42
|
+
hasDistinctSignUpFlow,
|
|
41
43
|
}: LoginDialogProps) => (
|
|
42
44
|
<Dialog open={open} onOpenChange={(nextOpen) => !nextOpen && onCancel()}>
|
|
43
45
|
<DialogContent>
|
|
44
46
|
<DialogHeader>
|
|
45
47
|
<DialogTitle>Login to continue</DialogTitle>
|
|
46
48
|
</DialogHeader>
|
|
47
|
-
<DialogDescription>
|
|
49
|
+
<DialogDescription>
|
|
50
|
+
{hasDistinctSignUpFlow
|
|
51
|
+
? "Please login to access this page."
|
|
52
|
+
: "You'll be redirected to sign in or create an account."}
|
|
53
|
+
</DialogDescription>
|
|
48
54
|
<DialogFooter>
|
|
49
55
|
<Button variant="outline" onClick={onCancel}>
|
|
50
56
|
Cancel
|
|
51
57
|
</Button>
|
|
52
58
|
<div className="w-full" />
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
{hasDistinctSignUpFlow ? (
|
|
60
|
+
<>
|
|
61
|
+
<Button variant="secondary" onClick={onRegister}>
|
|
62
|
+
Register
|
|
63
|
+
</Button>
|
|
64
|
+
<Button onClick={onLogin}>Login</Button>
|
|
65
|
+
</>
|
|
66
|
+
) : (
|
|
67
|
+
<Button onClick={onLogin}>Continue</Button>
|
|
68
|
+
)}
|
|
57
69
|
</DialogFooter>
|
|
58
70
|
</DialogContent>
|
|
59
71
|
</Dialog>
|
|
@@ -155,6 +167,41 @@ export const RouteGuard = () => {
|
|
|
155
167
|
getAuthCheck,
|
|
156
168
|
]);
|
|
157
169
|
|
|
170
|
+
const needsAuth = needsToSignIn || isBlocked;
|
|
171
|
+
const redirectTo = isBlocked
|
|
172
|
+
? blocker.location.pathname + blocker.location.search
|
|
173
|
+
: location.pathname + location.search;
|
|
174
|
+
const showDialog =
|
|
175
|
+
auth.isBackendAvailable &&
|
|
176
|
+
needsAuth &&
|
|
177
|
+
auth.hasDistinctSignUpFlow;
|
|
178
|
+
const unifiedRedirectKeyRef = useRef<string | null>(null);
|
|
179
|
+
|
|
180
|
+
useEffect(() => {
|
|
181
|
+
if (
|
|
182
|
+
!auth.isBackendAvailable ||
|
|
183
|
+
auth.isPending ||
|
|
184
|
+
!needsAuth ||
|
|
185
|
+
auth.hasDistinctSignUpFlow
|
|
186
|
+
) {
|
|
187
|
+
unifiedRedirectKeyRef.current = null;
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (unifiedRedirectKeyRef.current === redirectTo) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
unifiedRedirectKeyRef.current = redirectTo;
|
|
196
|
+
void auth.login({ redirectTo });
|
|
197
|
+
}, [
|
|
198
|
+
auth.isBackendAvailable,
|
|
199
|
+
auth.isPending,
|
|
200
|
+
auth.hasDistinctSignUpFlow,
|
|
201
|
+
needsAuth,
|
|
202
|
+
redirectTo,
|
|
203
|
+
]);
|
|
204
|
+
|
|
158
205
|
if (isForbidden) {
|
|
159
206
|
return <ForbiddenPage />;
|
|
160
207
|
}
|
|
@@ -184,16 +231,12 @@ export const RouteGuard = () => {
|
|
|
184
231
|
return <ProductionUnlockPage />;
|
|
185
232
|
}
|
|
186
233
|
|
|
187
|
-
const showDialog = auth.isBackendAvailable && (needsToSignIn || isBlocked);
|
|
188
|
-
const redirectTo = isBlocked
|
|
189
|
-
? blocker.location.pathname + blocker.location.search
|
|
190
|
-
: location.pathname + location.search;
|
|
191
|
-
|
|
192
234
|
return (
|
|
193
235
|
<>
|
|
194
236
|
{!needsToSignIn && <Outlet />}
|
|
195
237
|
<LoginDialog
|
|
196
238
|
open={showDialog}
|
|
239
|
+
hasDistinctSignUpFlow={auth.hasDistinctSignUpFlow}
|
|
197
240
|
onCancel={needsToSignIn ? () => navigate(-1) : () => blocker.reset?.()}
|
|
198
241
|
onLogin={() => void auth.login({ redirectTo })}
|
|
199
242
|
onRegister={() => void auth.signup({ redirectTo })}
|
|
@@ -15,8 +15,14 @@ export type PlaygroundDialogProps = PropsWithChildren<PlaygroundContentProps>;
|
|
|
15
15
|
|
|
16
16
|
const PlaygroundDialog = (props: PlaygroundDialogProps) => {
|
|
17
17
|
const [open, setOpen] = useState(false);
|
|
18
|
-
const {
|
|
19
|
-
|
|
18
|
+
const {
|
|
19
|
+
isAuthEnabled,
|
|
20
|
+
login,
|
|
21
|
+
signup,
|
|
22
|
+
isPending,
|
|
23
|
+
isAuthenticated,
|
|
24
|
+
hasDistinctSignUpFlow,
|
|
25
|
+
} = useAuth();
|
|
20
26
|
|
|
21
27
|
return (
|
|
22
28
|
<Dialog onOpenChange={(open) => setOpen(open)}>
|
|
@@ -44,7 +50,7 @@ const PlaygroundDialog = (props: PlaygroundDialogProps) => {
|
|
|
44
50
|
<Playground
|
|
45
51
|
requiresLogin={isAuthEnabled && !isAuthenticated && !isPending}
|
|
46
52
|
onLogin={() => login()}
|
|
47
|
-
onSignUp={() => signup()}
|
|
53
|
+
onSignUp={hasDistinctSignUpFlow ? () => signup() : undefined}
|
|
48
54
|
{...props}
|
|
49
55
|
/>
|
|
50
56
|
)}
|