@stytch/nextjs 21.6.1 → 21.8.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/CHANGELOG.md +12 -0
- package/dist/index.d.ts +80 -5
- package/dist/index.esm.d.ts +80 -5
- package/dist/index.esm.js +86 -4
- package/dist/index.js +86 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @stytch/nextjs
|
|
2
2
|
|
|
3
|
+
## 21.8.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- d27e450: feat: add device history support to all authentication methods
|
|
8
|
+
|
|
9
|
+
## 21.7.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 14f8002: Add in Hook and HOC for accessing user roles
|
|
14
|
+
|
|
3
15
|
## 21.6.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { ReactNode } from "react";
|
|
4
|
-
import { Session, StytchProjectConfigurationInput, StytchUIClient, User, Callbacks, StringsOptions, StytchLoginConfig, StyleConfig } from "@stytch/vanilla-js";
|
|
5
|
-
import { StytchHeadlessClient } from "@stytch/vanilla-js/headless";
|
|
4
|
+
import { Session, StytchProjectConfigurationInput, StytchUIClient, User, Callbacks, StringsOptions, StytchLoginConfig, StyleConfig, IDPConsentScreenManifest } from "@stytch/vanilla-js";
|
|
5
|
+
import { PermissionsMap, StytchHeadlessClient } from "@stytch/vanilla-js/headless";
|
|
6
6
|
/**
|
|
7
7
|
* The Stytch Client object passed in to <StytchProvider /> in your application root.
|
|
8
8
|
* Either a StytchUIClient or StytchHeadlessClient.
|
|
@@ -119,6 +119,72 @@ declare const withStytchSession: <T extends object, TAssumeHydrated extends bool
|
|
|
119
119
|
stytchSessionIsInitialized: boolean;
|
|
120
120
|
stytchSessionIsFromCache: boolean;
|
|
121
121
|
}>) => React.ComponentType<T>;
|
|
122
|
+
type SWRIsAuthorizedUninitialized = {
|
|
123
|
+
/**
|
|
124
|
+
* Whether the logged-in user is allowed to perform the specified action on the specified resource.
|
|
125
|
+
*/
|
|
126
|
+
isAuthorized: false;
|
|
127
|
+
/**
|
|
128
|
+
* If true, indicates that the value returned is from the application cache and a state refresh is in progress.
|
|
129
|
+
*/
|
|
130
|
+
fromCache: false;
|
|
131
|
+
/**
|
|
132
|
+
* If true, indicates that the SDK has completed initialization.
|
|
133
|
+
*/
|
|
134
|
+
isInitialized: false;
|
|
135
|
+
};
|
|
136
|
+
type SWRIsAuthorizedInitialized = {
|
|
137
|
+
/**
|
|
138
|
+
* Whether the logged-in user is allowed to perform the specified action on the specified resource.
|
|
139
|
+
*/
|
|
140
|
+
isAuthorized: boolean;
|
|
141
|
+
/**
|
|
142
|
+
* If true, indicates that the value returned is from the application cache and a state refresh is in progress.
|
|
143
|
+
*/
|
|
144
|
+
fromCache: boolean;
|
|
145
|
+
/**
|
|
146
|
+
* If true, indicates that the SDK has completed initialization.
|
|
147
|
+
*/
|
|
148
|
+
isInitialized: boolean;
|
|
149
|
+
};
|
|
150
|
+
type SWRIsAuthorized<TAlwaysInitialized extends boolean> = TAlwaysInitialized extends true ? SWRIsAuthorizedInitialized : SWRIsAuthorizedInitialized | SWRIsAuthorizedUninitialized;
|
|
151
|
+
/**
|
|
152
|
+
* Determines whether the logged-in user is allowed to perform the specified action on the specified resource.
|
|
153
|
+
* Returns `true` if the user can perform the action, `false` otherwise.
|
|
154
|
+
*
|
|
155
|
+
* If the user is not logged in, this method will always return false.
|
|
156
|
+
* If the resource or action provided are not valid for the configured RBAC policy, this method will return false.
|
|
157
|
+
*
|
|
158
|
+
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
159
|
+
* @example
|
|
160
|
+
* const { isAuthorized } = useStytchIsAuthorized<Permissions>('documents', 'edit');
|
|
161
|
+
* return <button disabled={!isAuthorized}>Edit</button>
|
|
162
|
+
*/
|
|
163
|
+
declare const useStytchIsAuthorized: <TAssumeHydrated extends boolean = false>(resourceId: string, action: string) => SWRIsAuthorized<TAssumeHydrated>;
|
|
164
|
+
/**
|
|
165
|
+
* Wrap your component with this HOC in order to receive the permissions for the logged-in user.
|
|
166
|
+
* Evaluates all permissions granted to the logged-in user.
|
|
167
|
+
* Returns a Record<RoleId, Record<Action, boolean>> response indicating the user's permissions.
|
|
168
|
+
* Each boolean will be `true` if the user can perform the action, `false` otherwise.
|
|
169
|
+
*
|
|
170
|
+
* If the user is not logged in, all values will be false.
|
|
171
|
+
*
|
|
172
|
+
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
173
|
+
* @example
|
|
174
|
+
* type Permissions = {
|
|
175
|
+
* document: 'create' | 'read' | 'write
|
|
176
|
+
* image: 'create' | 'read'
|
|
177
|
+
* }
|
|
178
|
+
*
|
|
179
|
+
* const MyComponent = (props) => {
|
|
180
|
+
* const canEditDocuments = props.stytchPermissions.document.edit;
|
|
181
|
+
* const canReadImages = props.stytchPermissions.image.read;
|
|
182
|
+
* }
|
|
183
|
+
* return withStytchPermissions<Permissions>(MyComponent)
|
|
184
|
+
*/
|
|
185
|
+
declare const withStytchPermissions: <Permissions_1 extends Record<string, string>, T extends object>(Component: React.ComponentType<T & {
|
|
186
|
+
stytchPermissions: PermissionsMap<Permissions_1>;
|
|
187
|
+
}>) => React.ComponentType<T>;
|
|
122
188
|
interface StytchProviderProps<TProjectConfiguration extends StytchProjectConfigurationInput = Stytch.DefaultProjectConfiguration> {
|
|
123
189
|
/**
|
|
124
190
|
* A Stytch client instance, created using either {@link createStytchHeadlessClient} or {@link createStytchUIClient}
|
|
@@ -253,7 +319,16 @@ interface StytchResetPasswordProps<TProjectConfiguration extends StytchProjectCo
|
|
|
253
319
|
*/
|
|
254
320
|
passwordResetToken: string;
|
|
255
321
|
}
|
|
256
|
-
type
|
|
322
|
+
type IDPConsentScreenManifestGenerator = (input: {
|
|
323
|
+
scopes: string[];
|
|
324
|
+
clientName: string;
|
|
325
|
+
}) => IDPConsentScreenManifest;
|
|
326
|
+
type IdentityProviderProps = Omit<StytchProps, "config"> & {
|
|
327
|
+
/**
|
|
328
|
+
* Optional {@link IDPConsentScreenManifestGenerator} to customize the consent screen.
|
|
329
|
+
*/
|
|
330
|
+
getIDPConsentManifest?: IDPConsentScreenManifestGenerator;
|
|
331
|
+
};
|
|
257
332
|
/**
|
|
258
333
|
* The Stytch Reset Password component.
|
|
259
334
|
* This component can only be used with a Stytch UI Client
|
|
@@ -338,6 +413,6 @@ declare const StytchPasskeyRegistration: <TProjectConfiguration extends Partial<
|
|
|
338
413
|
* }}
|
|
339
414
|
* />
|
|
340
415
|
*/
|
|
341
|
-
declare const IdentityProvider: ({ styles, callbacks, strings }: IdentityProviderProps) => React.JSX.Element;
|
|
342
|
-
export { IdentityProvider, StytchLogin, StytchPasskeyRegistration, StytchPasswordReset, StytchProvider, useStytch, useStytchSession, useStytchUser, withStytch, withStytchSession, withStytchUser };
|
|
416
|
+
declare const IdentityProvider: ({ styles, callbacks, strings, getIDPConsentManifest }: IdentityProviderProps) => React.JSX.Element;
|
|
417
|
+
export { IdentityProvider, StytchLogin, StytchPasskeyRegistration, StytchPasswordReset, StytchProvider, useStytch, useStytchIsAuthorized, useStytchSession, useStytchUser, withStytch, withStytchSession, withStytchUser, withStytchPermissions };
|
|
343
418
|
export type { StytchProviderProps, IdentityProviderProps, StytchProps, StytchResetPasswordProps };
|
package/dist/index.esm.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { ReactNode } from "react";
|
|
4
|
-
import { Session, StytchProjectConfigurationInput, StytchUIClient, User, Callbacks, StringsOptions, StytchLoginConfig, StyleConfig } from "@stytch/vanilla-js";
|
|
5
|
-
import { StytchHeadlessClient } from "@stytch/vanilla-js/headless";
|
|
4
|
+
import { Session, StytchProjectConfigurationInput, StytchUIClient, User, Callbacks, StringsOptions, StytchLoginConfig, StyleConfig, IDPConsentScreenManifest } from "@stytch/vanilla-js";
|
|
5
|
+
import { PermissionsMap, StytchHeadlessClient } from "@stytch/vanilla-js/headless";
|
|
6
6
|
/**
|
|
7
7
|
* The Stytch Client object passed in to <StytchProvider /> in your application root.
|
|
8
8
|
* Either a StytchUIClient or StytchHeadlessClient.
|
|
@@ -119,6 +119,72 @@ declare const withStytchSession: <T extends object, TAssumeHydrated extends bool
|
|
|
119
119
|
stytchSessionIsInitialized: boolean;
|
|
120
120
|
stytchSessionIsFromCache: boolean;
|
|
121
121
|
}>) => React.ComponentType<T>;
|
|
122
|
+
type SWRIsAuthorizedUninitialized = {
|
|
123
|
+
/**
|
|
124
|
+
* Whether the logged-in user is allowed to perform the specified action on the specified resource.
|
|
125
|
+
*/
|
|
126
|
+
isAuthorized: false;
|
|
127
|
+
/**
|
|
128
|
+
* If true, indicates that the value returned is from the application cache and a state refresh is in progress.
|
|
129
|
+
*/
|
|
130
|
+
fromCache: false;
|
|
131
|
+
/**
|
|
132
|
+
* If true, indicates that the SDK has completed initialization.
|
|
133
|
+
*/
|
|
134
|
+
isInitialized: false;
|
|
135
|
+
};
|
|
136
|
+
type SWRIsAuthorizedInitialized = {
|
|
137
|
+
/**
|
|
138
|
+
* Whether the logged-in user is allowed to perform the specified action on the specified resource.
|
|
139
|
+
*/
|
|
140
|
+
isAuthorized: boolean;
|
|
141
|
+
/**
|
|
142
|
+
* If true, indicates that the value returned is from the application cache and a state refresh is in progress.
|
|
143
|
+
*/
|
|
144
|
+
fromCache: boolean;
|
|
145
|
+
/**
|
|
146
|
+
* If true, indicates that the SDK has completed initialization.
|
|
147
|
+
*/
|
|
148
|
+
isInitialized: boolean;
|
|
149
|
+
};
|
|
150
|
+
type SWRIsAuthorized<TAlwaysInitialized extends boolean> = TAlwaysInitialized extends true ? SWRIsAuthorizedInitialized : SWRIsAuthorizedInitialized | SWRIsAuthorizedUninitialized;
|
|
151
|
+
/**
|
|
152
|
+
* Determines whether the logged-in user is allowed to perform the specified action on the specified resource.
|
|
153
|
+
* Returns `true` if the user can perform the action, `false` otherwise.
|
|
154
|
+
*
|
|
155
|
+
* If the user is not logged in, this method will always return false.
|
|
156
|
+
* If the resource or action provided are not valid for the configured RBAC policy, this method will return false.
|
|
157
|
+
*
|
|
158
|
+
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
159
|
+
* @example
|
|
160
|
+
* const { isAuthorized } = useStytchIsAuthorized<Permissions>('documents', 'edit');
|
|
161
|
+
* return <button disabled={!isAuthorized}>Edit</button>
|
|
162
|
+
*/
|
|
163
|
+
declare const useStytchIsAuthorized: <TAssumeHydrated extends boolean = false>(resourceId: string, action: string) => SWRIsAuthorized<TAssumeHydrated>;
|
|
164
|
+
/**
|
|
165
|
+
* Wrap your component with this HOC in order to receive the permissions for the logged-in user.
|
|
166
|
+
* Evaluates all permissions granted to the logged-in user.
|
|
167
|
+
* Returns a Record<RoleId, Record<Action, boolean>> response indicating the user's permissions.
|
|
168
|
+
* Each boolean will be `true` if the user can perform the action, `false` otherwise.
|
|
169
|
+
*
|
|
170
|
+
* If the user is not logged in, all values will be false.
|
|
171
|
+
*
|
|
172
|
+
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
173
|
+
* @example
|
|
174
|
+
* type Permissions = {
|
|
175
|
+
* document: 'create' | 'read' | 'write
|
|
176
|
+
* image: 'create' | 'read'
|
|
177
|
+
* }
|
|
178
|
+
*
|
|
179
|
+
* const MyComponent = (props) => {
|
|
180
|
+
* const canEditDocuments = props.stytchPermissions.document.edit;
|
|
181
|
+
* const canReadImages = props.stytchPermissions.image.read;
|
|
182
|
+
* }
|
|
183
|
+
* return withStytchPermissions<Permissions>(MyComponent)
|
|
184
|
+
*/
|
|
185
|
+
declare const withStytchPermissions: <Permissions_1 extends Record<string, string>, T extends object>(Component: React.ComponentType<T & {
|
|
186
|
+
stytchPermissions: PermissionsMap<Permissions_1>;
|
|
187
|
+
}>) => React.ComponentType<T>;
|
|
122
188
|
interface StytchProviderProps<TProjectConfiguration extends StytchProjectConfigurationInput = Stytch.DefaultProjectConfiguration> {
|
|
123
189
|
/**
|
|
124
190
|
* A Stytch client instance, created using either {@link createStytchHeadlessClient} or {@link createStytchUIClient}
|
|
@@ -253,7 +319,16 @@ interface StytchResetPasswordProps<TProjectConfiguration extends StytchProjectCo
|
|
|
253
319
|
*/
|
|
254
320
|
passwordResetToken: string;
|
|
255
321
|
}
|
|
256
|
-
type
|
|
322
|
+
type IDPConsentScreenManifestGenerator = (input: {
|
|
323
|
+
scopes: string[];
|
|
324
|
+
clientName: string;
|
|
325
|
+
}) => IDPConsentScreenManifest;
|
|
326
|
+
type IdentityProviderProps = Omit<StytchProps, "config"> & {
|
|
327
|
+
/**
|
|
328
|
+
* Optional {@link IDPConsentScreenManifestGenerator} to customize the consent screen.
|
|
329
|
+
*/
|
|
330
|
+
getIDPConsentManifest?: IDPConsentScreenManifestGenerator;
|
|
331
|
+
};
|
|
257
332
|
/**
|
|
258
333
|
* The Stytch Reset Password component.
|
|
259
334
|
* This component can only be used with a Stytch UI Client
|
|
@@ -338,6 +413,6 @@ declare const StytchPasskeyRegistration: <TProjectConfiguration extends Partial<
|
|
|
338
413
|
* }}
|
|
339
414
|
* />
|
|
340
415
|
*/
|
|
341
|
-
declare const IdentityProvider: ({ styles, callbacks, strings }: IdentityProviderProps) => React.JSX.Element;
|
|
342
|
-
export { IdentityProvider, StytchLogin, StytchPasskeyRegistration, StytchPasswordReset, StytchProvider, useStytch, useStytchSession, useStytchUser, withStytch, withStytchSession, withStytchUser };
|
|
416
|
+
declare const IdentityProvider: ({ styles, callbacks, strings, getIDPConsentManifest }: IdentityProviderProps) => React.JSX.Element;
|
|
417
|
+
export { IdentityProvider, StytchLogin, StytchPasskeyRegistration, StytchPasswordReset, StytchProvider, useStytch, useStytchIsAuthorized, useStytchSession, useStytchUser, withStytch, withStytchSession, withStytchUser, withStytchPermissions };
|
|
343
418
|
export type { StytchProviderProps, IdentityProviderProps, StytchProps, StytchResetPasswordProps };
|
package/dist/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { createContext, useContext, useMemo, useCallback, useRef
|
|
1
|
+
import React, { createContext, useContext, useEffect, useMemo, useCallback, useRef } from 'react';
|
|
2
2
|
import { i as invariant, u as useAsyncState, m as mergeWithStableProps, a as useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect-681e2138.js';
|
|
3
3
|
import { i as isStytchSSRProxy, n as noProviderError, p as providerMustBeUniqueError, a as noHeadlessClientError } from './StytchSSRProxy-34c789b5.js';
|
|
4
4
|
|
|
@@ -95,6 +95,87 @@ const withStytchSession = (Component) => {
|
|
|
95
95
|
WithStytchSession.displayName = `withStytchSession(${Component.displayName || Component.name || 'Component'})`;
|
|
96
96
|
return WithStytchSession;
|
|
97
97
|
};
|
|
98
|
+
/**
|
|
99
|
+
* Determines whether the logged-in user is allowed to perform the specified action on the specified resource.
|
|
100
|
+
* Returns `true` if the user can perform the action, `false` otherwise.
|
|
101
|
+
*
|
|
102
|
+
* If the user is not logged in, this method will always return false.
|
|
103
|
+
* If the resource or action provided are not valid for the configured RBAC policy, this method will return false.
|
|
104
|
+
*
|
|
105
|
+
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
106
|
+
* @example
|
|
107
|
+
* const { isAuthorized } = useStytchIsAuthorized<Permissions>('documents', 'edit');
|
|
108
|
+
* return <button disabled={!isAuthorized}>Edit</button>
|
|
109
|
+
*/
|
|
110
|
+
const useStytchIsAuthorized = (resourceId, action) => {
|
|
111
|
+
invariant(useIsMounted__INTERNAL(), noProviderError('useStytchIsAuthorized', 'StytchProvider'));
|
|
112
|
+
const client = useStytch();
|
|
113
|
+
const { user } = useStytchUser();
|
|
114
|
+
const [isAuthorized, setIsAuthorized] = useAsyncState({
|
|
115
|
+
isInitialized: false,
|
|
116
|
+
fromCache: false,
|
|
117
|
+
isAuthorized: false,
|
|
118
|
+
});
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
if (isStytchSSRProxy(client)) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
setIsAuthorized({
|
|
124
|
+
isInitialized: true,
|
|
125
|
+
fromCache: true,
|
|
126
|
+
isAuthorized: client.rbac.isAuthorizedSync(resourceId, action),
|
|
127
|
+
});
|
|
128
|
+
}, [action, client, resourceId, setIsAuthorized]);
|
|
129
|
+
useEffect(() => {
|
|
130
|
+
if (isStytchSSRProxy(client)) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
client.rbac.isAuthorized(resourceId, action).then((isAuthorized) => {
|
|
134
|
+
setIsAuthorized({ isAuthorized, fromCache: false, isInitialized: true });
|
|
135
|
+
});
|
|
136
|
+
}, [client, user === null || user === void 0 ? void 0 : user.roles, resourceId, action, setIsAuthorized]);
|
|
137
|
+
return isAuthorized;
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Wrap your component with this HOC in order to receive the permissions for the logged-in user.
|
|
141
|
+
* Evaluates all permissions granted to the logged-in user.
|
|
142
|
+
* Returns a Record<RoleId, Record<Action, boolean>> response indicating the user's permissions.
|
|
143
|
+
* Each boolean will be `true` if the user can perform the action, `false` otherwise.
|
|
144
|
+
*
|
|
145
|
+
* If the user is not logged in, all values will be false.
|
|
146
|
+
*
|
|
147
|
+
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
148
|
+
* @example
|
|
149
|
+
* type Permissions = {
|
|
150
|
+
* document: 'create' | 'read' | 'write
|
|
151
|
+
* image: 'create' | 'read'
|
|
152
|
+
* }
|
|
153
|
+
*
|
|
154
|
+
* const MyComponent = (props) => {
|
|
155
|
+
* const canEditDocuments = props.stytchPermissions.document.edit;
|
|
156
|
+
* const canReadImages = props.stytchPermissions.image.read;
|
|
157
|
+
* }
|
|
158
|
+
* return withStytchPermissions<Permissions>(MyComponent)
|
|
159
|
+
*/
|
|
160
|
+
const withStytchPermissions = (Component) => {
|
|
161
|
+
const WithStytchPermissions = (props) => {
|
|
162
|
+
invariant(useIsMounted__INTERNAL(), noProviderError('useRBACPermissions', 'StytchProvider'));
|
|
163
|
+
const client = useStytch();
|
|
164
|
+
const { user } = useStytchUser();
|
|
165
|
+
const [permissions, setPermissions] = useAsyncState({ loaded: false, value: null });
|
|
166
|
+
useEffect(() => {
|
|
167
|
+
client.rbac.allPermissions().then((permissions) => {
|
|
168
|
+
setPermissions({ loaded: true, value: permissions });
|
|
169
|
+
});
|
|
170
|
+
}, [client, user === null || user === void 0 ? void 0 : user.roles, setPermissions]);
|
|
171
|
+
if (!permissions.loaded) {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
return React.createElement(Component, Object.assign({}, props, { stytchPermissions: permissions.value }));
|
|
175
|
+
};
|
|
176
|
+
WithStytchPermissions.displayName = `withStytchPermissions(${Component.displayName || Component.name || 'Component'})`;
|
|
177
|
+
return WithStytchPermissions;
|
|
178
|
+
};
|
|
98
179
|
/**
|
|
99
180
|
* The Stytch Context Provider.
|
|
100
181
|
* Wrap your application with this component in order to use Stytch everywhere in your app.
|
|
@@ -334,7 +415,7 @@ const StytchPasskeyRegistration = ({ config, styles, callbacks, strings, }) => {
|
|
|
334
415
|
* }}
|
|
335
416
|
* />
|
|
336
417
|
*/
|
|
337
|
-
const IdentityProvider = ({ styles, callbacks, strings }) => {
|
|
418
|
+
const IdentityProvider = ({ styles, callbacks, strings, getIDPConsentManifest }) => {
|
|
338
419
|
invariant(useIsMounted__INTERNAL(), noProviderError('<IdentityProvider />'));
|
|
339
420
|
const stytchClient = useStytch();
|
|
340
421
|
const user = useStytchUser();
|
|
@@ -355,9 +436,10 @@ const IdentityProvider = ({ styles, callbacks, strings }) => {
|
|
|
355
436
|
elementId: `#${containerEl.current.id}`,
|
|
356
437
|
styles,
|
|
357
438
|
strings,
|
|
439
|
+
getIDPConsentManifest,
|
|
358
440
|
});
|
|
359
|
-
}, [stytchClient, styles, callbacks, user, strings]);
|
|
441
|
+
}, [stytchClient, styles, callbacks, user, strings, getIDPConsentManifest]);
|
|
360
442
|
return React.createElement("div", { ref: containerEl });
|
|
361
443
|
};
|
|
362
444
|
|
|
363
|
-
export { IdentityProvider, StytchLogin, StytchPasskeyRegistration, StytchPasswordReset, StytchProvider, useStytch, useStytchSession, useStytchUser, withStytch, withStytchSession, withStytchUser };
|
|
445
|
+
export { IdentityProvider, StytchLogin, StytchPasskeyRegistration, StytchPasswordReset, StytchProvider, useStytch, useStytchIsAuthorized, useStytchSession, useStytchUser, withStytch, withStytchPermissions, withStytchSession, withStytchUser };
|
package/dist/index.js
CHANGED
|
@@ -103,6 +103,87 @@ const withStytchSession = (Component) => {
|
|
|
103
103
|
WithStytchSession.displayName = `withStytchSession(${Component.displayName || Component.name || 'Component'})`;
|
|
104
104
|
return WithStytchSession;
|
|
105
105
|
};
|
|
106
|
+
/**
|
|
107
|
+
* Determines whether the logged-in user is allowed to perform the specified action on the specified resource.
|
|
108
|
+
* Returns `true` if the user can perform the action, `false` otherwise.
|
|
109
|
+
*
|
|
110
|
+
* If the user is not logged in, this method will always return false.
|
|
111
|
+
* If the resource or action provided are not valid for the configured RBAC policy, this method will return false.
|
|
112
|
+
*
|
|
113
|
+
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
114
|
+
* @example
|
|
115
|
+
* const { isAuthorized } = useStytchIsAuthorized<Permissions>('documents', 'edit');
|
|
116
|
+
* return <button disabled={!isAuthorized}>Edit</button>
|
|
117
|
+
*/
|
|
118
|
+
const useStytchIsAuthorized = (resourceId, action) => {
|
|
119
|
+
useIsomorphicLayoutEffect.invariant(useIsMounted__INTERNAL(), StytchSSRProxy.noProviderError('useStytchIsAuthorized', 'StytchProvider'));
|
|
120
|
+
const client = useStytch();
|
|
121
|
+
const { user } = useStytchUser();
|
|
122
|
+
const [isAuthorized, setIsAuthorized] = useIsomorphicLayoutEffect.useAsyncState({
|
|
123
|
+
isInitialized: false,
|
|
124
|
+
fromCache: false,
|
|
125
|
+
isAuthorized: false,
|
|
126
|
+
});
|
|
127
|
+
React.useEffect(() => {
|
|
128
|
+
if (StytchSSRProxy.isStytchSSRProxy(client)) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
setIsAuthorized({
|
|
132
|
+
isInitialized: true,
|
|
133
|
+
fromCache: true,
|
|
134
|
+
isAuthorized: client.rbac.isAuthorizedSync(resourceId, action),
|
|
135
|
+
});
|
|
136
|
+
}, [action, client, resourceId, setIsAuthorized]);
|
|
137
|
+
React.useEffect(() => {
|
|
138
|
+
if (StytchSSRProxy.isStytchSSRProxy(client)) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
client.rbac.isAuthorized(resourceId, action).then((isAuthorized) => {
|
|
142
|
+
setIsAuthorized({ isAuthorized, fromCache: false, isInitialized: true });
|
|
143
|
+
});
|
|
144
|
+
}, [client, user === null || user === void 0 ? void 0 : user.roles, resourceId, action, setIsAuthorized]);
|
|
145
|
+
return isAuthorized;
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Wrap your component with this HOC in order to receive the permissions for the logged-in user.
|
|
149
|
+
* Evaluates all permissions granted to the logged-in user.
|
|
150
|
+
* Returns a Record<RoleId, Record<Action, boolean>> response indicating the user's permissions.
|
|
151
|
+
* Each boolean will be `true` if the user can perform the action, `false` otherwise.
|
|
152
|
+
*
|
|
153
|
+
* If the user is not logged in, all values will be false.
|
|
154
|
+
*
|
|
155
|
+
* Remember - authorization checks for sensitive actions should always occur on the backend as well.
|
|
156
|
+
* @example
|
|
157
|
+
* type Permissions = {
|
|
158
|
+
* document: 'create' | 'read' | 'write
|
|
159
|
+
* image: 'create' | 'read'
|
|
160
|
+
* }
|
|
161
|
+
*
|
|
162
|
+
* const MyComponent = (props) => {
|
|
163
|
+
* const canEditDocuments = props.stytchPermissions.document.edit;
|
|
164
|
+
* const canReadImages = props.stytchPermissions.image.read;
|
|
165
|
+
* }
|
|
166
|
+
* return withStytchPermissions<Permissions>(MyComponent)
|
|
167
|
+
*/
|
|
168
|
+
const withStytchPermissions = (Component) => {
|
|
169
|
+
const WithStytchPermissions = (props) => {
|
|
170
|
+
useIsomorphicLayoutEffect.invariant(useIsMounted__INTERNAL(), StytchSSRProxy.noProviderError('useRBACPermissions', 'StytchProvider'));
|
|
171
|
+
const client = useStytch();
|
|
172
|
+
const { user } = useStytchUser();
|
|
173
|
+
const [permissions, setPermissions] = useIsomorphicLayoutEffect.useAsyncState({ loaded: false, value: null });
|
|
174
|
+
React.useEffect(() => {
|
|
175
|
+
client.rbac.allPermissions().then((permissions) => {
|
|
176
|
+
setPermissions({ loaded: true, value: permissions });
|
|
177
|
+
});
|
|
178
|
+
}, [client, user === null || user === void 0 ? void 0 : user.roles, setPermissions]);
|
|
179
|
+
if (!permissions.loaded) {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
return React__default["default"].createElement(Component, Object.assign({}, props, { stytchPermissions: permissions.value }));
|
|
183
|
+
};
|
|
184
|
+
WithStytchPermissions.displayName = `withStytchPermissions(${Component.displayName || Component.name || 'Component'})`;
|
|
185
|
+
return WithStytchPermissions;
|
|
186
|
+
};
|
|
106
187
|
/**
|
|
107
188
|
* The Stytch Context Provider.
|
|
108
189
|
* Wrap your application with this component in order to use Stytch everywhere in your app.
|
|
@@ -342,7 +423,7 @@ const StytchPasskeyRegistration = ({ config, styles, callbacks, strings, }) => {
|
|
|
342
423
|
* }}
|
|
343
424
|
* />
|
|
344
425
|
*/
|
|
345
|
-
const IdentityProvider = ({ styles, callbacks, strings }) => {
|
|
426
|
+
const IdentityProvider = ({ styles, callbacks, strings, getIDPConsentManifest }) => {
|
|
346
427
|
useIsomorphicLayoutEffect.invariant(useIsMounted__INTERNAL(), StytchSSRProxy.noProviderError('<IdentityProvider />'));
|
|
347
428
|
const stytchClient = useStytch();
|
|
348
429
|
const user = useStytchUser();
|
|
@@ -363,8 +444,9 @@ const IdentityProvider = ({ styles, callbacks, strings }) => {
|
|
|
363
444
|
elementId: `#${containerEl.current.id}`,
|
|
364
445
|
styles,
|
|
365
446
|
strings,
|
|
447
|
+
getIDPConsentManifest,
|
|
366
448
|
});
|
|
367
|
-
}, [stytchClient, styles, callbacks, user, strings]);
|
|
449
|
+
}, [stytchClient, styles, callbacks, user, strings, getIDPConsentManifest]);
|
|
368
450
|
return React__default["default"].createElement("div", { ref: containerEl });
|
|
369
451
|
};
|
|
370
452
|
|
|
@@ -374,8 +456,10 @@ exports.StytchPasskeyRegistration = StytchPasskeyRegistration;
|
|
|
374
456
|
exports.StytchPasswordReset = StytchPasswordReset;
|
|
375
457
|
exports.StytchProvider = StytchProvider;
|
|
376
458
|
exports.useStytch = useStytch;
|
|
459
|
+
exports.useStytchIsAuthorized = useStytchIsAuthorized;
|
|
377
460
|
exports.useStytchSession = useStytchSession;
|
|
378
461
|
exports.useStytchUser = useStytchUser;
|
|
379
462
|
exports.withStytch = withStytch;
|
|
463
|
+
exports.withStytchPermissions = withStytchPermissions;
|
|
380
464
|
exports.withStytchSession = withStytchSession;
|
|
381
465
|
exports.withStytchUser = withStytchUser;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stytch/nextjs",
|
|
3
|
-
"version": "21.
|
|
3
|
+
"version": "21.8.0",
|
|
4
4
|
"description": "Stytch's official Next.js Library",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.esm.js",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@babel/runtime": "7.27.1",
|
|
25
25
|
"@stytch/internal-tsconfigs": "0.0.0",
|
|
26
26
|
"@stytch/js-utils": "0.0.1",
|
|
27
|
-
"@stytch/vanilla-js": "5.
|
|
27
|
+
"@stytch/vanilla-js": "5.31.0",
|
|
28
28
|
"@testing-library/react": "14.0.0",
|
|
29
29
|
"@types/jest": "29.5.14",
|
|
30
30
|
"eslint-config-custom": "0.0.1",
|