@propelauth/nextjs 0.0.71 → 0.0.77
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +50 -8
- package/dist/client/index.d.ts +52 -9
- package/dist/client/index.js +183 -64
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +169 -51
- package/dist/client/index.mjs.map +1 -1
- package/dist/server/app-router/index.d.ts +6 -5
- package/dist/server/app-router/index.js +27 -20
- package/dist/server/app-router/index.js.map +1 -1
- package/dist/server/app-router/index.mjs +26 -20
- package/dist/server/app-router/index.mjs.map +1 -1
- package/dist/server/index.d.ts +60 -5
- package/dist/server/index.js +26 -6
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +24 -5
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/pages/index.d.ts +6 -5
- package/dist/server/pages/index.js +41 -4
- package/dist/server/pages/index.js.map +1 -1
- package/dist/server/pages/index.mjs +40 -4
- package/dist/server/pages/index.mjs.map +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
This library provides a simple way to integrate your Next.js application (either AppRouter or Pages) with PropelAuth.
|
6
6
|
|
7
|
-
Next.js SSR/AppRouter support is
|
7
|
+
Next.js SSR/AppRouter support is currently in beta.
|
8
8
|
|
9
9
|
## Installation
|
10
10
|
|
@@ -40,7 +40,6 @@ In your `src/app/api/auth/[slug]` directory, create a file called `route.ts` wit
|
|
40
40
|
|
41
41
|
```typescript
|
42
42
|
import {getRouteHandlers} from "@propelauth/nextjs/server/app-router";
|
43
|
-
import {User} from "@propelauth/nextjs/server";
|
44
43
|
import {NextRequest} from "next/server";
|
45
44
|
|
46
45
|
// postLoginRedirectPathFn is optional, but if you want to redirect the user to a different page after login, you can do so here.
|
@@ -55,7 +54,7 @@ export const POST = routeHandlers.postRouteHandler
|
|
55
54
|
|
56
55
|
### 2. Set up AuthProvider
|
57
56
|
|
58
|
-
####
|
57
|
+
#### App Router
|
59
58
|
|
60
59
|
In your root layout, `src/app/layout.tsx`, add the `AuthProvider`:
|
61
60
|
|
@@ -71,7 +70,7 @@ export default async function RootLayout({children}: {children: React.ReactNode}
|
|
71
70
|
}
|
72
71
|
```
|
73
72
|
|
74
|
-
#### Pages
|
73
|
+
#### Pages Router
|
75
74
|
|
76
75
|
In your `_app.tsx` file, add the `AuthProvider`:
|
77
76
|
|
@@ -85,7 +84,7 @@ export default function MyApp({Component, pageProps}: AppProps) {
|
|
85
84
|
}
|
86
85
|
```
|
87
86
|
|
88
|
-
### 3. Set up middleware (
|
87
|
+
### 3. Set up middleware (App Router only - skip if using Pages)
|
89
88
|
|
90
89
|
In your `src/middleware.ts` file, add the following:
|
91
90
|
|
@@ -108,7 +107,7 @@ export const config = {
|
|
108
107
|
|
109
108
|
## Usage
|
110
109
|
|
111
|
-
### Get the user in Server Components (
|
110
|
+
### Get the user in Server Components (App Router example)
|
112
111
|
|
113
112
|
```tsx
|
114
113
|
import {getUser} from "@propelauth/nextjs/server/app-router";
|
@@ -125,7 +124,7 @@ const WelcomeMessage = async () => {
|
|
125
124
|
```
|
126
125
|
|
127
126
|
```tsx
|
128
|
-
import {
|
127
|
+
import {getUserOrRedirect} from "@propelauth/nextjs/server/app-router";
|
129
128
|
|
130
129
|
const WelcomeMessage = async () => {
|
131
130
|
// If the user is not logged in, they will be redirected to the login page
|
@@ -157,6 +156,21 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
|
|
157
156
|
}
|
158
157
|
```
|
159
158
|
|
159
|
+
### Get the user in API Routes (Pages example)
|
160
|
+
|
161
|
+
```ts
|
162
|
+
import {NextApiRequest, NextApiResponse} from "next";
|
163
|
+
import {getUserFromApiRouteRequest} from "@propelauth/nextjs/server/pages";
|
164
|
+
|
165
|
+
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
166
|
+
const user = await getUserFromApiRouteRequest(req, res)
|
167
|
+
if (user) {
|
168
|
+
res.status(200).json({email: user.email})
|
169
|
+
} else {
|
170
|
+
res.status(401).json({error: "unauthorized"})
|
171
|
+
}
|
172
|
+
}
|
173
|
+
```
|
160
174
|
|
161
175
|
### Get the user in Client Components
|
162
176
|
|
@@ -180,7 +194,7 @@ const WelcomeMessage = () => {
|
|
180
194
|
|
181
195
|
### Checking organization membership / RBAC
|
182
196
|
|
183
|
-
Note that this works on both the client
|
197
|
+
Note that this works on both the client's `User` object or the client/server `UserFromToken` object, but the below example is on the server.
|
184
198
|
|
185
199
|
If you are curious where the organization information comes from, check out our documentation on [organizations](https://docs.propelauth.com/overview/organizations?utm_source=github&utm_medium=library&utm_campaign=nextjs).
|
186
200
|
The quick answer is:
|
@@ -254,3 +268,31 @@ export default function AccountAndOrgButtons() {
|
|
254
268
|
</>
|
255
269
|
}
|
256
270
|
```
|
271
|
+
|
272
|
+
### Using APIs
|
273
|
+
|
274
|
+
You can use our [APIs](https://docs.propelauth.com/reference/backend-apis/node) like so:
|
275
|
+
|
276
|
+
```ts
|
277
|
+
import {getPropelAuthApis} from "@propelauth/nextjs/server";
|
278
|
+
|
279
|
+
const apis = getPropelAuthApis()
|
280
|
+
await apis.disableUser(userId)
|
281
|
+
```
|
282
|
+
|
283
|
+
### Making a call to an external API
|
284
|
+
|
285
|
+
PropelAuth also supports backend that are not Next.js. To make an [authenticated request](https://docs.propelauth.com/getting-started/making-authenticated-requests)
|
286
|
+
to an external API, you'll need an access token. You can get an access token on the frontend from the `useUser` hook:
|
287
|
+
|
288
|
+
```tsx
|
289
|
+
import {useUser} from "@propelauth/nextjs/client";
|
290
|
+
|
291
|
+
const MyComponent = () => {
|
292
|
+
const {loading, accessToken} = useUser()
|
293
|
+
|
294
|
+
// Make a request to an external API with useEffect, useQuery, etc.
|
295
|
+
}
|
296
|
+
```
|
297
|
+
|
298
|
+
Within the App Router, you can also call `getAccessToken` to get the access token.
|
package/dist/client/index.d.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
|
3
|
-
declare class
|
3
|
+
declare class UserFromToken {
|
4
4
|
userId: string;
|
5
5
|
orgIdToOrgMemberInfo?: OrgIdToOrgMemberInfo;
|
6
6
|
email: string;
|
@@ -14,7 +14,7 @@ declare class User {
|
|
14
14
|
getOrgByName(orgName: string): OrgMemberInfo | undefined;
|
15
15
|
getOrgs(): OrgMemberInfo[];
|
16
16
|
isImpersonating(): boolean;
|
17
|
-
static fromJSON(json: string):
|
17
|
+
static fromJSON(json: string): UserFromToken;
|
18
18
|
}
|
19
19
|
type OrgIdToOrgMemberInfo = {
|
20
20
|
[orgId: string]: OrgMemberInfo;
|
@@ -42,30 +42,73 @@ declare class OrgMemberInfo {
|
|
42
42
|
get permissions(): string[];
|
43
43
|
}
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
45
|
+
declare class User {
|
46
|
+
userId: string;
|
47
|
+
email: string;
|
48
|
+
emailConfirmed: boolean;
|
49
|
+
hasPassword: boolean;
|
50
|
+
username?: string;
|
51
|
+
firstName?: string;
|
52
|
+
lastName?: string;
|
53
|
+
pictureUrl?: string;
|
54
|
+
orgIdToOrgMemberInfo?: OrgIdToOrgMemberInfo;
|
55
|
+
mfaEnabled: boolean;
|
56
|
+
canCreateOrgs: boolean;
|
57
|
+
updatePasswordRequired: boolean;
|
58
|
+
createdAt: number;
|
59
|
+
lastActiveAt: number;
|
60
|
+
legacyUserId?: string;
|
61
|
+
impersonatorUserId?: string;
|
62
|
+
constructor({ userId, email, emailConfirmed, hasPassword, username, firstName, lastName, pictureUrl, orgIdToOrgMemberInfo, mfaEnabled, canCreateOrgs, updatePasswordRequired, createdAt, lastActiveAt, legacyUserId, impersonatorUserId, }: {
|
63
|
+
userId: string;
|
64
|
+
email: string;
|
65
|
+
emailConfirmed: boolean;
|
66
|
+
hasPassword: boolean;
|
67
|
+
username?: string;
|
68
|
+
firstName?: string;
|
69
|
+
lastName?: string;
|
70
|
+
pictureUrl?: string;
|
71
|
+
orgIdToOrgMemberInfo?: OrgIdToOrgMemberInfo;
|
72
|
+
mfaEnabled: boolean;
|
73
|
+
canCreateOrgs: boolean;
|
74
|
+
updatePasswordRequired: boolean;
|
75
|
+
createdAt: number;
|
76
|
+
lastActiveAt: number;
|
77
|
+
legacyUserId?: string;
|
78
|
+
impersonatorUserId?: string;
|
79
|
+
});
|
80
|
+
getOrg(orgId: string): OrgMemberInfo | undefined;
|
81
|
+
getOrgByName(orgName: string): OrgMemberInfo | undefined;
|
82
|
+
getOrgs(): OrgMemberInfo[];
|
83
|
+
isImpersonating(): boolean;
|
84
|
+
}
|
51
85
|
type UseUserLoading = {
|
52
86
|
loading: true;
|
53
87
|
isLoggedIn: never;
|
54
88
|
user: never;
|
89
|
+
accessToken: never;
|
55
90
|
};
|
56
91
|
type UseUserLoggedIn = {
|
57
92
|
loading: false;
|
58
93
|
isLoggedIn: true;
|
59
94
|
user: User;
|
95
|
+
accessToken: string;
|
60
96
|
};
|
61
97
|
type UseUserNotLoggedIn = {
|
62
98
|
loading: false;
|
63
99
|
isLoggedIn: false;
|
64
100
|
user: undefined;
|
101
|
+
accessToken: undefined;
|
65
102
|
};
|
66
103
|
type UseUser = UseUserLoading | UseUserLoggedIn | UseUserNotLoggedIn;
|
67
104
|
declare function useUser(): UseUser;
|
68
105
|
|
106
|
+
type AuthProviderProps = {
|
107
|
+
authUrl: string;
|
108
|
+
children?: React.ReactNode;
|
109
|
+
};
|
110
|
+
declare const AuthProvider: (props: AuthProviderProps) => React.JSX.Element;
|
111
|
+
|
69
112
|
declare function useHostedPageUrls(): {
|
70
113
|
getLoginPageUrl: () => string;
|
71
114
|
getSignupPageUrl: () => string;
|
@@ -92,4 +135,4 @@ declare function RedirectToLogin({ children }: RedirectProps): React.JSX.Element
|
|
92
135
|
|
93
136
|
declare function useRefreshAuth(): () => Promise<User | undefined>;
|
94
137
|
|
95
|
-
export { AuthProvider, AuthProviderProps, OrgIdToOrgMemberInfo, OrgMemberInfo, RedirectProps, RedirectToLogin, RedirectToSignup, UseUser, UseUserLoading, UseUserLoggedIn, UseUserNotLoggedIn, User, useHostedPageUrls, useLogoutFunction, useRedirectFunctions, useRefreshAuth, useUser };
|
138
|
+
export { AuthProvider, AuthProviderProps, OrgIdToOrgMemberInfo, OrgMemberInfo, RedirectProps, RedirectToLogin, RedirectToSignup, UseUser, UseUserLoading, UseUserLoggedIn, UseUserNotLoggedIn, User, UserFromToken, useHostedPageUrls, useLogoutFunction, useRedirectFunctions, useRefreshAuth, useUser };
|
package/dist/client/index.js
CHANGED
@@ -56,6 +56,7 @@ __export(client_exports, {
|
|
56
56
|
RedirectToLogin: () => RedirectToLogin,
|
57
57
|
RedirectToSignup: () => RedirectToSignup,
|
58
58
|
User: () => User,
|
59
|
+
UserFromToken: () => UserFromToken,
|
59
60
|
useHostedPageUrls: () => useHostedPageUrls,
|
60
61
|
useLogoutFunction: () => useLogoutFunction,
|
61
62
|
useRedirectFunctions: () => useRedirectFunctions,
|
@@ -65,7 +66,7 @@ __export(client_exports, {
|
|
65
66
|
module.exports = __toCommonJS(client_exports);
|
66
67
|
|
67
68
|
// src/user.ts
|
68
|
-
var
|
69
|
+
var UserFromToken = class {
|
69
70
|
constructor(userId, email, orgIdToOrgMemberInfo, firstName, lastName, username, legacyUserId, impersonatorUserId) {
|
70
71
|
this.userId = userId;
|
71
72
|
this.orgIdToOrgMemberInfo = orgIdToOrgMemberInfo;
|
@@ -112,7 +113,7 @@ var User = class {
|
|
112
113
|
JSON.stringify(obj.orgIdToOrgMemberInfo[orgId])
|
113
114
|
);
|
114
115
|
}
|
115
|
-
return new
|
116
|
+
return new UserFromToken(
|
116
117
|
obj.userId,
|
117
118
|
obj.email,
|
118
119
|
orgIdToOrgMemberInfo,
|
@@ -170,9 +171,30 @@ var OrgMemberInfo = class {
|
|
170
171
|
return this.userPermissions;
|
171
172
|
}
|
172
173
|
};
|
174
|
+
function toOrgIdToOrgMemberInfo(snake_case) {
|
175
|
+
if (snake_case === void 0) {
|
176
|
+
return void 0;
|
177
|
+
}
|
178
|
+
const camelCase = {};
|
179
|
+
for (const key of Object.keys(snake_case)) {
|
180
|
+
const snakeCaseValue = snake_case[key];
|
181
|
+
if (snakeCaseValue) {
|
182
|
+
camelCase[key] = new OrgMemberInfo(
|
183
|
+
snakeCaseValue.org_id,
|
184
|
+
snakeCaseValue.org_name,
|
185
|
+
snakeCaseValue.org_metadata,
|
186
|
+
snakeCaseValue.url_safe_org_name,
|
187
|
+
snakeCaseValue.user_role,
|
188
|
+
snakeCaseValue.inherited_user_roles_plus_current_role,
|
189
|
+
snakeCaseValue.user_permissions
|
190
|
+
);
|
191
|
+
}
|
192
|
+
}
|
193
|
+
return camelCase;
|
194
|
+
}
|
173
195
|
|
174
196
|
// src/client/AuthProvider.tsx
|
175
|
-
var
|
197
|
+
var import_react2 = __toESM(require("react"));
|
176
198
|
|
177
199
|
// src/client/utils.ts
|
178
200
|
var USER_INFO_KEY = "__PROPEL_AUTH_USER_INFO";
|
@@ -237,53 +259,162 @@ function isEqual(a, b) {
|
|
237
259
|
|
238
260
|
// src/client/AuthProvider.tsx
|
239
261
|
var import_navigation = require("next/navigation");
|
240
|
-
|
262
|
+
|
263
|
+
// src/client/useUser.tsx
|
264
|
+
var import_react = require("react");
|
265
|
+
var User = class {
|
266
|
+
constructor({
|
267
|
+
userId,
|
268
|
+
email,
|
269
|
+
emailConfirmed,
|
270
|
+
hasPassword,
|
271
|
+
username,
|
272
|
+
firstName,
|
273
|
+
lastName,
|
274
|
+
pictureUrl,
|
275
|
+
orgIdToOrgMemberInfo,
|
276
|
+
mfaEnabled,
|
277
|
+
canCreateOrgs,
|
278
|
+
updatePasswordRequired,
|
279
|
+
createdAt,
|
280
|
+
lastActiveAt,
|
281
|
+
legacyUserId,
|
282
|
+
impersonatorUserId
|
283
|
+
}) {
|
284
|
+
this.userId = userId;
|
285
|
+
this.email = email;
|
286
|
+
this.emailConfirmed = emailConfirmed;
|
287
|
+
this.hasPassword = hasPassword;
|
288
|
+
this.username = username;
|
289
|
+
this.firstName = firstName;
|
290
|
+
this.lastName = lastName;
|
291
|
+
this.pictureUrl = pictureUrl;
|
292
|
+
this.orgIdToOrgMemberInfo = orgIdToOrgMemberInfo;
|
293
|
+
this.mfaEnabled = mfaEnabled;
|
294
|
+
this.canCreateOrgs = canCreateOrgs;
|
295
|
+
this.updatePasswordRequired = updatePasswordRequired;
|
296
|
+
this.createdAt = createdAt;
|
297
|
+
this.lastActiveAt = lastActiveAt;
|
298
|
+
this.legacyUserId = legacyUserId;
|
299
|
+
this.impersonatorUserId = impersonatorUserId;
|
300
|
+
}
|
301
|
+
getOrg(orgId) {
|
302
|
+
var _a;
|
303
|
+
return (_a = this.orgIdToOrgMemberInfo) == null ? void 0 : _a[orgId];
|
304
|
+
}
|
305
|
+
getOrgByName(orgName) {
|
306
|
+
if (!this.orgIdToOrgMemberInfo) {
|
307
|
+
return void 0;
|
308
|
+
}
|
309
|
+
const urlSafeOrgName = orgName.toLowerCase().replace(/ /g, "-");
|
310
|
+
for (const orgId in this.orgIdToOrgMemberInfo) {
|
311
|
+
const orgMemberInfo = this.orgIdToOrgMemberInfo[orgId];
|
312
|
+
if (orgMemberInfo.urlSafeOrgName === urlSafeOrgName) {
|
313
|
+
return orgMemberInfo;
|
314
|
+
}
|
315
|
+
}
|
316
|
+
return void 0;
|
317
|
+
}
|
318
|
+
getOrgs() {
|
319
|
+
if (!this.orgIdToOrgMemberInfo) {
|
320
|
+
return [];
|
321
|
+
}
|
322
|
+
return Object.values(this.orgIdToOrgMemberInfo);
|
323
|
+
}
|
324
|
+
isImpersonating() {
|
325
|
+
return !!this.impersonatorUserId;
|
326
|
+
}
|
327
|
+
};
|
328
|
+
function useUser() {
|
329
|
+
const context = (0, import_react.useContext)(AuthContext);
|
330
|
+
if (context === void 0) {
|
331
|
+
throw new Error("useUser must be used within an AuthProvider");
|
332
|
+
}
|
333
|
+
const { loading, userAndAccessToken } = context;
|
334
|
+
if (loading) {
|
335
|
+
return {
|
336
|
+
loading: true,
|
337
|
+
isLoggedIn: void 0,
|
338
|
+
user: void 0,
|
339
|
+
accessToken: void 0
|
340
|
+
};
|
341
|
+
} else if (userAndAccessToken.user) {
|
342
|
+
return {
|
343
|
+
loading: false,
|
344
|
+
isLoggedIn: true,
|
345
|
+
user: userAndAccessToken.user,
|
346
|
+
accessToken: userAndAccessToken.accessToken
|
347
|
+
};
|
348
|
+
} else {
|
349
|
+
return {
|
350
|
+
loading: false,
|
351
|
+
isLoggedIn: false,
|
352
|
+
user: void 0,
|
353
|
+
accessToken: void 0
|
354
|
+
};
|
355
|
+
}
|
356
|
+
}
|
357
|
+
|
358
|
+
// src/client/AuthProvider.tsx
|
359
|
+
var AuthContext = import_react2.default.createContext(void 0);
|
241
360
|
var initialAuthState = {
|
242
361
|
loading: true,
|
243
|
-
|
362
|
+
userAndAccessToken: {
|
363
|
+
user: void 0,
|
364
|
+
accessToken: void 0
|
365
|
+
},
|
244
366
|
authChangeDetected: false
|
245
367
|
};
|
246
368
|
function authStateReducer(_state, action) {
|
247
|
-
const authChangeDetected = !_state.loading && !isEqual(action.user, _state.user);
|
369
|
+
const authChangeDetected = !_state.loading && !isEqual(action.user, _state.userAndAccessToken.user);
|
248
370
|
if (!action.user) {
|
249
371
|
return {
|
250
372
|
loading: false,
|
251
|
-
|
373
|
+
userAndAccessToken: {
|
374
|
+
user: void 0,
|
375
|
+
accessToken: void 0
|
376
|
+
},
|
252
377
|
authChangeDetected
|
253
378
|
};
|
254
379
|
} else if (_state.loading) {
|
255
380
|
return {
|
256
381
|
loading: false,
|
257
|
-
|
382
|
+
userAndAccessToken: {
|
383
|
+
user: action.user,
|
384
|
+
accessToken: action.accessToken
|
385
|
+
},
|
258
386
|
authChangeDetected
|
259
387
|
};
|
260
388
|
} else {
|
261
389
|
return {
|
262
390
|
loading: false,
|
263
|
-
|
391
|
+
userAndAccessToken: {
|
392
|
+
user: action.user,
|
393
|
+
accessToken: action.accessToken
|
394
|
+
},
|
264
395
|
authChangeDetected
|
265
396
|
};
|
266
397
|
}
|
267
398
|
}
|
268
399
|
var AuthProvider = (props) => {
|
269
|
-
const [authState, dispatchInner] = (0,
|
400
|
+
const [authState, dispatchInner] = (0, import_react2.useReducer)(authStateReducer, initialAuthState);
|
270
401
|
const router = (0, import_navigation.useRouter)();
|
271
|
-
const dispatch = (0,
|
402
|
+
const dispatch = (0, import_react2.useCallback)((action) => {
|
272
403
|
dispatchInner(action);
|
273
404
|
saveUserToLocalStorage(action.user);
|
274
405
|
}, [dispatchInner]);
|
275
|
-
(0,
|
406
|
+
(0, import_react2.useEffect)(() => {
|
276
407
|
if (authState.authChangeDetected) {
|
277
408
|
router.refresh();
|
278
409
|
}
|
279
410
|
}, [authState.authChangeDetected, router]);
|
280
|
-
(0,
|
411
|
+
(0, import_react2.useEffect)(() => {
|
281
412
|
let didCancel = false;
|
282
413
|
function refreshAuthInfo2() {
|
283
414
|
return __async(this, null, function* () {
|
284
|
-
const
|
415
|
+
const action = yield apiGetUserInfo();
|
285
416
|
if (!didCancel) {
|
286
|
-
dispatch(
|
417
|
+
dispatch(action);
|
287
418
|
}
|
288
419
|
});
|
289
420
|
}
|
@@ -292,19 +423,19 @@ var AuthProvider = (props) => {
|
|
292
423
|
didCancel = true;
|
293
424
|
};
|
294
425
|
}, []);
|
295
|
-
(0,
|
426
|
+
(0, import_react2.useEffect)(() => {
|
296
427
|
let didCancel = false;
|
297
428
|
function refreshToken() {
|
298
429
|
return __async(this, null, function* () {
|
299
|
-
const
|
430
|
+
const action = yield apiGetUserInfo();
|
300
431
|
if (!didCancel) {
|
301
|
-
dispatch(
|
432
|
+
dispatch(action);
|
302
433
|
}
|
303
434
|
});
|
304
435
|
}
|
305
436
|
function onStorageEvent(event) {
|
306
437
|
return __async(this, null, function* () {
|
307
|
-
if (event.key === USER_INFO_KEY && !doesLocalStorageMatch(event.newValue, authState.user)) {
|
438
|
+
if (event.key === USER_INFO_KEY && !doesLocalStorageMatch(event.newValue, authState.userAndAccessToken.user)) {
|
308
439
|
yield refreshToken();
|
309
440
|
}
|
310
441
|
});
|
@@ -324,8 +455,8 @@ var AuthProvider = (props) => {
|
|
324
455
|
window.removeEventListener("focus", refreshToken);
|
325
456
|
}
|
326
457
|
};
|
327
|
-
}, [dispatch, authState.user]);
|
328
|
-
const logout = (0,
|
458
|
+
}, [dispatch, authState.userAndAccessToken.user]);
|
459
|
+
const logout = (0, import_react2.useCallback)(() => __async(void 0, null, function* () {
|
329
460
|
yield fetch("/api/auth/logout", {
|
330
461
|
method: "POST",
|
331
462
|
headers: {
|
@@ -333,14 +464,14 @@ var AuthProvider = (props) => {
|
|
333
464
|
},
|
334
465
|
credentials: "include"
|
335
466
|
});
|
336
|
-
dispatch({ user: void 0 });
|
467
|
+
dispatch({ user: void 0, accessToken: void 0 });
|
337
468
|
}), [dispatch]);
|
338
469
|
const getLoginPageUrl = () => "/api/auth/login";
|
339
470
|
const getSignupPageUrl = () => "/api/auth/signup";
|
340
|
-
const getAccountPageUrl = (0,
|
471
|
+
const getAccountPageUrl = (0, import_react2.useCallback)(() => {
|
341
472
|
return `${props.authUrl}/account`;
|
342
473
|
}, [props.authUrl]);
|
343
|
-
const getOrgPageUrl = (0,
|
474
|
+
const getOrgPageUrl = (0, import_react2.useCallback)(
|
344
475
|
(orgId) => {
|
345
476
|
if (orgId) {
|
346
477
|
return `${props.authUrl}/org?id=${orgId}`;
|
@@ -350,10 +481,10 @@ var AuthProvider = (props) => {
|
|
350
481
|
},
|
351
482
|
[props.authUrl]
|
352
483
|
);
|
353
|
-
const getCreateOrgPageUrl = (0,
|
484
|
+
const getCreateOrgPageUrl = (0, import_react2.useCallback)(() => {
|
354
485
|
return `${props.authUrl}/create_org`;
|
355
486
|
}, [props.authUrl]);
|
356
|
-
const getSetupSAMLPageUrl = (0,
|
487
|
+
const getSetupSAMLPageUrl = (0, import_react2.useCallback)(
|
357
488
|
(orgId) => {
|
358
489
|
return `${props.authUrl}/saml?id=${orgId}`;
|
359
490
|
},
|
@@ -369,13 +500,13 @@ var AuthProvider = (props) => {
|
|
369
500
|
const redirectToCreateOrgPage = () => redirectTo(getCreateOrgPageUrl());
|
370
501
|
const redirectToSetupSAMLPage = (orgId) => redirectTo(getSetupSAMLPageUrl(orgId));
|
371
502
|
const refreshAuthInfo = () => __async(void 0, null, function* () {
|
372
|
-
const
|
373
|
-
dispatch(
|
374
|
-
return user;
|
503
|
+
const action = yield apiGetUserInfo();
|
504
|
+
dispatch(action);
|
505
|
+
return action.user;
|
375
506
|
});
|
376
507
|
const value = {
|
377
508
|
loading: authState.loading,
|
378
|
-
|
509
|
+
userAndAccessToken: authState.userAndAccessToken,
|
379
510
|
logout,
|
380
511
|
redirectToLoginPage,
|
381
512
|
redirectToSignupPage,
|
@@ -391,7 +522,7 @@ var AuthProvider = (props) => {
|
|
391
522
|
getSetupSAMLPageUrl,
|
392
523
|
refreshAuthInfo
|
393
524
|
};
|
394
|
-
return /* @__PURE__ */
|
525
|
+
return /* @__PURE__ */ import_react2.default.createElement(AuthContext.Provider, { value }, props.children);
|
395
526
|
};
|
396
527
|
function apiGetUserInfo() {
|
397
528
|
return __async(this, null, function* () {
|
@@ -404,11 +535,27 @@ function apiGetUserInfo() {
|
|
404
535
|
credentials: "include"
|
405
536
|
});
|
406
537
|
if (userInfoResponse.ok) {
|
407
|
-
const
|
408
|
-
const user = User
|
409
|
-
|
538
|
+
const { userinfo, accessToken, impersonatorUserId } = yield userInfoResponse.json();
|
539
|
+
const user = new User({
|
540
|
+
userId: userinfo.user_id,
|
541
|
+
email: userinfo.email,
|
542
|
+
emailConfirmed: userinfo.email_confirmed,
|
543
|
+
hasPassword: userinfo.has_password,
|
544
|
+
username: userinfo.username,
|
545
|
+
firstName: userinfo.first_name,
|
546
|
+
lastName: userinfo.last_name,
|
547
|
+
pictureUrl: userinfo.picture_url,
|
548
|
+
orgIdToOrgMemberInfo: toOrgIdToOrgMemberInfo(userinfo.org_id_to_org_info),
|
549
|
+
mfaEnabled: userinfo.mfa_enabled,
|
550
|
+
canCreateOrgs: userinfo.can_create_orgs,
|
551
|
+
updatePasswordRequired: userinfo.update_password_required,
|
552
|
+
createdAt: userinfo.created_at,
|
553
|
+
lastActiveAt: userinfo.last_active_at,
|
554
|
+
impersonatorUserId
|
555
|
+
});
|
556
|
+
return { user, accessToken };
|
410
557
|
} else if (userInfoResponse.status === 401) {
|
411
|
-
return { user: void 0 };
|
558
|
+
return { user: void 0, accessToken: void 0 };
|
412
559
|
} else {
|
413
560
|
console.log("Failed to refresh token", userInfoResponse);
|
414
561
|
}
|
@@ -419,35 +566,6 @@ function apiGetUserInfo() {
|
|
419
566
|
});
|
420
567
|
}
|
421
568
|
|
422
|
-
// src/client/useUser.tsx
|
423
|
-
var import_react2 = require("react");
|
424
|
-
function useUser() {
|
425
|
-
const context = (0, import_react2.useContext)(AuthContext);
|
426
|
-
if (context === void 0) {
|
427
|
-
throw new Error("useUser must be used within an AuthProvider");
|
428
|
-
}
|
429
|
-
const { loading, user } = context;
|
430
|
-
if (loading) {
|
431
|
-
return {
|
432
|
-
loading: true,
|
433
|
-
isLoggedIn: void 0,
|
434
|
-
user: void 0
|
435
|
-
};
|
436
|
-
} else if (user) {
|
437
|
-
return {
|
438
|
-
loading: false,
|
439
|
-
isLoggedIn: true,
|
440
|
-
user
|
441
|
-
};
|
442
|
-
} else {
|
443
|
-
return {
|
444
|
-
loading: false,
|
445
|
-
isLoggedIn: false,
|
446
|
-
user: void 0
|
447
|
-
};
|
448
|
-
}
|
449
|
-
}
|
450
|
-
|
451
569
|
// src/client/useHostedPageUrls.tsx
|
452
570
|
var import_react3 = require("react");
|
453
571
|
function useHostedPageUrls() {
|
@@ -538,6 +656,7 @@ function useRefreshAuth() {
|
|
538
656
|
RedirectToLogin,
|
539
657
|
RedirectToSignup,
|
540
658
|
User,
|
659
|
+
UserFromToken,
|
541
660
|
useHostedPageUrls,
|
542
661
|
useLogoutFunction,
|
543
662
|
useRedirectFunctions,
|